mitao
2024-06-26 884f5c68ac8c738f90f1ca257605cfbb5d7f12db
提交【管理后台】-工作台接口
3个文件已添加
16个文件已修改
487 ■■■■■ 已修改文件
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/RuoYiAuctionApplication.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/async/AuctionAsyncMethodService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionGoodsServiceImpl.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/task/AuctionGoodsScheduler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/RuoYiGoodsApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/async/AsyncMethodService.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSkuServiceImpl.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/management/MgtBusinessDataController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/management/dto/MgtOrderStaticsQuery.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/management/vo/MgtAmountChartVO.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/management/vo/MgtCountChartVO.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/management/vo/MgtOrderStaticsChartVO.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/management/vo/MgtOrderStaticsVO.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/mapper/OrderMapper.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/IOrderService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/MgtBusinessDataService.java 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/OrderServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderMapper.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java
@@ -10,7 +10,7 @@
    /**
     * 缓存有效期,默认720(分钟)
     */
    public final static long EXPIRATION = 720;
    public final static long EXPIRATION = 720 * 10;
    /**
     * 缓存刷新时间,默认120(分钟)
ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/RuoYiAuctionApplication.java
@@ -6,12 +6,16 @@
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
 * 系统模块
 * 
 * @author ruoyi
 */
@EnableAsync
@EnableScheduling
@EnableCustomConfig
@MapperScan({"com.ruoyi.auction.mapper"})
@EnableCustomSwagger2
ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/async/AuctionAsyncMethodService.java
@@ -32,6 +32,7 @@
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void auctionGoodsScheduleTask(List<AuctionGoods> auctionGoodsList) {
        log.info("开始执行定时任务");
        for (AuctionGoods auctionGoods : auctionGoodsList) {
            LocalDateTime startTime = auctionGoods.getStartTime();
            LocalDateTime endTime = auctionGoods.getEndTime();
@@ -93,9 +94,6 @@
    private void handleStartDelayTask(Long id, DelayTaskEnum delayTaskEnum, LocalDateTime startTime,
            Long timeout) {
        String startTaskKey = delayTaskEnum.getCode() + "-" + id;
        redisService.setCacheObject(
                startTaskKey,
                startTime, timeout, TimeUnit.SECONDS);
        // 查询延时任务
        DelayTask startDelayTask = sysUserClient.getDelayTask(
                startTaskKey, SecurityConstants.INNER).getData();
@@ -109,10 +107,8 @@
            sysUserClient.addDelayTask(startDelayTask, SecurityConstants.INNER);
        } else {
            if (!startDelayTask.getExecuteTime().isEqual(startTime)) {
                sysUserClient.deleteDelayTask(
                        startTaskKey, SecurityConstants.INNER);
                redisService.deleteObject(
                        startTaskKey);
                sysUserClient.deleteDelayTask(startTaskKey, SecurityConstants.INNER);
                redisService.deleteObject(startTaskKey);
                startDelayTask.setDelFlag(0);
                startDelayTask.setCreateTime(LocalDateTime.now());
                startDelayTask.setExecuteTime(LocalDateTime.now().plusSeconds(timeout));
@@ -121,6 +117,7 @@
                sysUserClient.addDelayTask(startDelayTask, SecurityConstants.INNER);
            }
        }
        redisService.setCacheObject(startTaskKey, startTime, timeout, TimeUnit.SECONDS);
        log.info(">>>>>>>>>>>>>>>>>>>>延时任务{}执行了<<<<<<<<<<<<<<<<<<<<", startTaskKey);
    }
}
ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionGoodsServiceImpl.java
@@ -66,7 +66,14 @@
import io.seata.spring.annotation.GlobalTransactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import javax.annotation.Resource;
@@ -213,6 +220,15 @@
            if (goodsSku.getStock() + auctionGoodsOrg.getAuctionStock() < dto.getAuctionStock()) {
                throw new ServiceException("商品库存不足");
            }
            if (!auctionGoodsOrg.getAuctionStock().equals(dto.getAuctionStock())) {
                // 更新商品库存
                GoodsStockUpdDTO goodsStockUpdDTO = new GoodsStockUpdDTO();
                goodsStockUpdDTO.setGoodsSkuId(goodsSkuId);
                goodsStockUpdDTO.setAuctionStock(
                        auctionGoodsOrg.getAuctionStock() - dto.getAuctionStock());
                goodsSkuClient.updGoodsStock(Lists.newArrayList(goodsStockUpdDTO),
                        SecurityConstants.INNER);
            }
            auctionGoodsOrg.setStartingPrice(dto.getStartingPrice());
            auctionGoodsOrg.setMinimumMarkupAmount(dto.getMinimumMarkupAmount());
            auctionGoodsOrg.setStartTime(dto.getStartTime());
@@ -224,15 +240,8 @@
            auctionGoodsOrg.setShareTitle(dto.getShareTitle());
            auctionGoodsOrg.setSharePic(dto.getSharePic());
            this.updateById(auctionGoodsOrg);
            // 更新商品库存
            GoodsStockUpdDTO goodsStockUpdDTO = new GoodsStockUpdDTO();
            goodsStockUpdDTO.setGoodsSkuId(goodsSkuId);
            goodsStockUpdDTO.setAuctionStock(
                    auctionGoodsOrg.getAuctionStock() - dto.getAuctionStock());
            goodsSkuClient.updGoodsStock(Lists.newArrayList(goodsStockUpdDTO),
                    SecurityConstants.INNER);
            auctionAsyncMethodService.auctionGoodsScheduleTask(Lists.newArrayList(auctionGoods));
        }
        auctionAsyncMethodService.auctionGoodsScheduleTask(Lists.newArrayList(auctionGoods));
    }
    /**
@@ -640,7 +649,6 @@
                .equals(AuctionStartStatusEnum.IN_AUCTION)) {
            auctionGoods.setStartStatus(AuctionStartStatusEnum.ENDED);
            this.updateById(auctionGoods);
            // TODO 退保证金
            orderClient.returnBondByAuctionGoodsId(id, SecurityConstants.INNER);
            Map<String, Object> map = new ConcurrentHashMap<>();
ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/task/AuctionGoodsScheduler.java
@@ -31,7 +31,7 @@
    }
    private void handleTaskStart() {
        log.info(">>>>>>>>>>>>>>>>>>>>定时任务秒杀/团购开始执行<<<<<<<<<<<<<<<<<<<<");
        log.info(">>>>>>>>>>>>>>>>>>>>定时任务普通拍品开始执行<<<<<<<<<<<<<<<<<<<<");
        LocalDateTime checkTime = LocalDateTime.now().plusHours(1);
        List<AuctionGoods> list = auctionGoodsService.lambdaQuery()
                .eq(AuctionGoods::getListingStatus, ListingStatusEnum.ON_SHELVES)
ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/RuoYiGoodsApplication.java
@@ -6,6 +6,7 @@
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
@@ -13,6 +14,7 @@
 * 
 * @author ruoyi
 */
