汇总当天订单的数据

This commit is contained in:
2026-05-17 10:16:04 +08:00
parent 6d20b98702
commit 52c505df89
5 changed files with 219 additions and 36 deletions

View File

@@ -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<LbOrderRowMapper, LbOrder
/** 与 hxr.admin.order-select-url 中 {@code limit} 一致,用于判断是否还有下一页 */
private static final int HXR_ORDER_PAGE_SIZE = 90;
/** 从第三方同步的订单明细默认 data_type */
private static final String SYNC_DATA_TYPE_DETAIL = "detail_data";
private static final String SUM_DATA_TYPE = "sum_data";
private static final long SUM_PLACEHOLDER_USER_ID = 10000L;
private static final String SUM_ORDER_SN = "order_sn_10000";
private static final DateTimeFormatter DAY_TIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final DateTimeFormatter DAY_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
@Autowired
private HxrAdminOrderSelectService hxrAdminOrderSelectService;
@@ -201,7 +219,7 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> syncFromHxrAdmin(
String buyTimeStart, String buyTimeEnd, String tenantId, Integer isResell, String dataType) {
String buyTimeStart, String buyTimeEnd, String tenantId, Integer isResell) {
Map<String, Object> result = new HashMap<>();
try {
if (tenantId == null || tenantId.trim().isEmpty()) {
@@ -212,7 +230,6 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
String tid = tenantId.trim();
String rowDataType = resolveSyncDataType(dataType, isResell);
HxrOrderSelectResponse firstBody = null;
int page = 1;
int totalSynced = 0;
@@ -248,13 +265,9 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
break;
}
BigDecimal todayTotalMoneySum = parseMoney(firstBody.allMoney());
int todayOrderCount = firstBody.count();
int todayUnresellCount = countUnresell(rows);
List<LbOrderRow> 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<LbOrderRowMapper, LbOrder
}
}
private static String resolveSyncDataType(String dataType, Integer isResell) {
if (dataType != null && !dataType.trim().isEmpty()) {
return dataType.trim();
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> generateDailySumData(
String buyTimeStart, String buyTimeEnd, String tenantId) {
Map<String, Object> 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<LbOrderRow> 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<LbOrderRow> 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<LocalDate, List<LbOrderRow>> 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<LbOrderRow> sumRows = new ArrayList<>(byDay.size());
for (Map.Entry<LocalDate, List<LbOrderRow>> 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<HxrOrderRow> rows) {
int n = 0;
for (HxrOrderRow row : rows) {
if (row.isResell() == 0) {
n++;
private LbOrderRow buildDailySumRow(
String tenantId, LocalDate day, List<LbOrderRow> 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<LbOrderRow> 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<LbOrderRowMapper, LbOrder
}
}
private static LbOrderRow toLbOrderRow(
HxrOrderRow row,
String tenantId,
String dataType,
BigDecimal todayTotalMoneySum,
Integer todayOrderCount,
Integer todayUnresellCount) {
private static LbOrderRow toLbOrderRow(HxrOrderRow row, String tenantId) {
LbOrderRow e = new LbOrderRow();
e.setId(row.id());
e.setDataType("detail_data");
e.setOldId(row.oldId());
e.setTenantId(tenantId);
e.setDataType(dataType);
e.setTodayTotalMoneySum(todayTotalMoneySum);
e.setTodayOrderCount(todayOrderCount);
e.setTodayUnresellCount(todayUnresellCount);
e.setDataType(SYNC_DATA_TYPE_DETAIL);
e.setTodayTotalMoneySum(BigDecimal.ZERO);
e.setTodayOrderCount(0);
e.setTodayUnresellCount(0);
e.setSellerId(row.sellerId());
e.setBuyerId(row.buyerId());
e.setOrderSn(row.orderSn());