Browse Source

feat(realname): 新增 RealNameBackfillService 真实姓名回填组件

Sisyphus Agent 4 days ago
parent
commit
c245bac0b2

+ 43 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/RealNameBackfillService.java

@@ -0,0 +1,43 @@
+package com.etotem.cfc.service;
+
+import com.etotem.cfc.entity.User;
+import com.etotem.cfc.mapper.UserMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+/**
+ * 真实姓名回填:用户第一次输入地址/收货人时,若 users.real_name 尚未填写,
+ * 用联系人姓名回填(规格:docs/superpowers/specs/2026-10-10-address-contact-backfill-realname-design.md)。
+ * 幂等:回填一次后 realName 非空,后续保存不再触发。
+ * 风格参照 ConsigneeService.syncUserRegion():失败静默,不阻塞主流程。
+ */
+@Service
+public class RealNameBackfillService {
+
+    private static final Logger log = LoggerFactory.getLogger(RealNameBackfillService.class);
+
+    @Resource
+    private UserMapper userMapper;
+
+    /**
+     * 若 userId 对应用户的 realName 为空白,则用 contactName(去首尾空白后)回填。
+     * contactName 空白、userId 为空、用户不存在时直接跳过。
+     */
+    public void backfill(Long userId, String contactName) {
+        try {
+            if (userId == null) return;
+            if (contactName == null || contactName.trim().isEmpty()) return;
+            User user = userMapper.selectById(userId);
+            if (user == null) return;
+            String realName = user.getRealName();
+            if (realName != null && !realName.trim().isEmpty()) return;
+            user.setRealName(contactName.trim());
+            userMapper.updateById(user);
+        } catch (Exception e) {
+            log.warn("[RealNameBackfill] 回填失败 userId={} : {}", userId, e.getMessage());
+        }
+    }
+}

+ 100 - 0
cfc-backend/src/test/java/com/etotem/cfc/service/RealNameBackfillServiceTest.java

@@ -0,0 +1,100 @@
+package com.etotem.cfc.service;
+
+import com.etotem.cfc.entity.User;
+import com.etotem.cfc.mapper.UserMapper;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+class RealNameBackfillServiceTest {
+
+    @Mock
+    private UserMapper userMapper;
+
+    @InjectMocks
+    private RealNameBackfillService realNameBackfillService;
+
+    @Test
+    void backfill_真实姓名为null时回填联系人姓名() {
+        User user = new User();
+        user.setRealName(null);
+        when(userMapper.selectById(1L)).thenReturn(user);
+
+        realNameBackfillService.backfill(1L, "张三");
+
+        assertEquals("张三", user.getRealName());
+        verify(userMapper).updateById(user);
+    }
+
+    @Test
+    void backfill_真实姓名为空白时回填联系人姓名() {
+        User user = new User();
+        user.setRealName("   ");
+        when(userMapper.selectById(1L)).thenReturn(user);
+
+        realNameBackfillService.backfill(1L, "李四");
+
+        assertEquals("李四", user.getRealName());
+        verify(userMapper).updateById(user);
+    }
+
+    @Test
+    void backfill_联系人姓名去除首尾空白后回填() {
+        User user = new User();
+        user.setRealName(null);
+        when(userMapper.selectById(1L)).thenReturn(user);
+
+        realNameBackfillService.backfill(1L, "  王五  ");
+
+        assertEquals("王五", user.getRealName());
+        verify(userMapper).updateById(user);
+    }
+
+    @Test
+    void backfill_真实姓名已有值时不覆盖() {
+        User user = new User();
+        user.setRealName("原有姓名");
+        when(userMapper.selectById(1L)).thenReturn(user);
+
+        realNameBackfillService.backfill(1L, "张三");
+
+        assertEquals("原有姓名", user.getRealName());
+        verify(userMapper, never()).updateById(any());
+    }
+
+    @Test
+    void backfill_联系人姓名为null时跳过() {
+        realNameBackfillService.backfill(1L, null);
+
+        verifyNoInteractions(userMapper);
+    }
+
+    @Test
+    void backfill_联系人姓名为空白时跳过() {
+        realNameBackfillService.backfill(1L, "   ");
+
+        verifyNoInteractions(userMapper);
+    }
+
+    @Test
+    void backfill_userId为null时跳过() {
+        realNameBackfillService.backfill(null, "张三");
+
+        verifyNoInteractions(userMapper);
+    }
+
+    @Test
+    void backfill_用户不存在时跳过() {
+        when(userMapper.selectById(99L)).thenReturn(null);
+
+        realNameBackfillService.backfill(99L, "张三");
+
+        verify(userMapper, never()).updateById(any());
+    }
+}