refactor: 合同表移除风险留痕字段,客商风险改为列表详情实时关联客商档案组装(含变更单)
This commit is contained in:
-6
@@ -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;
|
||||
|
||||
|
||||
-9
@@ -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;
|
||||
|
||||
|
||||
+8
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
+8
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
+10
@@ -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 一致)
|
||||
*/
|
||||
|
||||
+35
@@ -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<ContractChangeMap
|
||||
private static final DateTimeFormatter CODE_DATE = DateTimeFormatter.ofPattern("yyyyMMdd");
|
||||
|
||||
private final IContractManageService contractManageService;
|
||||
private final HcsCreditCheckSupport hcsCreditCheckSupport;
|
||||
|
||||
@Override
|
||||
public IPage<ContractChangeVO> selectContractChangePage(IPage<ContractChange> page, ContractChangeVO contractChange) {
|
||||
IPage<ContractChange> entityPage = page(page, buildQuery(contractChange).orderByDesc(ContractChange::getCreateTime));
|
||||
IPage<ContractChangeVO> 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<ContractChangeMap
|
||||
public ContractChangeVO detail(Long id) {
|
||||
ContractChangeVO contractChangeVO = ContractChangeWrapper.build().entityVO(loadExists(id));
|
||||
fillReadonly(contractChangeVO);
|
||||
this.fillContractRisk(java.util.Collections.singletonList(contractChangeVO));
|
||||
return contractChangeVO;
|
||||
}
|
||||
|
||||
@@ -97,10 +102,40 @@ public class ContractChangeServiceImpl extends BaseServiceImpl<ContractChangeMap
|
||||
@TenantIgnore
|
||||
public ContractChangeVO publicDetail(Long id) {
|
||||
ContractChangeVO contractChangeVO = ContractChangeWrapper.build().entityVO(loadExists(id));
|
||||
this.fillContractRisk(java.util.Collections.singletonList(contractChangeVO));
|
||||
contractChangeVO.setReadonly(Boolean.TRUE);
|
||||
return contractChangeVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装客商风险展示数据(变更列表/详情共用,复用 HcsCreditCheckSupport 公共查询):
|
||||
* 等级取甲乙双方较高值、黑名单任一方金蝶命中记是;名称关联不到或内部组织客商按无数据处理
|
||||
*/
|
||||
private void fillContractRisk(java.util.List<ContractChangeVO> records) {
|
||||
if (Func.isEmpty(records)) {
|
||||
return;
|
||||
}
|
||||
java.util.Set<String> 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<String, CustomerArchive> 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) {
|
||||
|
||||
+33
@@ -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<ContractManageMap
|
||||
IPage<ContractManage> entityPage = page(page, buildQuery(contractManage));
|
||||
IPage<ContractManageVO> 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<ContractManageMap
|
||||
public ContractManageVO detail(Long id) {
|
||||
ContractManageVO contractManageVO = ContractManageWrapper.build().entityVO(loadExists(id));
|
||||
fillReadonly(contractManageVO);
|
||||
this.fillContractRisk(java.util.Collections.singletonList(contractManageVO));
|
||||
return contractManageVO;
|
||||
}
|
||||
|
||||
@@ -128,6 +131,36 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
|
||||
return contractManageVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装客商风险展示数据(列表/详情共用,复用 HcsCreditCheckSupport 公共查询):
|
||||
* 等级取甲乙双方较高值、黑名单任一方金蝶命中记是;名称关联不到或内部组织客商按无数据处理,前端展示"-"
|
||||
*/
|
||||
private void fillContractRisk(List<ContractManageVO> records) {
|
||||
if (Func.isEmpty(records)) {
|
||||
return;
|
||||
}
|
||||
Set<String> 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<String, CustomerArchive> 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) {
|
||||
|
||||
+3
-7
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+59
@@ -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<String, CustomerArchive> queryArchiveRiskMap(Collection<String> partyNames) {
|
||||
if (Func.isEmpty(partyNames)) {
|
||||
return Map.of();
|
||||
}
|
||||
Map<String, CustomerArchive> archiveMap = new HashMap<>();
|
||||
for (CustomerArchive archive : customerArchiveMapper.selectList(Wrappers.<CustomerArchive>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);
|
||||
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user