From d5033f3b05d60241a2bcb985e62e088d31373823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=B3=89=E4=BD=B3?= <1107186916@qq.com> Date: Fri, 30 Oct 2026 14:41:41 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=90=88=E5=90=8C=E8=A1=A8?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=E9=A3=8E=E9=99=A9=E7=95=99=E7=97=95=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=EF=BC=8C=E5=AE=A2=E5=95=86=E9=A3=8E=E9=99=A9=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E5=88=97=E8=A1=A8=E8=AF=A6=E6=83=85=E5=AE=9E=E6=97=B6?= =?UTF-8?q?=E5=85=B3=E8=81=94=E5=AE=A2=E5=95=86=E6=A1=A3=E6=A1=88=E7=BB=84?= =?UTF-8?q?=E8=A3=85=EF=BC=88=E5=90=AB=E5=8F=98=E6=9B=B4=E5=8D=95=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../transport/pojo/entity/ContractChange.java | 6 -- .../transport/pojo/entity/ContractManage.java | 9 --- .../transport/pojo/vo/ContractChangeVO.java | 8 +++ .../transport/pojo/vo/ContractManageVO.java | 8 +++ .../transport/constant/HcsSyncConstant.java | 10 ++++ .../impl/ContractChangeServiceImpl.java | 35 +++++++++++ .../impl/ContractManageServiceImpl.java | 33 +++++++++++ .../support/hcs/HcsContractSyncSupport.java | 10 +--- .../support/hcs/HcsCreditCheckSupport.java | 59 +++++++++++++++++++ ...ade_contract_risk_fields_drop_20261030.sql | 54 +++++++++++++++++ 10 files changed, 210 insertions(+), 22 deletions(-) create mode 100644 doc/sql/transport/lqj/temp/05_blade_contract_risk_fields_drop_20261030.sql diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ContractChange.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ContractChange.java index 0ca18f11..dacae817 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ContractChange.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ContractChange.java @@ -204,12 +204,6 @@ public class ContractChange extends TenantEntity { @Schema(description = "其他事项说明") private String remark; - @Schema(description = "合规客商风险等级(展示用)") - private String hcsRiskLevel; - - @Schema(description = "合规客商黑名单状态(展示用)") - private String kingdeeBlackStatus; - @Schema(description = "审批状态") private String approvalStatus; diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ContractManage.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ContractManage.java index adb92905..ec4d89f9 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ContractManage.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ContractManage.java @@ -240,15 +240,6 @@ public class ContractManage extends TenantEntity { @Schema(description = "合规履约计划ID(C103-9 返回 fdExeplanId)") private String hcsExeplanId; - @Schema(description = "合规客商风险等级(C101-1,甲方/乙方取高)") - private String hcsRiskLevel; - - @Schema(description = "合规客商黑名单状态(C101-1,甲方/乙方取是)") - private String kingdeeBlackStatus; - - @Schema(description = "合规风险校验时间") - private LocalDateTime hcsRiskTime; - @Schema(description = "合规特批流程ID(C103-8 返回)") private String hcsSpecFdId; diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/ContractChangeVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/ContractChangeVO.java index 086d498e..f43cbb7a 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/ContractChangeVO.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/ContractChangeVO.java @@ -67,4 +67,12 @@ public class ContractChangeVO extends ContractChange { @Schema(description = "同步状态名称") private String syncStatusName; + @TableField(exist = false) + @Schema(description = "客商风险等级(甲乙双方关联客商档案实时组装,等级取高):0=低风险,1=中风险,2=高风险") + private String hcsRiskLevel; + + @TableField(exist = false) + @Schema(description = "客商黑名单状态(甲乙双方关联客商档案实时组装,任一方金蝶黑名单命中记是):yes/no") + private String kingdeeBlackStatus; + } diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/ContractManageVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/ContractManageVO.java index 5f76a439..a842a147 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/ContractManageVO.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/ContractManageVO.java @@ -83,4 +83,12 @@ public class ContractManageVO extends ContractManage { @Schema(description = "审核状态名称") private String approvalStatusName; + @TableField(exist = false) + @Schema(description = "客商风险等级(甲乙双方关联客商档案实时组装,等级取高):0=低风险,1=中风险,2=高风险") + private String hcsRiskLevel; + + @TableField(exist = false) + @Schema(description = "客商黑名单状态(甲乙双方关联客商档案实时组装,任一方金蝶黑名单命中记是):yes/no") + private String kingdeeBlackStatus; + } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/constant/HcsSyncConstant.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/constant/HcsSyncConstant.java index 7f870d9a..272a735b 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/constant/HcsSyncConstant.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/constant/HcsSyncConstant.java @@ -177,6 +177,16 @@ public final class HcsSyncConstant { */ public static final String CUSTOMER_KIND_INTERNAL = "internal"; + /** + * C101-1 黑名单状态:是(客商档案/合同客商风险展示与组装用) + */ + public static final String BLACK_STATUS_YES = "yes"; + + /** + * C101-1 黑名单状态:否 + */ + public static final String BLACK_STATUS_NO = "no"; + /** * 合同审核通过状态集合(首推/变更通过,客商风险定时刷新扫描口径与 HcsPushTask 一致) */ diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractChangeServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractChangeServiceImpl.java index ab043070..29007ba8 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractChangeServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractChangeServiceImpl.java @@ -36,7 +36,9 @@ import org.springblade.core.tool.utils.BeanUtil; import org.springblade.core.tool.utils.Func; import org.springblade.transport.constant.HcsSyncConstant; import org.springblade.transport.mapper.ContractChangeMapper; +import org.springblade.transport.support.hcs.HcsCreditCheckSupport; import org.springblade.transport.pojo.entity.ContractChange; +import org.springblade.transport.pojo.entity.CustomerArchive; import org.springblade.transport.pojo.entity.ContractManage; import org.springblade.transport.pojo.vo.ContractChangeVO; import org.springblade.transport.pojo.vo.ContractManageVO; @@ -77,12 +79,14 @@ public class ContractChangeServiceImpl extends BaseServiceImpl selectContractChangePage(IPage page, ContractChangeVO contractChange) { IPage entityPage = page(page, buildQuery(contractChange).orderByDesc(ContractChange::getCreateTime)); IPage voPage = ContractChangeWrapper.build().pageVO(entityPage); voPage.getRecords().forEach(this::fillReadonly); + this.fillContractRisk(voPage.getRecords()); return voPage; } @@ -90,6 +94,7 @@ public class ContractChangeServiceImpl extends BaseServiceImpl records) { + if (Func.isEmpty(records)) { + return; + } + java.util.Set partyNames = new java.util.HashSet<>(); + records.forEach(change -> { + if (Func.isNotEmpty(change.getPartyA())) { + partyNames.add(change.getPartyA().trim()); + } + if (Func.isNotEmpty(change.getPartyB())) { + partyNames.add(change.getPartyB().trim()); + } + }); + java.util.Map riskMap = this.hcsCreditCheckSupport.queryArchiveRiskMap(partyNames); + for (ContractChangeVO change : records) { + CustomerArchive partyARisk = Func.isEmpty(change.getPartyA()) ? null : riskMap.get(change.getPartyA().trim()); + CustomerArchive partyBRisk = Func.isEmpty(change.getPartyB()) ? null : riskMap.get(change.getPartyB().trim()); + change.setHcsRiskLevel(HcsCreditCheckSupport.higherRiskLevel( + partyARisk == null ? null : partyARisk.getHcsRiskLevel(), + partyBRisk == null ? null : partyBRisk.getHcsRiskLevel())); + change.setKingdeeBlackStatus( + HcsCreditCheckSupport.isKingdeeBlackHit(partyARisk) || HcsCreditCheckSupport.isKingdeeBlackHit(partyBRisk) + ? HcsSyncConstant.BLACK_STATUS_YES : HcsSyncConstant.BLACK_STATUS_NO); + } + } @Override @Transactional(rollbackFor = Exception.class) public ContractChangeVO createFromContract(Long contractId, String changeType) { diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractManageServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractManageServiceImpl.java index 721fa931..dac0cdca 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractManageServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractManageServiceImpl.java @@ -43,6 +43,7 @@ import org.springblade.transport.mapper.ContractManageMapper; import org.springblade.transport.mapper.HcsContractExeStageMapper; import org.springblade.transport.pojo.entity.ContractChange; import org.springblade.transport.pojo.entity.ContractManage; +import org.springblade.transport.pojo.entity.CustomerArchive; import org.springblade.transport.pojo.entity.HcsContractExeStage; import org.springblade.transport.pojo.vo.ContractManageVO; import org.springblade.transport.service.IContractExeStageService; @@ -109,6 +110,7 @@ public class ContractManageServiceImpl extends BaseServiceImpl entityPage = page(page, buildQuery(contractManage)); IPage voPage = ContractManageWrapper.build().pageVO(entityPage); voPage.getRecords().forEach(this::fillReadonly); + this.fillContractRisk(voPage.getRecords()); return voPage; } @@ -116,6 +118,7 @@ public class ContractManageServiceImpl extends BaseServiceImpl records) { + if (Func.isEmpty(records)) { + return; + } + Set partyNames = new HashSet<>(); + records.forEach(contract -> { + if (Func.isNotEmpty(contract.getPartyA())) { + partyNames.add(contract.getPartyA().trim()); + } + if (Func.isNotEmpty(contract.getPartyB())) { + partyNames.add(contract.getPartyB().trim()); + } + }); + Map riskMap = this.hcsCreditCheckSupport.queryArchiveRiskMap(partyNames); + for (ContractManageVO contract : records) { + CustomerArchive partyARisk = Func.isEmpty(contract.getPartyA()) ? null : riskMap.get(contract.getPartyA().trim()); + CustomerArchive partyBRisk = Func.isEmpty(contract.getPartyB()) ? null : riskMap.get(contract.getPartyB().trim()); + contract.setHcsRiskLevel(HcsCreditCheckSupport.higherRiskLevel( + partyARisk == null ? null : partyARisk.getHcsRiskLevel(), + partyBRisk == null ? null : partyBRisk.getHcsRiskLevel())); + contract.setKingdeeBlackStatus( + HcsCreditCheckSupport.isKingdeeBlackHit(partyARisk) || HcsCreditCheckSupport.isKingdeeBlackHit(partyBRisk) + ? HcsSyncConstant.BLACK_STATUS_YES : HcsSyncConstant.BLACK_STATUS_NO); + } + } + @Override @Transactional(rollbackFor = Exception.class) public boolean saveDraft(ContractManage contractManage) { diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsContractSyncSupport.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsContractSyncSupport.java index 7775a849..7feb31d0 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsContractSyncSupport.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsContractSyncSupport.java @@ -282,10 +282,7 @@ public class HcsContractSyncSupport { String riskLevel = StringUtil.isNotBlank(riskPartyA.riskLevel()) ? riskPartyA.riskLevel() : riskPartyB.riskLevel(); // 黑名单状态:任一方金蝶黑名单(A801-5)命中即为是(复用 HcsCreditCheckSupport.isKingdeeBlacklistHit 公共口径) boolean blacklist = riskPartyA.kingdeeHit() || riskPartyB.kingdeeHit(); - contractManage.setHcsRiskLevel(riskLevel); - contractManage.setKingdeeBlackStatus(blacklist ? BLACK_STATUS_YES : "no"); - contractManage.setHcsRiskTime(LocalDateTime.now()); - contractManageMapper.updateById(contractManage); + // 判定结果仅在内存参与推送/特批流程(risky),风险展示数据由列表/详情实时关联客商档案组装,合同表不再落库风险留痕 boolean risky = HcsSyncConstant.RISK_LEVEL_HIGH.equals(riskLevel) || blacklist; log.info("HCS合同风险校验完成:contractNo={},甲方[金蝶黑名单={},等级={}],乙方[金蝶黑名单={},等级={}],高风险/黑名单={}", contractManage.getContractNo(), riskPartyA.kingdeeHit(), riskPartyA.riskLevel(), @@ -312,9 +309,8 @@ public class HcsContractSyncSupport { // TMS 流程挂起为"特批审核",特批通过恢复展示、驳回联动合同审批驳回 contractManage.setCurrentNode(HcsSyncConstant.SPEC_REVIEW_NODE); contractManageMapper.updateById(contractManage); - log.info("HCS合同高风险/黑名单挂起特批审核:contractNo={},riskLevel={},blackStatus={},挂起节点={}", - contractManage.getContractNo(), contractManage.getHcsRiskLevel(), contractManage.getKingdeeBlackStatus(), - contractManage.getCurrentNode()); + log.info("HCS合同高风险/黑名单挂起特批审核:contractNo={},挂起节点={}", + contractManage.getContractNo(), contractManage.getCurrentNode()); } /** diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsCreditCheckSupport.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsCreditCheckSupport.java index a9371bec..7a043ad0 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsCreditCheckSupport.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsCreditCheckSupport.java @@ -60,6 +60,7 @@ import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -526,6 +527,64 @@ public class HcsCreditCheckSupport { return summary; } + /** + * 按甲乙方名称批量查客商档案风险数据(合同/变更列表与详情组装用,合同表不再落库风险留痕): + * 一次 IN 查询避免 N+1,键为客商名称;仅保留已有风险数据的档案(等级或金蝶黑名单字段非空), + * 名称重名时取第一条;内部组织客商无风险数据天然不入 map + * + * @param partyNames 甲/乙方名称集合 + * @return 客商名称 -> 客商档案(含 hcsRiskLevel/kingdeeBlackCategory/kingdeeBlackReason) + */ + public Map queryArchiveRiskMap(Collection partyNames) { + if (Func.isEmpty(partyNames)) { + return Map.of(); + } + Map archiveMap = new HashMap<>(); + for (CustomerArchive archive : customerArchiveMapper.selectList(Wrappers.lambdaQuery() + .in(CustomerArchive::getFullName, partyNames) + .eq(CustomerArchive::getIsDeleted, 0))) { + if (Func.isEmpty(archive.getFullName())) { + continue; + } + boolean hasRiskData = Func.isNotEmpty(archive.getHcsRiskLevel()) + || Func.isNotEmpty(archive.getKingdeeBlackCategory()) || Func.isNotEmpty(archive.getKingdeeBlackReason()); + if (hasRiskData) { + archiveMap.putIfAbsent(archive.getFullName(), archive); + } + } + return archiveMap; + } + + /** + * 合同客商风险等级合并(甲乙双方取较高值,2>1>0,无有效等级返回 null) + */ + public static String higherRiskLevel(String riskLevelA, String riskLevelB) { + int levelA = parseRiskLevel(riskLevelA); + int levelB = parseRiskLevel(riskLevelB); + if (levelA < 0 && levelB < 0) { + return null; + } + return String.valueOf(Math.max(levelA, levelB)); + } + + private static int parseRiskLevel(String riskLevel) { + if (Func.isEmpty(riskLevel)) { + return -1; + } + try { + return Integer.parseInt(riskLevel.trim()); + } catch (NumberFormatException exception) { + return -1; + } + } + + /** + * 客商档案金蝶黑名单命中判定(失信类别/列入事由任一非空) + */ + public static boolean isKingdeeBlackHit(CustomerArchive archive) { + return archive != null && (Func.isNotEmpty(archive.getKingdeeBlackCategory()) || Func.isNotEmpty(archive.getKingdeeBlackReason())); + } + /** * 金蝶黑名单批量查询(A801-5,定时刷新专用,调用方按 200 客商/批切分保证入参 ≤200): * 键为大写税号;失信类别取 awrp_combofield_title、缺失兜底 awrp_combofield(口径同提审校验 validateBlacklist); diff --git a/doc/sql/transport/lqj/temp/05_blade_contract_risk_fields_drop_20261030.sql b/doc/sql/transport/lqj/temp/05_blade_contract_risk_fields_drop_20261030.sql new file mode 100644 index 00000000..35482e7e --- /dev/null +++ b/doc/sql/transport/lqj/temp/05_blade_contract_risk_fields_drop_20261030.sql @@ -0,0 +1,54 @@ +-- 合同表移除客商风险留痕列(风险展示改为列表/详情实时关联客商档案组装,不再落库): +-- blade_contract_manage DROP hcs_risk_level / kingdee_black_status / hcs_risk_time +-- blade_contract_change DROP hcs_risk_level / kingdee_black_status +-- 幂等可重复执行:列存在才 DROP。 + +-- ① blade_contract_manage.hcs_risk_level +SET @ddl = (SELECT IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_contract_manage' AND COLUMN_NAME = 'hcs_risk_level') > 0, + 'ALTER TABLE `blade_contract_manage` DROP COLUMN `hcs_risk_level`', + 'SELECT 1')); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- ② blade_contract_manage.kingdee_black_status +SET @ddl = (SELECT IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_contract_manage' AND COLUMN_NAME = 'kingdee_black_status') > 0, + 'ALTER TABLE `blade_contract_manage` DROP COLUMN `kingdee_black_status`', + 'SELECT 1')); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- ③ blade_contract_manage.hcs_risk_time +SET @ddl = (SELECT IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_contract_manage' AND COLUMN_NAME = 'hcs_risk_time') > 0, + 'ALTER TABLE `blade_contract_manage` DROP COLUMN `hcs_risk_time`', + 'SELECT 1')); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- ④ blade_contract_change.hcs_risk_level +SET @ddl = (SELECT IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_contract_change' AND COLUMN_NAME = 'hcs_risk_level') > 0, + 'ALTER TABLE `blade_contract_change` DROP COLUMN `hcs_risk_level`', + 'SELECT 1')); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- ⑤ blade_contract_change.kingdee_black_status +SET @ddl = (SELECT IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_contract_change' AND COLUMN_NAME = 'kingdee_black_status') > 0, + 'ALTER TABLE `blade_contract_change` DROP COLUMN `kingdee_black_status`', + 'SELECT 1')); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt;