From 73d01a0a28372631f00a88796f56fc726a72fe45 Mon Sep 17 00:00:00 2001
From: luotaiqian <1147642922@qq.com>
Date: Wed, 19 Aug 2026 09:02:19 +0800
Subject: [PATCH] appendCapabilityAssessment
---
.../support/OrgPersonnelExcelImporter.java | 160 ++++++++++++------
.../app/support/OrgPersonnelImportRow.java | 8 +
.../constant/basic/SafetyCategoryEnum.java | 3 +
3 files changed, 117 insertions(+), 54 deletions(-)
diff --git a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelExcelImporter.java b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelExcelImporter.java
index e0997155..840baa59 100644
--- a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelExcelImporter.java
+++ b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelExcelImporter.java
@@ -12,6 +12,7 @@ import com.zcloud.gbscommon.utils.MD5;
import com.zcloud.gbscommon.utils.Sm2Util;
import org.qinan.safetyeval.client.co.OrgPersonnelImportErrorCO;
import org.qinan.safetyeval.client.co.OrgPersonnelImportResultCO;
+import org.qinan.safetyeval.domain.constant.CertTypeCodeEnum;
import org.qinan.safetyeval.domain.constant.QualificationLevelEnum;
import org.qinan.safetyeval.domain.constant.basic.IndustryEnum;
import org.qinan.safetyeval.domain.constant.basic.ProfessionalCapabilityEnum;
@@ -27,7 +28,9 @@ import org.qinan.safetyeval.domain.major.gateway.BasicDisciplineMajorGateway;
import org.qinan.safetyeval.domain.major.model.BasicDisciplineMajorE;
import org.qinan.safetyeval.domain.service.OrgPersonnelDomainService;
import org.qinan.safetyeval.infrastructure.adapter.ThreadLocalUserInfoAdapter;
+import org.qinan.safetyeval.infrastructure.convertor.BasicDisciplineMajorDoConvertor;
import org.qinan.safetyeval.infrastructure.remote.SystemRemote;
+import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
@@ -73,6 +76,9 @@ public class OrgPersonnelExcelImporter {
@Resource
private BasicDisciplineMajorGateway basicDisciplineMajorGateway;
+ @Resource
+ private BasicDisciplineMajorDoConvertor basicDisciplineMajorDoConvertor;
+
@Resource
private OrgPersonnelDomainService orgPersonnelDomainService;
@@ -124,7 +130,7 @@ public class OrgPersonnelExcelImporter {
return result;
}
- // 3. 批量校验并回填所学专业ID
+ // 3. 批量校验所学专业、系列/专业(两个字段名称合并为一次 in 查询基础学科专业对照表)
validateAndFillMajor(rows, errors);
rows = rows.stream().filter(it -> !it.isValidateFail()).collect(Collectors.toList());
if (rows.isEmpty()) {
@@ -136,9 +142,32 @@ public class OrgPersonnelExcelImporter {
Set existingAccounts = batchQueryExistingAccounts(rows, orgId);
// 5. 逐行转换、落库
+ int successCount = saveRows(rows, orgId, existingAccounts, errors);
+
+ result.setSuccessCount(successCount);
+ result.setErrors(errors);
+ return result;
+ }
+
+ /**
+ * 逐行转换、落库:
+ *
+ * - 账号在库中已存在 -> 跳过该行并记录异常;
+ * - 行内枚举/数据校验未通过(buildOrgPersonnel 返回 null)-> 跳过该行,异常已记录;
+ * - 校验通过 -> 添加底座用户并追加角色,随后保存人员信息;
+ * - 保存抛出异常 -> 记录异常并继续处理后续行。
+ *
+ *
+ * @param rows 待导入的行(前置批量校验均已通过)
+ * @param orgId 机构ID
+ * @param existingAccounts 库中已存在的账号集合
+ * @param errors 异常收集列表
+ * @return 成功落库的行数
+ */
+ private int saveRows(List rows, Long orgId, Set existingAccounts
+ , List errors) {
+
int successCount = 0;
-
-
for (OrgPersonnelImportRow row : rows) {
String account = trim(row.getBasic().getAccount());
@@ -168,9 +197,7 @@ public class OrgPersonnelExcelImporter {
}
}
- result.setSuccessCount(successCount);
- result.setErrors(errors);
- return result;
+ return successCount;
}
/**
@@ -259,9 +286,9 @@ public class OrgPersonnelExcelImporter {
OrgPersonnelImportRow row = new OrgPersonnelImportRow();
basic.setRowIndex(i + 2);
row.setBasic(basic);
- Pair capabilityRow = matchCapability(basic, capabilityMap, errors);
+ boolean validate = matchCapability(basic, capabilityMap, errors);
// 能力信息未匹配或存在多条,已记录异常,剔除该行
- if (!capabilityRow.getKey()) {
+ if (!validate) {
continue;
}
@@ -312,26 +339,24 @@ public class OrgPersonnelExcelImporter {
* 任一不通过记录异常并返回 null。
*
*/
- private Pair matchCapability(OrgPersonnelImportRow.BasicRow basic
+ private Boolean matchCapability(OrgPersonnelImportRow.BasicRow basic
, Map> capabilityMap, List errors) {
List capabilityList = capabilityMap.get(trim(basic.getIdCardNo()));
if (CollectionUtils.isEmpty(capabilityList)) {
- return Pair.of(true, null);
+ return true;
}
if (capabilityList.size() > 1) {
errors.add(new OrgPersonnelImportErrorCO(basic.getRowIndex(), trim(basic.getAccount()), trim(basic.getUserName()),
"专职人员能力信息中查询到多条数据"));
- return Pair.of(false, null);
+ return false;
}
OrgPersonnelImportRow.CapabilityRow capabilityRow = capabilityList.get(0);
-
// 校验基础信息
// 2. sheet2 能力信息校验(未匹配到能力信息时跳过),行号取 sheet2 行号,消息加前缀便于区分来源
- Set> capabilityViolations =
- validator.validate(capabilityRow);
+ Set> capabilityViolations = validator.validate(capabilityRow);
if (!capabilityViolations.isEmpty()) {
capabilityViolations.stream()
.collect(Collectors.toMap(
@@ -341,35 +366,35 @@ public class OrgPersonnelExcelImporter {
.values()
.forEach(v -> errors.add(new OrgPersonnelImportErrorCO(capabilityRow.getRowIndex(),
capabilityRow.getUserName(), capabilityRow.getIdCardNo(), "能力信息:" + v.getMessage())));
- return Pair.of(false, null);
+ return false;
}
// 能力认证一/二:认证行业、专业能力、来源 有值时校验枚举并回填,不通过记录异常
if (!validateAndFillCertEnums(basic, capabilityRow, errors)) {
- return Pair.of(false, null);
+ return false;
}
// 是否注册安全工程师:为[是]时 注安专业类别/注安等级/证书编号/执业证书编号 必填并校验枚举,通过后写入证书实体
if (!validateAndFillRegisterEngineerCert(basic, capabilityRow, errors)) {
- return Pair.of(false, null);
+ return false;
}
// 是否评价师:为[是]时 评价师等级/证书编号 必填并校验枚举,通过后写入证书实体
if (!validateAndFillEvaluatorCert(basic, capabilityRow, errors)) {
- return Pair.of(false, null);
+ return false;
}
// 职称:有值时校验枚举并回填,查询不到记录异常
if (!validateAndFillTitle(basic, capabilityRow, errors)) {
- return Pair.of(false, null);
+ return false;
}
-
+ // 学历类型、毕业院校、学历层次、所学专业 回填到基础信息行(@ExcelIgnore 字段,Excel原始值忽略)
basic.setEducationType(capabilityRow.getEducationType());
basic.setGraduateSchool(capabilityRow.getGraduateSchool());
basic.setEducationLevel(capabilityRow.getEducationLevel());
basic.setMajor(capabilityRow.getMajor());
- return Pair.of(true, capabilityRow);
+ return true;
}
/**
@@ -391,12 +416,6 @@ public class OrgPersonnelExcelImporter {
String userName = trim(basic.getUserName());
Integer rowIndex = capability.getRowIndex();
- // 学历类型、毕业院校、学历层次、所学专业 回填到基础信息行(@ExcelIgnore 字段,Excel原始值忽略)
- basic.setEducationType(trim(capability.getEducationType()));
- basic.setGraduateSchool(trim(capability.getGraduateSchool()));
- basic.setEducationLevel(trim(capability.getEducationLevel()));
- basic.setMajor(trim(capability.getMajor()));
-
// 能力认证一(必填):认证行业、专业能力、来源,查询不到枚举即记录异常并返回
String cert1Industry = trim(capability.getCert1Industry());
IndustryEnum cert1IndustryEnum = IndustryEnum.ofName(cert1Industry);
@@ -462,8 +481,6 @@ public class OrgPersonnelExcelImporter {
}
appendCapabilityAssessment(basic, cert2IndustryEnum, cert2AbilityEnum, cert2SourceEnum);
}
-
-
return true;
}
@@ -541,7 +558,7 @@ public class OrgPersonnelExcelImporter {
// 校验通过 -> 组装注安证书实体写入基础信息行
basic.getPersonnelCertEntities().add(
- buildRegisterEngineerCert(categoryEnum, levelEnum, certNo, practiceCertNo));
+ buildRegisterEngineerCert(categoryEnum, levelEnum, certNo, practiceCertNo, basic));
return true;
}
@@ -550,16 +567,16 @@ public class OrgPersonnelExcelImporter {
* 注安专业类别/注安等级 枚举均已校验通过,直接取编码与名称回填。
*/
private OrgPersonnelCertEntity buildRegisterEngineerCert(SafetyCategoryEnum categoryEnum
- , QualificationLevelEnum levelEnum, String certNo, String practiceCertNo) {
+ , QualificationLevelEnum levelEnum, String certNo, String practiceCertNo, OrgPersonnelImportRow.BasicRow basic) {
OrgPersonnelCertEntity cert = new OrgPersonnelCertEntity();
- cert.setCertName("注册安全工程师");
// 注安专业类别
- cert.setCertCategoryCode(categoryEnum.getValue());
- cert.setCertCategoryName(categoryEnum.getLabel());
+ cert.setCertTypeCode(CertTypeCodeEnum.REGISTERED_SAFETY_ENGINEER.getCode());
// 注安等级(编码同证书等级:SENIOR/MIDDLE/JUNIOR)
cert.setCertLevel(levelEnum.getCode());
+ cert.setCertCategoryCode(categoryEnum.getIndustry().getCode());
cert.setCertNo(certNo);
cert.setPractisingCertCode(practiceCertNo);
+ InsertFieldDefaults.applyIgnoreOrgId(cert);
return cert;
}
@@ -614,10 +631,12 @@ public class OrgPersonnelExcelImporter {
*/
private OrgPersonnelCertEntity buildEvaluatorCert(QualificationLevelEnum levelEnum, String certNo) {
OrgPersonnelCertEntity cert = new OrgPersonnelCertEntity();
- cert.setCertName("安全评价师");
- // 评价师等级(编码同证书等级:SENIOR/MIDDLE/JUNIOR)
+ // 注安专业类别
+ cert.setCertTypeCode(CertTypeCodeEnum.REGISTERED_SAFETY_ENGINEER.getCode());
+ // 注安等级(编码同证书等级:SENIOR/MIDDLE/JUNIOR)
cert.setCertLevel(levelEnum.getCode());
cert.setCertNo(certNo);
+ InsertFieldDefaults.applyIgnoreOrgId(cert);
return cert;
}
@@ -936,16 +955,33 @@ public class OrgPersonnelExcelImporter {
}
/**
- * 批量校验所学专业名称在基础学科专业对照表中是否存在(basic_discipline_major.professional_name),
- * 校验通过的同时回填 basicDisciplineMajorId;不存在的行记录异常并标记 validateFail。
- * 专业名称为空的行不参与校验(该字段可空)。
+ * 批量校验 所学专业(major)与 系列/专业(seriesMajor)名称在基础学科专业对照表中是否存在
+ * (basic_discipline_major.professional_name),两个字段名称合并为一次 in 查询;
+ * 有值但查询不到的记录异常并标记 validateFail,为空的字段不参与校验(字段可空)。
+ *
+ * 校验通过后回填:所学专业 -> basicDisciplineMajorId 与 {@link OrgPersonnelImportRow.CapabilityRow#setBdmMajor};
+ * 系列/专业 -> {@link OrgPersonnelImportRow.CapabilityRow#setBdmSeriesMajor}。
+ *
*/
private void validateAndFillMajor(List rows, List errors) {
- Set majorNames = rows.stream()
- .map(r -> r.getCapability() == null ? null : trim(r.getCapability().getMajor()))
- .filter(StringUtils::hasText)
- .collect(Collectors.toCollection(LinkedHashSet::new));
+ // 所学专业、系列/专业 两个字段名称合并收集,一次 in 查询
+ Set majorNames = new LinkedHashSet<>();
+ for (OrgPersonnelImportRow row : rows) {
+ OrgPersonnelImportRow.CapabilityRow capability = row.getCapability();
+ if (capability == null) {
+ continue;
+ }
+ String majorName = trim(capability.getMajor());
+ if (StringUtils.hasText(majorName)) {
+ majorNames.add(majorName);
+ }
+ String seriesMajorName = trim(capability.getSeriesMajor());
+ if (StringUtils.hasText(seriesMajorName)) {
+ majorNames.add(seriesMajorName);
+ }
+ }
+ // SELECT id,industry_code,professional_capability_code,professional_name FROM basic_discipline_major WHERE professional_name in (...)
Map majorMap = new HashMap<>();
if (!majorNames.isEmpty()) {
for (BasicDisciplineMajorE major : basicDisciplineMajorGateway.listByProfessionalNames(majorNames)) {
@@ -955,20 +991,36 @@ public class OrgPersonnelExcelImporter {
}
}
- // 逐行校验:专业名称为空的行跳过;对照表中不存在的行记录异常并标记;校验通过则回填专业ID
+ // 逐行校验:字段为空跳过;对照表中不存在的记录异常并标记;校验通过则回填
for (OrgPersonnelImportRow row : rows) {
- String name = row.getCapability() == null ? null : trim(row.getCapability().getMajor());
- if (!StringUtils.hasText(name)) {
- continue;
+ OrgPersonnelImportRow.CapabilityRow capability = row.getCapability();
+
+ // 所学专业:查询不到记录异常;查询到回填 basicDisciplineMajorId、bdmMajor
+ String majorName = trim(capability.getMajor());
+ if (StringUtils.hasText(majorName)) {
+ BasicDisciplineMajorE major = majorMap.get(majorName);
+ if (major == null) {
+ errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), row.getBasic().getAccount(), row.getBasic().getUserName(),
+ ErrorCode.ORG_PERSONNEL_IMPORT_MAJOR_NOT_FOUND.getMessage() + ":" + majorName));
+ row.setValidateFail(true);
+ } else {
+ row.setBasicDisciplineMajorId(major.getId());
+ capability.setBdmMajor(basicDisciplineMajorDoConvertor.convertEeToDo(major));
+ }
}
- BasicDisciplineMajorE major = majorMap.get(name);
- if (major == null) {
- errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), row.getBasic().getAccount(), row.getBasic().getUserName(),
- ErrorCode.ORG_PERSONNEL_IMPORT_MAJOR_NOT_FOUND.getMessage() + ":" + name));
- row.setValidateFail(true);
- continue;
+
+ // 系列/专业:查询不到记录异常;查询到回填 bdmSeriesMajor
+ String seriesMajorName = trim(capability.getSeriesMajor());
+ if (StringUtils.hasText(seriesMajorName)) {
+ BasicDisciplineMajorE seriesMajor = majorMap.get(seriesMajorName);
+ if (seriesMajor == null) {
+ errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), row.getBasic().getAccount(), row.getBasic().getUserName(),
+ ErrorCode.ORG_PERSONNEL_IMPORT_MAJOR_NOT_FOUND.getMessage() + ":" + seriesMajorName));
+ row.setValidateFail(true);
+ } else {
+ capability.setBdmSeriesMajor(basicDisciplineMajorDoConvertor.convertEeToDo(seriesMajor));
+ }
}
- row.setBasicDisciplineMajorId(major.getId());
}
}
diff --git a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelImportRow.java b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelImportRow.java
index 61101e78..1366a99c 100644
--- a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelImportRow.java
+++ b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelImportRow.java
@@ -5,9 +5,11 @@ import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
+import org.qinan.safetyeval.client.major.request.BasicDisciplineMajorAddCmd;
import org.qinan.safetyeval.domain.entity.CapabilityAssessmentDTO;
import org.qinan.safetyeval.domain.entity.OrgPersonnelCertEntity;
import org.qinan.safetyeval.domain.entity.TitleCodeCo;
+import org.qinan.safetyeval.infrastructure.persistence.domainobject.BasicDisciplineMajorDO;
import org.springframework.util.StringUtils;
import javax.validation.constraints.NotBlank;
@@ -270,6 +272,9 @@ public class OrgPersonnelImportRow {
@NotBlank(message = "所学专业不能为空")
private String major;
+ @ExcelIgnore
+ private BasicDisciplineMajorDO bdmMajor;
+
@ExcelProperty(value = "是否注册安全工程师", index = 12)
@Pattern(regexp = "^([是否])?$", message = "是否注册安全工程师仅允许:是、否")
@NotBlank(message = "是否注册安全工程师不能为空")
@@ -312,6 +317,9 @@ public class OrgPersonnelImportRow {
@Size(max = 64, message = "评价师证书编号长度不能超过64个字符")
private String seriesMajor;
+ @ExcelIgnore
+ private BasicDisciplineMajorDO bdmSeriesMajor;
+
@ExcelIgnore
private Integer rowIndex;
}
diff --git a/safety-eval-domain/src/main/java/org/qinan/safetyeval/domain/constant/basic/SafetyCategoryEnum.java b/safety-eval-domain/src/main/java/org/qinan/safetyeval/domain/constant/basic/SafetyCategoryEnum.java
index 5f2b0ed7..28fa244d 100644
--- a/safety-eval-domain/src/main/java/org/qinan/safetyeval/domain/constant/basic/SafetyCategoryEnum.java
+++ b/safety-eval-domain/src/main/java/org/qinan/safetyeval/domain/constant/basic/SafetyCategoryEnum.java
@@ -41,6 +41,9 @@ public enum SafetyCategoryEnum {
}
return null;
}
+ public IndustryEnum getIndustry(){
+ return getIndustry(this);
+ }
public static IndustryEnum getIndustry(SafetyCategoryEnum safetyCategoryEnum) {
switch (safetyCategoryEnum) {