From 392b42c4891cf2e6beda57ab32c51598f290f4b7 Mon Sep 17 00:00:00 2001
From: mitao <2763622819@qq.com>
Date: 星期五, 14 三月 2025 20:56:27 +0800
Subject: [PATCH] bug修改

---
 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/MgtBusinessDataService.java |  311 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 302 insertions(+), 9 deletions(-)

diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/MgtBusinessDataService.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/MgtBusinessDataService.java
index db8ee35..1b9284e 100644
--- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/MgtBusinessDataService.java
+++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/MgtBusinessDataService.java
@@ -1,44 +1,175 @@
 package com.ruoyi.order.service.impl;
 
+import com.alibaba.excel.EasyExcel;
+import com.google.common.collect.Lists;
+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.net.URLEncoder;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+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 javax.servlet.http.HttpServletResponse;
 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;
+
+        List<LocalDateTime> timeByTimeType = getTimeByTimeType(query);
+        LocalDateTime startTime = timeByTimeType.get(0);
+        LocalDateTime endTime = timeByTimeType.get(1);
+        List<Order> orderList = orderService.getStaticsOrderList(startTime, endTime);
+        MgtOrderStaticsVO mgtOrderStaticsVO = new MgtOrderStaticsVO();
+        if (CollUtils.isNotEmpty(orderList)) {
+            /* ***************************************商城订单统计*************************************** */
+            // 商城订单统计-订单总数
+            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 List<LocalDateTime> getTimeByTimeType(MgtOrderStaticsQuery query) {
+        LocalDateTime startTime;
+        LocalDateTime endTime;
+        List<LocalDateTime> range = new ArrayList<>();
+        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())) {
@@ -50,5 +181,167 @@
             startTime = DateUtils.getDayStart(now);
             endTime = DateUtils.getDayEnd(now);
         }
+        range.add(startTime);
+        range.add(endTime);
+        return range;
+    }
+
+    /**
+     * 获取图表数据
+     *
+     * @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);
+        // 使用 join 方法阻塞当前线程,直到所有任务完成
+        CompletableFuture.allOf(mallOrderCountFuture,
+                        mallOrderTotalAmountFuture, auctionOrderCountFuture, auctionOrderTotalAmountFuture)
+                .join();
+        MgtOrderStaticsChartVO mgtOrderStaticsChartVO = new MgtOrderStaticsChartVO();
+        try {
+            // 设置结果
+            mgtOrderStaticsChartVO.setMallOrderCountList(mallOrderCountFuture.get());
+            mgtOrderStaticsChartVO.setMallOrderTotalAmountList(mallOrderTotalAmountFuture.get());
+            mgtOrderStaticsChartVO.setAuctionOrderCountList(auctionOrderCountFuture.get());
+            mgtOrderStaticsChartVO.setAuctionOrderTotalAmountList(
+                    auctionOrderTotalAmountFuture.get());
+        } catch (InterruptedException | ExecutionException e) {
+            throw new RuntimeException(e);
+        } finally {
+            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());
+    }
+
+    /**
+     * 业务数据导出
+     *
+     * @param query
+     * @param response
+     */
+    public void exportBusinessData(MgtOrderStaticsQuery query, HttpServletResponse response) {
+        MgtOrderStaticsVO overview = getOverview(query);
+        // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
+        response.setContentType(
+                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
+        try {
+            String fileName = URLEncoder.encode("业务数据", "UTF-8").replaceAll("\\+", "%20");
+            response.setHeader("Content-disposition",
+                    "attachment;filename*=utf-8''" + fileName + ".xlsx");
+            EasyExcel.write(response.getOutputStream(), MgtOrderStaticsVO.class)
+                    .sheet("业务数据")
+                    .doWrite(Lists.newArrayList(overview));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 }

--
Gitblit v1.7.1