改造为支持人天统计

This commit is contained in:
2026-06-07 21:05:53 +08:00
parent 6e249db5a1
commit 21ec3321d0
5 changed files with 119 additions and 10 deletions

View File

@@ -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<LbOrderRowMapper, LbOrder
private static final String SUM_DATA_TYPE = "sum_data";
/** 按买家手机号 + 购买日期汇总的人天统计 */
private static final String BUYER_DAY_STAT_DATA_TYPE = "day_stat";
private static final long BUYER_DAY_STAT_ID_BASE = 20_000_000_000_000_000L;
private static final int DINGTALK_SELLER_CONFIRM_BATCH_SIZE = 15;
private static final String DINGTALK_SELLER_CONFIRM_PREFIX =
@@ -462,19 +468,45 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
String nowStr = LocalDateTime.now().format(DAY_TIME_FMT);
List<LbOrderRow> sumRows = new ArrayList<>(byDay.size());
List<LbOrderRow> buyerDayStatRows = new ArrayList<>();
int skippedNoBuyerPhone = 0;
for (Map.Entry<LocalDate, List<LbOrderRow>> entry : byDay.entrySet()) {
sumRows.add(buildDailySumRow(tid, entry.getKey(), entry.getValue(), nowStr));
LocalDate day = entry.getKey();
List<LbOrderRow> dayRows = entry.getValue();
sumRows.add(buildDailySumRow(tid, day, dayRows, nowStr));
Map<String, List<LbOrderRow>> 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<String, List<LbOrderRow>> buyerEntry : byBuyerPhone.entrySet()) {
buyerDayStatRows.add(
buildBuyerDayStatRow(
tid, day, buyerEntry.getKey(), buyerEntry.getValue(), nowStr));
}
}
int upserted = upsertBatch(sumRows);
List<LbOrderRow> 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<LbOrderRowMapper, LbOrder
}
}
int orderCount = dayRows.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 = resolveSumRowId(tenantId, payTime);
@@ -595,7 +632,8 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
sum.setDataType(SUM_DATA_TYPE);
sum.setTodayTotalMoneySum(moneySum);
sum.setTodayUnresellCount(unresellCount);
sum.setTodayOrderCount(dayRows.size());
sum.setTodayOrderCount(orderCount);
sum.setAvgAmt(avgAmt);
sum.setSellerId(SUM_PLACEHOLDER_USER_ID);
sum.setBuyerId(SUM_PLACEHOLDER_USER_ID);
sum.setOrderSn(SUM_ORDER_SN);
@@ -613,6 +651,70 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
return sum;
}
/** 按 buyer_phone + 购买日期生成人天统计day_stat */
private LbOrderRow buildBuyerDayStatRow(
String tenantId,
LocalDate day,
String buyerPhone,
List<LbOrderRow> 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<LbOrderRow> 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<LbOrderRow> w = new LambdaQueryWrapper<>();