work join date
parent
0ca52c4077
commit
a5a30f8d7e
|
|
@ -4,6 +4,7 @@ import io.swagger.annotations.Api;
|
|||
import io.swagger.annotations.ApiOperation;
|
||||
import org.qinan.safetyeval.client.api.QualFilingApi;
|
||||
import org.qinan.safetyeval.client.co.QualFilingCO;
|
||||
import org.qinan.safetyeval.client.co.QualFilingComplianceCheckResultCO;
|
||||
import org.qinan.safetyeval.client.co.QualFilingDetailCO;
|
||||
import org.qinan.safetyeval.client.dto.PageResponse;
|
||||
import org.qinan.safetyeval.client.dto.SingleResponse;
|
||||
|
|
@ -137,4 +138,10 @@ public class QualFilingController {
|
|||
public PageResponse<QualFilingCO> page(@Validated QualFilingPageQuery query) {
|
||||
return qualFilingApi.page(query);
|
||||
}
|
||||
|
||||
@ApiOperation("合规检查")
|
||||
@GetMapping("/compliance-check")
|
||||
public SingleResponse<List<QualFilingComplianceCheckResultCO>> complianceCheck(@RequestParam Long id) {
|
||||
return qualFilingApi.complianceCheck(id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.qinan.safetyeval.app.executor;
|
|||
import org.qinan.safetyeval.app.orchestrator.QualFilingOrchestrator;
|
||||
import org.qinan.safetyeval.client.api.QualFilingApi;
|
||||
import org.qinan.safetyeval.client.co.QualFilingCO;
|
||||
import org.qinan.safetyeval.client.co.QualFilingComplianceCheckResultCO;
|
||||
import org.qinan.safetyeval.client.co.QualFilingDetailCO;
|
||||
import org.qinan.safetyeval.client.dto.PageResponse;
|
||||
import org.qinan.safetyeval.client.dto.SingleResponse;
|
||||
|
|
@ -20,6 +21,7 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 资质备案申请执行器(App层)
|
||||
|
|
@ -130,6 +132,11 @@ public class QualFilingExecutor implements QualFilingApi {
|
|||
return SingleResponse.success(qualFilingOrchestrator.uploadMainAttachment(cmd.getId(), cmd.getAttachmentUrl()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleResponse<List<QualFilingComplianceCheckResultCO>> complianceCheck(Long id) {
|
||||
return SingleResponse.success(qualFilingOrchestrator.complianceCheck(id));
|
||||
}
|
||||
|
||||
private QualFilingCO toLegacyCO(QualFilingEntity entity) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -1,44 +1,14 @@
|
|||
package org.qinan.safetyeval.app.orchestrator;
|
||||
|
||||
import org.qinan.safetyeval.app.support.QualFilingAttachmentHelper;
|
||||
import org.qinan.safetyeval.app.support.QualFilingChangeDiffer;
|
||||
import org.qinan.safetyeval.app.support.QualFilingMaterialTemplateProvider;
|
||||
import org.qinan.safetyeval.app.support.QualFilingOrgEquipmentImporter;
|
||||
import org.qinan.safetyeval.app.support.QualFilingOrgPersonnelImporter;
|
||||
import org.qinan.safetyeval.app.support.QualFilingStatusGuard;
|
||||
import org.qinan.safetyeval.client.co.QualFilingChangeHistoryCO;
|
||||
import org.qinan.safetyeval.client.co.QualFilingChangeHistoryItemCO;
|
||||
import org.qinan.safetyeval.client.co.QualFilingCO;
|
||||
import org.qinan.safetyeval.client.co.QualFilingCommitmentCO;
|
||||
import org.qinan.safetyeval.client.co.QualFilingDetailCO;
|
||||
import org.qinan.safetyeval.client.co.QualFilingEquipmentCO;
|
||||
import org.qinan.safetyeval.client.co.QualFilingMaterialCO;
|
||||
import org.qinan.safetyeval.client.co.QualFilingPersonnelCO;
|
||||
import org.qinan.safetyeval.app.support.*;
|
||||
import org.qinan.safetyeval.client.co.*;
|
||||
import org.qinan.safetyeval.client.dto.QualFilingModifyCmd;
|
||||
import org.qinan.safetyeval.client.dto.QualFilingPageQuery;
|
||||
import org.qinan.safetyeval.domain.constant.QualFilingApplyTypeEnum;
|
||||
import org.qinan.safetyeval.domain.constant.QualFilingMaterialUploadStatusEnum;
|
||||
import org.qinan.safetyeval.domain.constant.QualFilingStatusEnum;
|
||||
import org.qinan.safetyeval.domain.entity.OrgInfoEntity;
|
||||
import org.qinan.safetyeval.domain.entity.QualFilingChangeDetailEntity;
|
||||
import org.qinan.safetyeval.domain.entity.QualFilingChangeEntity;
|
||||
import org.qinan.safetyeval.domain.entity.QualFilingCommitmentEntity;
|
||||
import org.qinan.safetyeval.domain.entity.QualFilingEntity;
|
||||
import org.qinan.safetyeval.domain.entity.QualFilingEquipmentEntity;
|
||||
import org.qinan.safetyeval.domain.entity.QualFilingMaterialEntity;
|
||||
import org.qinan.safetyeval.domain.entity.QualFilingPersonnelCertEntity;
|
||||
import org.qinan.safetyeval.domain.entity.QualFilingPersonnelEntity;
|
||||
import org.qinan.safetyeval.domain.constant.*;
|
||||
import org.qinan.safetyeval.domain.entity.*;
|
||||
import org.qinan.safetyeval.domain.exception.BizException;
|
||||
import org.qinan.safetyeval.domain.exception.ErrorCode;
|
||||
import org.qinan.safetyeval.domain.gateway.OrgInfoGateway;
|
||||
import org.qinan.safetyeval.domain.gateway.QualFilingChangeDetailGateway;
|
||||
import org.qinan.safetyeval.domain.gateway.QualFilingChangeGateway;
|
||||
import org.qinan.safetyeval.domain.gateway.QualFilingCommitmentGateway;
|
||||
import org.qinan.safetyeval.domain.gateway.QualFilingEquipmentGateway;
|
||||
import org.qinan.safetyeval.domain.gateway.QualFilingGateway;
|
||||
import org.qinan.safetyeval.domain.gateway.QualFilingMaterialGateway;
|
||||
import org.qinan.safetyeval.domain.gateway.QualFilingPersonnelCertGateway;
|
||||
import org.qinan.safetyeval.domain.gateway.QualFilingPersonnelGateway;
|
||||
import org.qinan.safetyeval.domain.gateway.*;
|
||||
import org.qinan.safetyeval.domain.query.PageResult;
|
||||
import org.qinan.safetyeval.domain.query.QualFilingQuery;
|
||||
import org.qinan.safetyeval.infrastructure.adapter.auth.AuthUserContextAdapter;
|
||||
|
|
@ -50,7 +20,11 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
|
@ -139,7 +113,9 @@ public class QualFilingOrchestrator {
|
|||
return toCO(saved);
|
||||
}
|
||||
|
||||
/** 用户点击暂存:暂存保持;已打回保持原状态 */
|
||||
/**
|
||||
* 用户点击暂存:暂存保持;已打回保持原状态
|
||||
*/
|
||||
private void markDraftSaved(QualFilingEntity filing) {
|
||||
Integer code = filing.getFilingStatusCode();
|
||||
if (code == null || code == QualFilingStatusEnum.DRAFT.getCode()) {
|
||||
|
|
@ -766,6 +742,156 @@ public class QualFilingOrchestrator {
|
|||
return co;
|
||||
}
|
||||
|
||||
/**
|
||||
* 合规检查:根据备案ID逐项检查是否满足法规要求
|
||||
*/
|
||||
public List<QualFilingComplianceCheckResultCO> complianceCheck(Long id) {
|
||||
QualFilingEntity filing = qualFilingGateway.get(id);
|
||||
if (filing == null) {
|
||||
throw new BizException(ErrorCode.QUAL_FILING_NOT_FOUND);
|
||||
}
|
||||
|
||||
List<QualFilingComplianceCheckResultCO> results = new ArrayList<>();
|
||||
|
||||
// 1. 主体资格
|
||||
results.add(checkMainQualification(filing));
|
||||
|
||||
// 2. 场所与设备
|
||||
results.add(checkWorkplace(filing));
|
||||
|
||||
// 3. 人员数量与结构
|
||||
results.add(checkPersonnelCount(id));
|
||||
|
||||
// 4. 人员资历
|
||||
results.add(checkPersonnelExperience(id));
|
||||
|
||||
// 5. 关键岗位要求(暂默认通过,标记警告)
|
||||
results.add(buildResult(QualFilingComplianceCheckEnum.KEY_POSITION,
|
||||
QualFilingComplianceCheckEnum.STATUS_WARN));
|
||||
|
||||
// 6. 管理体系(暂无法判断,标记警告)
|
||||
results.add(buildResult(QualFilingComplianceCheckEnum.MANAGEMENT_SYSTEM,
|
||||
QualFilingComplianceCheckEnum.STATUS_WARN));
|
||||
|
||||
// 7. 责任承诺
|
||||
results.add(checkCommitment(id));
|
||||
|
||||
// 8. 信息公开
|
||||
results.add(checkInfoDisclosure(filing));
|
||||
|
||||
// 9. 信用记录
|
||||
results.add(checkCreditRecord(id));
|
||||
|
||||
// 10. 其他
|
||||
results.add(buildResult(QualFilingComplianceCheckEnum.OTHER,
|
||||
QualFilingComplianceCheckEnum.STATUS_PASS));
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 主体资格:固定资产 >= 1000万元
|
||||
*/
|
||||
private QualFilingComplianceCheckResultCO checkMainQualification(QualFilingEntity filing) {
|
||||
// 1000万元 = 10,000,000元 = 1,000,000,000分
|
||||
boolean pass = filing.getFixedAssetAmount() != null
|
||||
&& filing.getFixedAssetAmount() >= 1_000_000_000L;
|
||||
return buildResult(QualFilingComplianceCheckEnum.MAIN_QUALIFICATION,
|
||||
pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 场所与设备:工作场所建筑面积 >= 1000㎡
|
||||
*/
|
||||
private QualFilingComplianceCheckResultCO checkWorkplace(QualFilingEntity filing) {
|
||||
boolean pass = filing.getWorkplaceArea() != null
|
||||
&& filing.getWorkplaceArea()
|
||||
.compareTo(new BigDecimal(QualFilingComplianceCheckEnum.WORKPLACE_LOWER)) >= 0;
|
||||
return buildResult(QualFilingComplianceCheckEnum.WORKPLACE,
|
||||
pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 人员数量与结构:专职技术人员 >= 25人,中级注安师 >= 30%
|
||||
*/
|
||||
private QualFilingComplianceCheckResultCO checkPersonnelCount(Long filingId) {
|
||||
List<QualFilingPersonnelEntity> personnelList =
|
||||
qualFilingPersonnelGateway.listByFilingId(filingId);
|
||||
int total = personnelList.size();
|
||||
if (total == 0) {
|
||||
return buildResult(QualFilingComplianceCheckEnum.PERSONNEL_COUNT,
|
||||
QualFilingComplianceCheckEnum.STATUS_FAIL);
|
||||
}
|
||||
long engineerCount = personnelList.stream()
|
||||
.filter(p -> p.getRegisterEngineerFlag() != null
|
||||
&& p.getRegisterEngineerFlag() == 1)
|
||||
.count();
|
||||
boolean pass = total >= QualFilingComplianceCheckEnum.PERSONNEL_COUNT_LOWER
|
||||
&& engineerCount * 100 / total >= QualFilingComplianceCheckEnum.PERSONNEL_RATE;
|
||||
return buildResult(QualFilingComplianceCheckEnum.PERSONNEL_COUNT,
|
||||
pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 人员资历:所有专职技术人员在本行业领域工作二年以上
|
||||
*/
|
||||
private QualFilingComplianceCheckResultCO checkPersonnelExperience(Long filingId) {
|
||||
List<QualFilingPersonnelEntity> personnelList =
|
||||
qualFilingPersonnelGateway.listByFilingId(filingId);
|
||||
if (personnelList.isEmpty()) {
|
||||
return buildResult(QualFilingComplianceCheckEnum.PERSONNEL_EXPERIENCE,
|
||||
QualFilingComplianceCheckEnum.STATUS_FAIL);
|
||||
}
|
||||
LocalDate now = LocalDate.now();
|
||||
boolean allQualified = personnelList.stream()
|
||||
.allMatch(p -> p.getJoinWorkDate() != null
|
||||
&& ChronoUnit.YEARS.between(p.getJoinWorkDate(), now) >= 2);
|
||||
return buildResult(QualFilingComplianceCheckEnum.PERSONNEL_EXPERIENCE,
|
||||
allQualified ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 责任承诺:qual_filing_commitment 表是否有数据
|
||||
*/
|
||||
private QualFilingComplianceCheckResultCO checkCommitment(Long filingId) {
|
||||
QualFilingCommitmentEntity commitment =
|
||||
qualFilingCommitmentGateway.getByFilingId(filingId);
|
||||
return buildResult(QualFilingComplianceCheckEnum.COMMITMENT,
|
||||
commitment != null ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 信息公开:info_disclosure_url 是否已填写
|
||||
*/
|
||||
private QualFilingComplianceCheckResultCO checkInfoDisclosure(QualFilingEntity filing) {
|
||||
boolean pass = filing.getInfoDisclosureUrl() != null
|
||||
&& !filing.getInfoDisclosureUrl().isEmpty();
|
||||
return buildResult(QualFilingComplianceCheckEnum.INFO_DISCLOSURE,
|
||||
pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 信用记录:qual_filing_material 表 upload_status_code=2 且 material_type=4
|
||||
*/
|
||||
private QualFilingComplianceCheckResultCO checkCreditRecord(Long filingId) {
|
||||
List<QualFilingMaterialEntity> materials =
|
||||
qualFilingMaterialGateway.listByFilingId(filingId);
|
||||
boolean pass = materials.stream()
|
||||
.anyMatch(m -> m.getUploadStatusCode() != null
|
||||
&& m.getUploadStatusCode() == QualFilingMaterialUploadStatusEnum.UPLOADED.getCode()
|
||||
&& MaterialTypeEnum.NO_VIOLATION_RECORD.getCode() == m.getMaterialType());
|
||||
return buildResult(QualFilingComplianceCheckEnum.CREDIT_RECORD,
|
||||
pass ? QualFilingComplianceCheckEnum.STATUS_PASS : QualFilingComplianceCheckEnum.STATUS_FAIL);
|
||||
}
|
||||
|
||||
private QualFilingComplianceCheckResultCO buildResult(QualFilingComplianceCheckEnum item, String status) {
|
||||
QualFilingComplianceCheckResultCO co = new QualFilingComplianceCheckResultCO();
|
||||
co.setTitle(item.getTitle());
|
||||
co.setDescription(item.getDescription());
|
||||
co.setStatus(status);
|
||||
return co;
|
||||
}
|
||||
|
||||
private Long resolveOrgId() {
|
||||
return orgContextResolver.resolveOrgId(null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.qinan.safetyeval.client.api;
|
||||
|
||||
import org.qinan.safetyeval.client.co.QualFilingCO;
|
||||
import org.qinan.safetyeval.client.co.QualFilingComplianceCheckResultCO;
|
||||
import org.qinan.safetyeval.client.co.QualFilingDetailCO;
|
||||
import org.qinan.safetyeval.client.dto.PageResponse;
|
||||
import org.qinan.safetyeval.client.dto.SingleResponse;
|
||||
|
|
@ -10,6 +11,8 @@ import org.qinan.safetyeval.client.dto.QualFilingModifyCmd;
|
|||
import org.qinan.safetyeval.client.dto.QualFilingPageQuery;
|
||||
import org.qinan.safetyeval.client.dto.QualFilingRejectCmd;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 资质备案申请接口定义(Client层)
|
||||
*/
|
||||
|
|
@ -40,4 +43,6 @@ public interface QualFilingApi {
|
|||
SingleResponse<QualFilingCO> filedDraft();
|
||||
|
||||
SingleResponse<QualFilingCO> uploadAttachment(QualFilingAttachmentUploadCmd cmd);
|
||||
|
||||
SingleResponse<List<QualFilingComplianceCheckResultCO>> complianceCheck(Long id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
package org.qinan.safetyeval.client.co;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 资质备案合规检查结果CO
|
||||
*
|
||||
* @author safety-eval
|
||||
*/
|
||||
@Data
|
||||
public class QualFilingComplianceCheckResultCO {
|
||||
|
||||
/** 检查项标题 */
|
||||
private String title;
|
||||
|
||||
/** 检查项描述 */
|
||||
private String description;
|
||||
|
||||
/** 检查结果状态:✅ 通过 / ❌ 未通过 / ⚠️ 警告 */
|
||||
private String status;
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ public class QualFilingMaterialCO {
|
|||
private Long filingId;
|
||||
|
||||
/** materialType */
|
||||
private String materialType;
|
||||
private Integer materialType;
|
||||
|
||||
/** materialContent */
|
||||
private String materialContent;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import lombok.Data;
|
|||
public class QualFilingMaterialAddCmd {
|
||||
|
||||
/** materialType */
|
||||
private String materialType;
|
||||
private Integer materialType;
|
||||
|
||||
/** materialContent */
|
||||
private String materialContent;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public class QualFilingMaterialModifyCmd {
|
|||
private Long id;
|
||||
|
||||
/** materialType */
|
||||
private String materialType;
|
||||
private Integer materialType;
|
||||
|
||||
/** materialContent */
|
||||
private String materialContent;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public class QualFilingMaterialPageQuery extends BasePageQuery {
|
|||
private Long filingId;
|
||||
|
||||
/** 材料类型 */
|
||||
private String materialType;
|
||||
private Integer materialType;
|
||||
|
||||
/** 材料内容 */
|
||||
private String materialContent;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
package org.qinan.safetyeval.domain.constant;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 资质备案合规检查项枚举
|
||||
*
|
||||
* @author safety-eval
|
||||
*/
|
||||
public enum QualFilingComplianceCheckEnum {
|
||||
|
||||
MAIN_QUALIFICATION("主体资格", "独立法人资格,固定资产不少于一千万元"),
|
||||
WORKPLACE("场所与设备", "工作场所建筑面积不少于1000㎡"),
|
||||
PERSONNEL_COUNT("人员数量与结构", "专职技术人员≥25人,中级注安师≥30%"),
|
||||
PERSONNEL_EXPERIENCE("人员资历", "专职技术人员在本行业领域工作二年以上"),
|
||||
KEY_POSITION("关键岗位要求", "负责人具有高级职称,工作八年以上"),
|
||||
MANAGEMENT_SYSTEM("管理体系", "需核验文件化管理体系是否符合要求"),
|
||||
COMMITMENT("责任承诺", "法定代表人已出具承诺书"),
|
||||
INFO_DISCLOSURE("信息公开", "未检测到公示网站"),
|
||||
CREDIT_RECORD("信用记录", "三年内无重大违法失信记录"),
|
||||
OTHER("其他", "法律、行政法规规定的其他条件"),
|
||||
;
|
||||
|
||||
/**
|
||||
* 结果状态:通过
|
||||
*/
|
||||
public static final String STATUS_PASS = "PASS";
|
||||
/**
|
||||
* 结果状态:未通过
|
||||
*/
|
||||
public static final String STATUS_FAIL = "NOT_PASS";
|
||||
/**
|
||||
* 结果状态:警告/暂无法判断
|
||||
*/
|
||||
public static final String STATUS_WARN = "WARN";
|
||||
|
||||
/**
|
||||
* 场所与设备 底线
|
||||
*/
|
||||
public static final int WORKPLACE_LOWER = 1000;
|
||||
public static final int PERSONNEL_COUNT_LOWER = 25;
|
||||
public static final int PERSONNEL_RATE = 30;
|
||||
|
||||
private final String title;
|
||||
private final String description;
|
||||
|
||||
QualFilingComplianceCheckEnum(String title, String description) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ public class QualFilingMaterialEntity {
|
|||
private Long filingId;
|
||||
|
||||
/** 材料类型 */
|
||||
private String materialType;
|
||||
private Integer materialType;
|
||||
|
||||
/** 材料内容 */
|
||||
private String materialContent;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ public class QualFilingMaterialQuery {
|
|||
private Long filingId;
|
||||
|
||||
/** 材料类型 */
|
||||
private String materialType;
|
||||
private Integer materialType;
|
||||
|
||||
/** 材料内容 */
|
||||
private String materialContent;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public class QualFilingMaterialDO {
|
|||
|
||||
private Long id;
|
||||
private Long filingId;
|
||||
private String materialType;
|
||||
private Integer materialType;
|
||||
private String materialContent;
|
||||
private String materialFormat;
|
||||
private Integer sortOrder;
|
||||
|
|
|
|||
Loading…
Reference in New Issue