From d699da385dda6257677ee93bef47388c0635f64e Mon Sep 17 00:00:00 2001
From: “mitao” <“2763622819@qq.com”>
Date: 星期五, 17 四月 2026 08:57:41 +0800
Subject: [PATCH] feat:APP个人中心
---
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/points/service/PointsSettlementService.java | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 52 insertions(+), 0 deletions(-)
diff --git a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/points/service/PointsSettlementService.java b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/points/service/PointsSettlementService.java
index 0f27862..a24ee43 100644
--- a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/points/service/PointsSettlementService.java
+++ b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/points/service/PointsSettlementService.java
@@ -17,6 +17,8 @@
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@@ -29,6 +31,9 @@
public class PointsSettlementService {
private static final DateTimeFormatter ORDER_NO_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
+ private static final String SETTLEMENT_CLEAR_SOURCE_PREFIX = "config-clear-";
+ private static final String SETTLEMENT_CLEAR_REFERENCE_PREFIX = "POINTS_CONFIG-";
+ private static final Logger log = LoggerFactory.getLogger(PointsSettlementService.class);
private final PointsConfigMapper pointsConfigMapper;
private final UserPointsAccountMapper userPointsAccountMapper;
@@ -62,6 +67,9 @@
.eq(PointsConfig::getSettlementStatus, 0)
.le(PointsConfig::getActivityEndAt, now)
.orderByAsc(PointsConfig::getId));
+ if (!configs.isEmpty()) {
+ log.info("points settlement scan found {} expired pending configs", configs.size());
+ }
for (PointsConfig config : configs) {
settleConfig(config.getId());
}
@@ -80,9 +88,13 @@
return;
}
+ log.info("points settlement start, configId={}, activityEndAt={}, requiredPoints={}",
+ config.getId(), config.getActivityEndAt(), config.getRequiredPoints());
List<PointsSettlementCandidateRow> candidates = userPointsAccountMapper.selectSettlementCandidates();
List<PointsExchangeOrderItem> createdItems = new ArrayList<PointsExchangeOrderItem>();
LocalDateTime now = LocalDateTime.now();
+ int qualifiedCount = 0;
+ int clearedOnlyCount = 0;
for (PointsSettlementCandidateRow candidate : candidates) {
int balance = candidate.getPointsBalance() == null ? 0 : candidate.getPointsBalance();
if (balance <= 0) {
@@ -92,6 +104,28 @@
PointsExchangeOrderItem item = buildOrderItem(config, candidate, now);
pointsExchangeOrderItemMapper.insert(item);
createdItems.add(item);
+ qualifiedCount++;
+ } else {
+ pointsLedgerAppService.createSettlementClearLedger(
+ buildSettlementClearSourceId(config.getId(), candidate.getAppUserId()),
+ candidate.getAppUserId(),
+ candidate.getUserNickname(),
+ candidate.getUserPhone(),
+ candidate.getClinicId(),
+ candidate.getClinicName(),
+ candidate.getProvinceCode(),
+ candidate.getProvinceName(),
+ candidate.getCityCode(),
+ candidate.getCityName(),
+ candidate.getDistrictCode(),
+ candidate.getDistrictName(),
+ config.getGiftName(),
+ config.getId(),
+ buildSettlementReferenceNo(config.getId()),
+ balance,
+ now
+ );
+ clearedOnlyCount++;
}
UserPointsAccount account = userPointsAccountMapper.selectById(candidate.getAccountId());
if (account != null) {
@@ -105,6 +139,8 @@
config.setSettlementStatus(1);
config.setSettledAt(now);
pointsConfigMapper.updateById(config);
+ log.info("points settlement completed, configId={}, qualifiedCount={}, clearedOnlyCount={}, createdItemCount={}, settledAt={}",
+ config.getId(), qualifiedCount, clearedOnlyCount, createdItems.size(), now);
}
private PointsExchangeOrderItem buildOrderItem(PointsConfig config, PointsSettlementCandidateRow candidate, LocalDateTime now) {
@@ -275,4 +311,20 @@
}
return "-";
}
+
+ /**
+ * 构建活动结束清零流水的唯一来源标识,确保重复调度不会重复入账。
+ */
+ private Long buildSettlementClearSourceId(Long configId, Long appUserId) {
+ String compositeId = SETTLEMENT_CLEAR_SOURCE_PREFIX + (configId == null ? "0" : configId)
+ + "-" + (appUserId == null ? "0" : appUserId);
+ return Long.valueOf(Math.abs((long) compositeId.hashCode()));
+ }
+
+ /**
+ * 构建活动结算流水引用编号,便于后台追溯到积分活动。
+ */
+ private String buildSettlementReferenceNo(Long configId) {
+ return SETTLEMENT_CLEAR_REFERENCE_PREFIX + (configId == null ? 0L : configId.longValue());
+ }
}
--
Gitblit v1.7.1