فهرست منبع

fix: totalIncome/crossIncome 按类型精确过滤,避免跨店双计

新增 sumDailyRechargeIncome / sumDailyCrossIncome / sumDailyCrossExpend
等按类型+方向精确统计方法。totalIncome 改为 充值收入+跨店收入 合并,
crossIncome/crossExpend 各自按专属类型过滤,消除 CROSS_EXPEND 与
CROSS_INCOME 配对记录被重复计入的问题。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
skyline 1 روز پیش
والد
کامیت
36ce5bd171

+ 12 - 0
car-wash-service/src/main/java/com/kym/service/SplitRecordService.java

@@ -39,4 +39,16 @@ public interface SplitRecordService extends MyBaseService<SplitRecord> {
     Map<String, Integer> countDailyRefund(LocalDate statDay);
 
     Map<String, Integer> countMonthRefund(LocalDate statDay);
+
+    Map<String, Integer> sumDailyRechargeIncome(LocalDate statDay);
+
+    Map<String, Integer> sumMonthRechargeIncome(LocalDate statDay);
+
+    Map<String, Integer> sumDailyCrossIncome(LocalDate statDay);
+
+    Map<String, Integer> sumMonthCrossIncome(LocalDate statDay);
+
+    Map<String, Integer> sumDailyCrossExpend(LocalDate statDay);
+
+    Map<String, Integer> sumMonthCrossExpend(LocalDate statDay);
 }

+ 9 - 5
car-wash-service/src/main/java/com/kym/service/impl/DailyStatServiceImpl.java

@@ -89,17 +89,21 @@ public class DailyStatServiceImpl extends MyBaseServiceImpl<DailyStatMapper, Dai
         var amountMap = washOrderService.sumAmountByDate(statDay);
         var registerMap = userService.countDailyRegister(statDay);
         var ordersCountMap = washOrderService.countDailyOrders(statDay);
-        var incomeMap = splitRecordService.sumDailyIncome(statDay);
-        var crossIncomeMap = splitRecordService.sumDailyIncome(statDay, Boolean.TRUE);
-        var expendMap = splitRecordService.sumDailyExpend(statDay, Boolean.TRUE);
+        var rechargeIncomeMap = splitRecordService.sumDailyRechargeIncome(statDay);
+        var crossIncomeMap = splitRecordService.sumDailyCrossIncome(statDay);
+        var crossExpendMap = splitRecordService.sumDailyCrossExpend(statDay);
         var refundMap = splitRecordService.sumDailyRefund(statDay);
         var rechargeCountMap = splitRecordService.countDailyRecharge(statDay);
         var refundCountMap = splitRecordService.countDailyRefund(statDay);
         var activeUserMap = washOrderService.countDailyActiveUsers(statDay);
 
+        // 总入账 = 充值收入 + 跨店收入
+        var incomeMap = new HashMap<>(rechargeIncomeMap);
+        crossIncomeMap.forEach((k, v) -> incomeMap.merge(k, v, Integer::sum));
+
         // 收集所有出现过的站点(过滤掉无归属的null和"未分配"占位符)
         var allStationIds = Stream.of(amountMap, registerMap, ordersCountMap, incomeMap,
-                        crossIncomeMap, expendMap, refundMap, rechargeCountMap, refundCountMap, activeUserMap)
+                        crossIncomeMap, crossExpendMap, refundMap, rechargeCountMap, refundCountMap, activeUserMap)
                 .flatMap(m -> m.keySet().stream())
                 .filter(s -> s != null && !"未分配".equals(s))
                 .collect(Collectors.toSet());
@@ -125,7 +129,7 @@ public class DailyStatServiceImpl extends MyBaseServiceImpl<DailyStatMapper, Dai
                 stat.setOrdersCount(ordersCountMap.getOrDefault(stationId, 0));
                 stat.setTotalIncome(incomeMap.getOrDefault(stationId, 0));
                 stat.setCrossIncome(crossIncomeMap.getOrDefault(stationId, 0));
-                stat.setCrossExpend(expendMap.getOrDefault(stationId, 0));
+                stat.setCrossExpend(crossExpendMap.getOrDefault(stationId, 0));
                 stat.setTotalRefund(refundMap.getOrDefault(stationId, 0));
                 stat.setRechargeCount(rechargeCountMap.getOrDefault(stationId, 0));
                 stat.setRefundCount(refundCountMap.getOrDefault(stationId, 0));

+ 14 - 9
car-wash-service/src/main/java/com/kym/service/impl/MonthStatServiceImpl.java

@@ -22,6 +22,7 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.YearMonth;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -91,13 +92,17 @@ public class MonthStatServiceImpl extends MyBaseServiceImpl<MonthStatMapper, Mon
         Map<String, Integer> amountMap = washOrderService.sumMonthAmount(statDay);
         Map<String, Integer> registerMap = userService.countMonthRegister(statDay);
         Map<String, Integer> ordersCountMap = washOrderService.countMonthOrders(statDay);
