diff --git a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiCustFmyRelationQueryDTO.java b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiCustFmyRelationQueryDTO.java index 965e4fde..cb0fc82f 100644 --- a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiCustFmyRelationQueryDTO.java +++ b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiCustFmyRelationQueryDTO.java @@ -33,6 +33,10 @@ public class CcdiCustFmyRelationQueryDTO implements Serializable { @Schema(description = "关系人姓名") private String relationName; + /** 关系人身份证号 */ + @Schema(description = "关系人身份证号") + private String relationCertNo; + /** 状态 */ @Schema(description = "状态:0-无效,1-有效") private Integer status; diff --git a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiStaffFmyRelationQueryDTO.java b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiStaffFmyRelationQueryDTO.java index 4d752eb6..9ab4e3fe 100644 --- a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiStaffFmyRelationQueryDTO.java +++ b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiStaffFmyRelationQueryDTO.java @@ -37,6 +37,10 @@ public class CcdiStaffFmyRelationQueryDTO implements Serializable { @Schema(description = "关系人姓名") private String relationName; + /** 关系人身份证号 */ + @Schema(description = "关系人身份证号") + private String relationCertNo; + /** 状态 */ @Schema(description = "状态:0-无效,1-有效") private Integer status; diff --git a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiIntermediaryEnterpriseRelationExcel.java b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiIntermediaryEnterpriseRelationExcel.java index f6aed554..45dfb839 100644 --- a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiIntermediaryEnterpriseRelationExcel.java +++ b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiIntermediaryEnterpriseRelationExcel.java @@ -2,6 +2,7 @@ package com.ruoyi.info.collection.domain.excel; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.ruoyi.common.annotation.Required; import lombok.Data; import java.io.Serial; @@ -17,17 +18,19 @@ public class CcdiIntermediaryEnterpriseRelationExcel implements Serializable { private static final long serialVersionUID = 1L; /** 中介本人证件号码 */ - @ExcelProperty(value = "中介本人证件号码*", index = 0) + @ExcelProperty(value = "中介本人证件号码", index = 0) @ColumnWidth(24) + @Required private String ownerPersonId; /** 统一社会信用代码 */ - @ExcelProperty(value = "统一社会信用代码*", index = 1) + @ExcelProperty(value = "统一社会信用代码", index = 1) @ColumnWidth(24) + @Required private String socialCreditCode; - /** 关联人职务 */ - @ExcelProperty(value = "关联人职务", index = 2) + /** 关联职务 */ + @ExcelProperty(value = "关联职务", index = 2) @ColumnWidth(20) private String relationPersonPost; diff --git a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiStaffRecruitmentExcel.java b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiStaffRecruitmentExcel.java index 9d2d0084..f3468006 100644 --- a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiStaffRecruitmentExcel.java +++ b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiStaffRecruitmentExcel.java @@ -21,8 +21,8 @@ public class CcdiStaffRecruitmentExcel implements Serializable { @Serial private static final long serialVersionUID = 1L; - /** 招聘项目编号 */ - @ExcelProperty(value = "招聘项目编号", index = 0) + /** 招聘记录编号 */ + @ExcelProperty(value = "招聘记录编号", index = 0) @ColumnWidth(20) @Required private String recruitId; @@ -51,66 +51,72 @@ public class CcdiStaffRecruitmentExcel implements Serializable { @Required private String posDesc; - /** 应聘人员姓名 */ - @ExcelProperty(value = "应聘人员姓名", index = 5) - @ColumnWidth(15) - @Required - private String candName; - - /** 应聘人员学历 */ - @ExcelProperty(value = "应聘人员学历", index = 6) - @ColumnWidth(15) - @Required - private String candEdu; - - /** 应聘人员证件号码 */ - @ExcelProperty(value = "应聘人员证件号码", index = 7) - @ColumnWidth(20) - @Required - private String candId; - - /** 应聘人员毕业院校 */ - @ExcelProperty(value = "应聘人员毕业院校", index = 8) - @ColumnWidth(20) - @Required - private String candSchool; - - /** 应聘人员专业 */ - @ExcelProperty(value = "应聘人员专业", index = 9) - @ColumnWidth(15) - @Required - private String candMajor; - - /** 应聘人员毕业年月 */ - @ExcelProperty(value = "应聘人员毕业年月", index = 10) - @ColumnWidth(15) - @Required - private String candGrad; - /** 录用情况 */ - @ExcelProperty(value = "录用情况", index = 11) + @ExcelProperty(value = "录用情况", index = 5) @ColumnWidth(10) @DictDropdown(dictType = "ccdi_admit_status") @Required private String admitStatus; + /** 候选人姓名 */ + @ExcelProperty(value = "候选人姓名", index = 6) + @ColumnWidth(15) + @Required + private String candName; + + /** 招聘类型 */ + @ExcelProperty(value = "招聘类型", index = 7) + @ColumnWidth(12) + @Required + private String recruitType; + + /** 应聘人员学历 */ + @ExcelProperty(value = "学历", index = 8) + @ColumnWidth(15) + @Required + private String candEdu; + + /** 应聘人员证件号码 */ + @ExcelProperty(value = "证件号码", index = 9) + @ColumnWidth(20) + @Required + private String candId; + + /** 应聘人员毕业年月 */ + @ExcelProperty(value = "毕业年月", index = 10) + @ColumnWidth(15) + @Required + private String candGrad; + + /** 应聘人员毕业院校 */ + @ExcelProperty(value = "毕业院校", index = 11) + @ColumnWidth(20) + @Required + private String candSchool; + + /** 应聘人员专业 */ + @ExcelProperty(value = "专业", index = 12) + @ColumnWidth(15) + @Required + private String candMajor; + /** 面试官1姓名 */ - @ExcelProperty(value = "面试官1姓名", index = 12) + @ExcelProperty(value = "面试官1姓名", index = 13) @ColumnWidth(15) private String interviewerName1; /** 面试官1工号 */ - @ExcelProperty(value = "面试官1工号", index = 13) + @ExcelProperty(value = "面试官1工号", index = 14) @ColumnWidth(15) private String interviewerId1; /** 面试官2姓名 */ - @ExcelProperty(value = "面试官2姓名", index = 14) + @ExcelProperty(value = "面试官2姓名", index = 15) @ColumnWidth(15) private String interviewerName2; /** 面试官2工号 */ - @ExcelProperty(value = "面试官2工号", index = 15) + @ExcelProperty(value = "面试官2工号", index = 16) @ColumnWidth(15) private String interviewerId2; } diff --git a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiStaffRecruitmentWorkExcel.java b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiStaffRecruitmentWorkExcel.java index 2ee6ee9b..3831d1cb 100644 --- a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiStaffRecruitmentWorkExcel.java +++ b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiStaffRecruitmentWorkExcel.java @@ -61,20 +61,20 @@ public class CcdiStaffRecruitmentWorkExcel implements Serializable { @ColumnWidth(18) private String departmentName; - /** 岗位 */ - @ExcelProperty(value = "岗位", index = 7) + /** 岗位名称 */ + @ExcelProperty(value = "岗位名称", index = 7) @ColumnWidth(20) @Required private String positionName; /** 入职年月 */ - @ExcelProperty(value = "入职年月", index = 8) + @ExcelProperty(value = "入职时间", index = 8) @ColumnWidth(12) @Required private String jobStartMonth; /** 离职年月 */ - @ExcelProperty(value = "离职年月", index = 9) + @ExcelProperty(value = "离职时间", index = 9) @ColumnWidth(12) private String jobEndMonth; @@ -83,8 +83,8 @@ public class CcdiStaffRecruitmentWorkExcel implements Serializable { @ColumnWidth(30) private String departureReason; - /** 工作内容 */ - @ExcelProperty(value = "工作内容", index = 11) + /** 主要工作内容 */ + @ExcelProperty(value = "主要工作内容", index = 11) @ColumnWidth(35) private String workContent; diff --git a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/IntermediaryEnterpriseRelationImportFailureVO.java b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/IntermediaryEnterpriseRelationImportFailureVO.java index a60f581d..5c52d440 100644 --- a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/IntermediaryEnterpriseRelationImportFailureVO.java +++ b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/IntermediaryEnterpriseRelationImportFailureVO.java @@ -22,7 +22,7 @@ public class IntermediaryEnterpriseRelationImportFailureVO implements Serializab @Schema(description = "统一社会信用代码") private String socialCreditCode; - @Schema(description = "关联人职务") + @Schema(description = "关联职务") private String relationPersonPost; @Schema(description = "备注") diff --git a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiIntermediaryEnterpriseRelationImportServiceImpl.java b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiIntermediaryEnterpriseRelationImportServiceImpl.java index b4c5a523..9e5f7b86 100644 --- a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiIntermediaryEnterpriseRelationImportServiceImpl.java +++ b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiIntermediaryEnterpriseRelationImportServiceImpl.java @@ -79,12 +79,14 @@ public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcd try { validateExcel(excel); - String ownerBizId = ownerBizIdByPersonId.get(excel.getOwnerPersonId()); + String ownerPersonId = trim(excel.getOwnerPersonId()); + String socialCreditCode = trim(excel.getSocialCreditCode()); + String ownerBizId = ownerBizIdByPersonId.get(ownerPersonId); if (StringUtils.isEmpty(ownerBizId)) { throw new RuntimeException("中介本人不存在,请先导入或维护中介本人信息"); } - String combination = ownerBizId + "|" + excel.getSocialCreditCode(); + String combination = ownerBizId + "|" + socialCreditCode; if (existingCombinations.contains(combination)) { throw new RuntimeException("中介实体关联关系已存在,请勿重复导入"); } @@ -95,6 +97,9 @@ public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcd CcdiIntermediaryEnterpriseRelation relation = new CcdiIntermediaryEnterpriseRelation(); BeanUtils.copyProperties(excel, relation); relation.setIntermediaryBizId(ownerBizId); + relation.setSocialCreditCode(socialCreditCode); + relation.setRelationPersonPost(trim(excel.getRelationPersonPost())); + relation.setRemark(trim(excel.getRemark())); relation.setCreatedBy(userName); relation.setUpdatedBy(userName); successRecords.add(relation); @@ -165,6 +170,7 @@ public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcd private Map getOwnerBizIdByPersonId(List excelList) { List ownerPersonIds = excelList.stream() .map(CcdiIntermediaryEnterpriseRelationExcel::getOwnerPersonId) + .map(this::trim) .filter(StringUtils::isNotEmpty) .distinct() .collect(Collectors.toList()); @@ -183,11 +189,12 @@ public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcd List excelList) { List combinations = excelList.stream() .map(excel -> { - String ownerBizId = ownerBizIdByPersonId.get(excel.getOwnerPersonId()); - if (StringUtils.isEmpty(ownerBizId) || StringUtils.isEmpty(excel.getSocialCreditCode())) { + String ownerBizId = ownerBizIdByPersonId.get(trim(excel.getOwnerPersonId())); + String socialCreditCode = trim(excel.getSocialCreditCode()); + if (StringUtils.isEmpty(ownerBizId) || StringUtils.isEmpty(socialCreditCode)) { return null; } - return ownerBizId + "|" + excel.getSocialCreditCode(); + return ownerBizId + "|" + socialCreditCode; }) .filter(StringUtils::isNotEmpty) .distinct() @@ -199,24 +206,33 @@ public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcd } private void validateExcel(CcdiIntermediaryEnterpriseRelationExcel excel) { - if (StringUtils.isEmpty(excel.getOwnerPersonId())) { + String ownerPersonId = trim(excel.getOwnerPersonId()); + String socialCreditCode = trim(excel.getSocialCreditCode()); + String relationPersonPost = trim(excel.getRelationPersonPost()); + String remark = trim(excel.getRemark()); + + if (StringUtils.isEmpty(ownerPersonId)) { throw new RuntimeException("中介本人证件号码不能为空"); } - if (StringUtils.isEmpty(excel.getSocialCreditCode())) { + if (StringUtils.isEmpty(socialCreditCode)) { throw new RuntimeException("统一社会信用代码不能为空"); } - String ownerPersonIdError = IdCardUtil.getErrorMessage(excel.getOwnerPersonId()); + String ownerPersonIdError = IdCardUtil.getErrorMessage(ownerPersonId); if (ownerPersonIdError != null) { throw new RuntimeException("中介本人证件号码" + ownerPersonIdError); } - if (StringUtils.isNotEmpty(excel.getRelationPersonPost()) && excel.getRelationPersonPost().length() > 100) { - throw new RuntimeException("关联人职务长度不能超过100个字符"); + if (StringUtils.isNotEmpty(relationPersonPost) && relationPersonPost.length() > 100) { + throw new RuntimeException("关联职务长度不能超过100个字符"); } - if (StringUtils.isNotEmpty(excel.getRemark()) && excel.getRemark().length() > 500) { + if (StringUtils.isNotEmpty(remark) && remark.length() > 500) { throw new RuntimeException("备注长度不能超过500个字符"); } } + private String trim(String value) { + return value == null ? null : value.trim(); + } + private IntermediaryEnterpriseRelationImportFailureVO createFailureVO(CcdiIntermediaryEnterpriseRelationExcel excel, String errorMessage) { IntermediaryEnterpriseRelationImportFailureVO failure = new IntermediaryEnterpriseRelationImportFailureVO(); diff --git a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiStaffRecruitmentImportServiceImpl.java b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiStaffRecruitmentImportServiceImpl.java index 86c82b95..ae1f27a4 100644 --- a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiStaffRecruitmentImportServiceImpl.java +++ b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiStaffRecruitmentImportServiceImpl.java @@ -178,7 +178,7 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm try { CcdiStaffRecruitmentAddDTO addDTO = new CcdiStaffRecruitmentAddDTO(); BeanUtils.copyProperties(excel, addDTO); - addDTO.setRecruitType(RecruitType.inferCode(addDTO.getRecruitName())); + addDTO.setRecruitType(normalizeRecruitType(excel.getRecruitType())); validateRecruitmentData(addDTO, mainRow.sheetRowNum()); @@ -376,22 +376,22 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "职位描述不能为空"); } if (StringUtils.isEmpty(addDTO.getCandName())) { - throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员姓名不能为空"); + throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "候选人姓名不能为空"); } if (StringUtils.isEmpty(addDTO.getCandEdu())) { - throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员学历不能为空"); + throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "学历不能为空"); } if (StringUtils.isEmpty(addDTO.getCandId())) { throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "证件号码不能为空"); } if (StringUtils.isEmpty(addDTO.getCandSchool())) { - throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员毕业院校不能为空"); + throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "毕业院校不能为空"); } if (StringUtils.isEmpty(addDTO.getCandMajor())) { - throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员专业不能为空"); + throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "专业不能为空"); } if (StringUtils.isEmpty(addDTO.getCandGrad())) { - throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员毕业年月不能为空"); + throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "毕业年月不能为空"); } if (StringUtils.isEmpty(addDTO.getAdmitStatus())) { throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "录用情况不能为空"); @@ -414,10 +414,23 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm } if (RecruitType.getDescByCode(addDTO.getRecruitType()) == null) { - throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "招聘类型只能填写'SOCIAL'或'CAMPUS'"); + throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "招聘类型只能填写'SOCIAL/社招'或'CAMPUS/校招'"); } } + private String normalizeRecruitType(String recruitType) { + String value = trim(recruitType); + if (StringUtils.isEmpty(value)) { + return value; + } + for (RecruitType type : RecruitType.values()) { + if (type.getCode().equals(value) || type.getDesc().equals(value)) { + return type.getCode(); + } + } + return value; + } + private void validateWorkGroup(List workRows, CcdiStaffRecruitment recruitment) { Set processedSortOrders = new HashSet<>(); for (WorkImportRow workRow : workRows) { @@ -451,14 +464,14 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "工作单位不能为空"); } if (StringUtils.isEmpty(trim(excel.getPositionName()))) { - throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "岗位不能为空"); + throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "岗位名称不能为空"); } if (StringUtils.isEmpty(trim(excel.getJobStartMonth()))) { - throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "入职年月不能为空"); + throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "入职时间不能为空"); } - validateMonth(excel.getJobStartMonth(), "入职年月", sheetRowNum); + validateMonth(excel.getJobStartMonth(), "入职时间", sheetRowNum); if (StringUtils.isNotEmpty(trim(excel.getJobEndMonth()))) { - validateMonth(excel.getJobEndMonth(), "离职年月", sheetRowNum); + validateMonth(excel.getJobEndMonth(), "离职时间", sheetRowNum); } if (recruitment == null) { throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "招聘记录编号不存在,请先维护招聘主信息"); diff --git a/ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiCustFmyRelationMapper.xml b/ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiCustFmyRelationMapper.xml index 850c8b2b..34ad2f67 100644 --- a/ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiCustFmyRelationMapper.xml +++ b/ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiCustFmyRelationMapper.xml @@ -53,6 +53,9 @@ AND r.relation_name LIKE CONCAT('%', #{query.relationName}, '%') + + AND r.relation_cert_no LIKE CONCAT('%', #{query.relationCertNo}, '%') + ORDER BY r.create_time DESC diff --git a/ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiStaffFmyRelationMapper.xml b/ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiStaffFmyRelationMapper.xml index fff7799e..5a305806 100644 --- a/ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiStaffFmyRelationMapper.xml +++ b/ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiStaffFmyRelationMapper.xml @@ -61,6 +61,9 @@ AND r.relation_name LIKE CONCAT('%', #{query.relationName}, '%') + + AND r.relation_cert_no LIKE CONCAT('%', #{query.relationCertNo}, '%') + AND r.status = #{query.status} @@ -115,6 +118,9 @@ AND r.relation_name LIKE CONCAT('%', #{query.relationName}, '%') + + AND r.relation_cert_no LIKE CONCAT('%', #{query.relationCertNo}, '%') + AND r.status = #{query.status} diff --git a/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiAssetInfoImportServiceImplTest.java b/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiAssetInfoImportServiceImplTest.java index fb2b27c0..ded87844 100644 --- a/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiAssetInfoImportServiceImplTest.java +++ b/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiAssetInfoImportServiceImplTest.java @@ -96,6 +96,26 @@ class CcdiAssetInfoImportServiceImplTest { assertEquals("320101199001010011", captor.getValue().get(0).getPersonId()); } + @Test + void importAssetInfoSync_shouldResolveFamilyIdFromCurrentWorkbookRelation() { + CcdiAssetInfoExcel excel = buildExcel("320101199001010033", "股权"); + when(redisTemplate.opsForHash()).thenReturn(hashOperations); + when(assetInfoMapper.selectOwnerCandidatesByRelationCertNos(List.of("320101199001010033"))) + .thenReturn(List.of()); + + service.importAssetInfoSync( + List.of(excel), + "task-current-workbook", + "tester", + Map.of("320101199001010033", Set.of("320101199009090099")) + ); + + ArgumentCaptor> captor = ArgumentCaptor.forClass(List.class); + verify(assetInfoMapper).insertBatch(captor.capture()); + assertEquals("320101199009090099", captor.getValue().get(0).getFamilyId()); + assertEquals("320101199001010033", captor.getValue().get(0).getPersonId()); + } + @Test void importAssetInfoAsync_shouldFailWhenEmployeeIdCardIsUsedForFamilyAssetImport() { CcdiAssetInfoExcel excel = buildExcel("320101199001010011", "房产"); diff --git a/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiBaseStaffAssetImportServiceImplTest.java b/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiBaseStaffAssetImportServiceImplTest.java index 593d757a..9e12d4bd 100644 --- a/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiBaseStaffAssetImportServiceImplTest.java +++ b/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiBaseStaffAssetImportServiceImplTest.java @@ -19,6 +19,7 @@ import org.springframework.data.redis.core.ValueOperations; import java.math.BigDecimal; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -79,6 +80,26 @@ class CcdiBaseStaffAssetImportServiceImplTest { assertEquals("320101199001010011", captor.getValue().get(0).getPersonId()); } + @Test + void importAssetInfoSync_shouldImportWhenOwnerComesFromCurrentWorkbook() { + CcdiBaseStaffAssetInfoExcel excel = buildExcel("320101199001010033", "存款"); + when(redisTemplate.opsForHash()).thenReturn(hashOperations); + when(assetInfoMapper.selectOwnerCandidatesByBaseStaffIdCards(List.of("320101199001010033"))) + .thenReturn(List.of()); + + service.importAssetInfoSync( + List.of(excel), + "task-current-workbook", + "tester", + Map.of("320101199001010033", Set.of("320101199001010033")) + ); + + ArgumentCaptor> captor = ArgumentCaptor.forClass(List.class); + verify(assetInfoMapper).insertBatch(captor.capture()); + assertEquals("320101199001010033", captor.getValue().get(0).getFamilyId()); + assertEquals("320101199001010033", captor.getValue().get(0).getPersonId()); + } + @Test void importAssetInfoAsync_shouldFailWhenFamilyCertificateIsUsed() { CcdiBaseStaffAssetInfoExcel excel = buildExcel("320101199201010022", "车辆"); diff --git a/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiStaffEnterpriseRelationServiceImplTest.java b/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiStaffEnterpriseRelationServiceImplTest.java index 0876ac80..553cf13f 100644 --- a/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiStaffEnterpriseRelationServiceImplTest.java +++ b/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiStaffEnterpriseRelationServiceImplTest.java @@ -2,6 +2,8 @@ package com.ruoyi.info.collection.service; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.info.collection.domain.CcdiStaffEnterpriseRelation; import com.ruoyi.info.collection.domain.CcdiStaffFmyRelation; import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationAddDTO; @@ -10,8 +12,10 @@ import com.ruoyi.info.collection.domain.vo.CcdiStaffEnterpriseRelationOptionVO; import com.ruoyi.info.collection.mapper.CcdiStaffEnterpriseRelationMapper; import com.ruoyi.info.collection.mapper.CcdiStaffFmyRelationMapper; import com.ruoyi.info.collection.service.impl.CcdiStaffEnterpriseRelationServiceImpl; +import com.ruoyi.info.collection.service.support.EnterpriseAutoFillService; import org.apache.ibatis.builder.MapperBuilderAssistant; import org.apache.ibatis.session.Configuration; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -20,13 +24,17 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; import java.util.List; +import java.util.Set; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -55,8 +63,17 @@ class CcdiStaffEnterpriseRelationServiceImplTest { @Mock private RedisTemplate redisTemplate; + @Mock + private EnterpriseAutoFillService enterpriseAutoFillService; + + @AfterEach + void clearSecurityContext() { + SecurityContextHolder.clearContext(); + } + @Test void insertRelation_shouldAllowValidFamily() { + mockLoginUser("tester"); CcdiStaffEnterpriseRelationAddDTO addDTO = buildAddDto(); CcdiStaffFmyRelation familyRelation = new CcdiStaffFmyRelation(); familyRelation.setRelationCertNo(addDTO.getPersonId()); @@ -75,6 +92,13 @@ class CcdiStaffEnterpriseRelationServiceImplTest { assertEquals(1, captor.getValue().getStatus()); assertEquals("MANUAL", captor.getValue().getDataSource()); assertEquals(1, captor.getValue().getIsEmpFamily()); + verify(enterpriseAutoFillService).ensureExists(argThat(item -> + "91310000123456789A".equals(item.socialCreditCode()) + && "测试企业".equals(item.enterpriseName()) + && "EMP_RELATION".equals(item.entSource()) + && "MANUAL".equals(item.dataSource()) + && "tester".equals(item.userName()) + )); } @Test @@ -153,4 +177,13 @@ class CcdiStaffEnterpriseRelationServiceImplTest { assistant.setCurrentNamespace(namespace); TableInfoHelper.initTableInfo(assistant, entityClass); } + + private void mockLoginUser(String userName) { + SysUser user = new SysUser(); + user.setUserName(userName); + LoginUser loginUser = new LoginUser(1L, 1L, user, Set.of()); + UsernamePasswordAuthenticationToken authentication = + new UsernamePasswordAuthenticationToken(loginUser, null, List.of()); + SecurityContextHolder.getContext().setAuthentication(authentication); + } } diff --git a/docs/reports/implementation/2026-05-06-family-relation-cert-no-list-query.md b/docs/reports/implementation/2026-05-06-family-relation-cert-no-list-query.md new file mode 100644 index 00000000..22ab6a2d --- /dev/null +++ b/docs/reports/implementation/2026-05-06-family-relation-cert-no-list-query.md @@ -0,0 +1,29 @@ +# 员工亲属关系与信贷客户家庭关系关系人身份证号展示实施记录 + +## 修改内容 + +- 在【员工亲属关系维护】列表新增“关系人身份证号”列,展示接口返回的 `relationCertNo`。 +- 在【信贷客户家庭关系】列表新增“关系人身份证号”列,展示接口返回的 `relationCertNo`。 +- 两个页面查询区新增“关系人身份证号”筛选项,支持按关系人身份证号模糊查询。 +- 后端查询 DTO 与 MyBatis 分页 SQL 补充 `relationCertNo` 查询条件,保持页面查询条件与接口过滤逻辑一致。 + +## 影响范围 + +- 前端页面: + - `ruoyi-ui/src/views/ccdiStaffFmyRelation/index.vue` + - `ruoyi-ui/src/views/ccdiCustFmyRelation/index.vue` +- 后端查询: + - `CcdiStaffFmyRelationQueryDTO` + - `CcdiCustFmyRelationQueryDTO` + - `CcdiStaffFmyRelationMapper.xml` + - `CcdiCustFmyRelationMapper.xml` + +## 验证情况 + +- 已确认两个分页接口原 SQL 与 VO 均包含 `relation_cert_no` / `relationCertNo` 字段。 +- 已执行 `mvn -pl ccdi-info-collection -am compile -DskipTests`,编译通过。 +- 已按 `ruoyi-ui/.nvmrc` 使用 Node `14.21.3` 执行 `npm run build:prod`,构建通过,仅存在既有资源体积告警。 +- 已通过 `browser-use` 打开真实前端页面验证: + - `/maintain/staffFmyRelation` 展示“关系人身份证号”筛选项与表格列,并可按 `330101196501010011` 查询到对应员工亲属关系记录。 + - `/maintain/custFmyRelation` 展示“关系人身份证号”筛选项与表格列,并可按 `330101197806060077` 查询到对应信贷客户家庭关系记录。 +- 浏览器控制台未发现错误日志。 diff --git a/docs/reports/implementation/2026-05-06-recruitment-intermediary-import-template-fix.md b/docs/reports/implementation/2026-05-06-recruitment-intermediary-import-template-fix.md new file mode 100644 index 00000000..955f9028 --- /dev/null +++ b/docs/reports/implementation/2026-05-06-recruitment-intermediary-import-template-fix.md @@ -0,0 +1,67 @@ +# 招聘信息与中介实体关系导入模板修复实施记录 + +## 背景 + +- 【招聘信息维护】当前页面与数据库口径已调整为“招聘记录编号”,原导入模板仍存在旧字段名称和字段顺序不一致问题,导致按模板导入失败。 +- 【中介库管理】“导入中介实体关联关系”按钮对应模板字段与新增关联机构弹窗不一致,且导入提示仍要求统一社会信用代码必须已存在于机构表。 + +## 修改内容 + +### 招聘信息维护 + +- 更新招聘主 Sheet 模板字段顺序,使其与新增页字段顺序一致: + - 招聘记录编号、招聘项目名称、职位名称、职位类别、职位描述、录用情况、候选人姓名、招聘类型、学历、证件号码、毕业年月、毕业院校、专业、面试官1姓名、面试官1工号、面试官2姓名、面试官2工号。 +- 更新历史工作经历 Sheet 字段文案: + - 岗位名称、入职时间、离职时间、主要工作内容。 +- 导入逻辑不再从招聘项目名称推断招聘类型,改为读取模板中的“招聘类型”字段。 +- 招聘类型支持填写编码或页面文案: + - `SOCIAL` / `社招` + - `CAMPUS` / `校招` +- 同步调整导入校验提示,使错误信息与当前页面字段保持一致。 +- 前端导入弹窗增加招聘类型填写说明。 + +### 中介库管理 + +- 更新“导入中介实体关联关系”模板字段: + - 中介本人证件号码、统一社会信用代码、关联职务、备注。 +- 将必填标识改为 `@Required`,避免字段标题携带 `*` 后与页面字段不一致。 +- 导入逻辑统一 trim 证件号、统一社会信用代码、关联职务、备注,避免空格导致查询不到中介本人或重复判断失效。 +- 失败记录字段文案由“关联人职务”统一为“关联职务”。 +- 前端导入说明调整为: + - 中介本人证件号码用于定位新增弹窗中的所属中介; + - 其余字段与新增关联机构弹窗一致; + - 统一社会信用代码未存在于实体库时会自动补入。 + +## 影响范围 + +- 后端导入模板与导入解析: + - `CcdiStaffRecruitmentExcel` + - `CcdiStaffRecruitmentWorkExcel` + - `CcdiStaffRecruitmentImportServiceImpl` + - `CcdiIntermediaryEnterpriseRelationExcel` + - `CcdiIntermediaryEnterpriseRelationImportServiceImpl` + - `IntermediaryEnterpriseRelationImportFailureVO` +- 前端导入弹窗与失败记录展示: + - 招聘信息维护导入提示 + - 中介库管理导入中介实体关联关系提示 + - 中介实体关系导入失败记录字段标签 + +## 验证情况 + +- 后端编译:`mvn -pl ccdi-info-collection -am compile -DskipTests` 通过。 +- 前端构建:`ruoyi-ui` 下执行 `nvm use` 后,`npm run build:prod` 通过。 +- 真实模板下载: + - `/ccdi/staffRecruitment/importTemplate` 下载模板成功,表头已变为当前字段顺序。 + - `/ccdi/intermediary/importEnterpriseRelationTemplate` 下载模板成功,表头已变为“中介本人证件号码、统一社会信用代码、关联职务、备注”。 +- 真实接口导入: + - 招聘信息基于下载模板造数,主 Sheet 与历史工作经历 Sheet 共 2 行导入成功,详情接口回查历史工作经历 1 条。 + - 中介实体关联关系基于下载模板造数,导入成功 1 条,列表可回查关联职务。 +- 清理情况: + - 已删除本轮成功导入的招聘记录及历史工作经历。 + - 已删除本轮成功导入的中介实体关联关系。 + - 已删除本轮由导入自动补入的实体库测试数据。 +- 真实页面检查: + - 使用 `browser-use` 打开真实页面 `/maintain/staffRecruitment`,确认招聘信息导入弹窗显示新的双 Sheet 和招聘类型说明。 + - 使用 `browser-use` 打开真实页面 `/maintain/intermediary`,确认“导入中介实体关联关系”按钮可打开导入弹窗,字段说明与新增关联机构口径一致。 + - `browser-use` 当前不支持文件上传,页面文件选择动作无法在浏览器插件内完成;文件上传动作已通过同一真实导入接口完成验证。 +- 测试完成后已停止本轮启动的后端与前端进程。 diff --git a/docs/reports/implementation/2026-05-06-staff-asset-import-and-enterprise-autofill-backend-implementation.md b/docs/reports/implementation/2026-05-06-staff-asset-import-and-enterprise-autofill-backend-implementation.md index b763f6de..3c2e4ee0 100644 --- a/docs/reports/implementation/2026-05-06-staff-asset-import-and-enterprise-autofill-backend-implementation.md +++ b/docs/reports/implementation/2026-05-06-staff-asset-import-and-enterprise-autofill-backend-implementation.md @@ -24,6 +24,13 @@ - 招投标供应商新增、编辑和导入时,对合法统一社会信用代码的供应商自动补入实体库。 - 新增企业来源枚举 `SUPPLIER`,用于标识供应商来源。 +### 测试补充 + +- 同步调整员工信息维护、员工亲属关系维护导入 Controller 单测,按新的统一编排入口断言返回任务 ID。 +- 补充员工资产导入单测,验证同一模板中本轮成功导入的员工身份证号可作为员工资产归属。 +- 补充亲属资产导入单测,验证同一模板中本轮成功导入的亲属关系可作为亲属资产归属。 +- 补充员工亲属实体关联新增单测,验证成功新增时调用实体库自动补入服务,来源为 `EMP_RELATION`、数据来源为 `MANUAL`。 + ## 影响范围 - `/ccdi/baseStaff/importData` @@ -36,6 +43,16 @@ - 执行 `mvn -pl ccdi-info-collection -am -DskipTests compile`,结果:BUILD SUCCESS。 - 执行 `mvn -DskipTests compile`,结果:BUILD SUCCESS。 - 代码路径核对:员工主 Sheet 为空时仅调用员工资产导入服务并返回 `assetTaskId`;亲属关系主 Sheet 为空时仅调用亲属资产导入服务并返回 `assetTaskId`。 +- 复测执行 `mvn -pl ccdi-info-collection -am -Dtest=CcdiBaseStaffControllerTest,CcdiStaffFmyRelationControllerTest,CcdiBaseStaffAssetImportServiceImplTest,CcdiAssetInfoImportServiceImplTest,CcdiBaseStaffDualImportServiceTest,CcdiStaffFmyRelationImportServiceImplTest,CcdiStaffEnterpriseRelationServiceImplTest,CcdiStaffEnterpriseRelationImportServiceImplTest -Dsurefire.failIfNoSpecifiedTests=false test`,结果:BUILD SUCCESS,Tests run: 39, Failures: 0, Errors: 0, Skipped: 0。 +- 复测执行 `mvn -pl ccdi-info-collection -am -Dsurefire.failIfNoSpecifiedTests=false test`,结果:BUILD FAILURE;本次问题相关用例均已通过,剩余失败为中介实体关联测试未注入自动补入服务,以及 `CcdiPurchaseTransactionFeatureContractTest` 依赖的 `sql/ccdi_purchase_transaction.sql` 文件不存在。 +- 使用 `bin/restart_java_backend.sh` 重启后端并通过 `/login/test` 探活,结果:HTTP 200。 +- 通过真实接口下载当前导入模板,基于模板生成测试文件,执行 `/ccdi/baseStaff/importData`:员工任务 `8ea63988-deb2-4791-a24a-f15ca2c8cd6e` 与员工资产任务 `f281beca-bb58-4076-86db-6f9f948bbaf0` 均为 `SUCCESS`,成功 1 条、失败 0 条。 +- 回查 `ccdi_base_staff` 与 `ccdi_asset_info`:员工主数据写入成功;员工资产 `family_id` 与 `person_id` 均为本轮员工身份证号,第二个 Sheet 未再出现“未找到资产归属员工”。 +- 执行 `/ccdi/staffFmyRelation/importData`:亲属关系任务 `702466a9-0113-4e89-bcf1-8d760ee34543` 与亲属资产任务 `f11906d4-b9f3-4656-834c-fc9dc1a27704` 均为 `SUCCESS`,成功 1 条、失败 0 条。 +- 回查 `ccdi_staff_fmy_relation` 与 `ccdi_asset_info`:亲属关系主数据写入成功;亲属资产 `family_id` 为员工身份证号、`person_id` 为亲属身份证号,第二个 Sheet 已正确关联到本轮亲属主数据。 +- 执行 `/ccdi/staffEnterpriseRelation/importData`:员工亲属实体关联任务 `6361fc94-0d32-4da0-b1a0-7419b399710d` 为 `SUCCESS`,成功 1 条、失败 0 条。 +- 回查 `ccdi_staff_enterprise_relation` 与 `ccdi_enterprise_base_info`:实体关联写入成功;实体库自动生成对应企业,`ent_source=EMP_RELATION`、`data_source=IMPORT`。 +- 验证结束后执行清理 SQL,回查本轮员工、亲属、资产、亲属实体关联和实体库测试数据计数均为 0。 ## 备注 diff --git a/ruoyi-ui/src/views/ccdiCustFmyRelation/index.vue b/ruoyi-ui/src/views/ccdiCustFmyRelation/index.vue index 474c3614..c031857c 100644 --- a/ruoyi-ui/src/views/ccdiCustFmyRelation/index.vue +++ b/ruoyi-ui/src/views/ccdiCustFmyRelation/index.vue @@ -36,6 +36,17 @@ /> + + + + + @@ -100,6 +111,7 @@ + +