feat: 客商风险C101-1查询改按统一社会信用代码, 信用代码为空各链路跳过留痕不阻断
This commit is contained in:
+12
-5
@@ -337,14 +337,14 @@ public class HcsContractSyncSupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询单方客商风险:按名称反查客商档案(§9-U6 编码体系联调确认),反查不到记 skip 留痕不阻断;
|
||||
* 查询单方客商风险:按名称反查客商档案(§9-U6 编码体系联调确认),反查不到档案或信用代码为空记 skip 留痕不阻断;
|
||||
* 内部组织客商默认无风险跳过(与展示/提交/付款链路口径一致,不调 C101-1)
|
||||
*/
|
||||
private RiskResult queryRisk(ContractManage contractManage, String standing, String partyName) {
|
||||
CustomerArchive customerArchive = queryCustomerArchive(partyName);
|
||||
if (customerArchive == null) {
|
||||
writeCheckLog(contractManage, HcsSyncConstant.CHECK_RESULT_SKIP,
|
||||
standing + "方[" + partyName + "]反查不到客商编号,跳过风险校验(§9-U6)", null);
|
||||
standing + "方[" + partyName + "]反查不到客商档案,跳过风险校验(§9-U6)", null);
|
||||
return new RiskResult(false, null);
|
||||
}
|
||||
// 内部组织类型客商默认无风险,不调 C101-1(与展示/提交/付款链路口径一致)
|
||||
@@ -353,13 +353,20 @@ public class HcsContractSyncSupport {
|
||||
standing + "方[" + partyName + "]为内部组织客商,默认无风险跳过校验", null);
|
||||
return new RiskResult(false, null);
|
||||
}
|
||||
// C101-1 改按统一社会信用代码查询:信用代码为空无法查询,跳过并留痕(同反查不到口径)
|
||||
String creditCode = customerArchive.getUnifiedCreditCode();
|
||||
if (StringUtil.isBlank(creditCode)) {
|
||||
writeCheckLog(contractManage, HcsSyncConstant.CHECK_RESULT_SKIP,
|
||||
standing + "方[" + partyName + "]信用代码为空,跳过风险校验", null);
|
||||
return new RiskResult(false, null);
|
||||
}
|
||||
HcsRiskQueryDTO param = new HcsRiskQueryDTO();
|
||||
// 【必填】客商编号:按甲乙方名称反查 CustomerArchive 客商编码(§9-U6)
|
||||
param.setFdNumber(customerArchive.getCustomerCode());
|
||||
// 【必填】统一社会信用代码:按甲乙方名称反查 CustomerArchive(C101-1 改按信用代码查询)
|
||||
param.setFdNumber(creditCode);
|
||||
HcsResult<HcsRiskVO> result = hcsClient.getRelativeRisk(param);
|
||||
if (result == null || !result.isSuccess()) {
|
||||
log.error("HCS客商风险查询失败响应:{},contractNo={},standing={},fdNumber={}",
|
||||
result == null ? "无响应" : String.format("msg=%s, traceId=%s", result.getMsg(), result.getTraceId()), contractManage.getContractNo(), standing, customerArchive.getCustomerCode());
|
||||
result == null ? "无响应" : String.format("msg=%s, traceId=%s", result.getMsg(), result.getTraceId()), contractManage.getContractNo(), standing, creditCode);
|
||||
throw new HcsException("C101-1 客商风险查询失败:" + (result == null ? "响应为空" : result.getMsg()));
|
||||
}
|
||||
HcsRiskVO risk = result.getData();
|
||||
|
||||
+46
-19
@@ -123,8 +123,8 @@ public class HcsCreditCheckSupport {
|
||||
CustomerArchive customerArchive = queryCustomerArchive(payment.getPayeeName());
|
||||
if (customerArchive == null) {
|
||||
writeCheckLog(payment, HcsSyncConstant.CHECK_TYPE_RISK, HcsSyncConstant.CHECK_RESULT_SKIP,
|
||||
"收款方[" + payment.getPayeeName() + "]反查不到客商编号,跳过风险校验(§9-U6)", null);
|
||||
log.warn("HCS付款提交风险校验跳过:paymentNo={},收款方反查不到客商编号", payment.getPaymentNo());
|
||||
"收款方[" + payment.getPayeeName() + "]反查不到客商档案,跳过风险校验(§9-U6)", null);
|
||||
log.warn("HCS付款提交风险校验跳过:paymentNo={},收款方反查不到客商档案", payment.getPaymentNo());
|
||||
return;
|
||||
}
|
||||
// 内部组织类型客商默认无风险,不查 C101-1(与 queryCustomerRisk 展示口径一致)
|
||||
@@ -133,13 +133,21 @@ public class HcsCreditCheckSupport {
|
||||
"收款方[" + payment.getPayeeName() + "]为内部组织客商,默认无风险跳过校验", null);
|
||||
return;
|
||||
}
|
||||
// C101-1 改按统一社会信用代码查询:信用代码为空无法查询,跳过并留痕(同反查不到口径)
|
||||
String creditCode = customerArchive.getUnifiedCreditCode();
|
||||
if (StringUtil.isBlank(creditCode)) {
|
||||
writeCheckLog(payment, HcsSyncConstant.CHECK_TYPE_RISK, HcsSyncConstant.CHECK_RESULT_SKIP,
|
||||
"收款方[" + payment.getPayeeName() + "]信用代码为空,跳过风险校验", null);
|
||||
log.warn("HCS付款提交风险校验跳过:paymentNo={},收款方信用代码为空", payment.getPaymentNo());
|
||||
return;
|
||||
}
|
||||
HcsRiskQueryDTO param = new HcsRiskQueryDTO();
|
||||
// 【必填】客商编号:按收款方名称反查 CustomerArchive 客商编码(用哪个编码待联调,§9-U6)
|
||||
param.setFdNumber(customerArchive.getCustomerCode());
|
||||
// 【必填】统一社会信用代码:按收款方名称反查 CustomerArchive(C101-1 改按信用代码查询)
|
||||
param.setFdNumber(creditCode);
|
||||
HcsResult<HcsRiskVO> result = hcsClient.getRelativeRisk(param);
|
||||
if (result == null || !result.isSuccess()) {
|
||||
log.error("HCS客商风险查询失败响应:{},paymentNo={},fdNumber={}",
|
||||
result == null ? "无响应" : String.format("msg=%s, traceId=%s", result.getMsg(), result.getTraceId()), payment.getPaymentNo(), customerArchive.getCustomerCode());
|
||||
result == null ? "无响应" : String.format("msg=%s, traceId=%s", result.getMsg(), result.getTraceId()), payment.getPaymentNo(), creditCode);
|
||||
throw new HcsException("C101-1 客商风险查询失败:" + (result == null ? "响应为空" : result.getMsg()));
|
||||
}
|
||||
HcsRiskVO risk = result.getData();
|
||||
@@ -204,7 +212,7 @@ public class HcsCreditCheckSupport {
|
||||
|
||||
/**
|
||||
* 客商风险查询(C101-1,展示与提交校验共用,前端接入设计 §3.3):
|
||||
* 内部组织类型客商默认无风险(不调 C101-1);外部客商按编号查询风险等级与黑名单状态并留痕;
|
||||
* 内部组织类型客商默认无风险(不调 C101-1);外部客商按信用代码查询风险等级与黑名单状态并留痕;
|
||||
* 金蝶黑名单(A801-5)命中同样判定为风险客商(risky=true,C101-1 空数据不漏提示);
|
||||
* riskTip 经 {@link #buildRiskDetail} 统一组装(等级 + 金蝶黑名单失信类别/列入事由),与列表悬浮明细同口径
|
||||
*
|
||||
@@ -247,12 +255,13 @@ public class HcsCreditCheckSupport {
|
||||
riskVO.setRisky(Boolean.FALSE);
|
||||
return riskVO;
|
||||
}
|
||||
RelativeRiskResult fetch = this.fetchRelativeRisk(customerCode, customerName);
|
||||
// 档案存在以档案信用代码为准;档案缺失(新增客商实时校验)兜底用前端传入信用代码
|
||||
String archiveCreditCode = customerArchive == null ? null : customerArchive.getUnifiedCreditCode();
|
||||
String effectiveCreditCode = StringUtil.isNotBlank(archiveCreditCode) ? archiveCreditCode : creditCode;
|
||||
RelativeRiskResult fetch = this.fetchRelativeRisk(customerCode, effectiveCreditCode, customerName);
|
||||
CustomerRiskVO riskVO = fetch.risk();
|
||||
// 表单实时提示与列表明细统一组装口径:追加金蝶黑名单段(A801-5 按信用代码查询,失败静默缺失;
|
||||
// 档案缺失(新增客商实时校验)时兜底用入参信用代码)
|
||||
String archiveCreditCode = customerArchive == null ? null : customerArchive.getUnifiedCreditCode();
|
||||
String effectiveCreditCode = StringUtil.isNotBlank(archiveCreditCode) ? archiveCreditCode : creditCode;
|
||||
BfiBlacklistVO hit = StringUtil.isBlank(effectiveCreditCode) ? null
|
||||
: this.queryBlacklistByCodes(List.of(effectiveCreditCode.trim().toUpperCase())).get(effectiveCreditCode.trim().toUpperCase());
|
||||
String blackCategory = hit == null ? null
|
||||
@@ -275,20 +284,31 @@ public class HcsCreditCheckSupport {
|
||||
|
||||
/**
|
||||
* C101-1 单客商远程查询并组装展示信息(不查档案、不写留痕,供单查与定时批量刷新复用);
|
||||
* riskTip 不在本方法组装,由调用方经 {@link #buildRiskDetail} 统一组装
|
||||
* riskTip 不在本方法组装,由调用方经 {@link #buildRiskDetail} 统一组装;
|
||||
* C101-1 改按统一社会信用代码查询,信用代码为空时不调远程、按无风险数据返回
|
||||
*
|
||||
* @param customerCode 客商编号
|
||||
* @param customerCode 客商编号(留痕与展示用)
|
||||
* @param creditCode 统一社会信用代码(C101-1 查询键)
|
||||
* @param customerName 客商名称(展示信息用)
|
||||
* @return 风险展示信息 + 合规 traceId
|
||||
*/
|
||||
private RelativeRiskResult fetchRelativeRisk(String customerCode, String customerName) {
|
||||
private RelativeRiskResult fetchRelativeRisk(String customerCode, String creditCode, String customerName) {
|
||||
if (StringUtil.isBlank(creditCode)) {
|
||||
log.warn("HCS客商风险查询跳过:customerCode={}, 信用代码为空", customerCode);
|
||||
CustomerRiskVO emptyRisk = new CustomerRiskVO();
|
||||
emptyRisk.setCustomerCode(customerCode);
|
||||
emptyRisk.setCustomerName(customerName);
|
||||
emptyRisk.setCustomerKind("external");
|
||||
emptyRisk.setRisky(Boolean.FALSE);
|
||||
return new RelativeRiskResult(emptyRisk, null);
|
||||
}
|
||||
HcsRiskQueryDTO param = new HcsRiskQueryDTO();
|
||||
// 【必填】客商编号(用哪个编码待联调,§9-U6)
|
||||
param.setFdNumber(customerCode);
|
||||
// 【必填】统一社会信用代码(C101-1 改按信用代码查询,字段名 fdNumber 保持合规侧定义)
|
||||
param.setFdNumber(creditCode);
|
||||
HcsResult<HcsRiskVO> result = hcsClient.getRelativeRisk(param);
|
||||
if (result == null || !result.isSuccess()) {
|
||||
log.error("HCS客商风险查询失败响应:{},fdNumber={}",
|
||||
result == null ? "无响应" : String.format("msg=%s, traceId=%s", result.getMsg(), result.getTraceId()), customerCode);
|
||||
result == null ? "无响应" : String.format("msg=%s, traceId=%s", result.getMsg(), result.getTraceId()), creditCode);
|
||||
throw new HcsException("C101-1 客商风险查询失败:" + (result == null ? "响应为空" : result.getMsg()));
|
||||
}
|
||||
HcsRiskVO risk = result.getData();
|
||||
@@ -441,7 +461,7 @@ public class HcsCreditCheckSupport {
|
||||
/**
|
||||
* 客商风险批量查询(C101-1,客商列表页展示用,前端接入设计 §3.3):
|
||||
* 逐个复用 {@link #queryCustomerRisk}(内部客商默认无风险,外部客商查 C101-1,与付款页面展示口径一致);
|
||||
* C101-1 仅支持单编号查询,逐个串行调用;展示场景单个失败跳过不阻断整页(强制校验仍在合同/付款链路)
|
||||
* C101-1 仅支持单信用代码查询,逐个串行调用;展示场景单个失败跳过不阻断整页(强制校验仍在合同/付款链路)
|
||||
*
|
||||
* @param customerCodes 客商编号集合
|
||||
* @return 风险展示信息列表(查询失败的客商不在结果中)
|
||||
@@ -465,7 +485,7 @@ public class HcsCreditCheckSupport {
|
||||
* 客商风险每日定时刷新(C101-1,客商档案列表展示与筛选数据源):
|
||||
* ① 取合同期限内(正式/临时期限任一覆盖当天)审核通过且未终止合同的甲乙方名称;
|
||||
* ② 按名称反查客商档案,内部组织客商默认无风险跳过;
|
||||
* ③ 逐个查询 C101-1(接口仅支持单编号,属远程调用非数据库 N+1;复用 {@link #fetchRelativeRisk},不重复查档案),
|
||||
* ③ 逐个查询 C101-1(接口仅支持单信用代码,属远程调用非数据库 N+1;复用 {@link #fetchRelativeRisk},不重复查档案),
|
||||
* 单个失败记 error 日志不中断(失败原因备查);
|
||||
* ④ 外部客商按 200/批切分,每批黑名单(A801-5)一次批量查询 + C101-1 逐个远程查询,失信类别/列入事由落原始字段
|
||||
* (明细文案由列表查询统一组装);
|
||||
@@ -501,7 +521,7 @@ public class HcsCreditCheckSupport {
|
||||
int internalCount = archiveList.size() - externalArchives.size();
|
||||
int refreshCount = 0;
|
||||
int failCount = 0;
|
||||
// 外部客商按 200/批处理:每批黑名单一次批量查询 + C101-1 逐个远程查询(接口仅支持单编号,非数据库 N+1),
|
||||
// 外部客商按 200/批处理:每批黑名单一次批量查询 + C101-1 逐个远程查询(接口仅支持单信用代码,非数据库 N+1),
|
||||
// 批内成功结果立即批量落库与留痕,风险/黑名单批次互不影响,单批失败不中断其余批次
|
||||
for (int start = 0; start < externalArchives.size(); start += HcsSyncConstant.CUSTOMER_RISK_REFRESH_BATCH) {
|
||||
List<CustomerArchive> batch = externalArchives.subList(start, Math.min(start + HcsSyncConstant.CUSTOMER_RISK_REFRESH_BATCH, externalArchives.size()));
|
||||
@@ -515,7 +535,14 @@ public class HcsCreditCheckSupport {
|
||||
List<HcsContractCheckLog> batchCheckLogs = new ArrayList<>();
|
||||
for (CustomerArchive customerArchive : batch) {
|
||||
try {
|
||||
RelativeRiskResult fetch = this.fetchRelativeRisk(customerArchive.getCustomerCode(), customerArchive.getFullName());
|
||||
// C101-1 改按信用代码查询:信用代码为空的档案跳过刷新(不计入失败数)
|
||||
if (Func.isEmpty(customerArchive.getUnifiedCreditCode())) {
|
||||
log.warn("定时刷新客商风险跳过:customerCode={}, fullName={}, 信用代码为空",
|
||||
customerArchive.getCustomerCode(), customerArchive.getFullName());
|
||||
continue;
|
||||
}
|
||||
RelativeRiskResult fetch = this.fetchRelativeRisk(customerArchive.getCustomerCode(),
|
||||
customerArchive.getUnifiedCreditCode(), customerArchive.getFullName());
|
||||
CustomerRiskVO risk = fetch.risk();
|
||||
// 仅提交风险列,避免整行回写覆盖刷新期间其它并发修改(审批状态/额度/金蝶推送等)
|
||||
CustomerArchive riskPatch = new CustomerArchive();
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ public class HcsRiskQueryDTO implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 客商编号(必填;用客商哪个编码待联调确认,§9-U6)
|
||||
* 统一社会信用代码(必填;C101-1 改按信用代码查询,字段名 fdNumber 保持合规侧定义)
|
||||
*/
|
||||
private String fdNumber;
|
||||
}
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ public interface IHcsClient {
|
||||
HcsResult<HcsPageVO<HcsProjectVO>> projectList(@RequestBody HcsPageQueryDTO param);
|
||||
|
||||
/**
|
||||
* C101-1 客商获取相对方风险等级
|
||||
* C101-1 客商获取相对方风险等级(入参 fdNumber 传统一社会信用代码)
|
||||
*
|
||||
* @param param 请求参数
|
||||
* @return 相对方风险信息
|
||||
|
||||
Reference in New Issue
Block a user