:fix: 统一内部组织客商判定口径、精简高风险提示文案并移除mock控制器
This commit is contained in:
-123
@@ -1,123 +0,0 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.controller;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.log.exception.ServiceException;
|
||||
import org.springblade.core.tenant.annotation.TenantIgnore;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* HCS 合规回调 Mock 端点
|
||||
* <p>
|
||||
* 合同法务审批结果回调(D103)、付款法务审批结果回调(D104)、项目金蝶同步结果回调(D902)、
|
||||
* 合同金蝶同步结果回传接收(D903)四个入站回调的纯 mock 实现:仅校验来源系统标识后返回固定结果,
|
||||
* 不读写业务数据、不联动状态。真实处理逻辑保留在对应 Support 中,联调时把端点切回
|
||||
* {@link } 并调用 Support 方法即可。
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@TenantIgnore
|
||||
@RequestMapping("hcs")
|
||||
@Tag(name = "HCS合规回调Mock", description = "HCS合规回调Mock端点(仅自测,返回固定 mock 数据)")
|
||||
public class HcsMockController {
|
||||
|
||||
/**
|
||||
* 来源系统标识(合规方约定值,与 third-party.hcs.src-system 默认值一致)
|
||||
*/
|
||||
private static final String SOURCE_SYSTEM = "WLTMS";
|
||||
|
||||
/**
|
||||
* 合同法务审批结果回调(D103)
|
||||
*/
|
||||
@PostMapping("/contractLegal/result")
|
||||
@ApiOperationSupport(order = 15)
|
||||
@Operation(summary = "合同法务审批结果回调Mock", description = "D103 合规推送合同特批(金蝶同步)结果,仅校验来源系统并返回 mock 数据")
|
||||
public R<String> contractLegalResult(@RequestBody(required = false) Map<String, Object> param) {
|
||||
this.checkSourceSystem("合同法务审批结果", param);
|
||||
return R.data("mock特批结果已处理:approved");
|
||||
}
|
||||
|
||||
/**
|
||||
* 付款法务审批结果回调(D104)
|
||||
*/
|
||||
@PostMapping("/paymentLegal/result")
|
||||
@ApiOperationSupport(order = 16)
|
||||
@Operation(summary = "付款法务审批结果回调Mock", description = "D104 合规推送付款特批结果,仅校验来源系统并返回 mock 数据")
|
||||
public R<String> paymentLegalResult(@RequestBody(required = false) Map<String, Object> param) {
|
||||
this.checkSourceSystem("付款法务审批结果", param);
|
||||
return R.data("mock付款特批结果接收已处理:approved");
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目金蝶同步结果回调(D902)
|
||||
*/
|
||||
@PostMapping("/projectLegal/result")
|
||||
@ApiOperationSupport(order = 18)
|
||||
@Operation(summary = "项目金蝶同步结果回调Mock", description = "D902 合规推送项目金蝶同步结果,仅校验来源系统并返回 mock 数据")
|
||||
public R<String> projectLegalResult(@RequestBody(required = false) Map<String, Object> param) {
|
||||
this.checkSourceSystem("项目金蝶同步结果", param);
|
||||
return R.data("mock项目金蝶同步结果接收已处理:approved");
|
||||
}
|
||||
|
||||
/**
|
||||
* 合同金蝶同步结果回传接收(D903)
|
||||
*/
|
||||
@PostMapping("/contractKingdee/result")
|
||||
@ApiOperationSupport(order = 19)
|
||||
@Operation(summary = "合同金蝶同步结果回传接收Mock", description = "D903 合规推送合同金蝶最终同步结果,仅校验来源系统并返回 mock 数据")
|
||||
public R<String> contractKingdeeResult(@RequestBody(required = false) Map<String, Object> param) {
|
||||
this.checkSourceSystem("合同金蝶同步结果", param);
|
||||
return R.data("mock合同金蝶同步结果接收处理:approved");
|
||||
}
|
||||
|
||||
/**
|
||||
* 来源系统校验:仅接受合规方约定的来源标识,防伪造回传
|
||||
*
|
||||
* @param bizName 业务名称(日志用)
|
||||
* @param param 回调报文
|
||||
*/
|
||||
private void checkSourceSystem(String bizName, Map<String, Object> param) {
|
||||
String sourceSystem = param == null ? null : Objects.toString(param.get("sourceSystem"), null);
|
||||
if (!StrUtil.equalsIgnoreCase(sourceSystem, SOURCE_SYSTEM)) {
|
||||
log.warn("{}推送来源系统标识错误:sourceSystem={}", bizName, sourceSystem);
|
||||
throw new ServiceException("来源系统标识错误");
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-24
@@ -337,22 +337,29 @@ public class HcsContractSyncSupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询单方客商风险:按名称反查客商编号(§9-U6 编码体系联调确认),反查不到记 skip 留痕不阻断
|
||||
* 查询单方客商风险:按名称反查客商档案(§9-U6 编码体系联调确认),反查不到记 skip 留痕不阻断;
|
||||
* 内部组织客商默认无风险跳过(与展示/提交/付款链路口径一致,不调 C101-1)
|
||||
*/
|
||||
private RiskResult queryRisk(ContractManage contractManage, String standing, String partyName) {
|
||||
String customerCode = queryCustomerCode(partyName);
|
||||
if (StringUtil.isBlank(customerCode)) {
|
||||
CustomerArchive customerArchive = queryCustomerArchive(partyName);
|
||||
if (customerArchive == null) {
|
||||
writeCheckLog(contractManage, HcsSyncConstant.CHECK_RESULT_SKIP,
|
||||
standing + "方[" + partyName + "]反查不到客商编号,跳过风险校验(§9-U6)", null);
|
||||
return new RiskResult(null, null, false);
|
||||
}
|
||||
// 内部组织类型客商默认无风险,不调 C101-1(与展示/提交/付款链路口径一致)
|
||||
if (HcsCreditCheckSupport.isInternalCustomer(customerArchive)) {
|
||||
writeCheckLog(contractManage, HcsSyncConstant.CHECK_RESULT_SKIP,
|
||||
standing + "方[" + partyName + "]为内部组织客商,默认无风险跳过校验", null);
|
||||
return new RiskResult(null, null, false);
|
||||
}
|
||||
HcsRiskQueryDTO param = new HcsRiskQueryDTO();
|
||||
// 【必填】客商编号:按甲乙方名称反查 CustomerArchive 客商编码(§9-U6)
|
||||
param.setFdNumber(customerCode);
|
||||
param.setFdNumber(customerArchive.getCustomerCode());
|
||||
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, customerCode);
|
||||
result == null ? "无响应" : String.format("msg=%s, traceId=%s", result.getMsg(), result.getTraceId()), contractManage.getContractNo(), standing, customerArchive.getCustomerCode());
|
||||
throw new HcsException("C101-1 客商风险查询失败:" + (result == null ? "响应为空" : result.getMsg()));
|
||||
}
|
||||
HcsRiskVO risk = result.getData();
|
||||
@@ -534,8 +541,8 @@ public class HcsContractSyncSupport {
|
||||
// 甲乙方各反查一次客商档案,编号与内部组织判定共用查询结果
|
||||
CustomerArchive partyAArchive = queryCustomerArchive(contractManage.getPartyA());
|
||||
CustomerArchive partyBArchive = queryCustomerArchive(contractManage.getPartyB());
|
||||
boolean partyAInternal = isInternalCustomer(partyAArchive);
|
||||
boolean partyBInternal = isInternalCustomer(partyBArchive);
|
||||
boolean partyAInternal = HcsCreditCheckSupport.isInternalCustomer(partyAArchive);
|
||||
boolean partyBInternal = HcsCreditCheckSupport.isInternalCustomer(partyBArchive);
|
||||
String partyAType;
|
||||
String partyBType;
|
||||
if (partyAInternal || partyBInternal) {
|
||||
@@ -672,14 +679,6 @@ public class HcsContractSyncSupport {
|
||||
return templateId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按名称反查客商编码(照 KingdeeApBillSyncSupport#queryCustomerCode 惯例,查不到返回 null)
|
||||
*/
|
||||
private String queryCustomerCode(String partyName) {
|
||||
CustomerArchive customerArchive = queryCustomerArchive(partyName);
|
||||
return customerArchive == null ? null : customerArchive.getCustomerCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 按名称反查客商档案(全称或简称精确匹配,查不到返回 null)
|
||||
*/
|
||||
@@ -693,15 +692,6 @@ public class HcsContractSyncSupport {
|
||||
.last("limit 1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部组织客商判定(集团内我方签约主体,档案登记 customerKind=internal/内部组织)
|
||||
*/
|
||||
private boolean isInternalCustomer(CustomerArchive customerArchive) {
|
||||
return customerArchive != null
|
||||
&& (HcsSyncConstant.CUSTOMER_KIND_INTERNAL.equals(customerArchive.getCustomerKind())
|
||||
|| "内部组织".equals(customerArchive.getCustomerKind()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联项目取值:合同所选项目对应合同系统项目ID(blade_project_apply.hcs_fd_id,C102-1 立项同步回填),
|
||||
* 未选择项目、立项单不存在或未同步合规时返回 null 不传(fdProject 选填)
|
||||
|
||||
+18
-3
@@ -118,7 +118,7 @@ public class HcsCreditCheckSupport {
|
||||
return;
|
||||
}
|
||||
// 内部组织类型客商默认无风险,不查 C101-1(与 queryCustomerRisk 展示口径一致)
|
||||
if (HcsSyncConstant.CUSTOMER_KIND_INTERNAL.equals(customerArchive.getCustomerKind())) {
|
||||
if (isInternalCustomer(customerArchive)) {
|
||||
writeCheckLog(payment, HcsSyncConstant.CHECK_TYPE_RISK, HcsSyncConstant.CHECK_RESULT_SKIP,
|
||||
"收款方[" + payment.getPayeeName() + "]为内部组织客商,默认无风险跳过校验", null);
|
||||
return;
|
||||
@@ -212,7 +212,7 @@ public class HcsCreditCheckSupport {
|
||||
riskVO.setCustomerCode(customerCode);
|
||||
riskVO.setCustomerName(customerArchive == null ? customerCode : customerArchive.getFullName());
|
||||
// 内部组织类型客商默认无风险;档案不存在按外部客商查询(不静默放行)
|
||||
boolean internal = customerArchive != null && HcsSyncConstant.CUSTOMER_KIND_INTERNAL.equals(customerArchive.getCustomerKind());
|
||||
boolean internal = isInternalCustomer(customerArchive);
|
||||
riskVO.setCustomerKind(internal ? HcsSyncConstant.CUSTOMER_KIND_INTERNAL : "external");
|
||||
if (internal) {
|
||||
riskVO.setRisky(Boolean.FALSE);
|
||||
@@ -236,7 +236,9 @@ public class HcsCreditCheckSupport {
|
||||
riskVO.setRiskLevelName(riskLevelName(blackStatus, riskLevel));
|
||||
riskVO.setRisky(risky);
|
||||
if (risky) {
|
||||
riskVO.setRiskTip("【" + riskVO.getCustomerName() + "】:被列入外部黑名单;涉贪污受贿裁判相关提及方(3年以上及其他);被执行人信息;买卖合同纠纷;劳动纠纷;重大纠纷");
|
||||
// 风险提示固定短文案(C101-1 未返回风险项明细,不拼接枚举清单):黑名单与高风险区分表述
|
||||
riskVO.setRiskTip("【" + riskVO.getCustomerName() + "】:"
|
||||
+ (BLACK_STATUS_YES.equalsIgnoreCase(blackStatus) ? "被列入外部黑名单" : "为高风险客商"));
|
||||
}
|
||||
try {
|
||||
HcsContractCheckLog checkLog = new HcsContractCheckLog();
|
||||
@@ -271,6 +273,19 @@ public class HcsCreditCheckSupport {
|
||||
return queryCustomerRisk(customerCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部组织客商判定(集团内我方签约主体,档案登记 customerKind=internal/内部组织);
|
||||
* 展示、提交校验、付款校验、合同推送、signer 单位类型各链路统一复用本判定
|
||||
*
|
||||
* @param customerArchive 客商档案
|
||||
* @return 是否内部组织客商
|
||||
*/
|
||||
public static boolean isInternalCustomer(CustomerArchive customerArchive) {
|
||||
return customerArchive != null
|
||||
&& (HcsSyncConstant.CUSTOMER_KIND_INTERNAL.equals(customerArchive.getCustomerKind())
|
||||
|| "内部组织".equals(customerArchive.getCustomerKind()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 风险等级转义(C101-1 枚举 0=低风险/1=中风险/2=高风险):黑名单状态优先展示,无等级返回空
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user