修改买家统计的逻
This commit is contained in:
@@ -66,13 +66,13 @@ public class LbBuyerShoppingController {
|
|||||||
|
|
||||||
@PostMapping("/generate-stat")
|
@PostMapping("/generate-stat")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "按买家生成天统计或总和统计",
|
summary = "全表按买家生成天统计或总和统计",
|
||||||
description =
|
description =
|
||||||
"根据 buyerId 汇总 detail_data 明细:day_stat 按购买日期每天生成一条统计"
|
"扫描全表 detail_data 明细并按 buyer_id 分组:day_stat 为每个买家按购买日期"
|
||||||
+ "(stat_total_money、total_order_count、avg_amount);"
|
+ "每天生成一条统计(stat_total_money、total_order_count、avg_amount);"
|
||||||
+ "sum_data 生成该买家全部订单的一条总和统计")
|
+ "sum_data 为每个买家生成一条总和统计")
|
||||||
public ResponseEntity<Map<String, Object>> generateStat(
|
public ResponseEntity<Map<String, Object>> generateStat(
|
||||||
@Parameter(description = "买家 ID 与统计类型(day_stat / sum_data)", required = true)
|
@Parameter(description = "统计类型(day_stat / sum_data)", required = true)
|
||||||
@RequestBody LbBuyerShoppingGenerateStatRequest request) {
|
@RequestBody LbBuyerShoppingGenerateStatRequest request) {
|
||||||
Map<String, Object> result = lbBuyerShoppingService.generateBuyerStat(request);
|
Map<String, Object> result = lbBuyerShoppingService.generateBuyerStat(request);
|
||||||
return toResponse(result);
|
return toResponse(result);
|
||||||
|
|||||||
@@ -4,15 +4,12 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按买家 ID 将 lb_buyer_shopping 明细汇总为天统计或总和统计并写入表。
|
* 将 lb_buyer_shopping 全表明细按买家 ID 汇总为天统计或总和统计并写入表。
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "买方购物生成统计请求")
|
@Schema(description = "买方购物生成统计请求")
|
||||||
public class LbBuyerShoppingGenerateStatRequest {
|
public class LbBuyerShoppingGenerateStatRequest {
|
||||||
|
|
||||||
@Schema(description = "买家 ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private Long buyerId;
|
|
||||||
|
|
||||||
@Schema(description = "统计类型:day_stat=天统计,sum_data=总和统计", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "统计类型:day_stat=天统计,sum_data=总和统计", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private String statType;
|
private String statType;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public interface ILbBuyerShoppingService extends IService<LbBuyerShopping> {
|
|||||||
Map<String, Object> pullFromThirdParty(LbBuyerShoppingPullRequest request);
|
Map<String, Object> pullFromThirdParty(LbBuyerShoppingPullRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按买家 ID 将明细汇总为 {@code day_stat} 或 {@code sum_data} 并写入表。
|
* 将全表 detail_data 明细按买家 ID 汇总为 {@code day_stat} 或 {@code sum_data} 并写入表。
|
||||||
*/
|
*/
|
||||||
Map<String, Object> generateBuyerStat(LbBuyerShoppingGenerateStatRequest request);
|
Map<String, Object> generateBuyerStat(LbBuyerShoppingGenerateStatRequest request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -562,11 +562,6 @@ public class LbBuyerShoppingServiceImpl
|
|||||||
result.put("message", "请求体不能为空");
|
result.put("message", "请求体不能为空");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (request.getBuyerId() == null) {
|
|
||||||
result.put("success", false);
|
|
||||||
result.put("message", "buyerId不能为空");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
String statType = request.getStatType() != null ? request.getStatType().trim() : "";
|
String statType = request.getStatType() != null ? request.getStatType().trim() : "";
|
||||||
if (statType.isEmpty()) {
|
if (statType.isEmpty()) {
|
||||||
result.put("success", false);
|
result.put("success", false);
|
||||||
@@ -579,54 +574,84 @@ public class LbBuyerShoppingServiceImpl
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Long buyerId = request.getBuyerId();
|
List<LbBuyerShopping> allDetails = listAllDetailRows();
|
||||||
List<LbBuyerShopping> details = listDetailRowsByBuyerId(buyerId);
|
if (allDetails.isEmpty()) {
|
||||||
if (details.isEmpty()) {
|
|
||||||
result.put("success", true);
|
result.put("success", true);
|
||||||
result.put("message", "该买家无明细订单");
|
result.put("message", "全表无明细订单");
|
||||||
result.put("generated", 0);
|
result.put("generated", 0);
|
||||||
result.put("sourceCount", 0);
|
result.put("sourceCount", 0);
|
||||||
|
result.put("buyerCount", 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<LbBuyerShopping> statRows;
|
Map<Long, List<LbBuyerShopping>> byBuyer = new LinkedHashMap<>();
|
||||||
|
int skippedNoBuyerId = 0;
|
||||||
|
for (LbBuyerShopping row : allDetails) {
|
||||||
|
if (row.getBuyerId() == null) {
|
||||||
|
skippedNoBuyerId++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
byBuyer.computeIfAbsent(row.getBuyerId(), k -> new ArrayList<>()).add(row);
|
||||||
|
}
|
||||||
|
if (byBuyer.isEmpty()) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "明细均无 buyer_id,无法按买家汇总");
|
||||||
|
result.put("sourceCount", allDetails.size());
|
||||||
|
result.put("skippedNoBuyerId", skippedNoBuyerId);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<LbBuyerShopping> statRows = new ArrayList<>();
|
||||||
int skippedNoBuyTime = 0;
|
int skippedNoBuyTime = 0;
|
||||||
|
int skippedBuyersNoBuyTime = 0;
|
||||||
if (DATA_TYPE_DAY_STAT.equals(statType)) {
|
if (DATA_TYPE_DAY_STAT.equals(statType)) {
|
||||||
Map<LocalDate, List<LbBuyerShopping>> byDay = new LinkedHashMap<>();
|
for (Map.Entry<Long, List<LbBuyerShopping>> buyerEntry : byBuyer.entrySet()) {
|
||||||
for (LbBuyerShopping row : details) {
|
Long buyerId = buyerEntry.getKey();
|
||||||
LocalDate day = resolveBuyDate(row.getBuyTime());
|
Map<LocalDate, List<LbBuyerShopping>> byDay = new LinkedHashMap<>();
|
||||||
if (day == null) {
|
for (LbBuyerShopping row : buyerEntry.getValue()) {
|
||||||
skippedNoBuyTime++;
|
LocalDate day = resolveBuyDate(row.getBuyTime());
|
||||||
|
if (day == null) {
|
||||||
|
skippedNoBuyTime++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
byDay.computeIfAbsent(day, k -> new ArrayList<>()).add(row);
|
||||||
|
}
|
||||||
|
if (byDay.isEmpty()) {
|
||||||
|
skippedBuyersNoBuyTime++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
byDay.computeIfAbsent(day, k -> new ArrayList<>()).add(row);
|
for (Map.Entry<LocalDate, List<LbBuyerShopping>> dayEntry : byDay.entrySet()) {
|
||||||
|
statRows.add(buildDayStatRow(buyerId, dayEntry.getKey(), dayEntry.getValue()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (byDay.isEmpty()) {
|
if (statRows.isEmpty()) {
|
||||||
result.put("success", false);
|
result.put("success", false);
|
||||||
result.put("message", "明细 buy_time 均无法解析为日期,无法按天汇总");
|
result.put("message", "明细 buy_time 均无法解析为日期,无法按天汇总");
|
||||||
result.put("skippedNoBuyTime", skippedNoBuyTime);
|
result.put("skippedNoBuyTime", skippedNoBuyTime);
|
||||||
|
result.put("skippedBuyersNoBuyTime", skippedBuyersNoBuyTime);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
statRows = new ArrayList<>(byDay.size());
|
|
||||||
for (Map.Entry<LocalDate, List<LbBuyerShopping>> entry : byDay.entrySet()) {
|
|
||||||
statRows.add(buildDayStatRow(buyerId, entry.getKey(), entry.getValue()));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
statRows = List.of(buildSumStatRow(buyerId, details));
|
for (Map.Entry<Long, List<LbBuyerShopping>> buyerEntry : byBuyer.entrySet()) {
|
||||||
|
statRows.add(buildSumStatRow(buyerEntry.getKey(), buyerEntry.getValue()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int upserted = upsertStatRows(statRows);
|
int upserted = upsertStatRows(statRows);
|
||||||
result.put("success", upserted >= 0);
|
result.put("success", upserted >= 0);
|
||||||
result.put("message", upserted >= 0 ? "统计完成" : "保存失败");
|
result.put("message", upserted >= 0 ? "统计完成" : "保存失败");
|
||||||
result.put("generated", Math.max(upserted, 0));
|
result.put("generated", Math.max(upserted, 0));
|
||||||
result.put("sourceCount", details.size());
|
result.put("sourceCount", allDetails.size());
|
||||||
|
result.put("buyerCount", byBuyer.size());
|
||||||
|
result.put("skippedNoBuyerId", skippedNoBuyerId);
|
||||||
result.put("skippedNoBuyTime", skippedNoBuyTime);
|
result.put("skippedNoBuyTime", skippedNoBuyTime);
|
||||||
|
result.put("skippedBuyersNoBuyTime", skippedBuyersNoBuyTime);
|
||||||
if (upserted >= 0) {
|
if (upserted >= 0) {
|
||||||
result.put("data", statRows);
|
result.put("data", statRows);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("买方购物统计异常 buyerId={}", request != null ? request.getBuyerId() : null, e);
|
log.error("买方购物统计异常 statType={}", request != null ? request.getStatType() : null, e);
|
||||||
result.put("success", false);
|
result.put("success", false);
|
||||||
result.put("message", "统计异常:" + e.getMessage());
|
result.put("message", "统计异常:" + e.getMessage());
|
||||||
result.put("generated", 0);
|
result.put("generated", 0);
|
||||||
@@ -634,10 +659,10 @@ public class LbBuyerShoppingServiceImpl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<LbBuyerShopping> listDetailRowsByBuyerId(Long buyerId) {
|
private List<LbBuyerShopping> listAllDetailRows() {
|
||||||
LambdaQueryWrapper<LbBuyerShopping> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<LbBuyerShopping> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
queryWrapper.eq(LbBuyerShopping::getBuyerId, buyerId)
|
queryWrapper.eq(LbBuyerShopping::getDataType, DATA_TYPE_DETAIL)
|
||||||
.eq(LbBuyerShopping::getDataType, DATA_TYPE_DETAIL)
|
.orderByAsc(LbBuyerShopping::getBuyerId)
|
||||||
.orderByAsc(LbBuyerShopping::getBuyTime)
|
.orderByAsc(LbBuyerShopping::getBuyTime)
|
||||||
.orderByAsc(LbBuyerShopping::getId);
|
.orderByAsc(LbBuyerShopping::getId);
|
||||||
return this.list(queryWrapper);
|
return this.list(queryWrapper);
|
||||||
|
|||||||
Reference in New Issue
Block a user