Explorar el Código

feat(workhours): 回填应填报人姓名

malk hace 2 días
padre
commit
aa400ab442

+ 42 - 0
mjava-akdsbeisen/src/main/java/com/malk/service/workhours/WorkHoursCalcService.java

@@ -56,6 +56,8 @@ public class WorkHoursCalcService {
     // prd 在职状态字段 + 离职取值 (防御开关: status=离职 且 offlineDate=空 → 数据不一致, 该员工不写工时)
     private static final String PERSONNEL_STATUS = "radioField_mp1sngq1";
     private static final String STATUS_INACTIVE = "离职";
+    // prd 应填报人显示名称文本,用于报表按姓名筛选;姓名取自人员档案成员组件显示值
+    private static final String REQUIRED_HOURS_EMPLOYEE_NAME = "textField_ms4bzjkm";
 
     // prd 外部员工关联项目经理:项目档案成员子表字段
     private static final String PROJECT_SUB_TABLE = "tableField_mkowyn6d";      // 成员子表(人员明细)
@@ -1530,6 +1532,9 @@ public class WorkHoursCalcService {
                     info.put("textField_mmekrcji", formData.get("selectField_mh8xhqc4"));
                     // prd: 是否cf员工,源 textField_mow9w7d8(人员档案)→ 目标 textField_mpp7a2k7(应填报工时)
                     info.put("textField_mpp7a2k7", formData.get("textField_mow9w7d8"));
+                    // prd 应填报人(文本):读取成员组件显示名称,并清理离职标记
+                    info.put(REQUIRED_HOURS_EMPLOYEE_NAME,
+                            normalizeEmployeeName(formData.get("employeeField_mkow4ydp")));
                     // prd 离职时间: 携带原值供 concurrentUpsert 过滤 workDay > offlineDate
                     info.put(PERSONNEL_OFFLINE_DATE, formData.get(PERSONNEL_OFFLINE_DATE));
                     // prd 在职状态: 携带供 concurrentUpsert 防御 (status=离职 且 offlineDate=空 时跳过写入)
@@ -1970,6 +1975,8 @@ public class WorkHoursCalcService {
             putIfNotNull(formData, "textField_mmekrcji", personnelInfo.get("textField_mmekrcji"));
             // prd: 是否cf员工(源 textField_mow9w7d8 → 目标 textField_mpp7a2k7)
             putIfNotNull(formData, "textField_mpp7a2k7", personnelInfo.get("textField_mpp7a2k7"));
+            putIfNotNull(formData, REQUIRED_HOURS_EMPLOYEE_NAME,
+                    personnelInfo.get(REQUIRED_HOURS_EMPLOYEE_NAME));
         }
 
         // fixme: 日期组件在 searchCondition 中必须使用数组格式 [start, end]
@@ -1998,6 +2005,41 @@ public class WorkHoursCalcService {
         }
     }
 
+    /**
+     * 从成员组件显示值提取姓名,并去除宜搭对离职成员追加的“已离职”标记。
+     *
+     * @param employeeValue 成员组件显示值,通常为单元素 List,也兼容字符串
+     * @return 清理后的姓名;空值返回 null
+     */
+    static String normalizeEmployeeName(Object employeeValue) {
+        if (employeeValue == null) {
+            return null;
+        }
+        Object nameValue = employeeValue;
+        if (employeeValue instanceof List) {
+            List<?> names = (List<?>) employeeValue;
+            if (names.isEmpty()) {
+                return null;
+            }
+            nameValue = names.get(0);
+        } else if (String.valueOf(employeeValue).trim().startsWith("[")) {
+            try {
+                List<String> names = JSON.parseArray(String.valueOf(employeeValue), String.class);
+                if (names == null || names.isEmpty()) {
+                    return null;
+                }
+                nameValue = names.get(0);
+            } catch (Exception ignored) {
+                // fixme 非 JSON 的普通姓名若以 "[" 开头,按原字符串继续清洗
+            }
+        }
+        String name = String.valueOf(nameValue)
+                .replaceAll("\\s*[\\[((]?\\s*已离职\\s*[\\]))]?\\s*", " ")
+                .replaceAll("\\s+", " ")
+                .trim();
+        return name.isEmpty() ? null : name;
+    }
+
     /**
      * 从 formData 中提取员工字段的 userId
      * ppExt: 员工字段返回格式可能为 userId字符串、JSON数组字符串 或 _id 后缀字段

+ 13 - 0
mjava-akdsbeisen/src/test/java/com/malk/service/workhours/WorkHoursCalcServiceTest.java

@@ -67,6 +67,19 @@ public class WorkHoursCalcServiceTest {
         assertFalse(WorkHoursCalcService.isAfterOfflineDate(offlineDate.plusDays(1), null));
     }
 
+    @Test
+    public void normalizeEmployeeNameShouldReadMemberDisplayNameAndRemoveInactiveMarker() {
+        assertEquals("张三/San Zhang", WorkHoursCalcService.normalizeEmployeeName(
+                Collections.singletonList("已离职 张三/San Zhang")));
+        assertEquals("李四/Si Li", WorkHoursCalcService.normalizeEmployeeName("李四/Si Li 已离职"));
+        assertEquals("王五/Wu Wang", WorkHoursCalcService.normalizeEmployeeName("王五/Wu Wang(已离职)"));
+        assertEquals("赵六/Liu Zhao", WorkHoursCalcService.normalizeEmployeeName(
+                "[\"赵六/Liu Zhao (已离职)\"]"));
+        assertEquals("钱七/Qi Qian", WorkHoursCalcService.normalizeEmployeeName("钱七/Qi Qian[已离职]"));
+        assertEquals(null, WorkHoursCalcService.normalizeEmployeeName(Collections.emptyList()));
+        assertEquals(null, WorkHoursCalcService.normalizeEmployeeName("已离职"));
+    }
+
     @Test
     public void cleanupFutureHoursDryRunShouldReportFutureRecordsWithoutDeleting() {
         YDClient ydClient = mock(YDClient.class);