dev-tmp1
luotaiqian 2026-08-10 11:41:18 +08:00
parent f0baa891af
commit d35e46046f
7 changed files with 260 additions and 52 deletions

View File

@ -0,0 +1,37 @@
package org.qinan.safetyeval.client.co;
import lombok.Data;
/**
*
*
* @author safety-eval
*/
@Data
public class PersonnelCertFilingCheckCO {
/**
* id
*/
private Long id;
/**
* id
*/
private Long personnelId;
/**
*
*/
private String professionalCapabilityCode;
/**
*
*/
private String certTypeCode;
/**
*
*/
private String certLevel;
}

View File

@ -49,11 +49,11 @@ public class QualFilingPersonnelInfoCO {
@ApiModelProperty(value = "是否注册安全工程师(1是2否)") @ApiModelProperty(value = "是否注册安全工程师(1是2否)")
private Integer registerEngineerFlag; private Integer registerEngineerFlag;
@ApiModelProperty(value = "是否技术负责人(0否1是)") @ApiModelProperty(value = "是否技术负责人")
private Integer technicalDirectorFlag; private Boolean technicalDirectorFlag;
@ApiModelProperty(value = "是否过程控制负责人(0否1是)") @ApiModelProperty(value = "是否过程控制负责人")
private Integer processControlLeaderFlag; private Boolean processControlLeaderFlag;
@ApiModelProperty(value = "人员岗位类型(TECHNICAL_LEADER=>技术负责人; PROCESS_CONTROL_LEADER=>过程控制负责人)") @ApiModelProperty(value = "人员岗位类型(TECHNICAL_LEADER=>技术负责人; PROCESS_CONTROL_LEADER=>过程控制负责人)")
private String personnelPositionType; private String personnelPositionType;

View File

@ -2,6 +2,8 @@ package org.qinan.safetyeval.client.dto;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import org.qinan.safetyeval.client.co.PersonnelCertFilingCheckCO;
import org.qinan.safetyeval.client.co.PersonnelCertFilingPageCO;
import org.qinan.safetyeval.domain.entity.CapabilityAssessmentDTO; import org.qinan.safetyeval.domain.entity.CapabilityAssessmentDTO;
import org.qinan.safetyeval.domain.entity.TitleCodeCo; import org.qinan.safetyeval.domain.entity.TitleCodeCo;
@ -23,7 +25,6 @@ public class QualFilingPersonnelFilingCheckDTO {
@ApiModelProperty(value = "能力认定") @ApiModelProperty(value = "能力认定")
private List<CapabilityAssessmentDTO> capabilityAssessment; private List<CapabilityAssessmentDTO> capabilityAssessment;
@ApiModelProperty(value = "是否技术负责人(false否true是)") @ApiModelProperty(value = "是否技术负责人(false否true是)")
private Boolean technicalDirectorFlag; private Boolean technicalDirectorFlag;
@ -33,6 +34,6 @@ public class QualFilingPersonnelFilingCheckDTO {
@ApiModelProperty(value = "职称(多个逗号分隔)") @ApiModelProperty(value = "职称(多个逗号分隔)")
private List<TitleCodeCo> titleCodeArr; private List<TitleCodeCo> titleCodeArr;
// @ApiModelProperty(value = "人员证书信息") @ApiModelProperty(value = "人员证书信息")
// private List<PersonnelCertFilingPageCO> personnelCertFilingPageCOList; private List<PersonnelCertFilingCheckCO> personnelCertFilingCheckCOList;
} }

View File

@ -44,4 +44,16 @@ public enum IndustryEnum {
} }
return null; return null;
} }
public static String getValueByCode(String code) {
if (code == null) {
return null;
}
for (IndustryEnum item : values()) {
if (item.code.equals(code)) {
return item.getValue();
}
}
return null;
}
} }

View File

