Explorar o código

fix: 恢复钉钉花名册银行信息同步

lfx hai 3 días
pai
achega
0f60171590

+ 51 - 0
src/main/java/com/malk/minglei/service/impl/employee/EmployeeRosterRecord.java

@@ -16,6 +16,9 @@ public class EmployeeRosterRecord {
     private String firstDepartment;
     private String hireDate;
     private String positionName;
+    private String bankCardNo;
+    private String bankName;
+    private String bankBranchCode;
 
     public String getDingtalkId() {
         return dingtalkId;
@@ -104,4 +107,52 @@ public class EmployeeRosterRecord {
     public void setPositionName(String positionName) {
         this.positionName = positionName;
     }
+
+    /**
+     * 获取银行卡号。
+     * @return 银行卡号
+     */
+    public String getBankCardNo() {
+        return bankCardNo;
+    }
+
+    /**
+     * 设置银行卡号。
+     * @param bankCardNo 银行卡号
+     */
+    public void setBankCardNo(String bankCardNo) {
+        this.bankCardNo = bankCardNo;
+    }
+
+    /**
+     * 获取开户行。
+     * @return 开户行
+     */
+    public String getBankName() {
+        return bankName;
+    }
+
+    /**
+     * 设置开户行。
+     * @param bankName 开户行
+     */
+    public void setBankName(String bankName) {
+        this.bankName = bankName;
+    }
+
+    /**
+     * 获取支行联行号。
+     * @return 支行联行号
+     */
+    public String getBankBranchCode() {
+        return bankBranchCode;
+    }
+
+    /**
+     * 设置支行联行号。
+     * @param bankBranchCode 支行联行号
+     */
+    public void setBankBranchCode(String bankBranchCode) {
+        this.bankBranchCode = bankBranchCode;
+    }
 }

+ 10 - 4
src/main/java/com/malk/minglei/service/impl/employee/EmployeeRosterRepository.java

@@ -178,7 +178,10 @@ public class EmployeeRosterRepository {
         statement.setString(index++, record.getDepartment());
         statement.setString(index++, record.getFirstDepartment());
         statement.setString(index++, record.getHireDate());
-        statement.setString(index, record.getPositionName());
+        statement.setString(index++, record.getPositionName());
+        statement.setString(index++, record.getBankCardNo());
+        statement.setString(index++, record.getBankName());
+        statement.setString(index, record.getBankBranchCode());
     }
 
     private JdbcTemplate requireJdbcTemplate() {
@@ -191,8 +194,8 @@ public class EmployeeRosterRepository {
 
     private String createMergeSql(String tableName) {
         return "INSERT INTO " + tableName + " " +
-                "(dingtalk_id, employee_no, username, job_title, job_title_id, job_grade, job_grade_id, department, first_department, hire_date, position_name) " +
-                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " +
+                "(dingtalk_id, employee_no, username, job_title, job_title_id, job_grade, job_grade_id, department, first_department, hire_date, position_name, bank_card_no, bank_name, bank_branch_code) " +
+                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " +
                 "ON DUPLICATE KEY UPDATE " +
                 "dingtalk_id = VALUES(dingtalk_id), " +
                 "employee_no = VALUES(employee_no), " +
@@ -204,7 +207,10 @@ public class EmployeeRosterRepository {
                 "department = VALUES(department), " +
                 "first_department = VALUES(first_department), " +
                 "hire_date = VALUES(hire_date), " +
-                "position_name = VALUES(position_name)";
+                "position_name = VALUES(position_name), " +
+                "bank_card_no = VALUES(bank_card_no), " +
+                "bank_name = VALUES(bank_name), " +
+                "bank_branch_code = VALUES(bank_branch_code)";
     }
 
     private int nextSequence(String prefix, String employeeNo) {

+ 3 - 0
src/main/java/com/malk/minglei/service/impl/employee/EmployeeRosterServiceImpl.java

@@ -317,6 +317,9 @@ public class EmployeeRosterServiceImpl implements EmployeeRosterService {
         record.setJobGradeId(findRosterValue(rosterValues, "职等", "ad410990-cee4-4e19-b70f-189a8ab87527", "job_grade"));
         record.setDepartment(findRosterValue(rosterValues, "部门", "所在部门", "部门名称", "department"));
         record.setFirstDepartment(findRosterValue(rosterValues, "一级部门", "一级部门名称", "first_department"));
+        record.setBankCardNo(findRosterValue(rosterValues, "银行卡号", "bank_card_no"));
+        record.setBankName(findRosterValue(rosterValues, "开户行", "bank_name"));
+        record.setBankBranchCode(findRosterValue(rosterValues, "支行联行号", "bank_branch_code"));
         return record;
     }
 

+ 3 - 0
src/main/resources/db/employee_roster.sql

@@ -9,6 +9,9 @@ CREATE TABLE employee_roster (
   job_grade_id VARCHAR(64) DEFAULT NULL COMMENT '职等ID',
   department VARCHAR(128) DEFAULT NULL COMMENT '部门',
   first_department VARCHAR(128) DEFAULT NULL COMMENT '一级部门',
+  bank_card_no VARCHAR(64) DEFAULT NULL COMMENT '银行卡号',
+  bank_name VARCHAR(128) DEFAULT NULL COMMENT '开户行',
+  bank_branch_code VARCHAR(64) DEFAULT NULL COMMENT '支行联行号',
   PRIMARY KEY (id),
   UNIQUE KEY uk_dingtalk_id (dingtalk_id),
   UNIQUE KEY uk_employee_no (employee_no),

+ 56 - 0
src/test/java/com/malk/minglei/service/impl/employee/EmployeeRosterServiceImplTest.java

@@ -8,8 +8,14 @@ import com.malk.server.dingtalk.DDConf;
 import com.malk.service.dingtalk.DDClient;
 import com.malk.service.dingtalk.DDClient_Contacts;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 import org.mockito.ArgumentCaptor;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.PreparedStatementSetter;
 
+import java.sql.PreparedStatement;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.LinkedHashMap;
@@ -19,6 +25,7 @@ import java.util.Map;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.ArgumentMatchers.anyMap;
 import static org.mockito.ArgumentMatchers.eq;
@@ -28,6 +35,55 @@ import static org.mockito.Mockito.verify;
 
 class EmployeeRosterServiceImplTest {
 
+    @ParameterizedTest
+    @ValueSource(booleans = {true, false})
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    void syncFullWritesBankInformationFromRosterNamesOrCodes(boolean useFieldNames) throws Exception {
+        DDClient dingTalkClient = mock(DDClient.class);
+        DDClient_Contacts contactsClient = mock(DDClient_Contacts.class);
+        DingTalkEmployeeRosterClient rosterClient = mock(DingTalkEmployeeRosterClient.class);
+        JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class);
+        ObjectProvider<JdbcTemplate> jdbcTemplateProvider = mock(ObjectProvider.class);
+        given(jdbcTemplateProvider.getIfAvailable()).willReturn(jdbcTemplate);
+        EmployeeRosterRepository repository = new EmployeeRosterRepository(jdbcTemplateProvider, new EmployeeRosterProperties());
+        DDConf configuration = new DDConf();
+        configuration.setAgentId(123456L);
+        String cardCode = useFieldNames ? "custom-card" : "bank_card_no";
+        String bankCode = useFieldNames ? "custom-bank" : "bank_name";
+        String branchCode = useFieldNames ? "custom-branch" : "bank_branch_code";
+        given(dingTalkClient.getAccessToken()).willReturn("access-token");
+        given(contactsClient.listDeptUserDetail_v2(eq("access-token"), eq(1L), anyMap())).willReturn(mapOf(
+                "list", Collections.singletonList(user("user-1", "Alice", "1001")), "has_more", false));
+        given(rosterClient.listRosterFieldGroups("access-token", 123456L)).willReturn(Collections.singletonList(mapOf(
+                "field_list", Arrays.asList(
+                        field(cardCode, useFieldNames ? "银行卡号" : "Card"),
+                        field(bankCode, useFieldNames ? "开户行" : "Bank"),
+                        field(branchCode, useFieldNames ? "支行联行号" : "Branch")))));
+        given(rosterClient.listEmployeeRoster(eq("access-token"), eq(Collections.singletonList("user-1")),
+                eq(123456L), eq(Arrays.asList(cardCode, bankCode, branchCode))))
+                .willReturn(Collections.singletonList(mapOf("userid", "user-1", "field_data_list", Arrays.asList(
+                        rosterField(cardCode, "6222020000000000000"),
+                        rosterField(bankCode, "Test Bank"),
+                        rosterField(branchCode, "001234567890")))));
+
+        EmployeeRosterServiceImpl service = new EmployeeRosterServiceImpl(dingTalkClient, contactsClient,
+                configuration, rosterClient, repository, new EmployeeRosterProperties());
+        service.syncFull();
+
+        ArgumentCaptor<String> sql = ArgumentCaptor.forClass(String.class);
+        ArgumentCaptor<PreparedStatementSetter> setter = ArgumentCaptor.forClass(PreparedStatementSetter.class);
+        verify(jdbcTemplate).update(sql.capture(), setter.capture());
+        assertTrue(sql.getValue().contains("bank_card_no, bank_name, bank_branch_code"));
+        assertTrue(sql.getValue().contains("bank_card_no = VALUES(bank_card_no)"));
+        assertTrue(sql.getValue().contains("bank_name = VALUES(bank_name)"));
+        assertTrue(sql.getValue().contains("bank_branch_code = VALUES(bank_branch_code)"));
+        PreparedStatement statement = mock(PreparedStatement.class);
+        setter.getValue().setValues(statement);
+        verify(statement).setString(12, "6222020000000000000");
+        verify(statement).setString(13, "Test Bank");
+        verify(statement).setString(14, "001234567890");
+    }
+
     @Test
     void findByEmployeeNoDelegatesToRepository() {
         EmployeeRosterRepository repository = mock(EmployeeRosterRepository.class);