-        Map<String, Integer> incomeMap = splitRecordService.sumMonthIncome(statDay);
-        Map<String, Integer> crossIncomeMap = splitRecordService.sumMonthIncome(statDay, Boolean.TRUE);
-        Map<String, Integer> expendMap = splitRecordService.sumMonthExpend(statDay, Boolean.TRUE);
-        Map<String, Integer> refundMap = splitRecordService.sumMonthRefund(statDay);
-        Map<String, Integer> rechargeCountMap = splitRecordService.countMonthRecharge(statDay);
-        Map<String, Integer> refundCountMap = splitRecordService.countMonthRefund(statDay);
-        Map<String, Integer> activeUserMap = washOrderService.countMonthActiveUsers(statDay);
+        var rechargeIncomeMap = splitRecordService.sumMonthRechargeIncome(statDay);
+        var crossIncomeMap = splitRecordService.sumMonthCrossIncome(statDay);
+        var crossExpendMap = splitRecordService.sumMonthCrossExpend(statDay);
+        var refundMap = splitRecordService.sumMonthRefund(statDay);
+        var rechargeCountMap = splitRecordService.countMonthRecharge(statDay);
+        var refundCountMap = splitRecordService.countMonthRefund(statDay);
+        var activeUserMap = washOrderService.countMonthActiveUsers(statDay);
+
+        // 总入账 = 充值收入 + 跨店收入
+        var incomeMap = new HashMap<>(rechargeIncomeMap);
+        crossIncomeMap.forEach((k, v) -> incomeMap.merge(k, v, Integer::sum));
 
         var platformFeeMap = settlementService.lambdaQuery()
                 .eq(SettlementRecord::getSettlementPeriod, statMonth)
@@ -109,7 +114,7 @@ public class MonthStatServiceImpl extends MyBaseServiceImpl<MonthStatMapper, Mon
                         Integer::sum));
 
         var allStationIds = Stream.of(amountMap, registerMap, ordersCountMap, incomeMap,
-                        crossIncomeMap, expendMap, refundMap, rechargeCountMap, refundCountMap,
+                        crossIncomeMap, crossExpendMap, refundMap, rechargeCountMap, refundCountMap,
                         activeUserMap, platformFeeMap)
                 .flatMap(m -> m.keySet().stream())
                 .filter(s -> s != null && !"未分配".equals(s))
@@ -136,7 +141,7 @@ public class MonthStatServiceImpl extends MyBaseServiceImpl<MonthStatMapper, Mon
                 stat.setOrdersCount(ordersCountMap.getOrDefault(stationId, 0));
                 stat.setTotalIncome(incomeMap.getOrDefault(stationId, 0));
                 stat.setCrossIncome(crossIncomeMap.getOrDefault(stationId, 0));
-                stat.setCrossExpend(expendMap.getOrDefault(stationId, 0));
+                stat.setCrossExpend(crossExpendMap.getOrDefault(stationId, 0));
                 stat.setTotalRefund(refundMap.getOrDefault(stationId, 0));
                 stat.setPlatformFee(platformFeeMap.getOrDefault(stationId, 0));
                 stat.setRechargeCount(rechargeCountMap.getOrDefault(stationId, 0));

+ 30 - 0
car-wash-service/src/main/java/com/kym/service/impl/SplitRecordServiceImpl.java

@@ -149,6 +149,36 @@ public class SplitRecordServiceImpl extends MyBaseServiceImpl<SplitRecordMapper,
         return countByType(Boolean.FALSE, statDay, SplitRecord::getFromStationId, SplitRecord.TYPE_REFUND);
     }
 
+    @Override
+    public Map<String, Integer> sumDailyRechargeIncome(LocalDate statDay) {
+        return sumByType(Boolean.TRUE, statDay, SplitRecord::getToStationId, SplitRecord.TYPE_RECHARGE);
+    }
+
+    @Override
+    public Map<String, Integer> sumMonthRechargeIncome(LocalDate statDay) {
+        return sumByType(Boolean.FALSE, statDay, SplitRecord::getToStationId, SplitRecord.TYPE_RECHARGE);
+    }
+
+    @Override
+    public Map<String, Integer> sumDailyCrossIncome(LocalDate statDay) {
+        return sumByType(Boolean.TRUE, statDay, SplitRecord::getToStationId, SplitRecord.TYPE_CROSS_INCOME);
+    }
+
+    @Override
+    public Map<String, Integer> sumMonthCrossIncome(LocalDate statDay) {
+        return sumByType(Boolean.FALSE, statDay, SplitRecord::getToStationId, SplitRecord.TYPE_CROSS_INCOME);
+    }
+
+    @Override
+    public Map<String, Integer> sumDailyCrossExpend(LocalDate statDay) {
+        return sumByType(Boolean.TRUE, statDay, SplitRecord::getFromStationId, SplitRecord.TYPE_CROSS_EXPEND);
+    }
+
+    @Override
+    public Map<String, Integer> sumMonthCrossExpend(LocalDate statDay) {
+        return sumByType(Boolean.FALSE, statDay, SplitRecord::getFromStationId, SplitRecord.TYPE_CROSS_EXPEND);
+    }
+
     private Map<String, Integer> sumByType(Boolean isDaily, LocalDate statDay, Function<SplitRecord, String> classifier, Integer type) {
         LocalDateTime startTime = isDaily ? getStartOfDay(statDay) : getStartOfMonth(statDay);
         LocalDateTime endTime = isDaily ? getEndOfDay(statDay) : getEndOfMonth(statDay);