From b313663589095246fa32562b08bb7e17c3de853a Mon Sep 17 00:00:00 2001 From: luotaiqian <1147642922@qq.com> Date: Thu, 16 Jul 2026 14:14:25 +0800 Subject: [PATCH] init --- .../executor/QualFilingChangeExecutor.java | 1 - .../co/IndustryProfessionalPersonCo.java | 5 ++ ...sonnelCertCapabilityComplianceCheckCO.java | 32 ++++++++++ .../mapper/OrgPersonnelCertMapper.java | 11 ++++ .../utils/ComplianceCheckUtil.java | 63 +++++++++++++++---- .../mapper/OrgPersonnelCertMapper.xml | 15 +++++ 6 files changed, 114 insertions(+), 13 deletions(-) create mode 100644 safety-eval-client/src/main/java/org/qinan/safetyeval/client/co/OrgPersonnelCertCapabilityComplianceCheckCO.java diff --git a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/QualFilingChangeExecutor.java b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/QualFilingChangeExecutor.java index b0dba38..74fe810 100644 --- a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/QualFilingChangeExecutor.java +++ b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/QualFilingChangeExecutor.java @@ -255,7 +255,6 @@ public class QualFilingChangeExecutor implements QualFilingChangeApi { @Transactional(rollbackFor = Exception.class) public SingleResponse aggregationSaveOrEdit(AggregationSaveOrEditQualFilingChangeCmd cmd) { validateBeforeSaveOrEdit(cmd); - // 合规性校验:只要有一项未通过则抛出异常 if (reviewEnable) { AggregationSaveOrEditQualFilingCmd qualFilingCmd = convertToQualFilingCmd(cmd); diff --git a/safety-eval-client/src/main/java/org/qinan/safetyeval/client/co/IndustryProfessionalPersonCo.java b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/co/IndustryProfessionalPersonCo.java index ad2ca47..92f75bb 100644 --- a/safety-eval-client/src/main/java/org/qinan/safetyeval/client/co/IndustryProfessionalPersonCo.java +++ b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/co/IndustryProfessionalPersonCo.java @@ -20,4 +20,9 @@ public class IndustryProfessionalPersonCo { * 人员数量 */ private Long personNum; + + /** + * 来源人员id + */ + private Long sourcePersonnelId; } diff --git a/safety-eval-client/src/main/java/org/qinan/safetyeval/client/co/OrgPersonnelCertCapabilityComplianceCheckCO.java b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/co/OrgPersonnelCertCapabilityComplianceCheckCO.java new file mode 100644 index 0000000..e975b1b --- /dev/null +++ b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/co/OrgPersonnelCertCapabilityComplianceCheckCO.java @@ -0,0 +1,32 @@ +package org.qinan.safetyeval.client.co; + +import lombok.Data; + +/** + * 人员证书专业能力查询结果 + * + * @author safety-eval + */ +@Data +public class OrgPersonnelCertCapabilityComplianceCheckCO { + + /** + * 人员id + */ + private Long personnelId; + + /** + * 备案安全评价业务范围 + */ + private String businessScope; + + /** + * 专业能力编码 + */ + private String professionalCapabilityCode; + + /** + * 专业能力ID + */ + private Long professionalCapabilityId; +} diff --git a/safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/mapper/OrgPersonnelCertMapper.java b/safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/mapper/OrgPersonnelCertMapper.java index c251188..203f2da 100644 --- a/safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/mapper/OrgPersonnelCertMapper.java +++ b/safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/mapper/OrgPersonnelCertMapper.java @@ -2,8 +2,19 @@ package org.qinan.safetyeval.infrastructure.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import org.qinan.safetyeval.infrastructure.dataobject.OrgPersonnelCertDO; +import java.util.List; + @Mapper public interface OrgPersonnelCertMapper extends BaseMapper { + + /** + * 根据人员id列表查询证书专业能力信息 + * + * @param personnelIds 人员id列表 + * @return 证书专业能力列表 + */ + List selectCapabilityByPersonnelIds(@Param("personnelIds") List personnelIds); } diff --git a/safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/utils/ComplianceCheckUtil.java b/safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/utils/ComplianceCheckUtil.java index d0dca4b..005d783 100644 --- a/safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/utils/ComplianceCheckUtil.java +++ b/safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/utils/ComplianceCheckUtil.java @@ -6,11 +6,13 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; import org.qinan.safetyeval.client.co.IndustryProfessionalPersonCo; +import org.qinan.safetyeval.client.co.OrgPersonnelCertCapabilityComplianceCheckCO; import org.qinan.safetyeval.client.co.QualFilingComplianceCheckResultCO; import org.qinan.safetyeval.client.dto.*; import org.qinan.safetyeval.domain.constant.*; import org.qinan.safetyeval.domain.exception.BizException; import org.qinan.safetyeval.infrastructure.convertor.QualFilingPersonnelCoConvertor; +import org.qinan.safetyeval.infrastructure.mapper.OrgPersonnelCertMapper; import org.qinan.safetyeval.infrastructure.mapper.OrgPersonnelMapper; import org.qinan.safetyeval.infrastructure.persistence.domainobject.IndustryProfessionalStandardsDO; import org.qinan.safetyeval.infrastructure.persistence.domainobject.OrgPersonnelLeaderCountDO; @@ -40,6 +42,10 @@ public class ComplianceCheckUtil { List results = new ArrayList<>(); + // 0. 查询人员证书专业能力信息 + List + certCapabilityList = queryOrgPersonnelCertCapability(personnelList); + // 1. 独立法人资格 results.add(checkMainQualification(filing)); @@ -57,7 +63,7 @@ public class ComplianceCheckUtil { results.add(checkPersonnelCount(filing, personnelList)); // 6. 人员比例 - results.add(checkPersonnelRatio(filing.getBusinessScope(), personnelList)); + results.add(checkPersonnelRatio(filing.getBusinessScope(), personnelList, certCapabilityList)); // 7. 负责人配备 results.add(checkKeyPosition(filing, personnelList)); @@ -79,6 +85,31 @@ public class ComplianceCheckUtil { return results; } + /** + * 查询人员证书专业能力信息 + *

+ * 根据备案人员列表中的 sourcePersonnelId(对应 org_personnel_cert.personnel_id), + * 查询 org_personnel_cert 表的 business_scope、professional_capability_code、professional_capability_id。 + * + * @param personnelList 备案人员列表 + * @return 人员证书专业能力信息列表 + */ + private List queryOrgPersonnelCertCapability(List personnelList) { + if (CollectionUtils.isEmpty(personnelList)) { + return Collections.emptyList(); + } + List sourcePersonnelIds = personnelList.stream() + .map(QualFilingPersonnelAddCmd::getSourcePersonnelId) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + if (sourcePersonnelIds.isEmpty()) { + return Collections.emptyList(); + } + OrgPersonnelCertMapper mapper = SpringUtil.getBean(OrgPersonnelCertMapper.class); + return mapper.selectCapabilityByPersonnelIds(sourcePersonnelIds); + } + /** * 独立法人资格(暂默认通过,标记警告) */ @@ -132,7 +163,7 @@ public class ComplianceCheckUtil { * 人员比例:中级注安师 >= 30%,高级职称 >= 30%,合计 >= 60% */ private QualFilingComplianceCheckResultCO checkPersonnelRatio(List businessScope - , List personnelList) { + , List personnelList, List personnelCertCoList) { if (personnelList == null || personnelList.isEmpty()) { return buildResult(QualFilingComplianceCheckEnum.PERSONNEL_RATIO, QualFilingComplianceCheckEnum.STATUS_FAIL, "无人员数据"); @@ -153,9 +184,10 @@ public class ComplianceCheckUtil { String currentValue = "注册安全工程师 " + engineerRate + "%,高级职称 " + seniorTitleRate + "%,合计 " + sumRate + "%"; - List industryProfessionalPersonCos = SpringUtil.getBean(QualFilingPersonnelCoConvertor.class) + List personnelCoList = SpringUtil.getBean(QualFilingPersonnelCoConvertor.class) .convertCmdsToCos(personnelList); - Pair booleanStringPair = industryProfessionalStandardsValid(businessScope, industryProfessionalPersonCos); + Pair booleanStringPair = industryProfessionalStandardsValid( + businessScope, personnelCoList, personnelCertCoList); if (Boolean.FALSE.equals(booleanStringPair.getKey())) { throw new BizException(PERSON_NOT_ENOUGH, booleanStringPair.getValue()); } @@ -266,12 +298,14 @@ public class ComplianceCheckUtil { /** * industryProfessionalStandardsValid * - * @param industryCodeList industryCodeList - * @param industryProfessionalPersonCos industryProfessionalPersonCos + * @param industryCodeList industryCodeList + * @param personnelCoList industryProfessionalPersonCos + * @param personnelCertCoList certCapabilityList * @return Pair key 是否通过 ,value 失败消息(通过时为 null) */ public static Pair industryProfessionalStandardsValid(List industryCodeList - , List industryProfessionalPersonCos) { + , List personnelCoList + , List personnelCertCoList) { if (CollectionUtils.isEmpty(industryCodeList)) { return Pair.of(false, "没有业务范围"); } @@ -290,10 +324,16 @@ public class ComplianceCheckUtil { // 按 industryCode 分组后循环调用 doIndustryProfessionalStandardsValid Map> standardsGroupByIndustry = standardsDOList.stream() .collect(Collectors.groupingBy(IndustryProfessionalStandardsDO::getIndustryCode)); + Map> personnelCoGroupByIndustry = personnelCoList.stream() + .collect(Collectors.groupingBy(IndustryProfessionalPersonCo::getIndustryCode)); + Map> personnelCertCoGroupByIndustry = personnelCertCoList.stream() + .collect(Collectors.groupingBy(OrgPersonnelCertCapabilityComplianceCheckCO::getBusinessScope)); StringJoiner failureMsg = new StringJoiner(";"); for (Map.Entry> entry : standardsGroupByIndustry.entrySet()) { - Pair result = doIndustryProfessionalStandardsValid(entry.getValue(), industryProfessionalPersonCos); + Pair result = doIndustryProfessionalStandardsValid( + entry.getValue(), personnelCoGroupByIndustry.getOrDefault(entry.getKey(), new ArrayList<>()) + , personnelCertCoGroupByIndustry.getOrDefault(entry.getKey(), new ArrayList<>())); if (Boolean.FALSE.equals(result.getKey()) && result.getValue() != null) { failureMsg.add(result.getValue()); } @@ -306,18 +346,17 @@ public class ComplianceCheckUtil { * * @param standardsDOList 人员要求标准(按 行业code + 专业能力code 分类的人数要求) * @param industryProfessionalPersonCos 当前实际人员数(按 行业code + 专业能力code 分类汇总) + * @param certCapabilityList certCapabilityList * @return Pair key 是否通过 ,value 失败消息(通过时为 null) */ public static Pair doIndustryProfessionalStandardsValid(List standardsDOList - , List industryProfessionalPersonCos) { + , List industryProfessionalPersonCos, List certCapabilityList) { if (CollectionUtils.isEmpty(standardsDOList)) { return Pair.of(true, null); } - List currentList = - industryProfessionalPersonCos == null ? Collections.emptyList() : industryProfessionalPersonCos; // 当前人员数按 行业code + 专业能力code 分类汇总 - Map currentCountMap = currentList.stream() + Map currentCountMap = industryProfessionalPersonCos.stream() .collect(Collectors.groupingBy( c -> groupKey(c.getIndustryCode(), c.getProfessionalCapabilityCode()), Collectors.summingLong(c -> c.getPersonNum() == null ? 0L : c.getPersonNum()))); diff --git a/safety-eval-infrastructure/src/main/resources/mapper/OrgPersonnelCertMapper.xml b/safety-eval-infrastructure/src/main/resources/mapper/OrgPersonnelCertMapper.xml index d6a67e1..010f9e0 100644 --- a/safety-eval-infrastructure/src/main/resources/mapper/OrgPersonnelCertMapper.xml +++ b/safety-eval-infrastructure/src/main/resources/mapper/OrgPersonnelCertMapper.xml @@ -41,4 +41,19 @@ `id`, `org_id`, `personnel_id`, `cert_name`, `cert_type_code`, `cert_type_name`, `cert_category_code`, `cert_category_name`, `operation_category_code`, `operation_category_name`, `cert_no`, `issue_org`, `valid_start_date`, `valid_end_date`, `review_date`, `cert_attachment_url`, `business_scope`, `professional_capability_code`, `professional_capability_id`, `delete_enum`, `remarks`, `create_name`, `update_name`, `tenant_id`, `version`, `create_time`, `update_time`, `create_id`, `update_id`, `env` + + +