瀏覽代碼

feat(backend): 家庭挑战到期惰性结算 + 角色校验(家长管理/孩子打卡)

Xiaogang Liao 1 月之前
父節點
當前提交
bbf49083be

+ 25 - 8
cfc-backend/src/main/java/com/etotem/cfc/controller/FamilyChallengeController.java

@@ -17,7 +17,7 @@ public class FamilyChallengeController {
     private FamilyChallengeService familyChallengeService;
 
     @PostMapping("/list")
-    public Result<List<FamilyChallenge>> getList(@RequestAttribute("familyId") Long familyId) {
+    public Result<List<FamilyChallenge>> getList(@RequestAttribute(value = "familyId", required = false) Long familyId) {
         if (familyId == null) {
             return Result.noFamily("请先创建或加入家庭");
         }
@@ -25,7 +25,7 @@ public class FamilyChallengeController {
     }
 
     @PostMapping("/history")
-    public Result<List<FamilyChallenge>> getHistory(@RequestAttribute("familyId") Long familyId) {
+    public Result<List<FamilyChallenge>> getHistory(@RequestAttribute(value = "familyId", required = false) Long familyId) {
         if (familyId == null) {
             return Result.noFamily("请先创建或加入家庭");
         }
@@ -34,14 +34,19 @@ public class FamilyChallengeController {
 
     @PostMapping("/progress")
     public Result<Void> updateProgress(@RequestBody Map<String, Object> params,
+                                       @RequestAttribute(value = "role", required = false) String role,
                                        @RequestAttribute(value = "currentMemberId", required = false) Long currentMemberId) {
+        if (!"child".equals(role)) {
+            return Result.error("仅孩子可打卡");
+        }
+        if (currentMemberId == null) {
+            return Result.error("未识别当前成员");
+        }
         Long challengeId = params.get("challengeId") != null
                 ? Long.valueOf(params.get("challengeId").toString()) : null;
-        Long memberId = params.get("memberId") != null
-                ? Long.valueOf(params.get("memberId").toString()) : currentMemberId;
         int delta = params.get("delta") != null
                 ? Integer.parseInt(params.get("delta").toString()) : 0;
-        return familyChallengeService.updateProgress(challengeId, memberId, delta);
+        return familyChallengeService.updateProgress(challengeId, currentMemberId, delta);
     }
 
     @PostMapping("/templates")
@@ -51,23 +56,35 @@ public class FamilyChallengeController {
 
     @PostMapping("/create")
     public Result<Long> createChallenge(@RequestBody Map<String, Object> params,
-                                        @RequestAttribute("familyId") Long familyId,
+                                        @RequestAttribute(value = "role", required = false) String role,
+                                        @RequestAttribute(value = "familyId", required = false) Long familyId,
                                         @RequestAttribute("userId") Long userId) {
+        if (!"parent".equals(role)) {
+            return Result.error("仅家长可创建挑战");
+        }
         return familyChallengeService.createChallenge(familyId, userId, params);
     }
 
     @PostMapping("/update/{id}")
     public Result<Void> updateChallenge(@PathVariable("id") Long challengeId,
                                         @RequestBody Map<String, Object> params,
-                                        @RequestAttribute("familyId") Long familyId,
+                                        @RequestAttribute(value = "role", required = false) String role,
+                                        @RequestAttribute(value = "familyId", required = false) Long familyId,
                                         @RequestAttribute("userId") Long userId) {
+        if (!"parent".equals(role)) {
+            return Result.error("仅家长可修改挑战");
+        }
         return familyChallengeService.updateChallenge(challengeId, userId, familyId, params);
     }
 
     @PostMapping("/delete/{id}")
     public Result<Void> deleteChallenge(@PathVariable("id") Long challengeId,
-                                        @RequestAttribute("familyId") Long familyId,
+                                        @RequestAttribute(value = "role", required = false) String role,
+                                        @RequestAttribute(value = "familyId", required = false) Long familyId,
                                         @RequestAttribute("userId") Long userId) {
+        if (!"parent".equals(role)) {
+            return Result.error("仅家长可删除挑战");
+        }
         return familyChallengeService.deleteChallenge(challengeId, userId, familyId);
     }
 }

+ 8 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyChallengeService.java

@@ -45,6 +45,14 @@ public class FamilyChallengeService {
                 .orderByDesc(FamilyChallenge::getCreatedAt);
         List<FamilyChallenge> active = familyChallengeMapper.selectList(wrapper);
 
+        for (FamilyChallenge c : active) {
+            if (c.getEndDate() != null && new Date().after(c.getEndDate())) {
+                checkAndSettle(c);
+            }
+        }
+
+        active = familyChallengeMapper.selectList(wrapper);
+
         fillProgress(active);
         return active;
     }

+ 20 - 0
cfc-backend/src/test/java/com/etotem/cfc/service/FamilyChallengeServiceTest.java

@@ -110,4 +110,24 @@ public class FamilyChallengeServiceTest {
         verify(familyChallengeProgressMapper).updateById(argThat(p2 -> Boolean.TRUE.equals(p2.getCompleted())));
         verify(pointsService).awardSystemPoints(eq(100L), eq(50), anyString());
     }
+
+    @Test
+    void getActiveChallenges_shouldSettleExpiredChallenges() {
+        FamilyChallenge expired = new FamilyChallenge();
+        expired.setId(2L);
+        expired.setFamilyId(10L);
+        expired.setStatus("active");
+        expired.setTargetMode("aggregate");
+        expired.setTargetValue(10);
+        expired.setEndDate(new Date(System.currentTimeMillis() - 86400000L));
+
+        when(familyChallengeMapper.selectList(any())).thenReturn(java.util.Arrays.asList(expired));
+        when(familyChallengeProgressMapper.selectList(any())).thenReturn(java.util.Collections.emptyList());
+        when(familyMemberMapper.selectList(any())).thenReturn(java.util.Collections.emptyList());
+        when(familyChallengeMapper.update(any(), any())).thenReturn(1);
+
+        service.getActiveChallenges(10L);
+
+        verify(familyChallengeMapper).update(any(), any());
+    }
 }