فهرست منبع

fix(family): computeRelationshipLabel 按 family_relationships 存储约定解析辈分差

generation_value 存储约定 = from.generation - to.generation(正数=起点辈分更高、
对方是晚辈)。原实现按「对方相对查看者辈分差」解析,方向相反,导致
createRelationsForNewMember 及家庭关系列表兜底标签反转(把父辈标成女儿)。
翻转映射以与存储约定一致;新增契约级单测固化语义(6例)。
Xiaogang Liao 4 روز پیش
والد
کامیت
746bcab8da

+ 14 - 10
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyRelationshipService.java

@@ -163,28 +163,32 @@ public class FamilyRelationshipService {
         if (generationValue == null) return "未知";
         boolean isMale = "male".equals(gender);
 
+        // generation_value 沿用 family_relationships 存储约定 = from.generation - to.generation:
+        // 正数 = 起点辈分更高(对方是晚辈,向下);负数 = 起点辈分更低(对方是长辈,向上)。
+        // 2026-11-08 修复:原按「对方相对查看者辈分差」解析,与存储约定方向相反,导致
+        // createRelationsForNewMember 及家庭关系列表兜底标签出现「把父辈标成女儿」的反转。
         switch (generationValue) {
-            // 向上(对方是长辈)
+            // 向下(对方是晚辈)
             case 3:
-                return "曾祖" + (isMale ? "父" : "母");
+                return "曾" + (isMale ? "孙" : "孙女");
             case 2:
-                return isMale ? "祖父" : "祖母";
+                return isMale ? "孙子" : "孙女";
             case 1:
-                return isMale ? "父亲" : "母亲";
+                return isMale ? "儿子" : "女儿";
             // 同辈
             case 0:
                 return isMale ? "兄弟" : "姐妹";
-            // 向下(对方是晚辈)
+            // 向上(对方是长辈)
             case -1:
-                return isMale ? "儿子" : "女儿";
+                return isMale ? "父亲" : "母亲";
             case -2:
-                return isMale ? "孙子" : "孙女";
+                return isMale ? "祖父" : "祖母";
             case -3:
-                return "曾" + (isMale ? "孙" : "孙女");
+                return "曾祖" + (isMale ? "父" : "母");
             default:
                 return generationValue > 0
-                    ? "上" + generationValue + "代"
-                    : "下" + Math.abs(generationValue) + "代";
+                    ? "下" + generationValue + "代"
+                    : "上" + Math.abs(generationValue) + "代";
         }
     }
 

+ 60 - 0
cfc-backend/src/test/java/com/etotem/cfc/unit/FamilyRelationshipServiceLabelTest.java

@@ -0,0 +1,60 @@
+package com.etotem.cfc.unit;
+
+import com.etotem.cfc.service.FamilyRelationshipService;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * family_relationships.generation_value 的标签约定回归(契约 = from.generation - to.generation):
+ * 正数 = 起点辈分更高(对方是晚辈:子/孙/曾孙…);负数 = 起点辈分更低(对方是长辈:父/祖/曾祖…)。
+ *
+ * <p>2026-11-08 修复:computeRelationshipLabel 原按「对方相对查看者的辈分差」解析,与 family_relationships
+ * 存储约定(from.generation - to.generation)方向相反,导致 createRelationsForNewMember 及家庭关系列表
+ * 兜底标签出现「把父辈标成女儿」的反转。本测试固化「存储约定」语义。</p>
+ */
+class FamilyRelationshipServiceLabelTest {
+
+    private final FamilyRelationshipService service = new FamilyRelationshipService();
+
+    @Test
+    void 正向差_对方是晚辈_子辈标签() {
+        assertEquals("儿子", service.computeRelationshipLabel(1, "male"));
+        assertEquals("女儿", service.computeRelationshipLabel(1, "female"));
+    }
+
+    @Test
+    void 负向差_对方是长辈_父辈标签() {
+        assertEquals("父亲", service.computeRelationshipLabel(-1, "male"));
+        assertEquals("母亲", service.computeRelationshipLabel(-1, "female"));
+    }
+
+    @Test
+    void 同辈标签() {
+        assertEquals("兄弟", service.computeRelationshipLabel(0, "male"));
+        assertEquals("姐妹", service.computeRelationshipLabel(0, "female"));
+    }
+
+    @Test
+    void 祖孙辈标签() {
+        assertEquals("孙子", service.computeRelationshipLabel(2, "male"));
+        assertEquals("孙女", service.computeRelationshipLabel(2, "female"));
+        assertEquals("祖父", service.computeRelationshipLabel(-2, "male"));
+        assertEquals("祖母", service.computeRelationshipLabel(-2, "female"));
+        assertEquals("曾孙", service.computeRelationshipLabel(3, "male"));
+        assertEquals("曾祖母", service.computeRelationshipLabel(-3, "female"));
+    }
+
+    @Test
+    void 超过三代_上下N代标签() {
+        assertEquals("下4代", service.computeRelationshipLabel(4, "male"));
+        assertEquals("上4代", service.computeRelationshipLabel(-4, "male"));
+    }
+
+    @Test
+    void 配偶关系不受辈分影响() {
+        assertEquals("丈夫", service.computeRelationshipLabel(0, "male", "spouse"));
+        assertEquals("妻子", service.computeRelationshipLabel(0, "female", "spouse"));
+    }
+
+}