From 77a9f19e6532fef315d22f52008ef9c73dc69bc8 Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期二, 04 八月 2026 17:12:04 +0800
Subject: [PATCH] fix: 大屏充电用户数
---
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java | 117 ++++++++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 93 insertions(+), 24 deletions(-)
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
index 978b52a..4a5563a 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
@@ -6711,6 +6711,14 @@
if (summary != null) {
result.putAll(summary);
}
+ // 充电用户数精确去重(用户-站点对表, 跨站不重复); 对表未回填时回退到按站点求和
+ Long pairCount = this.baseMapper.userSiteTableCount();
+ if (pairCount != null && pairCount > 0) {
+ Long exactUserCount = this.baseMapper.userCountFromStat(siteIds);
+ if (exactUserCount != null) {
+ result.put("chargingUserCount", exactUserCount);
+ }
+ }
Long registered = this.baseMapper.registeredFromStat();
result.put("registeredUserCount", registered == null ? 0L : registered);
} catch (Exception e) {
@@ -6836,6 +6844,7 @@
LocalDate currentMonth = LocalDate.now().withDayOfMonth(1);
while (!month.isAfter(currentMonth)) {
writeMonthSlice(month, month.plusMonths(1));
+ writeUserSitePairs(month, month.plusMonths(1));
month = month.plusMonths(1);
}
// 2. 近90天日切片
@@ -6856,40 +6865,100 @@
LocalDate currentMonth = LocalDate.now().withDayOfMonth(1);
writeMonthSlice(currentMonth, currentMonth.plusMonths(1));
writeDaySlice(LocalDate.now());
+ writeUserSitePairs(LocalDate.now(), LocalDate.now().plusDays(1));
writeGlobal();
log.info("大屏预聚合表刷新完成, 耗时 {}ms", System.currentTimeMillis() - start);
}
/**
- * 写入一个月度切片聚合(M 行)
+ * 写入时间切片内的 (site_id, app_user_id) 对(充电用户精确去重用, INSERT IGNORE 幂等)
*/
- private void writeMonthSlice(LocalDate monthStart, LocalDate monthEnd) {
- List<Map<String, Object>> rows = this.baseMapper.monthSliceAgg(
- monthStart.atStartOfDay().format(LARGE_SCREEN_SQL_FMT),
- monthEnd.atStartOfDay().format(LARGE_SCREEN_SQL_FMT));
- if (rows == null || rows.isEmpty()) {
+ private void writeUserSitePairs(LocalDate sliceStart, LocalDate sliceEnd) {
+ List<Map<String, Object>> pairs = this.baseMapper.userSitePairsAgg(
+ sliceStart.atStartOfDay().format(LARGE_SCREEN_SQL_FMT),
+ sliceEnd.atStartOfDay().format(LARGE_SCREEN_SQL_FMT));
+ if (pairs == null || pairs.isEmpty()) {
return;
}
- List<Map<String, Object>> statRows = new ArrayList<>();
- for (Map<String, Object> row : rows) {
- if (row == null || row.get("site_id") == null) {
+ List<Map<String, Object>> rows = new ArrayList<>();
+ for (Map<String, Object> pair : pairs) {
+ if (pair == null || pair.get("site_id") == null || pair.get("app_user_id") == null) {
continue;
}
- BigDecimal electricFee = decimalValue(row, "electric_fee");
- BigDecimal serviceFee = decimalValue(row, "service_fee");
- Map<String, Object> stat = new HashMap<>();
- stat.put("statType", "M");
- stat.put("period", monthStart.format(LARGE_SCREEN_MONTH_FMT));
- stat.put("siteId", row.get("site_id"));
- stat.put("orderCount", decimalValue(row, "order_count"));
- stat.put("userCount", decimalValue(row, "user_count"));
- stat.put("capacity", decimalValue(row, "capacity"));
- stat.put("electricFee", electricFee);
- stat.put("serviceFee", serviceFee);
- stat.put("income", electricFee.add(serviceFee));
- stat.put("totalPower", BigDecimal.ZERO);
- stat.put("registeredUserCount", 0L);
- statRows.add(stat);
+ Map<String, Object> row = new HashMap<>();
+ row.put("siteId", pair.get("site_id"));
+ row.put("appUserId", pair.get("app_user_id"));
+ rows.add(row);
+ }
+ if (!rows.isEmpty()) {
+ this.baseMapper.insertUserSitePairs(rows);
+ }
+ }
+
+ /**
+ * 写入一个月度切片聚合(M 行)
+ * 金额/订单数取 monthSliceAgg(已结束+已支付口径);
+ * 充电用户数取 monthSliceUserAgg(工作台口径: 该站点所有订单的去重用户, 不区分状态/删除标记)
+ */
+ private void writeMonthSlice(LocalDate monthStart, LocalDate monthEnd) {
+ String startTime = monthStart.atStartOfDay().format(LARGE_SCREEN_SQL_FMT);
+ String endTime = monthEnd.atStartOfDay().format(LARGE_SCREEN_SQL_FMT);
+ List<Map<String, Object>> rows = this.baseMapper.monthSliceAgg(startTime, endTime);
+ List<Map<String, Object>> userRows = this.baseMapper.monthSliceUserAgg(startTime, endTime);
+ if ((rows == null || rows.isEmpty()) && (userRows == null || userRows.isEmpty())) {
+ return;
+ }
+ Map<Object, BigDecimal> userCountBySite = new HashMap<>();
+ if (userRows != null) {
+ for (Map<String, Object> userRow : userRows) {
+ if (userRow != null && userRow.get("site_id") != null) {
+ userCountBySite.put(userRow.get("site_id"), decimalValue(userRow, "user_count"));
+ }
+ }
+ }
+ String period = monthStart.format(LARGE_SCREEN_MONTH_FMT);
+ List<Map<String, Object>> statRows = new ArrayList<>();
+ Map<Object, Boolean> written = new HashMap<>();
+ if (rows != null) {
+ for (Map<String, Object> row : rows) {
+ if (row == null || row.get("site_id") == null) {
+ continue;
+ }
+ BigDecimal electricFee = decimalValue(row, "electric_fee");
+ BigDecimal serviceFee = decimalValue(row, "service_fee");
+ Map<String, Object> stat = new HashMap<>();
+ stat.put("statType", "M");
+ stat.put("period", period);
+ stat.put("siteId", row.get("site_id"));
+ stat.put("orderCount", decimalValue(row, "order_count"));
+ stat.put("userCount", userCountBySite.getOrDefault(row.get("site_id"), BigDecimal.ZERO));
+ stat.put("capacity", decimalValue(row, "capacity"));
+ stat.put("electricFee", electricFee);
+ stat.put("serviceFee", serviceFee);
+ stat.put("income", electricFee.add(serviceFee));
+ stat.put("totalPower", BigDecimal.ZERO);
+ stat.put("registeredUserCount", 0L);
+ statRows.add(stat);
+ written.put(row.get("site_id"), Boolean.TRUE);
+ }
+ }
+ // 当月仅有充电用户、暂无已结束订单的站点, 补一行保用户数(金额为0)
+ for (Map.Entry<Object, BigDecimal> entry : userCountBySite.entrySet()) {
+ if (!written.containsKey(entry.getKey())) {
+ Map<String, Object> stat = new HashMap<>();
+ stat.put("statType", "M");
+ stat.put("period", period);
+ stat.put("siteId", entry.getKey());
+ stat.put("orderCount", BigDecimal.ZERO);
+ stat.put("userCount", entry.getValue());
+ stat.put("capacity", BigDecimal.ZERO);
+ stat.put("electricFee", BigDecimal.ZERO);
+ stat.put("serviceFee", BigDecimal.ZERO);
+ stat.put("income", BigDecimal.ZERO);
+ stat.put("totalPower", BigDecimal.ZERO);
+ stat.put("registeredUserCount", 0L);
+ statRows.add(stat);
+ }
}
if (!statRows.isEmpty()) {
this.baseMapper.replaceSiteStatBatch(statRows);
--
Gitblit v1.7.1