From 21ec3321d0fedf152987a7de8c6a846e4a430f0e Mon Sep 17 00:00:00 2001 From: cst61 Date: Sun, 7 Jun 2026 21:05:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E9=80=A0=E4=B8=BA=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E4=BA=BA=E5=A4=A9=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rj/controller/LbOrderRowController.java | 7 +- src/main/java/com/rj/entity/LbOrderRow.java | 4 + .../com/rj/service/ILbOrderRowService.java | 3 +- .../service/impl/LbOrderRowServiceImpl.java | 108 +++++++++++++++++- .../resources/mapper/LbOrderRowMapper.xml | 7 +- 5 files changed, 119 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/rj/controller/LbOrderRowController.java b/src/main/java/com/rj/controller/LbOrderRowController.java index 0650989..2ba91c3 100644 --- a/src/main/java/com/rj/controller/LbOrderRowController.java +++ b/src/main/java/com/rj/controller/LbOrderRowController.java @@ -116,10 +116,11 @@ public class LbOrderRowController { @PostMapping("/generate-daily-sum") @Operation( - summary = "按日汇总生成 sum_data", + summary = "按日汇总生成 sum_data 与人天统计", description = - "按购买时间区间、租户 id 查询 lb_order_row 明细,每天生成一条 sum_data(today_total_money_sum、" - + "today_unresell_count、today_order_count 等)并写入表") + "按购买时间区间、租户 id 查询 lb_order_row 明细:每天生成一条 sum_data(today_total_money_sum、" + + "today_unresell_count、today_order_count、avg_amt 等);同时按 buyer_phone + 购买日期" + + "生成 day_stat 人天统计(当天购买总单数、当天购买总金额、平均金额)并写入表") public ResponseEntity> generateDailySum( @Parameter(description = "汇总条件", required = true) @RequestBody LbOrderRowGenerateSumRequest request) { diff --git a/src/main/java/com/rj/entity/LbOrderRow.java b/src/main/java/com/rj/entity/LbOrderRow.java index 4e0cfc9..9c62180 100644 --- a/src/main/java/com/rj/entity/LbOrderRow.java +++ b/src/main/java/com/rj/entity/LbOrderRow.java @@ -146,4 +146,8 @@ public class LbOrderRow implements Serializable { @TableField("today_order_count") @Schema(description = "当天交易单数") private Integer todayOrderCount; + + @TableField("avg_amt") + @Schema(description = "平均金额(sum_data 按日汇总时:总金额 / 当天交易单数)") + private BigDecimal avgAmt; } diff --git a/src/main/java/com/rj/service/ILbOrderRowService.java b/src/main/java/com/rj/service/ILbOrderRowService.java index 7ef4fd0..cf3df12 100644 --- a/src/main/java/com/rj/service/ILbOrderRowService.java +++ b/src/main/java/com/rj/service/ILbOrderRowService.java @@ -49,7 +49,8 @@ public interface ILbOrderRowService extends IService { Integer hxrOrderStatus); /** - * 按购买时间区间与租户查询明细,按天汇总为 {@code sum_data} 写入 {@code lb_order_row}。 + * 按购买时间区间与租户查询明细,按天汇总为 {@code sum_data},并按 {@code buyer_phone} + 购买日期 + * 生成 {@code day_stat} 人天统计,写入 {@code lb_order_row}。 */ Map generateDailySumData(String buyTimeStart, String buyTimeEnd, String tenantId); diff --git a/src/main/java/com/rj/service/impl/LbOrderRowServiceImpl.java b/src/main/java/com/rj/service/impl/LbOrderRowServiceImpl.java index 2dd6428..53cf2f5 100644 --- a/src/main/java/com/rj/service/impl/LbOrderRowServiceImpl.java +++ b/src/main/java/com/rj/service/impl/LbOrderRowServiceImpl.java @@ -18,6 +18,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; +import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -41,6 +42,11 @@ public class LbOrderRowServiceImpl extends ServiceImpl sumRows = new ArrayList<>(byDay.size()); + List buyerDayStatRows = new ArrayList<>(); + int skippedNoBuyerPhone = 0; for (Map.Entry> entry : byDay.entrySet()) { - sumRows.add(buildDailySumRow(tid, entry.getKey(), entry.getValue(), nowStr)); + LocalDate day = entry.getKey(); + List dayRows = entry.getValue(); + sumRows.add(buildDailySumRow(tid, day, dayRows, nowStr)); + Map> byBuyerPhone = new LinkedHashMap<>(); + for (LbOrderRow row : dayRows) { + String buyerPhone = trimToNull(row.getBuyerPhone()); + if (buyerPhone == null) { + skippedNoBuyerPhone++; + continue; + } + byBuyerPhone.computeIfAbsent(buyerPhone, k -> new ArrayList<>()).add(row); + } + for (Map.Entry> buyerEntry : byBuyerPhone.entrySet()) { + buyerDayStatRows.add( + buildBuyerDayStatRow( + tid, day, buyerEntry.getKey(), buyerEntry.getValue(), nowStr)); + } } - int upserted = upsertBatch(sumRows); + List allStatRows = new ArrayList<>(sumRows.size() + buyerDayStatRows.size()); + allStatRows.addAll(sumRows); + allStatRows.addAll(buyerDayStatRows); + + int upserted = upsertBatch(allStatRows); boolean ok = upserted >= 0; result.put("success", ok); result.put("message", ok ? "按日汇总完成" : "保存失败"); result.put("generated", ok ? upserted : 0); + result.put("sumDataGenerated", ok ? sumRows.size() : 0); + result.put("buyerDayStatGenerated", ok ? buyerDayStatRows.size() : 0); result.put("sourceCount", details.size()); result.put("skippedNoBuyTime", skippedNoBuyTime); + result.put("skippedNoBuyerPhone", skippedNoBuyerPhone); if (ok) { result.put("data", sumRows); + result.put("buyerDayStatData", buyerDayStatRows); } return result; } catch (Exception e) { @@ -586,6 +618,11 @@ public class LbOrderRowServiceImpl extends ServiceImpl 0 + ? moneySum.divide(BigDecimal.valueOf(orderCount), 2, RoundingMode.HALF_UP) + : BigDecimal.ZERO; + String payTime = day.atStartOfDay().format(DAY_TIME_FMT); Long id = resolveSumRowId(tenantId, payTime); @@ -595,7 +632,8 @@ public class LbOrderRowServiceImpl extends ServiceImpl buyerDayRows, + String nowStr) { + BigDecimal moneySum = BigDecimal.ZERO; + for (LbOrderRow row : buyerDayRows) { + if (row.getTotalMoney() != null) { + moneySum = moneySum.add(row.getTotalMoney()); + } + } + + int orderCount = buyerDayRows.size(); + BigDecimal avgAmt = orderCount > 0 + ? moneySum.divide(BigDecimal.valueOf(orderCount), 2, RoundingMode.HALF_UP) + : BigDecimal.ZERO; + + String payTime = day.atStartOfDay().format(DAY_TIME_FMT); + Long id = resolveBuyerDayStatRowId(tenantId, buyerPhone, payTime); + LbOrderRow sample = buyerDayRows.get(0); + + LbOrderRow stat = new LbOrderRow(); + stat.setId(id); + stat.setTenantId(tenantId); + stat.setDataType(BUYER_DAY_STAT_DATA_TYPE); + stat.setBuyerPhone(buyerPhone); + stat.setBuyerId(sample.getBuyerId()); + stat.setBuyerName(sample.getBuyerName()); + stat.setPhone(buyerPhone); + stat.setTodayTotalMoneySum(moneySum); + stat.setTodayOrderCount(orderCount); + stat.setAvgAmt(avgAmt); + stat.setTotalMoney(moneySum); + stat.setOrderSn("day_stat_" + buyerPhone + "_" + day.format(DAY_FMT)); + stat.setPayTime(payTime); + stat.setBuyTime(payTime); + stat.setStatus(1); + stat.setIsShow(1); + stat.setCreatedAt(nowStr); + stat.setUpdatedAt(nowStr); + return stat; + } + + /** 同一天、同一租户、同一 buyer_phone 已存在 day_stat 则复用其 id,否则生成占位 id */ + private Long resolveBuyerDayStatRowId(String tenantId, String buyerPhone, String payTime) { + LambdaQueryWrapper w = new LambdaQueryWrapper<>(); + w.eq(LbOrderRow::getTenantId, tenantId) + .eq(LbOrderRow::getDataType, BUYER_DAY_STAT_DATA_TYPE) + .eq(LbOrderRow::getBuyerPhone, buyerPhone) + .eq(LbOrderRow::getPayTime, payTime) + .last("LIMIT 1"); + LbOrderRow existing = this.getOne(w, false); + if (existing != null && existing.getId() != null) { + return existing.getId(); + } + LocalDate day = LocalDate.parse(payTime.substring(0, 10), DAY_FMT); + long dayKey = day.getYear() * 10000L + day.getMonthValue() * 100L + day.getDayOfMonth(); + int phoneSlot = Math.floorMod(buyerPhone.hashCode(), 10000); + int tenantSlot = Math.floorMod(tenantId.hashCode(), 100); + return BUYER_DAY_STAT_ID_BASE + dayKey * 1_000_000L + phoneSlot * 100L + tenantSlot; + } + /** 同一天、同一租户已存在 sum_data 则复用其 id,否则生成占位 id */ private Long resolveSumRowId(String tenantId, String payTime) { LambdaQueryWrapper w = new LambdaQueryWrapper<>(); diff --git a/src/main/resources/mapper/LbOrderRowMapper.xml b/src/main/resources/mapper/LbOrderRowMapper.xml index 1a75c44..476bcea 100644 --- a/src/main/resources/mapper/LbOrderRowMapper.xml +++ b/src/main/resources/mapper/LbOrderRowMapper.xml @@ -12,7 +12,7 @@ pay_time, pay_img, status, is_resell, is_show, consignee, phone, province, city, area, address, merchandise_id, confirm_time, buy_time, created_at, updated_at, - today_total_money_sum, today_unresell_count, today_order_count + today_total_money_sum, today_unresell_count, today_order_count, avg_amt ) VALUES ( @@ -23,7 +23,7 @@ #{item.payTime}, #{item.payImg}, #{item.status}, #{item.isResell}, #{item.isShow}, #{item.consignee}, #{item.phone}, #{item.province}, #{item.city}, #{item.area}, #{item.address}, #{item.merchandiseId}, #{item.confirmTime}, #{item.buyTime}, #{item.createdAt}, #{item.updatedAt}, - #{item.todayTotalMoneySum}, #{item.todayUnresellCount}, #{item.todayOrderCount} + #{item.todayTotalMoneySum}, #{item.todayUnresellCount}, #{item.todayOrderCount}, #{item.avgAmt} ) ON DUPLICATE KEY UPDATE @@ -56,7 +56,8 @@ updated_at = VALUES(updated_at), today_total_money_sum = VALUES(today_total_money_sum), today_unresell_count = VALUES(today_unresell_count), - today_order_count = VALUES(today_order_count) + today_order_count = VALUES(today_order_count), + avg_amt = VALUES(avg_amt)