@EnableAsync
@EnableCustomConfig
@MapperScan({"com.ruoyi.goods.mapper"})
@EnableCustomSwagger2
ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/async/AsyncMethodService.java
@@ -3,7 +3,6 @@
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.system.api.domain.GoodsGroupPurchase;
import com.ruoyi.system.api.constants.DelayTaskEnum;
import com.ruoyi.system.api.domain.DelayTask;
import com.ruoyi.system.api.domain.GoodsGroupPurchase;
@@ -120,9 +119,6 @@
    private void handleStartDelayTask(Long id, DelayTaskEnum delayTaskEnum, LocalDateTime startTime,
            Long timeout) {
        String startTaskKey = delayTaskEnum.getCode() + "-" + id;
        redisService.setCacheObject(
                startTaskKey,
                startTime, timeout, TimeUnit.SECONDS);
        //查询延时任务
        DelayTask startDelayTask = sysUserClient.getDelayTask(
                startTaskKey, SecurityConstants.INNER).getData();
@@ -148,6 +144,7 @@
                sysUserClient.addDelayTask(startDelayTask, SecurityConstants.INNER);
            }
        }
        redisService.setCacheObject(startTaskKey, startTime, timeout, TimeUnit.SECONDS);
        log.info(">>>>>>>>>>>>>>>>>>>>延时任务{}执行了<<<<<<<<<<<<<<<<<<<<", startTaskKey);
    }
}
ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSkuServiceImpl.java
@@ -17,7 +17,6 @@
import com.ruoyi.goods.controller.management.dto.GoodsInfoTitleValueDTO;
import com.ruoyi.goods.controller.management.dto.GoodsSkuDTO;
import com.ruoyi.goods.controller.management.dto.GoodsSkuQuery;
import com.ruoyi.system.api.domain.vo.GoodsInfoTitleValueVO;
import com.ruoyi.goods.controller.management.vo.GoodsSkuVO;
import com.ruoyi.goods.domain.GoodsBrowseRecord;
import com.ruoyi.goods.domain.GoodsInfoTitleValue;
@@ -39,6 +38,7 @@
import com.ruoyi.system.api.domain.dto.GoodsStockUpdDTO;
import com.ruoyi.system.api.domain.dto.HomeGoodsSkuDTO;
import com.ruoyi.system.api.domain.dto.ListStatusDTO;
import com.ruoyi.system.api.domain.vo.GoodsInfoTitleValueVO;
import com.ruoyi.system.api.domain.vo.HomeGoodsSkuInfoVO;
import com.ruoyi.system.api.domain.vo.HomeGoodsSkuListVO;
import com.ruoyi.system.api.domain.vo.OrderVO;
@@ -270,6 +270,7 @@
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updGoodsStock(List<GoodsStockUpdDTO> goodsStockUpdDTOS) {
        log.info("开始批量更新商品库存");
        List<Long> goodsSkuIdList = goodsStockUpdDTOS.stream()
                .map(GoodsStockUpdDTO::getGoodsSkuId)
                .collect(Collectors.toList());
@@ -287,7 +288,7 @@
            try {
                redissonLock.lock(30, TimeUnit.SECONDS);
                Integer auctionStock = stockMap.get(skus.getId());
                if (StringUtils.isNotNull(auctionStock) && auctionStock > 0) {
                if (StringUtils.isNotNull(auctionStock)) {
                    // 更新商品库存,更新五次失败抛出异常
                    boolean isUpdated = false;
                    for (int i = 0; i < 5; i++) {
@@ -306,7 +307,7 @@
                redissonLock.unlock();
            }
        }
        log.info("批量更新商品库存结束");
    }
    @Override
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/management/MgtBusinessDataController.java
@@ -2,11 +2,14 @@
import com.ruoyi.common.core.domain.R;
import com.ruoyi.order.controller.management.dto.MgtOrderStaticsQuery;
import com.ruoyi.order.controller.management.vo.MgtOrderStaticsChartVO;
import com.ruoyi.order.controller.management.vo.MgtOrderStaticsVO;
import com.ruoyi.order.service.impl.MgtBusinessDataService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -16,7 +19,7 @@
 * @author mitao
 * @date 2024/6/19
 */
@Api(tags = "业务数据相关接口")
@Api(tags = {"管理后台-工作台-业务数据统计"})
@RestController
@RequestMapping("/mgt/business-data")
@RequiredArgsConstructor
@@ -24,8 +27,27 @@
    private final MgtBusinessDataService mgtBusinessDataService;
    /**
     * 获取业务数据统计
     *
     * @param query 订单统计查询对象
     * @return MgtOrderStaticsVO
     */
    @ApiOperation(value = "获取业务数据统计", notes = "获取业务数据统计")
    @PostMapping("/get-overview")
    public R<MgtOrderStaticsVO> getOverview(@Validated @RequestBody MgtOrderStaticsQuery query) {
        return R.ok(mgtBusinessDataService.getOverview(query));
    }
    /**
     * 获取图表数据
     *
     * @return MgtOrderStaticsChartVO
     */
    @ApiOperation(value = "获取业务数据统计图表数据", notes = "获取业务数据统计图表数据")
    @GetMapping("/get-chart")
    public R<MgtOrderStaticsChartVO> getChart() {
        return R.ok(mgtBusinessDataService.getChart());
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/management/dto/MgtOrderStaticsQuery.java
@@ -6,13 +6,19 @@
import java.io.Serializable;
import java.time.LocalDateTime;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
 * @author mitao
 * @date 2024/6/19
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel("订单统计查询对象")
public class MgtOrderStaticsQuery implements Serializable {
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/management/vo/MgtAmountChartVO.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.order.controller.management.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.math.BigDecimal;
import lombok.Data;
@Data
@ApiModel("订单金额统计图表对象")
public class MgtAmountChartVO implements Serializable {
    private static final long serialVersionUID = 8440194640873107140L;
    @ApiModelProperty(value = "日期", notes = "X轴")
    private String date;
    @ApiModelProperty(value = "总金额", notes = "Y轴")
    private BigDecimal value;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/management/vo/MgtCountChartVO.java
New file
@@ -0,0 +1,18 @@
package com.ruoyi.order.controller.management.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import lombok.Data;
@Data
@ApiModel("订单总数统计图表对象")
public class MgtCountChartVO implements Serializable {
    private static final long serialVersionUID = 8440194640873107140L;
    @ApiModelProperty(value = "日期", notes = "X轴")
    private String date;
    @ApiModelProperty(value = "订单总数", notes = "Y轴")
    private Long value;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/management/vo/MgtOrderStaticsChartVO.java
New file
@@ -0,0 +1,30 @@
package com.ruoyi.order.controller.management.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
import lombok.Data;
/**
 * @author mitao
 * @date 2024/6/25
 */
@Data
@ApiModel("订单统计图表对象")
public class MgtOrderStaticsChartVO {
    @ApiModelProperty(value = "商城订单总数", notes = "商城订单总数")
    private List<MgtCountChartVO> mallOrderCountList;
    @ApiModelProperty(value = "商城订单总金额", notes = "商城订单总金额")
    private List<MgtAmountChartVO> mallOrderTotalAmountList;
    @ApiModelProperty(value = "拍卖订单总数", notes = "拍卖订单总数")
    private List<MgtCountChartVO> auctionOrderCount;
    @ApiModelProperty(value = "拍卖订单总金额", notes = "拍卖订单总金额")
    private List<MgtAmountChartVO> auctionOrderTotalAmount;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/management/vo/MgtOrderStaticsVO.java
@@ -16,16 +16,16 @@
    private static final long serialVersionUID = -6511810306263817540L;
    @ApiModelProperty("商城订单统计-订单总数")
    private Integer mallOrderTotalCount;
    private Long mallOrderTotalCount;
    @ApiModelProperty("商城订单统计-商城订单")
    private Integer mallOrderCount;
    private Long mallOrderCount;
    @ApiModelProperty("商城订单统计-秒杀订单")
    private Integer seckillOrderCount;
    private Long seckillOrderCount;
    @ApiModelProperty("商城订单统计-团购订单")
    private Integer groupPurchaseOrderCount;
    private Long groupPurchaseOrderCount;
    @ApiModelProperty("商城订单统计-订单总金额")
    private BigDecimal mallOrderTotalAmount;
@@ -40,13 +40,13 @@
    private BigDecimal groupPurchaseTotalAmount;
    @ApiModelProperty("拍卖订单统计-订单总数")
    private Integer auctionOrderTotalCount;
    private Long auctionOrderTotalCount;
    @ApiModelProperty("拍卖订单统计-拍卖商品订单")
    private Integer auctionGoodsOrderCount;
    private Long auctionGoodsOrderCount;
    @ApiModelProperty("拍卖订单统计-拍卖场订单")
    private Integer auctionSalesroomOrderCount;
    private Long auctionSalesroomOrderCount;
    @ApiModelProperty("拍卖订单统计-订单总金额")
    private BigDecimal auctionOrderTotalAmount;
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/mapper/OrderMapper.java
@@ -2,11 +2,11 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.system.api.domain.Order;
import java.util.List;
import com.ruoyi.system.api.domain.dto.HomeGoodsSkuDTO;
import com.ruoyi.system.api.domain.dto.MemberOrderDTO;
import com.ruoyi.system.api.domain.vo.OrderVO;
import java.time.LocalDateTime;
import java.util.List;
import org.apache.ibatis.annotations.Param;
/**
@@ -42,4 +42,13 @@
    List<OrderVO> getOrderByGroupPurchaseMemberList(HomeGoodsSkuDTO homeGoodsSkuDTO);
    /**
     * 查询统计订单列表
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return List<Order>
     */
    List<Order> getStaticsOrderList(@Param("startTime") LocalDateTime startTime,
            @Param("endTime") LocalDateTime endTime);
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/IOrderService.java
@@ -14,6 +14,7 @@
import com.ruoyi.system.api.domain.vo.MemberOrderNumVO;
import com.ruoyi.system.api.domain.vo.MemberTiOrderVO;
import com.ruoyi.system.api.domain.vo.OrderVO;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import org.springframework.web.bind.annotation.RequestBody;
@@ -128,4 +129,13 @@
     * @param id 订单id
     */
    void refundBond(Long id);
    /**
     * 查询统计订单列表
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return List<Order>
     */
    List<Order> getStaticsOrderList(LocalDateTime startTime, LocalDateTime endTime);
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/MgtBusinessDataService.java
@@ -1,44 +1,163 @@
package com.ruoyi.order.service.impl;
import com.ruoyi.common.core.enums.AuctionOrderTypeEnum;
import com.ruoyi.common.core.enums.OrderFromEnum;
import com.ruoyi.common.core.enums.OrderTypeEnum;
import com.ruoyi.common.core.enums.TimeTypeEnum;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.page.CollUtils;
import com.ruoyi.order.controller.management.dto.MgtOrderStaticsQuery;
import com.ruoyi.order.controller.management.vo.MgtAmountChartVO;
import com.ruoyi.order.controller.management.vo.MgtCountChartVO;
import com.ruoyi.order.controller.management.vo.MgtOrderStaticsChartVO;
import com.ruoyi.order.controller.management.vo.MgtOrderStaticsVO;
import com.ruoyi.order.service.IOrderService;
import com.ruoyi.system.api.domain.Order;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
/**
 * @author mitao
 * @date 2024/6/19
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MgtBusinessDataService {
    private final IOrderService orderService;
    /**
     * 获取业务数据统计
     *
     * @param query 订单统计查询对象
     * @return MgtOrderStaticsVO
     */
    public MgtOrderStaticsVO getOverview(MgtOrderStaticsQuery query) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime = null;
        LocalDateTime endTime = null;
        getTimeByTimeType(query, startTime, endTime, now);
        return null;
        getTimeByTimeType(query, startTime, endTime);
        List<Order> orderList = orderService.getStaticsOrderList(startTime, endTime);
        if (orderList.isEmpty()) {
            throw new ServiceException("暂无数据");
        }
        MgtOrderStaticsVO mgtOrderStaticsVO = new MgtOrderStaticsVO();
        /* ***************************************商城订单统计*************************************** */
        // 商城订单统计-订单总数
        long mallOrderTotalCount = orderList.stream()
                .filter(order -> !order.getOrderFrom().equals(OrderFromEnum.AUCTION_ORDERS))
                .count();
        // 商城订单统计-订单总数
        long mallOrderCount = orderList.stream()
                .filter(order -> order.getOrderFrom().equals(OrderFromEnum.COMMODITY_ORDER))
                .count();
        // 商城订单统计-商城订单
        long seckillOrderCount = orderList.stream()
                .filter(order -> order.getOrderFrom().equals(OrderFromEnum.SNAP_ORDERS))
                .count();
        // 商城订单统计-团购订单
        long groupPurchaseOrderCount = orderList.stream()
                .filter(order -> order.getOrderFrom().equals(OrderFromEnum.GROUP_PURCHASE_ORDERS))
                .count();
        // 商城订单统计-订单总金额
        BigDecimal mallOrderTotalAmount = orderList.stream()
                .filter(order -> !order.getOrderFrom().equals(OrderFromEnum.AUCTION_ORDERS))
                .map(Order::getTotalAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        // 商城订单统计 - 商城总金额
        BigDecimal mallTotalAmount = orderList.stream()
                .filter(order -> order.getOrderFrom().equals(OrderFromEnum.COMMODITY_ORDER))
                .map(Order::getTotalAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        // 商城订单统计-秒杀总金额
        BigDecimal seckillTotalAmount = orderList.stream()
                .filter(order -> order.getOrderFrom().equals(OrderFromEnum.SNAP_ORDERS))
                .map(Order::getTotalAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        // 商城订单统计-团购总金额
        BigDecimal groupPurchaseTotalAmount = orderList.stream()
                .filter(order -> order.getOrderFrom().equals(OrderFromEnum.GROUP_PURCHASE_ORDERS))
                .map(Order::getTotalAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        mgtOrderStaticsVO.setMallOrderTotalCount(mallOrderTotalCount);
        mgtOrderStaticsVO.setMallOrderCount(mallOrderCount);
        mgtOrderStaticsVO.setSeckillOrderCount(seckillOrderCount);
        mgtOrderStaticsVO.setGroupPurchaseOrderCount(groupPurchaseOrderCount);
        mgtOrderStaticsVO.setMallOrderTotalAmount(mallOrderTotalAmount);
        mgtOrderStaticsVO.setMallTotalAmount(mallTotalAmount);
        mgtOrderStaticsVO.setSeckillTotalAmount(seckillTotalAmount);
        mgtOrderStaticsVO.setGroupPurchaseTotalAmount(groupPurchaseTotalAmount);
        /* ***************************************拍卖订单统计*************************************** */
        // 拍卖订单统计-订单总数
        long auctionOrderTotalCount = orderList.stream()
                .filter(order -> order.getOrderFrom().equals(OrderFromEnum.AUCTION_ORDERS))
                .count();
        // 商城订单统计-订单总数
        long auctionGoodsOrderCount = orderList.stream()
                .filter(order -> order.getOrderFrom().equals(OrderFromEnum.AUCTION_ORDERS)
                        && order.getAuctionOrderType().equals(AuctionOrderTypeEnum.REGULAR_ITEMS))
                .count();
        // 拍卖订单统计-拍卖商品订单
        long auctionSalesroomOrderCount = orderList.stream()
                .filter(order -> order.getOrderFrom().equals(OrderFromEnum.AUCTION_ORDERS)
                        && order.getAuctionOrderType().equals(AuctionOrderTypeEnum.AUCTION_ITEMS))
                .count();
        // 拍卖订单统计-订单总金额
        BigDecimal auctionOrderTotalAmount = orderList.stream()
                .filter(order -> order.getOrderFrom().equals(OrderFromEnum.AUCTION_ORDERS))
                .map(Order::getTotalAmount)
                .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        // 拍卖订单统计-拍卖商品总金额
        BigDecimal auctionGoodsTotalAmount = orderList.stream()
                .filter(order -> order.getOrderFrom().equals(OrderFromEnum.AUCTION_ORDERS)
                        && order.getAuctionOrderType().equals(AuctionOrderTypeEnum.REGULAR_ITEMS)
                )
                .map(Order::getTotalAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        // 拍卖订单统计-拍卖场总金额
        BigDecimal auctionSalesroomTotalAmount = orderList.stream()
                .filter(order -> order.getOrderFrom().equals(OrderFromEnum.AUCTION_ORDERS)
                        && order.getAuctionOrderType().equals(AuctionOrderTypeEnum.AUCTION_ITEMS))
                .map(Order::getTotalAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        mgtOrderStaticsVO.setAuctionOrderTotalCount(auctionOrderTotalCount);
        mgtOrderStaticsVO.setAuctionGoodsOrderCount(auctionGoodsOrderCount);
        mgtOrderStaticsVO.setAuctionSalesroomOrderCount(auctionSalesroomOrderCount);
        mgtOrderStaticsVO.setAuctionOrderTotalAmount(auctionOrderTotalAmount);
        mgtOrderStaticsVO.setAuctionGoodsTotalAmount(auctionGoodsTotalAmount);
        mgtOrderStaticsVO.setAuctionSalesroomTotalAmount(auctionSalesroomTotalAmount);
        return mgtOrderStaticsVO;
    }
    private static void getTimeByTimeType(MgtOrderStaticsQuery query, LocalDateTime startTime,
            LocalDateTime endTime, LocalDateTime now) {
    private void getTimeByTimeType(MgtOrderStaticsQuery query, LocalDateTime startTime,
            LocalDateTime endTime) {
        LocalDateTime now = LocalDateTime.now();
        if (Objects.equals(TimeTypeEnum.TODAY.getCode(), query.getTimeType())) {
            startTime = DateUtils.getDayStart(now);
            endTime = DateUtils.getDayEnd(now);
        } else if (Objects.equals(TimeTypeEnum.PAST_SEVEN_DAYS.getCode(), query.getTimeType())) {
            startTime = DateUtils.getDayStart(now.minusDays(7));
            startTime = DateUtils.getDayStart(now.minusDays(6)); // 过去七天 为过去六天加今天
            endTime = DateUtils.getDayEnd(now);
        } else if (Objects.equals(TimeTypeEnum.PAST_THIRTY_DAYS.getCode(), query.getTimeType())) {
            startTime = DateUtils.getDayStart(now.minusDays(30));
            startTime = DateUtils.getDayStart(now.minusDays(29)); // 过去30天 为过去29天加今天
            endTime = DateUtils.getDayEnd(now);
        } else if (Objects.equals(TimeTypeEnum.CUSTOM.getCode(), query.getTimeType())) {
            if (Objects.isNull(query.getStartTime()) || Objects.isNull(query.getEndTime())) {
@@ -51,4 +170,138 @@
            endTime = DateUtils.getDayEnd(now);
        }
    }
    /**
     * 获取图表数据
     *
     * @return MgtOrderStaticsChartVO
     */
    public MgtOrderStaticsChartVO getChart() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime = DateUtils.getDayStart(now.minusDays(29));
        LocalDateTime endTime = DateUtils.getDayEnd(now);
        List<LocalDate> datesBetween = getDatesBetween(startTime.toLocalDate(),
                endTime.toLocalDate());
        // 根据开始时间和结束时间,获取这个范围的每一天的日期
        List<Order> orderList = orderService.getStaticsOrderList(startTime, endTime);
        ExecutorService executorService = Executors.newFixedThreadPool(4);
        // 商城订单总数
        CompletableFuture<List<MgtCountChartVO>> mallOrderCountFuture = CompletableFuture.supplyAsync(
                () -> getMgtCountChartVOS(datesBetween, orderList, OrderTypeEnum.MALL_ODER),
                executorService);
        // 商城订单总金额
        CompletableFuture<List<MgtAmountChartVO>> mallOrderTotalAmountFuture = CompletableFuture.supplyAsync(
                () -> getMgtAmountChartVOS(datesBetween, orderList, OrderTypeEnum.MALL_ODER),
                executorService);
        // 拍卖订单总数
        CompletableFuture<List<MgtCountChartVO>> auctionOrderCountFuture = CompletableFuture.supplyAsync(
                () -> getMgtCountChartVOS(datesBetween, orderList, OrderTypeEnum.AUCTION_ORDER),
                executorService);
        // 拍卖订单总金额
        CompletableFuture<List<MgtAmountChartVO>> auctionOrderTotalAmountFuture = CompletableFuture.supplyAsync(
                () -> getMgtAmountChartVOS(datesBetween, orderList, OrderTypeEnum.AUCTION_ORDER),
                executorService);
        // 等待所有任务完成
        CompletableFuture<Void> futureAll = CompletableFuture.allOf(mallOrderCountFuture,
                mallOrderTotalAmountFuture, auctionOrderCountFuture, auctionOrderTotalAmountFuture);
        MgtOrderStaticsChartVO mgtOrderStaticsChartVO = new MgtOrderStaticsChartVO();
        futureAll.thenRun(() -> {
            try {
                mgtOrderStaticsChartVO.setMallOrderCountList(mallOrderCountFuture.get());
                mgtOrderStaticsChartVO.setMallOrderTotalAmountList(
                        mallOrderTotalAmountFuture.get());
                mgtOrderStaticsChartVO.setAuctionOrderCount(auctionOrderCountFuture.get());
                mgtOrderStaticsChartVO.setAuctionOrderTotalAmount(
                        auctionOrderTotalAmountFuture.get());
            } catch (InterruptedException | ExecutionException e) {
                throw new RuntimeException(e);
            }
            executorService.shutdown(); // 关闭线程池
        });
        return mgtOrderStaticsChartVO;
    }
    @NotNull
    private static List<MgtAmountChartVO> getMgtAmountChartVOS(List<LocalDate> datesBetween,
            List<Order> orderList, OrderTypeEnum type) {
        Map<String, BigDecimal> orderTotalAmountMap;
        if (type.equals(OrderTypeEnum.MALL_ODER)) {
            orderTotalAmountMap = orderList.stream()
                    .filter(order -> !order.getOrderFrom().equals(OrderFromEnum.AUCTION_ORDERS))
                    .collect(Collectors.groupingBy(order -> order.getOrderTime().toLocalDate()
                                    .format(DateTimeFormatter.ofPattern("MM-dd")),
                            Collectors.reducing(BigDecimal.ZERO, Order::getTotalAmount,
                                    BigDecimal::add)));
        } else if (type.equals(OrderTypeEnum.AUCTION_ORDER)) {
            orderTotalAmountMap = orderList.stream()
                    .filter(order -> order.getOrderFrom().equals(OrderFromEnum.AUCTION_ORDERS))
                    .collect(Collectors.groupingBy(order -> order.getOrderTime().toLocalDate()
                                    .format(DateTimeFormatter.ofPattern("MM-dd")),
                            Collectors.reducing(BigDecimal.ZERO, Order::getTotalAmount,
                                    BigDecimal::add)));
        } else {
            orderTotalAmountMap = null;
        }
        if (orderTotalAmountMap != null) {
            return datesBetween.stream().map(date -> {
                MgtAmountChartVO mgtAmountChartVO = new MgtAmountChartVO();
                mgtAmountChartVO.setDate(date.format(DateTimeFormatter.ofPattern("MM-dd")));
                BigDecimal orderTotalAmount = orderTotalAmountMap.get(
                        date.format(DateTimeFormatter.ofPattern("MM-dd")));
                mgtAmountChartVO.setValue(
                        orderTotalAmount == null ? BigDecimal.ZERO : orderTotalAmount);
                return mgtAmountChartVO;
            }).collect(Collectors.toList());
        } else {
            return CollUtils.emptyList();
        }
    }
    @NotNull
    private static List<MgtCountChartVO> getMgtCountChartVOS(List<LocalDate> datesBetween,
            List<Order> orderList, OrderTypeEnum type) {
        Map<String, Long> orderCountMap;
        if (type.equals(OrderTypeEnum.MALL_ODER)) {
            orderCountMap = orderList.stream()
                    .filter(order -> !order.getOrderFrom().equals(OrderFromEnum.AUCTION_ORDERS))
                    .collect(Collectors.groupingBy(order -> order.getOrderTime().toLocalDate()
                                    .format(DateTimeFormatter.ofPattern("MM-dd")),
                            Collectors.counting()));
        } else if (type.equals(OrderTypeEnum.AUCTION_ORDER)) {
            orderCountMap = orderList.stream()
                    .filter(order -> order.getOrderFrom().equals(OrderFromEnum.AUCTION_ORDERS))
                    .collect(Collectors.groupingBy(order -> order.getOrderTime().toLocalDate()
                                    .format(DateTimeFormatter.ofPattern("MM-dd")),
                            Collectors.counting()));
        } else {
            orderCountMap = null;
        }
        if (orderCountMap != null) {
            return datesBetween.stream().map(date -> {
                MgtCountChartVO mgtCountChartVO = new MgtCountChartVO();
                mgtCountChartVO.setDate(date.format(DateTimeFormatter.ofPattern("MM-dd")));
                Long orderCount = orderCountMap.get(
                        date.format(DateTimeFormatter.ofPattern("MM-dd")));
                mgtCountChartVO.setValue(orderCount == null ? 0L : orderCount);
                return mgtCountChartVO;
            }).collect(Collectors.toList());
        } else {
            return CollUtils.emptyList();
        }
    }
    public List<LocalDate> getDatesBetween(LocalDate startDate, LocalDate endDate) {
        // 检查开始日期是否晚于结束日期
        if (startDate.isAfter(endDate)) {
            throw new IllegalArgumentException("开始日期必须早于结束日期");
        }
        // 使用ChronoUnit.DAYS.between计算日期差,并生成日期范围的流
        long numOfDaysBetween = ChronoUnit.DAYS.between(startDate, endDate);
        // 使用Stream.iterate生成日期序列,再用limit限制天数,最后collect收集结果
        return Stream.iterate(startDate, date -> date.plusDays(1))
                .limit(numOfDaysBetween + 1) // 加1是因为包含结束日期
                .collect(Collectors.toList());
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/OrderServiceImpl.java
@@ -1198,4 +1198,16 @@
            }
        }
    }
    /**
     * 查询统计订单列表
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return List<Order>
     */
    @Override
    public List<Order> getStaticsOrderList(LocalDateTime startTime, LocalDateTime endTime) {
        return baseMapper.getStaticsOrderList(startTime, endTime);
    }
}
ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderMapper.xml
@@ -92,5 +92,17 @@
      AND   o.member_id=#{memberId}
    </where>
  </select>
  <select id="getStaticsOrderList" resultType="com.ruoyi.system.api.domain.Order">
    SELECT o.*
    FROM t_order o
    LEFT JOIN t_order_return_request torr ON o.id = torr.order_id
    <where>
      o.order_status IN (1, 2, 3, 4)
      OR (o.order_status = 6 AND torr.audit_status != 2)
      <if test="startTime != null and endTime != null">
        AND o.create_time between #{startTime,jdbcType=TIMESTAMP} and #{endTime,jdbcType=TIMESTAMP}
      </if>
    </where>
  </select>
</mapper>