Przeglądaj źródła

fix(benteler): preserve Tianjin vendor departments

malk 1 tydzień temu
rodzic
commit
5371492948

+ 1 - 0
mjava-benteler/src/main/java/com/malk/benteler/config/BentelerYidaConf.java

@@ -40,6 +40,7 @@ public class BentelerYidaConf {
     private String updateOutsourcingCompanyFieldId;
     private String updateNameFieldId;
     private String updateFactoryFieldId;
+    private String updateDepartmentCodeFieldId;
     private String updateProbationConfirmationFieldId;
     private String updateDingTalkDepartmentFieldId;
 

+ 33 - 2
mjava-benteler/src/main/java/com/malk/benteler/service/BentelerDingTalkSyncTaskService.java

@@ -18,6 +18,7 @@ import java.time.Clock;
 import java.time.Instant;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -38,6 +39,11 @@ public class BentelerDingTalkSyncTaskService {
     private static final int MAX_ERROR_LENGTH = 500;
     private static final long CLAIM_MINUTES = 10;
     private static final String CLAIM_PREFIX = "CLAIM:";
+    private static final String DEPARTMENT_LIST_FIELD = "dept_id_list";
+    static final String TIANJIN_REPLACE_DEPARTMENT_FIELD =
+            "dept_id_list_preserve_tianjin_0758_vendor";
+    private static final List<Long> TIANJIN_0758_VENDOR_DEPARTMENT_IDS = Arrays.asList(
+            1088354378L, 1088525237L, 1088534187L, 1088923059L, 1088933080L);
     private static final Pattern SENSITIVE_VALUE = Pattern.compile(
             "(?i)(access[_-]?token|appsecret|password|aeskey|privatekey)\\s*[=:]\\s*[^\\s,;]+"
     );
@@ -151,6 +157,27 @@ public class BentelerDingTalkSyncTaskService {
      */
     public void enqueueContactPrimaryDepartmentUpdate(String formInstanceId, int rowIndex,
                                                       String userId, Long departmentId) {
+        enqueueContactDepartmentUpdate(formInstanceId, rowIndex, userId, departmentId,
+                DEPARTMENT_LIST_FIELD);
+    }
+
+    /**
+     * Creates a Tianjin 0758 department replacement while preserving vendor departments.
+     *
+     * @param formInstanceId source YiDa form instance ID
+     * @param rowIndex source detail-row index
+     * @param userId DingTalk user ID
+     * @param departmentId target DingTalk department ID
+     */
+    public void enqueueTianjinDepartmentReplace(String formInstanceId, int rowIndex,
+                                                String userId, Long departmentId) {
+        enqueueContactDepartmentUpdate(formInstanceId, rowIndex, userId, departmentId,
+                TIANJIN_REPLACE_DEPARTMENT_FIELD);
+    }
+
+    private void enqueueContactDepartmentUpdate(String formInstanceId, int rowIndex,
+                                                String userId, Long departmentId,
+                                                String targetFieldCode) {
         if (StringUtils.isBlank(userId) || departmentId == null || departmentId <= 0) {
             return;
         }
@@ -164,7 +191,7 @@ public class BentelerDingTalkSyncTaskService {
         formData.put(conf.getDingTalkSyncSourceFormInstanceIdFieldId(), formInstanceId);
         formData.put(conf.getDingTalkSyncSourceRowIndexFieldId(), rowIndex);
         formData.put(conf.getDingTalkSyncUserIdFieldId(), userId);
-        formData.put(conf.getDingTalkSyncTargetFieldCodeFieldId(), "dept_id_list");
+        formData.put(conf.getDingTalkSyncTargetFieldCodeFieldId(), targetFieldCode);
         formData.put(conf.getDingTalkSyncTargetFieldValueFieldId(), String.valueOf(departmentId));
         formData.put(conf.getDingTalkSyncStatusFieldId(), DingTalkSyncTask.PENDING);
         formData.put(conf.getDingTalkSyncRetryCountFieldId(), 0);
@@ -309,11 +336,15 @@ public class BentelerDingTalkSyncTaskService {
         List<Long> departments = new ArrayList<>();
         Long target = Long.valueOf(task.getTargetFieldValue());
         departments.add(target);
+        boolean replaceTianjinDepartment = TIANJIN_REPLACE_DEPARTMENT_FIELD.equals(
+                task.getTargetFieldCode());
         Object existing = user.get("dept_id_list");
         if (existing instanceof List) {
             for (Object value : (List<?>) existing) {
                 Long department = Long.valueOf(String.valueOf(value));
-                if (!target.equals(department)) {
+                boolean retainExisting = !replaceTianjinDepartment
+                        || TIANJIN_0758_VENDOR_DEPARTMENT_IDS.contains(department);
+                if (!target.equals(department) && retainExisting) {
                     departments.add(department);
                 }
             }

+ 22 - 3
mjava-benteler/src/main/java/com/malk/benteler/service/BentelerYidaSyncService.java

@@ -118,7 +118,11 @@ public class BentelerYidaSyncService {
                 && "是".equals(text(formData.get(conf.getUpdateProbationConfirmationFieldId())));
         List<String> updateContents = operation == EiamBatchOperation.UPDATE
                 ? texts(formData.get(conf.getUpdateContentFieldId())) : new ArrayList<>();
-        Long dingTalkDepartmentId = updateContents.contains(BentelerYidaFormMapper.ADD_ORG)
+        boolean replaceTianjinDepartment = isTianjinDepartmentReplace(
+                operation, formData, updateContents);
+        boolean syncDingTalkDepartment = replaceTianjinDepartment
+                || updateContents.contains(BentelerYidaFormMapper.ADD_ORG);
+        Long dingTalkDepartmentId = syncDingTalkDepartment
                 ? longValue(formData.get(conf.getUpdateDingTalkDepartmentFieldId())) : null;
         if (StringUtils.isBlank(fieldValue) && !clearOutsourcing && dingTalkDepartmentId == null) {
             return;
@@ -140,8 +144,13 @@ public class BentelerYidaSyncService {
                             userId, fieldValue);
                 }
                 if (dingTalkDepartmentId != null) {
-                    dingTalkSyncTaskService.enqueueContactPrimaryDepartmentUpdate(formInstanceId,
-                            item.getIndex(), userId, dingTalkDepartmentId);
+                    if (replaceTianjinDepartment) {
+                        dingTalkSyncTaskService.enqueueTianjinDepartmentReplace(formInstanceId,
+                                item.getIndex(), userId, dingTalkDepartmentId);
+                    } else {
+                        dingTalkSyncTaskService.enqueueContactPrimaryDepartmentUpdate(formInstanceId,
+                                item.getIndex(), userId, dingTalkDepartmentId);
+                    }
                 }
             } catch (RuntimeException ex) {
                 log.error("钉钉花名册同步任务创建失败, formInstanceId={}, rowIndex={}",
@@ -150,6 +159,16 @@ public class BentelerYidaSyncService {
         }
     }
 
+    private boolean isTianjinDepartmentReplace(EiamBatchOperation operation,
+                                               Map<String, Object> formData,
+                                               List<String> updateContents) {
+        // prd 天津 0758 人员保留劳务部门,只替换其余所属部门。
+        return operation == EiamBatchOperation.UPDATE
+                && updateContents.contains(BentelerYidaFormMapper.REPLACE_PRIMARY_ORG)
+                && "BATJ II".equals(firstText(formData.get(conf.getUpdateFactoryFieldId())))
+                && "0758".equals(firstText(formData.get(conf.getUpdateDepartmentCodeFieldId())));
+    }
+
     private Long longValue(Object value) {
         Object selected = value instanceof List && !((List<?>) value).isEmpty()
                 ? ((List<?>) value).get(0) : value;

+ 1 - 0
mjava-benteler/src/main/resources/application.yml

@@ -57,6 +57,7 @@ benteler:
     updateOutsourcingCompanyFieldId: textField_msdyohrv
     updateNameFieldId: textField_mti9mulz
     updateFactoryFieldId: selectField_motg7pxc
+    updateDepartmentCodeFieldId: selectField_mokvns7e
     updateProbationConfirmationFieldId: selectField_mti9mum0
     updateDingTalkDepartmentFieldId: departmentSelectField_mrcw2nqg
     offboardingFormUuid: FORM-3D8B56B5A9EE45738A03D4DB6C1D22E16Z5T

+ 31 - 0
mjava-benteler/src/test/java/com/malk/benteler/service/BentelerDingTalkSyncTaskServiceTest.java

@@ -131,6 +131,37 @@ public class BentelerDingTalkSyncTaskServiceTest {
         assertEquals(Arrays.asList(100L, 200L), bodyCaptor.getValue().get("dept_id_list"));
     }
 
+    @Test
+    public void enqueueTianjinDepartmentReplace_marksProtectedReplacementMode() {
+        service.enqueueTianjinDepartmentReplace("source_1", 0, "user_1", 100L);
+
+        Map<String, Object> saved = capturedUpsertedForm();
+        assertEquals(BentelerDingTalkSyncTaskService.TIANJIN_REPLACE_DEPARTMENT_FIELD,
+                saved.get("field_code"));
+        assertEquals("100", saved.get("field_value"));
+    }
+
+    @Test
+    public void executeDueTasks_tianjinReplaceKeepsVendorDepartmentAndDropsOtherDepartments() {
+        Map<String, Object> record = taskRecord("task_1", DingTalkSyncTask.PENDING, 0,
+                NOW, "user_1", "100");
+        Map<String, Object> data = formData(record);
+        data.put("task_type", DingTalkSyncTask.CONTACT_PRIMARY_DEPARTMENT_UPDATE);
+        data.put("field_code", BentelerDingTalkSyncTaskService.TIANJIN_REPLACE_DEPARTMENT_FIELD);
+        dueTasks(record);
+        when(ddService.getAccessToken()).thenReturn("cached_token");
+        when(contactsClient.getUserInfoById("cached_token", "user_1"))
+                .thenReturn(Collections.singletonMap("dept_id_list",
+                        Arrays.asList(200L, 1088354378L, 1088525237L)));
+
+        service.executeDueTasks();
+
+        ArgumentCaptor<Map> bodyCaptor = ArgumentCaptor.forClass(Map.class);
+        verify(contactsClient).updateUser(eq("cached_token"), eq("user_1"), bodyCaptor.capture());
+        assertEquals(Arrays.asList(100L, 1088354378L, 1088525237L),
+                bodyCaptor.getValue().get("dept_id_list"));
+    }
+
     @Test
     public void enqueueRosterUpdate_existingUnfinishedTaskIsResetInsteadOfDuplicated() {
         when(ydClientForm.searchForm(any(YDAuth.class), eq("FORM_TASK"), anyString(),

+ 27 - 0
mjava-benteler/src/test/java/com/malk/benteler/service/BentelerYidaSyncServiceTest.java

@@ -179,6 +179,33 @@ public class BentelerYidaSyncServiceTest {
                 "form_update", 0, "user_1", 100L);
     }
 
+    @Test
+    public void syncUpdate_tianjin0758ReplaceEnqueuesProtectedDepartmentReplace() {
+        Map<String, Object> row = new HashMap<>();
+        row.put(conf.getUpdateEmployeeFieldId() + "_id", Collections.singletonList("user_1"));
+        Map<String, Object> formData = new HashMap<>();
+        formData.put(conf.getUpdateContentFieldId(),
+                Collections.singletonList(BentelerYidaFormMapper.REPLACE_PRIMARY_ORG));
+        formData.put(conf.getUpdateOrganizationalUnitIdFieldId(), "ou_target");
+        formData.put(conf.getUpdateFactoryFieldId(), "BATJ II");
+        formData.put(conf.getUpdateDepartmentCodeFieldId(), "0758");
+        formData.put(conf.getUpdateDingTalkDepartmentFieldId(), Collections.singletonList("100"));
+        formData.put(conf.getUpdateTableFieldId(), Collections.singletonList(row));
+        when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
+                .thenReturn(instance(formData));
+        when(eiamLocalService.batchUpdate(any())).thenReturn(batchResult(EiamBatchOperation.UPDATE, true));
+        when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
+                .thenReturn(Collections.emptyMap());
+
+        service.syncUpdate("form_update");
+
+        verify(dingTalkSyncTaskService).enqueueTianjinDepartmentReplace(
+                "form_update", 0, "user_1", 100L);
+        verify(dingTalkSyncTaskService, never()).enqueueContactPrimaryDepartmentUpdate(
+                anyString(), org.mockito.ArgumentMatchers.anyInt(), anyString(),
+                org.mockito.ArgumentMatchers.anyLong());
+    }
+
     @Test
     public void syncCreate_blankOutsourcingCompanyDoesNotEnqueueTask() {
         Map<String, Object> formData = new HashMap<>();

+ 1 - 0
mjava-benteler/src/test/java/com/malk/benteler/service/TestBentelerYidaConf.java

@@ -43,6 +43,7 @@ final class TestBentelerYidaConf {
         conf.setUpdateOutsourcingCompanyFieldId("outsourcing_update");
         conf.setUpdateNameFieldId("update_name");
         conf.setUpdateFactoryFieldId("update_factory");
+        conf.setUpdateDepartmentCodeFieldId("update_department_code");
         conf.setUpdateProbationConfirmationFieldId("probation_confirmation");
         conf.setUpdateDingTalkDepartmentFieldId("dingtalk_department");
         conf.setOffboardingTableFieldId("table_delete");