diff --git a/src/main/java/com/rj/controller/LbOrderRowController.java b/src/main/java/com/rj/controller/LbOrderRowController.java index 330d125..7799b99 100644 --- a/src/main/java/com/rj/controller/LbOrderRowController.java +++ b/src/main/java/com/rj/controller/LbOrderRowController.java @@ -1,5 +1,6 @@ package com.rj.controller; +import com.rj.dto.LbOrderRowGenerateSumRequest; import com.rj.dto.LbOrderRowSyncFromHxrRequest; import com.rj.entity.LbOrderRow; import com.rj.service.ILbOrderRowService; @@ -89,8 +90,28 @@ public class LbOrderRowController { request.getBuyTimeStart(), request.getBuyTimeEnd(), request.getTenantId(), - request.getIsResell(), - request.getDataType()); + request.getIsResell()); + Boolean success = (Boolean) result.get("success"); + if (success != null && success) { + return ResponseEntity.ok(result); + } + return ResponseEntity.badRequest().body(result); + } + + @PostMapping("/generate-daily-sum") + @Operation( + summary = "按日汇总生成 sum_data", + description = + "按购买时间区间、租户 id 查询 lb_order_row 明细,每天生成一条 sum_data(today_total_money_sum、" + + "today_unresell_count、today_order_count 等)并写入表") + public ResponseEntity> generateDailySum( + @Parameter(description = "汇总条件", required = true) @RequestBody + LbOrderRowGenerateSumRequest request) { + Map result = + lbOrderRowService.generateDailySumData( + request.getBuyTimeStart(), + request.getBuyTimeEnd(), + request.getTenantId()); Boolean success = (Boolean) result.get("success"); if (success != null && success) { return ResponseEntity.ok(result); diff --git a/src/main/java/com/rj/dto/LbOrderRowGenerateSumRequest.java b/src/main/java/com/rj/dto/LbOrderRowGenerateSumRequest.java new file mode 100644 index 0000000..00774c0 --- /dev/null +++ b/src/main/java/com/rj/dto/LbOrderRowGenerateSumRequest.java @@ -0,0 +1,21 @@ +package com.rj.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 按购买时间区间与租户,将 {@code lb_order_row} 明细按日汇总为 {@code sum_data} 并写入表。 + */ +@Data +@Schema(description = "LB 订单按日汇总生成 sum_data 请求") +public class LbOrderRowGenerateSumRequest { + + @Schema(description = "购买时间起(buy_time 下限),可空表示不限制") + private String buyTimeStart; + + @Schema(description = "购买时间止(buy_time 上限),可空表示不限制") + private String buyTimeEnd; + + @Schema(description = "租户 id", requiredMode = Schema.RequiredMode.REQUIRED) + private String tenantId; +} diff --git a/src/main/java/com/rj/dto/LbOrderRowSyncFromHxrRequest.java b/src/main/java/com/rj/dto/LbOrderRowSyncFromHxrRequest.java index b669de5..69a4847 100644 --- a/src/main/java/com/rj/dto/LbOrderRowSyncFromHxrRequest.java +++ b/src/main/java/com/rj/dto/LbOrderRowSyncFromHxrRequest.java @@ -21,7 +21,4 @@ public class LbOrderRowSyncFromHxrRequest { @Schema(description = "转卖状态筛选(对应后台 is_resell)", requiredMode = Schema.RequiredMode.REQUIRED) private Integer isResell; - - @Schema(description = "写入 lb_order_row.data_type;为空时默认使用 isResell 的字符串值") - private String dataType; } diff --git a/src/main/java/com/rj/service/ILbOrderRowService.java b/src/main/java/com/rj/service/ILbOrderRowService.java index 5437ca0..81a89f7 100644 --- a/src/main/java/com/rj/service/ILbOrderRowService.java +++ b/src/main/java/com/rj/service/ILbOrderRowService.java @@ -31,6 +31,10 @@ public interface ILbOrderRowService extends IService { String buyTimeStart, String buyTimeEnd, String tenantId, - Integer isResell, - String dataType); + Integer isResell); + + /** + * 按购买时间区间与租户查询明细,按天汇总为 {@code sum_data} 写入 {@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 321b003..e61459b 100644 --- a/src/main/java/com/rj/service/impl/LbOrderRowServiceImpl.java +++ b/src/main/java/com/rj/service/impl/LbOrderRowServiceImpl.java @@ -14,8 +14,13 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -26,6 +31,19 @@ public class LbOrderRowServiceImpl extends ServiceImpl syncFromHxrAdmin( - String buyTimeStart, String buyTimeEnd, String tenantId, Integer isResell, String dataType) { + String buyTimeStart, String buyTimeEnd, String tenantId, Integer isResell) { Map result = new HashMap<>(); try { if (tenantId == null || tenantId.trim().isEmpty()) { @@ -212,7 +230,6 @@ public class LbOrderRowServiceImpl extends ServiceImpl entities = new ArrayList<>(rows.size()); for (HxrOrderRow row : rows) { - entities.add(toLbOrderRow( - row, tid, rowDataType, todayTotalMoneySum, todayOrderCount, todayUnresellCount)); + entities.add(toLbOrderRow(row, tid)); } boolean ok = this.saveOrUpdateBatch(entities); @@ -300,21 +313,155 @@ public class LbOrderRowServiceImpl extends ServiceImpl generateDailySumData( + String buyTimeStart, String buyTimeEnd, String tenantId) { + Map result = new HashMap<>(); + try { + if (tenantId == null || tenantId.trim().isEmpty()) { + result.put("success", false); + result.put("message", "tenantId不能为空"); + return result; + } + String tid = tenantId.trim(); + + LambdaQueryWrapper w = new LambdaQueryWrapper<>(); + w.eq(LbOrderRow::getTenantId, tid); + w.eq(LbOrderRow::getDataType, SYNC_DATA_TYPE_DETAIL); + if (buyTimeStart != null && !buyTimeStart.trim().isEmpty()) { + w.ge(LbOrderRow::getBuyTime, buyTimeStart.trim()); + } + if (buyTimeEnd != null && !buyTimeEnd.trim().isEmpty()) { + w.le(LbOrderRow::getBuyTime, buyTimeEnd.trim()); + } + + List details = this.list(w); + if (details.isEmpty()) { + result.put("success", true); + result.put("message", "时间范围内无明细数据"); + result.put("generated", 0); + result.put("sourceCount", 0); + return result; + } + + Map> byDay = new LinkedHashMap<>(); + int skippedNoBuyTime = 0; + for (LbOrderRow row : details) { + LocalDate day = parseBuyTimeToDate(row.getBuyTime()); + if (day == null) { + skippedNoBuyTime++; + continue; + } + byDay.computeIfAbsent(day, k -> new ArrayList<>()).add(row); + } + + if (byDay.isEmpty()) { + result.put("success", false); + result.put("message", "明细 buy_time 均无法解析为日期,无法汇总"); + result.put("skippedNoBuyTime", skippedNoBuyTime); + return result; + } + + String nowStr = LocalDateTime.now().format(DAY_TIME_FMT); + List sumRows = new ArrayList<>(byDay.size()); + for (Map.Entry> entry : byDay.entrySet()) { + sumRows.add(buildDailySumRow(tid, entry.getKey(), entry.getValue(), nowStr)); + } + + boolean ok = this.saveOrUpdateBatch(sumRows); + result.put("success", ok); + result.put("message", ok ? "按日汇总完成" : "保存失败"); + result.put("generated", ok ? sumRows.size() : 0); + result.put("sourceCount", details.size()); + result.put("skippedNoBuyTime", skippedNoBuyTime); + if (ok) { + result.put("data", sumRows); + } + return result; + } catch (Exception e) { + result.put("success", false); + result.put("message", "汇总异常:" + e.getMessage()); + result.put("generated", 0); + return result; } - return isResell == null ? null : String.valueOf(isResell); } - private static int countUnresell(List rows) { - int n = 0; - for (HxrOrderRow row : rows) { - if (row.isResell() == 0) { - n++; + private LbOrderRow buildDailySumRow( + String tenantId, LocalDate day, List dayRows, String nowStr) { + BigDecimal moneySum = BigDecimal.ZERO; + int unresellCount = 0; + for (LbOrderRow row : dayRows) { + if (row.getTotalMoney() != null) { + moneySum = moneySum.add(row.getTotalMoney()); + } + if (row.getIsResell() == null || row.getIsResell() != 1) { + unresellCount++; } } - return n; + + String payTime = day.atStartOfDay().format(DAY_TIME_FMT); + Long id = resolveSumRowId(tenantId, payTime); + + LbOrderRow sum = new LbOrderRow(); + sum.setId(id); + sum.setTenantId(tenantId); + sum.setDataType(SUM_DATA_TYPE); + sum.setTodayTotalMoneySum(moneySum); + sum.setTodayUnresellCount(unresellCount); + sum.setTodayOrderCount(dayRows.size()); + sum.setSellerId(SUM_PLACEHOLDER_USER_ID); + sum.setBuyerId(SUM_PLACEHOLDER_USER_ID); + sum.setOrderSn(SUM_ORDER_SN); + sum.setTotalMoney(moneySum); + sum.setIsResell(1); + sum.setStatus(1); + sum.setIsShow(1); + sum.setPayTime(payTime); + sum.setBuyTime(payTime); + sum.setMerchandiseId(0L); + sum.setCreatedAt(nowStr); + sum.setUpdatedAt(nowStr); + return sum; + } + + /** 同一天、同一租户已存在 sum_data 则复用其 id,否则生成占位 id */ + private Long resolveSumRowId(String tenantId, String payTime) { + LambdaQueryWrapper w = new LambdaQueryWrapper<>(); + w.eq(LbOrderRow::getTenantId, tenantId) + .eq(LbOrderRow::getDataType, SUM_DATA_TYPE) + .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 tenantSlot = Math.floorMod(tenantId.hashCode(), 10000); + return 10_000_000_000_000_000L + dayKey * 10_000L + tenantSlot; + } + + private static LocalDate parseBuyTimeToDate(String buyTime) { + if (buyTime == null || buyTime.trim().isEmpty()) { + return null; + } + String text = buyTime.trim(); + try { + return LocalDateTime.parse(text, DAY_TIME_FMT).toLocalDate(); + } catch (DateTimeParseException ignored) { + // continue + } + try { + return LocalDate.parse(text.substring(0, Math.min(10, text.length())), DAY_FMT); + } catch (DateTimeParseException ignored) { + // continue + } + try { + return LocalDateTime.parse(text, DateTimeFormatter.ISO_LOCAL_DATE_TIME).toLocalDate(); + } catch (DateTimeParseException e) { + return null; + } } private static BigDecimal parseMoney(String money) { @@ -328,22 +475,15 @@ public class LbOrderRowServiceImpl extends ServiceImpl