|
@@ -1,6 +1,7 @@
|
|
|
package com.etotem.cfc.service;
|
|
package com.etotem.cfc.service;
|
|
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
|
|
import com.etotem.cfc.common.Result;
|
|
import com.etotem.cfc.common.Result;
|
|
|
import com.etotem.cfc.entity.FamilyChallenge;
|
|
import com.etotem.cfc.entity.FamilyChallenge;
|
|
|
import com.etotem.cfc.entity.FamilyChallengeProgress;
|
|
import com.etotem.cfc.entity.FamilyChallengeProgress;
|
|
@@ -32,6 +33,9 @@ public class FamilyChallengeService {
|
|
|
@Resource
|
|
@Resource
|
|
|
private HealthScoreService healthScoreService;
|
|
private HealthScoreService healthScoreService;
|
|
|
|
|
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private PointsService pointsService;
|
|
|
|
|
+
|
|
|
public List<FamilyChallenge> getActiveChallenges(Long familyId) {
|
|
public List<FamilyChallenge> getActiveChallenges(Long familyId) {
|
|
|
if (familyId == null) return new ArrayList<>();
|
|
if (familyId == null) return new ArrayList<>();
|
|
|
|
|
|
|
@@ -210,10 +214,34 @@ public class FamilyChallengeService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (isCompleted || challenge.getEndDate() == null || new Date().after(challenge.getEndDate())) {
|
|
if (isCompleted || challenge.getEndDate() == null || new Date().after(challenge.getEndDate())) {
|
|
|
- challenge.setStatus("completed");
|
|
|
|
|
- familyChallengeMapper.updateById(challenge);
|
|
|
|
|
- log.info("挑战已结算: id={}, type={}, targetMode={}, targetValue={}, completed={}",
|
|
|
|
|
- challenge.getId(), challenge.getChallengeType(), targetMode, targetValue, isCompleted);
|
|
|
|
|
|
|
+ // 幂等结算:仅当挑战仍是 active 时原子跃迁为 completed(条件更新 WHERE id=? AND status='active')。
|
|
|
|
|
+ // 并发打卡/重复触发结算时,只有一个请求能更新成功(影响行数=1),其余请求影响行数=0 直接跳过,
|
|
|
|
|
+ // 从根源杜绝重复发奖。
|
|
|
|
|
+ UpdateWrapper<FamilyChallenge> uw = new UpdateWrapper<FamilyChallenge>()
|
|
|
|
|
+ .eq("id", challenge.getId())
|
|
|
|
|
+ .eq("status", "active")
|
|
|
|
|
+ .set("status", "completed");
|
|
|
|
|
+ int updated = familyChallengeMapper.update(null, uw);
|
|
|
|
|
+ if (updated > 0) {
|
|
|
|
|
+ if (isCompleted) {
|
|
|
|
|
+ // 发放奖励:能量点 + 标记成员完成(仅成功结算的调用执行,不会重复)
|
|
|
|
|
+ int points = challenge.getRewardPoints() != null ? challenge.getRewardPoints() : 0;
|
|
|
|
|
+ for (FamilyChallengeProgress p : progresses) {
|
|
|
|
|
+ if (!Boolean.TRUE.equals(p.getCompleted())) {
|
|
|
|
|
+ p.setCompleted(true);
|
|
|
|
|
+ p.setUpdatedAt(new Date());
|
|
|
|
|
+ familyChallengeProgressMapper.updateById(p);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (points > 0) {
|
|
|
|
|
+ // 对接积分服务发放奖励(PointsService.awardSystemPoints,按 memberId 发放)
|
|
|
|
|
+ pointsService.awardSystemPoints(p.getChildId(), points,
|
|
|
|
|
+ "家庭挑战完成奖励: " + challenge.getTitle());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("挑战已结算: id={}, type={}, targetMode={}, targetValue={}, completed={}",
|
|
|
|
|
+ challenge.getId(), challenge.getChallengeType(), targetMode, targetValue, isCompleted);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|