Преглед изворни кода

feat(family.invite.joinValidationRules): S-cfc-58 使绿 - createJoinRequest 准入校验门禁 validateJoinRequiredInfo

- FamilyJoinRequestService.createJoinRequest 写库前新增 validateJoinRequiredInfo(currentUser) 门禁
- 真实姓名 trim 非空且长度 1-20 字;出生日期非空、不晚于今天、不早于 1900-01-01(不设年龄上限)
- 性别严格 male/female(大小写敏感);缺失/非法直接抛错、不落库
- 对齐 UserService.java:492-505 解析口径(规格 2026-11-07-family-join-required-info §3 AC-R3 / §5 WI-3)
- FamilyJoinValidationRulesContractTest 14/14 绿;同实现的 Gate 12/12、RequiredInfo 10/10 同步转绿
Sisyphus пре 5 дана
родитељ
комит
dc1b83a65d

+ 50 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyJoinRequestService.java

@@ -18,6 +18,7 @@ import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -125,6 +126,10 @@ public class FamilyJoinRequestService {
             throw new RuntimeException("您已有待审批的加入请求,请勿重复提交");
         }
 
+        // 准入校验:被邀请人必须已完善真实姓名/出生日期/性别(需求变更 2026-11-07-family-join-required-info,
+        // §3 AC-R3 / §5 WI-3,能力键 family.invite.joinValidationRules);任一缺失/非法直接抛错、不落库
+        validateJoinRequiredInfo(currentUser);
+
         // 创建请求
         FamilyJoinRequest request = new FamilyJoinRequest();
         request.setRequesterUserId(userId);
@@ -144,6 +149,51 @@ public class FamilyJoinRequestService {
         return request;
     }
 
+    private static final Date MIN_BIRTHDAY;
+
+    static {
+        Calendar c = Calendar.getInstance();
+        c.clear();
+        c.set(1900, Calendar.JANUARY, 1);
+        MIN_BIRTHDAY = c.getTime();
+    }
+
+    /**
+     * 准入校验:被邀请人必须已完善真实姓名/出生日期/性别(规格 2026-11-07-family-join-required-info §3 AC-R3 / §5 WI-3)。
+     * 与 UserService 解析口径保持一致(UserService.java:492-505):
+     * <ul>
+     *   <li>真实姓名:trim 后非空,长度 1–20 字;null/空/超 20 字 → 「请先完善真实姓名、出生日期与性别后再申请加入家庭」</li>
+     *   <li>出生日期:非空;晚于今天 → 「出生日期不能晚于今天」;早于 1900-01-01 → 「出生日期不合法」(不设年龄上限,主理人 2026-11-07 确认)</li>
+     *   <li>性别:仅限 male/female(大小写敏感);null/空/其他/混用 → 「请先完善真实姓名、出生日期与性别后再申请加入家庭」</li>
+     * </ul>
+     */
+    private void validateJoinRequiredInfo(User u) {
+        String realName = u.getRealName();
+        if (realName == null || realName.trim().isEmpty() || realName.trim().length() > 20) {
+            throw new RuntimeException("请先完善真实姓名、出生日期与性别后再申请加入家庭");
+        }
+        Date birthday = u.getBirthday();
+        if (birthday == null) {
+            throw new RuntimeException("请先完善真实姓名、出生日期与性别后再申请加入家庭");
+        }
+        String gender = u.getGender();
+        if (!"male".equals(gender) && !"female".equals(gender)) {
+            throw new RuntimeException("请先完善真实姓名、出生日期与性别后再申请加入家庭");
+        }
+        Calendar cal = Calendar.getInstance();
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        Date today = cal.getTime();
+        if (birthday.after(today)) {
+            throw new RuntimeException("出生日期不能晚于今天");
+        }
+        if (birthday.before(MIN_BIRTHDAY)) {
+            throw new RuntimeException("出生日期不合法");
+        }
+    }
+
     /**
      * 审批通过加入请求(兼容旧调用:不指定辈分 → 仅写 familyRole,不落地辈分/关系)
      */