Browse Source

feat(S-cfc-157): dan.assessment.recordCreate 契约守卫使绿

AssessmentService.createRecord 前置三项契约校验(非法输入抛 IllegalArgumentException,
由 GlobalExceptionHandler 映射 400,绝不落库):
1. 必填参数守卫:materialId / memberId 为空拒绝
2. 材料有效性:materialId 须指向存在且启用的测评材料(经 baseMapper)
3. 成员-家庭归属:memberId 须属于 familyId,防跨家庭越权(参照 SC-T-13)

DanAssessmentRecordCreateContractTest 结果:6 tests,4 失败(3 边界 + 1 权限)→ 0 失败全绿。
Agnes Agent 22 hours ago
parent
commit
d8969ea6f3

+ 25 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/AssessmentService.java

@@ -9,6 +9,7 @@ import com.etotem.cfc.entity.AssessmentPointsConfig;
 import com.etotem.cfc.entity.AssessmentRecord;
 import com.etotem.cfc.entity.AssessmentRecord;
 import com.etotem.cfc.entity.DanAssessmentResult;
 import com.etotem.cfc.entity.DanAssessmentResult;
 import com.etotem.cfc.entity.FamilyAssessmentConfig;
 import com.etotem.cfc.entity.FamilyAssessmentConfig;
+import com.etotem.cfc.entity.FamilyMember;
 import com.etotem.cfc.mapper.AssessmentMaterialMapper;
 import com.etotem.cfc.mapper.AssessmentMaterialMapper;
 import com.etotem.cfc.mapper.AssessmentPointsConfigMapper;
 import com.etotem.cfc.mapper.AssessmentPointsConfigMapper;
 import com.etotem.cfc.mapper.AssessmentRecordMapper;
 import com.etotem.cfc.mapper.AssessmentRecordMapper;
@@ -194,7 +195,31 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
         return familyConfigMapper.selectList(wrapper);
         return familyConfigMapper.selectList(wrapper);
     }
     }
 
 
+    /**
+     * 创建测评记录(S-cfc-157 / dan.assessment.recordCreate)。
+     *
+     * <p>契约守卫(非法输入抛 {@link IllegalArgumentException},由 GlobalExceptionHandler 映射为 400,绝不落库):
+     * <ol>
+     *   <li>必填参数:{@code materialId}、{@code memberId} 均不可为空;</li>
+     *   <li>材料有效性:{@code materialId} 必须指向存在且启用的测评材料(经 baseMapper);</li>
+     *   <li>成员-家庭归属:{@code memberId} 必须属于 {@code familyId}(防跨家庭越权,参照 SC-T-13 数据隔离)。</li>
+     * </ol>
+     */
     public AssessmentRecord createRecord(Long familyId, Long memberId, Long materialId) {
     public AssessmentRecord createRecord(Long familyId, Long memberId, Long materialId) {
+        if (materialId == null) {
+            throw new IllegalArgumentException("materialId 不能为空,无法创建测评记录");
+        }
+        if (memberId == null) {
+            throw new IllegalArgumentException("memberId 不能为空,测评记录必须归属明确家庭成员");
+        }
+        AssessmentMaterial material = this.getById(materialId);
+        if (material == null || !"active".equals(material.getStatus())) {
+            throw new IllegalArgumentException("测评材料不存在或未启用,无法创建测评记录");
+        }
+        FamilyMember member = familyMemberMapper.selectById(memberId);
+        if (member == null || familyId == null || !familyId.equals(member.getFamilyId())) {
+            throw new IllegalArgumentException("成员不属于该家庭,禁止跨家庭创建测评记录");
+        }
         AssessmentRecord record = new AssessmentRecord();
         AssessmentRecord record = new AssessmentRecord();
         record.setFamilyId(familyId);
         record.setFamilyId(familyId);
         record.setMemberId(memberId);
         record.setMemberId(memberId);