From a887dbe759ae99273e38847954bd5b7ed3fef46f Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期三, 05 八月 2026 10:01:36 +0800
Subject: [PATCH] fix: aggregate franchise order trend by month

---
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java
index a17d3d2..b6d11e5 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java
@@ -595,6 +595,9 @@
         Map<String, Object> series = new LinkedHashMap<>(); series.put("name", name); series.put("data", data); chart.put("series", new ArrayList<>(Collections.singletonList(series))); return chart;
     }
     private Map<String, Object> franchiseeOrderTrend(List<FranchiseeDayStat> stats, LocalDateTime[] range) {
+        if (franchiseeUseMonthlyTrend(range)) {
+            return franchiseeMonthlyOrderTrend(stats, range);
+        }
         Map<String, Object> chart = franchiseeDailyTrend(stats, range, "充电金额", FranchiseeDayStat::getOrderAmountEffective);
         ((List<Map<String, Object>>) chart.get("series")).get(0).put("type", "column");
         Map<LocalDate, FranchiseeDayStat> byDay = dayStatByDay(stats);
@@ -603,6 +606,36 @@
         for (int i = 0; i < categories.size(); i++) { LocalDate day = start.plusDays(i); FranchiseeDayStat stat = byDay.get(day); countData.add(BigDecimal.valueOf(stat == null ? 0L : numberValue(stat.getOrderCount()))); }
         Map<String, Object> countSeries = new LinkedHashMap<>(); countSeries.put("name", "充电订单"); countSeries.put("data", countData); countSeries.put("type", "line"); countSeries.put("style", "curve"); countSeries.put("index", 1); ((List<Map<String, Object>>) chart.get("series")).add(countSeries); return chart;
     }
+
+    /** Long date ranges use monthly buckets so the mobile chart stays readable. */
+    private boolean franchiseeUseMonthlyTrend(LocalDateTime[] range) {
+        if (range == null || range.length < 2 || range[0] == null || range[1] == null) {
+            return false;
+        }
+        return range[0].toLocalDate().plusDays(90).isBefore(range[1].toLocalDate());
+    }
+
+    private Map<String, Object> franchiseeMonthlyOrderTrend(List<FranchiseeDayStat> stats, LocalDateTime[] range) {
+        Map<YearMonth, List<FranchiseeDayStat>> statsByMonth = stats.stream()
+                .filter(stat -> stat != null && stat.getStatDay() != null)
+                .collect(Collectors.groupingBy(stat -> YearMonth.from(stat.getStatDay())));
+        LocalDate start = range[0].toLocalDate();
+        LocalDate end = range[1].toLocalDate();
+        YearMonth firstMonth = YearMonth.from(start);
+        YearMonth lastMonth = YearMonth.from(end.minusDays(1));
+        List<String> categories = new ArrayList<>();
+        List<BigDecimal> amountData = new ArrayList<>();
+        List<BigDecimal> countData = new ArrayList<>();
+        for (YearMonth month = firstMonth; !month.isAfter(lastMonth); month = month.plusMonths(1)) {
+            List<FranchiseeDayStat> monthStats = statsByMonth.getOrDefault(month, Collections.emptyList());
+            categories.add(month.toString());
+            amountData.add(sum(monthStats, FranchiseeDayStat::getOrderAmountEffective));
+            countData.add(BigDecimal.valueOf(monthStats.stream().mapToLong(stat -> numberValue(stat.getOrderCount())).sum()));
+        }
+        Map<String, Object> amountSeries = new LinkedHashMap<>(); amountSeries.put("name", "充电金额"); amountSeries.put("data", amountData); amountSeries.put("type", "column");
+        Map<String, Object> countSeries = new LinkedHashMap<>(); countSeries.put("name", "充电订单"); countSeries.put("data", countData); countSeries.put("type", "line"); countSeries.put("style", "curve"); countSeries.put("index", 1);
+        Map<String, Object> chart = new LinkedHashMap<>(); chart.put("categories", categories); chart.put("series", new ArrayList<>(Arrays.asList(amountSeries, countSeries))); return chart;
+    }
     private Map<String, Object> franchiseePhaseRing(List<Integer> siteIds, LocalDateTime[] range) {
         Map<Integer, BigDecimal> phase = new LinkedHashMap<>(); phase.put(1, BigDecimal.ZERO); phase.put(2, BigDecimal.ZERO); phase.put(3, BigDecimal.ZERO); phase.put(4, BigDecimal.ZERO);
         if (siteIds != null && !siteIds.isEmpty() && range != null && range[0] != null && range[1] != null) {

--
Gitblit v1.7.1