@ -5,6 +5,7 @@ import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import org.qinan.safetyeval.client.co.OrgPersonnelCertCapabilityComplianceCheckCO; import org.qinan.safetyeval.client.co.OrgPersonnelCertCapabilityComplianceCheckCO;
import org.qinan.safetyeval.client.co.OrgPersonnelCertDetailCO; import org.qinan.safetyeval.client.co.OrgPersonnelCertDetailCO;
import org.qinan.safetyeval.client.co.PersonnelCertFilingCheckCO;
import org.qinan.safetyeval.infrastructure.dataobject.OrgPersonnelCertDO; import org.qinan.safetyeval.infrastructure.dataobject.OrgPersonnelCertDO;
import java.util.List; import java.util.List;
@ -21,6 +22,14 @@ public interface OrgPersonnelCertMapper extends BaseMapper<OrgPersonnelCertDO> {
List<OrgPersonnelCertCapabilityComplianceCheckCO> selectCapabilityByPersonnelIds( List<OrgPersonnelCertCapabilityComplianceCheckCO> selectCapabilityByPersonnelIds(
@Param("personnelIds") List<Long> personnelIds); @Param("personnelIds") List<Long> personnelIds);
/**
* id
*
* @param personnelIds id
* @return
*/
List<PersonnelCertFilingCheckCO> selectCertByPersonnelIds(@Param("personnelIds") List<Long> personnelIds);
/** /**
* IDindustry_professional_standards * IDindustry_professional_standards
* *

View File

@ -1,6 +1,7 @@
package org.qinan.safetyeval.infrastructure.utils; package org.qinan.safetyeval.infrastructure.utils;
import cn.hutool.core.lang.Pair; import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil; import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -8,6 +9,7 @@ import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.qinan.safetyeval.client.co.IndustryProfessionalPersonCo; import org.qinan.safetyeval.client.co.IndustryProfessionalPersonCo;
import org.qinan.safetyeval.client.co.OrgPersonnelCertCapabilityComplianceCheckCO; import org.qinan.safetyeval.client.co.OrgPersonnelCertCapabilityComplianceCheckCO;
import org.qinan.safetyeval.client.co.PersonnelCertFilingCheckCO;
import org.qinan.safetyeval.client.co.QualFilingComplianceCheckResultCO; import org.qinan.safetyeval.client.co.QualFilingComplianceCheckResultCO;
import org.qinan.safetyeval.client.dto.*; import org.qinan.safetyeval.client.dto.*;
import org.qinan.safetyeval.domain.constant.*; import org.qinan.safetyeval.domain.constant.*;
@ -191,9 +193,32 @@ public class ComplianceCheckUtil {
.collect(Collectors.joining(CommonUtil.COMMA)); .collect(Collectors.joining(CommonUtil.COMMA));
throw new BizException(ErrorCode.UNKNOWN_ERROR, "人员信息不存在" + collect); throw new BizException(ErrorCode.UNKNOWN_ERROR, "人员信息不存在" + collect);
} }
setPersonnelCert(result);
return result; return result;
} }
/**
* setPersonnelCert
*
* @param result result
*/
private static void setPersonnelCert(List<QualFilingPersonnelFilingCheckDTO> result) {
List<Long> personnelIds = result.stream()
.map(QualFilingPersonnelFilingCheckDTO::getId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
List<PersonnelCertFilingCheckCO> certList = SpringUtil.getBean(OrgPersonnelCertMapper.class)
.selectCertByPersonnelIds(personnelIds);
Map<Long, List<PersonnelCertFilingCheckCO>> certMap = certList.stream()
.collect(Collectors.groupingBy(PersonnelCertFilingCheckCO::getPersonnelId));
for (QualFilingPersonnelFilingCheckDTO dto : result) {
dto.setPersonnelCertFilingCheckCOList(certMap.getOrDefault(dto.getId(), Collections.emptyList()));
}
}
/** /**
* *
* *
@ -232,7 +257,7 @@ public class ComplianceCheckUtil {
boolean pass = filing.getFixedAssetAmount() != null boolean pass = filing.getFixedAssetAmount() != null
&& filing.getFixedAssetAmount() >= 800L; && filing.getFixedAssetAmount() >= 800L;
String currentValue = filing.getFixedAssetAmount() != null String currentValue = filing.getFixedAssetAmount() != null
? filing.getFixedAssetAmount() + " 万元" : "未填写" ; ? filing.getFixedAssetAmount() + " 万元" : "未填写";
return buildResult(QualFilingComplianceCheckEnum.FIXED_AMOUNT, return buildResult(QualFilingComplianceCheckEnum.FIXED_AMOUNT,
pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL, pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL,
currentValue); currentValue);
@ -245,9 +270,9 @@ public class ComplianceCheckUtil {
boolean pass = filing.getWorkplaceArea() != null boolean pass = filing.getWorkplaceArea() != null
&& filing.getWorkplaceArea() && filing.getWorkplaceArea()
.compareTo(new BigDecimal(QualFilingComplianceCheckEnum.WORKPLACE_LOWER)) >= 0; .compareTo(new BigDecimal(QualFilingComplianceCheckEnum.WORKPLACE_LOWER)) >= 0;
String workplace = filing.getWorkplaceArea() != null ? filing.getWorkplaceArea().toPlainString() : "未填写" ; String workplace = filing.getWorkplaceArea() != null ? filing.getWorkplaceArea().toPlainString() : "未填写";
String archive = filing.getArchiveRoomArea() != null ? filing.getArchiveRoomArea().toPlainString() : "未填写" ; String archive = filing.getArchiveRoomArea() != null ? filing.getArchiveRoomArea().toPlainString() : "未填写";
String currentValue = "工作场所 " + workplace + " 平方米,档案室 " + archive + " 平方米" ; String currentValue = "工作场所 " + workplace + " 平方米,档案室 " + archive + " 平方米";
return buildResult(QualFilingComplianceCheckEnum.WORKPLACE, return buildResult(QualFilingComplianceCheckEnum.WORKPLACE,
pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL, pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL,
currentValue); currentValue);
@ -260,7 +285,7 @@ public class ComplianceCheckUtil {
int scopeCount = filing.getBusinessScope() != null ? filing.getBusinessScope().size() : 0; int scopeCount = filing.getBusinessScope() != null ? filing.getBusinessScope().size() : 0;
int total = personnelList == null ? 0 : personnelList.size(); int total = personnelList == null ? 0 : personnelList.size();
boolean pass = total >= QualFilingComplianceCheckEnum.PERSONNEL_COUNT_LOWER + (scopeCount - 1) * 5; boolean pass = total >= QualFilingComplianceCheckEnum.PERSONNEL_COUNT_LOWER + (scopeCount - 1) * 5;
String currentValue = scopeCount + " 个业务范围," + total + " 人" ; String currentValue = scopeCount + " 个业务范围," + total + " 人";
return buildResult(QualFilingComplianceCheckEnum.PERSONNEL_COUNT, return buildResult(QualFilingComplianceCheckEnum.PERSONNEL_COUNT,
pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL, pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL,
currentValue); currentValue);
@ -277,16 +302,22 @@ public class ComplianceCheckUtil {
QualFilingComplianceCheckEnum.STATUS_FAIL, "无人员数据"); QualFilingComplianceCheckEnum.STATUS_FAIL, "无人员数据");
} }
int total = personnelList.size(); int total = personnelList.size();
String code = CertTypeCodeEnum.REGISTERED_SAFETY_ENGINEER.getCode();
// 中/高 级注册安全工程师
Set<Long> engineerSet = personnelCertCoList.stream() Set<Long> engineerSet = personnelCertCoList.stream()
// .filter(p -> CertTypeCodeEnum.REGISTERED_SAFETY_ENGINEER .flatMap(it -> it.getPersonnelCertFilingCheckCOList().stream())
// .getCode().equals(p.getCertTypeCode()) && !CertLevelEnum.JUNIOR.getCode().equals(p.getCertLevel())) .filter(it -> code.equals(it.getCertTypeCode()))
.map(QualFilingPersonnelFilingCheckDTO::getId) .map(PersonnelCertFilingCheckCO::getPersonnelId)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
// 高级职称人员
Set<Long> seniorTitleSet = personnelList.stream() Set<Long> seniorTitleSet = personnelList.stream()
.filter(p -> p.getTitleCodeArr() != null && p.getTitleCodeArr().stream() .filter(p -> p.getTitleCodeArr() != null && p.getTitleCodeArr().stream()
.anyMatch(t -> QualificationLevelEnum.SENIOR.getCode().equals(t.getTitleCode()))) .anyMatch(t -> QualificationLevelEnum.SENIOR.getCode().equals(t.getTitleCode())))
.map(QualFilingPersonnelAddCmd::getSourcePersonnelId) .map(QualFilingPersonnelAddCmd::getSourcePersonnelId)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
long engineerRate = engineerSet.size() * 100L / total; long engineerRate = engineerSet.size() * 100L / total;
long seniorTitleRate = seniorTitleSet.size() * 100L / total; long seniorTitleRate = seniorTitleSet.size() * 100L / total;
engineerSet.addAll(seniorTitleSet); engineerSet.addAll(seniorTitleSet);
@ -294,24 +325,14 @@ public class ComplianceCheckUtil {
boolean pass = engineerRate >= QualFilingComplianceCheckEnum.PERSONNEL_RATE boolean pass = engineerRate >= QualFilingComplianceCheckEnum.PERSONNEL_RATE
&& seniorTitleRate >= QualFilingComplianceCheckEnum.PERSONNEL_RATE && seniorTitleRate >= QualFilingComplianceCheckEnum.PERSONNEL_RATE
&& sumRate >= 60; && sumRate >= 60;
String currentValue = "注册安工程师 " + engineerRate + "%,高级职称 " + seniorTitleRate + "%,合计 " + sumRate + "%" ; String currentValue = "注册安工程师 " + engineerRate + "%,高级职称 " + seniorTitleRate + "%,合计 " + sumRate + "%";
if (!pass && throwException) { if (!pass && throwException) {
throw new BizException(PERSON_NOT_ENOUGH, currentValue); throw new BizException(PERSON_NOT_ENOUGH, currentValue);
} }
// 根据人员id查询专业能力code并设置到CO中 // 安全评价机构业务范围与专业能力配备标准 校验
List<Long> sourcePersonnelIds = personnelList.stream() Pair<Boolean, String> booleanStringPair =
.map(QualFilingPersonnelAddCmd::getSourcePersonnelId) industryProfessionalStandardsPersonValid(businessScope, personnelCertCoList);
.distinct()
.collect(Collectors.toList());
List<IndustryProfessionalPersonCo> personnelCoList = SpringUtil.getBean(OrgPersonnelMapper.class)
.selectProfessionalCapabilityByPersonnelIds(sourcePersonnelIds);
Pair<Boolean, String> booleanStringPair = industryProfessionalStandardsValid(
businessScope, personnelCoList, null);
/*Pair<Boolean, String> booleanStringPair = industryProfessionalStandardsValid(
businessScope, personnelCoList, personnelCertCoList);*/
boolean personPassed = Boolean.TRUE.equals(booleanStringPair.getKey()); boolean personPassed = Boolean.TRUE.equals(booleanStringPair.getKey());
if (!personPassed && throwException) { if (!personPassed && throwException) {
throw new BizException(PERSON_NOT_ENOUGH, booleanStringPair.getValue()); throw new BizException(PERSON_NOT_ENOUGH, booleanStringPair.getValue());
@ -375,7 +396,7 @@ public class ComplianceCheckUtil {
if (industryEnum != null) { if (industryEnum != null) {
scope = industryEnum.getValue(); scope = industryEnum.getValue();
} else { } else {
scope = "未知行业范围" ; scope = "未知行业范围";
} }
currentValue.append("业务[").append(scope).append("] 技术负责人 ") currentValue.append("业务[").append(scope).append("] 技术负责人 ")
.append(technicalDirectorCount).append("/1过程控制负责人 ") .append(technicalDirectorCount).append("/1过程控制负责人 ")
@ -413,7 +434,7 @@ public class ComplianceCheckUtil {
&& m.getUploadStatusCode() == QualFilingMaterialUploadStatusEnum.UPLOADED.getCode() && m.getUploadStatusCode() == QualFilingMaterialUploadStatusEnum.UPLOADED.getCode()
&& m.getMaterialType() != null && m.getMaterialType() != null
&& m.getMaterialType() == MaterialTypeEnum.NO_VIOLATION_RECORD.getCode()); && m.getMaterialType() == MaterialTypeEnum.NO_VIOLATION_RECORD.getCode());
String currentValue = hasRecord ? "未命中重大违法失信记录" : "命中重大违法失信记录" ; String currentValue = hasRecord ? "未命中重大违法失信记录" : "命中重大违法失信记录";
return buildResult(QualFilingComplianceCheckEnum.CREDIT_RECORD, return buildResult(QualFilingComplianceCheckEnum.CREDIT_RECORD,
hasRecord ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL, hasRecord ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL,
currentValue); currentValue);
@ -439,19 +460,15 @@ public class ComplianceCheckUtil {
} }
/** /**
* industryProfessionalStandardsValid *
* *
* @param industryCodeList industryCodeList * @param industryCodeList industryCodeList
* @param personnelCoList industryProfessionalPersonCos
* @param personnelCertCoList certCapabilityList * @param personnelCertCoList certCapabilityList
* @return Pair<Boolean, String> key value null * @return Pair<Boolean, String> key value null
*/ */
public static Pair<Boolean, String> industryProfessionalStandardsValid(List<String> industryCodeList public static Pair<Boolean, String> industryProfessionalStandardsPersonValid(List<String> industryCodeList
, List<IndustryProfessionalPersonCo> personnelCoList , List<QualFilingPersonnelFilingCheckDTO> personnelCertCoList) {
, List<OrgPersonnelCertCapabilityComplianceCheckCO> personnelCertCoList) {
if (CollectionUtils.isEmpty(industryCodeList)) {
return Pair.of(false, "没有业务范围");
}
// 通过 SpringUtil 获取 Mapper根据 industryCodeList 查询专业能力配备标准 // 通过 SpringUtil 获取 Mapper根据 industryCodeList 查询专业能力配备标准
IndustryProfessionalStandardsMapper mapper = SpringUtil.getBean(IndustryProfessionalStandardsMapper.class); IndustryProfessionalStandardsMapper mapper = SpringUtil.getBean(IndustryProfessionalStandardsMapper.class);
LambdaQueryWrapper<IndustryProfessionalStandardsDO> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<IndustryProfessionalStandardsDO> queryWrapper = new LambdaQueryWrapper<>();
@ -460,29 +477,145 @@ public class ComplianceCheckUtil {
List<IndustryProfessionalStandardsDO> standardsDOList = mapper.selectList(queryWrapper); List<IndustryProfessionalStandardsDO> standardsDOList = mapper.selectList(queryWrapper);
if (CollectionUtils.isEmpty(standardsDOList)) { if (CollectionUtils.isEmpty(standardsDOList)) {
log.warn("没有配置标准"); log.warn("务范围与专业能力配备标准未开启");
return Pair.of(true, null); return Pair.of(false, "务范围与专业能力配备标准未开启");
} }
// 按 industryCode 分组后循环调用 doIndustryProfessionalStandardsValid // 按 industryCode 分组后循环调用 doIndustryProfessionalStandardsValid
Map<String, List<IndustryProfessionalStandardsDO>> standardsGroupByIndustry = standardsDOList.stream() Map<String, List<IndustryProfessionalStandardsDO>> standardsGroupByIndustry = standardsDOList.stream()
.collect(Collectors.groupingBy(IndustryProfessionalStandardsDO::getIndustryCode)); .collect(Collectors.groupingBy(IndustryProfessionalStandardsDO::getIndustryCode));
String notExistIndustryCodeList = industryCodeList.stream().filter(it -> !standardsGroupByIndustry.containsKey(it))
.map(IndustryEnum::getValueByCode)
.collect(Collectors.joining(CommonUtil.COMMA));
if (StrUtil.isNotBlank(notExistIndustryCodeList)) {
return Pair.of(false, "务范围 " + notExistIndustryCodeList + "与专业能力配备标准未开启");
}
List<IndustryProfessionalPersonCo> personnelCoCopyList = new ArrayList<>(personnelCoList);
Map<String, List<OrgPersonnelCertCapabilityComplianceCheckCO>> personnelCertCoGroupByIndustry = return doIndustryProfessionalStandardsValid(standardsGroupByIndustry, personnelCertCoList);
personnelCertCoList.stream().collect( }
Collectors.groupingBy(OrgPersonnelCertCapabilityComplianceCheckCO::getBusinessScope));
StringJoiner failureMsg = new StringJoiner(";");
for (Map.Entry<String, List<IndustryProfessionalStandardsDO>> entry : standardsGroupByIndustry.entrySet()) { /**
Pair<Boolean, String> result = doIndustryProfessionalStandardsValid(entry.getValue(), personnelCoCopyList *
, personnelCertCoGroupByIndustry.getOrDefault(entry.getKey(), new ArrayList<>())); * <p>
if (Boolean.FALSE.equals(result.getKey()) && result.getValue() != null) { *
failureMsg.add(result.getValue()); *
* <ul>
* <li></li>
* <li>使Dinic
* "一人一专业、多业务范围不重复计算" </li>
* </ul>
*
* @param standardsGroupByIndustryMap IndustryEnum
* @param personnelCertCoList capabilityAssessment.professionalCapabilityCode
* @return Pair<Boolean, String> key value null
*/
public static Pair<Boolean, String> doIndustryProfessionalStandardsValid(
Map<String, List<IndustryProfessionalStandardsDO>> standardsGroupByIndustryMap
, List<QualFilingPersonnelFilingCheckDTO> personnelCertCoList) {
// 1. 收集人员 → 具备的专业能力code集合来源于能力认定
Map<Long, Set<String>> personCapabilityMap = personnelCertCoList.stream()
.filter(p -> !CollectionUtils.isEmpty(p.getCapabilityAssessment()))
.collect(Collectors.toMap(
QualFilingPersonnelFilingCheckDTO::getId,
p -> p.getCapabilityAssessment().stream()
.map(CapabilityAssessmentDTO::getProfessionalCapabilityCode)
.filter(Objects::nonNull)
.collect(Collectors.toSet()),
(a, b) -> a));
StringBuilder failureMsg = new StringBuilder();
// 2. 阶段一:逐行业简单计数校验(行业内本身人员是否充足),不通过直接返回
for (Map.Entry<String, List<IndustryProfessionalStandardsDO>> entry : standardsGroupByIndustryMap.entrySet()) {
appendPhaseOneFailures(entry.getKey(), entry.getValue(), personCapabilityMap, failureMsg);
}
if (failureMsg.length() > 0) {
return Pair.of(false, failureMsg.toString());
}
// 3. 阶段二:全局最优分配校验(一人一专业,多业务范围不重复计算)
// 构建需求(复合键 industryCode::capCode和 能力→需求键 映射
Map<String, Long> demandMap = new LinkedHashMap<>();
Map<String, List<String>> capToDemandKeys = new HashMap<>();
for (Map.Entry<String, List<IndustryProfessionalStandardsDO>> entry : standardsGroupByIndustryMap.entrySet()) {
String industryCode = entry.getKey();
for (IndustryProfessionalStandardsDO standard : entry.getValue()) {
String capCode = standard.getProfessionalCapabilityCode();
String demandKey = industryCode + "::" + capCode;
demandMap.put(demandKey, standard.getPersonNum() == null ? 0L : standard.getPersonNum());
capToDemandKeys.computeIfAbsent(capCode, k -> new ArrayList<>()).add(demandKey);
} }
} }
return failureMsg.length() > 1 ? Pair.of(false, failureMsg.toString()) : Pair.of(true, null);
// 构建人员 → 需求键集合
Map<Long, Set<String>> personDemandMap = new HashMap<>();
for (Map.Entry<Long, Set<String>> entry : personCapabilityMap.entrySet()) {
Set<String> demandKeys = new HashSet<>();
for (String cap : entry.getValue()) {
List<String> keys = capToDemandKeys.get(cap);
if (keys != null) {
demandKeys.addAll(keys);
}
}
if (!demandKeys.isEmpty()) {
personDemandMap.put(entry.getKey(), demandKeys);
}
}
Map<String, Long> assignedMap = canFullyAssign(personDemandMap, demandMap);
// 比对分配结果,生成失败明细
for (Map.Entry<String, List<IndustryProfessionalStandardsDO>> entry : standardsGroupByIndustryMap.entrySet()) {
String industryCode = entry.getKey();
for (IndustryProfessionalStandardsDO standard : entry.getValue()) {
String capCode = standard.getProfessionalCapabilityCode();
long required = standard.getPersonNum() == null ? 0L : standard.getPersonNum();
long assigned = assignedMap.getOrDefault(industryCode + "::" + capCode, 0L);
appendIfShort(industryCode, capCode, required, assigned, failureMsg);
}
}
return failureMsg.length() > 0 ? Pair.of(false, failureMsg.toString()) : Pair.of(true, null);
}
/**
*
*/
private static void appendPhaseOneFailures(String industryCode, List<IndustryProfessionalStandardsDO> standards
, Map<Long, Set<String>> personCapabilityMap, StringBuilder failureMsg) {
String industryName = IndustryEnum.getValueByCode(industryCode);
for (IndustryProfessionalStandardsDO standard : standards) {
String capCode = standard.getProfessionalCapabilityCode();
long required = standard.getPersonNum() == null ? 0L : standard.getPersonNum();
long available = personCapabilityMap.values().stream()
.filter(caps -> caps.contains(capCode))
.count();
appendIfShort(industryName, capCode, required, available, failureMsg);
}
}
/**
*
*/
private static void appendIfShort(String industryOrCode, String capCode, long required
, long available, StringBuilder failureMsg) {
if (available >= required) {
return;
}
IndustryEnum industryEnum = IndustryEnum.ofCode(industryOrCode);
String industryName = industryEnum != null ? industryEnum.getValue() : industryOrCode;
ProfessionalCapabilityEnum capEnum = ProfessionalCapabilityEnum.ofCode(capCode);
String capName = capEnum != null ? capEnum.getValue() : capCode;
failureMsg.append(industryName)
.append(CommonUtil.COLON)
.append(capName)
.append(" 需要")
.append(required)
.append("人,当前可用")
.append(available)
.append("人;");
} }
/** /**

View File

@ -60,6 +60,22 @@
</foreach> </foreach>
</select> </select>
<!-- 根据人员id列表查询人员证书信息 -->
<select id="selectCertByPersonnelIds"
resultType="org.qinan.safetyeval.client.co.PersonnelCertFilingCheckCO">
SELECT opc.id,
opc.personnel_id,
opc.professional_capability_code,
opc.cert_type_code,
opc.cert_level
FROM org_personnel_cert opc
WHERE opc.delete_enum = 'false' and opc.personnel_id IN
<foreach collection="personnelIds" item="personnelId" open="(" separator="," close=")">
#{personnelId}
</foreach>
</select>
<!-- 根据主键ID查询人员证书详情关联industry_professional_standards获取专业能力名称 --> <!-- 根据主键ID查询人员证书详情关联industry_professional_standards获取专业能力名称 -->
<select id="selectDetailById" <select id="selectDetailById"
resultType="org.qinan.safetyeval.client.co.OrgPersonnelCertDetailCO"> resultType="org.qinan.safetyeval.client.co.OrgPersonnelCertDetailCO">