:feat: 新增合同金蝶同步结果回调(D903)
- 新增 /hcs/contractKingdee/result 免登回调端点,投送人/钢厂/结算中心合同共用 - 按合同编号定位回填金蝶合同ID,失败记录原因;本接口不处理法务审批结论 - contractType/sourceSystem 均按非必填处理,传值时校验来源标识为 WCCK - 回调成功/失败追加变更记录并原文留痕 blade_hcs_check_log(check_type=kingdee)
This commit is contained in:
+15
@@ -321,4 +321,19 @@ public class HcsSyncController {
|
||||
public R<String> projectLegalResult(@RequestBody(required = false) HcsProjectLegalResultDTO param) {
|
||||
return R.data(hcsProjectSyncSupport.handleLegalResult(param));
|
||||
}
|
||||
|
||||
/**
|
||||
* 合同金蝶同步结果回传接收(合规系统 contractKingdee/result 推送,D903,投送人/钢厂/结算中心合同共用,原文留痕)
|
||||
* <p>
|
||||
* 免登免授权:blade.secure skip-url + auth permitAll 放行(doc/nacos/blade.yaml);
|
||||
* iPaaS 网关注册映射:/gwzh/HTHG/contractKingdee/result → /hcs/contractKingdee/result;
|
||||
* 报文 {contractType?, contractCode, requestId, success, reason?, kingdeeId?, sourceSystem?},
|
||||
* 本接口不处理法务审批结论,仅按 contractCode=TMS 合同编号定位回填金蝶合同ID/记录失败原因。
|
||||
*/
|
||||
@PostMapping("/contractKingdee/result")
|
||||
@ApiOperationSupport(order = 19)
|
||||
@Operation(summary = "合同金蝶同步结果回传接收", description = "合规系统推送合同金蝶最终同步结果(D903,投送人/钢厂/结算中心共用),按合同编号定位回填金蝶ID,不处理法务审批结论,原文留痕")
|
||||
public R<String> contractKingdeeResult(@RequestBody(required = false) HcsContractLegalResultDTO param) {
|
||||
return R.data(hcsContractSyncSupport.handleKingdeeResult(param));
|
||||
}
|
||||
}
|
||||
|
||||
+125
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
package org.springblade.transport.support.hcs;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -37,6 +38,7 @@ import org.springblade.hcs.dto.HcsAttachmentRefDTO;
|
||||
import org.springblade.hcs.dto.HcsContractDraftDTO;
|
||||
import org.springblade.hcs.dto.HcsContractDraftVO;
|
||||
import org.springblade.hcs.dto.HcsContractFieldJsonDTO;
|
||||
import org.springblade.hcs.dto.HcsContractLegalResultDTO;
|
||||
import org.springblade.hcs.dto.HcsContractVO;
|
||||
import org.springblade.hcs.dto.HcsPageQueryDTO;
|
||||
import org.springblade.hcs.dto.HcsPageVO;
|
||||
@@ -66,6 +68,7 @@ import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -97,6 +100,11 @@ public class HcsContractSyncSupport {
|
||||
*/
|
||||
private static final String BLACK_STATUS_YES = "yes";
|
||||
|
||||
/**
|
||||
* 合同金蝶同步结果回传来源系统标识(D903 约定传 WCCK,非必填,传值时校验)
|
||||
*/
|
||||
private static final String KINGDEE_CALLBACK_SRC_SYSTEM = "WCCK";
|
||||
|
||||
private final IHcsClient hcsClient;
|
||||
private final HcsProperties hcsProperties;
|
||||
private final ContractManageMapper contractManageMapper;
|
||||
@@ -107,6 +115,123 @@ public class HcsContractSyncSupport {
|
||||
private final HcsExeStageSyncSupport hcsExeStageSyncSupport;
|
||||
private final HcsContractSpecSyncSupport hcsContractSpecSyncSupport;
|
||||
|
||||
/**
|
||||
* 合同金蝶同步结果接收处理(合规 contractKingdee/result 推送,D903,投送人/钢厂/结算中心合同共用):
|
||||
* 合规侧收到金蝶最终同步结果后通知 TMS 更新同步状态,本接口不处理法务审批结论(特批联动走 contractLegal/result + C103-4 兜底);
|
||||
* contractType(deliverer/gc/sett_center)非必填仅随原文留痕;sourceSystem 非必填,传值时须为 WCCK;
|
||||
* contractCode=TMS 合同编号定位(requestId 仅 X-ERP-Request-Id 回显不可定位);
|
||||
* success=true 回填金蝶合同ID(kingdeeId),success=false 记录失败原因;均追加变更记录并原文留痕 blade_hcs_check_log
|
||||
*
|
||||
* @param param 合规推送报文
|
||||
* @return 处理结果描述
|
||||
*/
|
||||
public String handleKingdeeResult(HcsContractLegalResultDTO param) {
|
||||
// sourceSystem 非必填(D903),传值时仅接受合规方约定的 WCCK,防伪造回传
|
||||
String sourceSystem = param == null ? null : param.getSourceSystem();
|
||||
if (StringUtil.isNotBlank(sourceSystem) && !KINGDEE_CALLBACK_SRC_SYSTEM.equalsIgnoreCase(sourceSystem)) {
|
||||
log.warn("合同金蝶同步结果推送来源系统标识错误:sourceSystem={}", sourceSystem);
|
||||
throw new ServiceException("来源系统标识错误");
|
||||
}
|
||||
String raw = JSONUtil.toJsonStr(param);
|
||||
ContractManage contractManage = locateContractByNo(param.getContractCode());
|
||||
if (contractManage == null) {
|
||||
log.warn("合同金蝶同步结果推送未定位到合同:contractCode={},报文已留痕", param.getContractCode());
|
||||
writeKingdeeCallbackLog(null, HcsSyncConstant.CHECK_RESULT_SKIP, "合同金蝶同步结果推送未定位到合同:" + raw);
|
||||
return "已留痕:未定位到合同(contractCode=" + param.getContractCode() + ")";
|
||||
}
|
||||
if (param.getSuccess() == null) {
|
||||
log.warn("合同金蝶同步结果推送 success 字段缺失:contractNo={},报文已留痕", contractManage.getContractNo());
|
||||
writeKingdeeCallbackLog(contractManage, HcsSyncConstant.CHECK_RESULT_SKIP, "合同金蝶同步结果推送 success 字段缺失:" + raw);
|
||||
return "已留痕:success 字段缺失(contractNo=" + contractManage.getContractNo() + ")";
|
||||
}
|
||||
if (param.getSuccess()) {
|
||||
// 成功:回填金蝶合同ID,同步结果信息随 hcs_sync_msg 留痕,不联动审批/特批状态
|
||||
contractManage.setKingdeeId(param.getKingdeeId());
|
||||
contractManage.setHcsSyncMsg(HcsSyncConstant.truncateMsg("合同金蝶同步结果回调:金蝶同步成功,kingdeeId=" + param.getKingdeeId()));
|
||||
appendKingdeeResultRecord(contractManage, "金蝶同步成功:金蝶合同ID=" + param.getKingdeeId());
|
||||
contractManageMapper.updateById(contractManage);
|
||||
writeKingdeeCallbackLog(contractManage, HcsSyncConstant.CHECK_RESULT_PASS, "合同金蝶同步结果推送:" + raw);
|
||||
log.info("合同金蝶同步结果推送处理完成:contractNo={},结果=success,kingdeeId={}", contractManage.getContractNo(), param.getKingdeeId());
|
||||
return "金蝶同步结果已处理:success";
|
||||
}
|
||||
// 失败:记录失败原因(金蝶同步在合规侧完成,TMS 不重推,失败重试由合规侧负责)
|
||||
contractManage.setHcsSyncMsg(HcsSyncConstant.truncateMsg("合同金蝶同步结果回调:金蝶同步失败:" + param.getReason()));
|
||||
appendKingdeeResultRecord(contractManage, "金蝶同步失败:" + param.getReason());
|
||||
contractManageMapper.updateById(contractManage);
|
||||
writeKingdeeCallbackLog(contractManage, HcsSyncConstant.CHECK_RESULT_FAIL, "合同金蝶同步结果推送:" + raw);
|
||||
log.info("合同金蝶同步结果推送处理完成:contractNo={},结果=fail,reason={}", contractManage.getContractNo(), param.getReason());
|
||||
return "金蝶同步结果已处理:fail";
|
||||
}
|
||||
|
||||
/**
|
||||
* 按 ERP 合同编号定位合同(合规推送 contractCode,合同编号唯一)
|
||||
*/
|
||||
private ContractManage locateContractByNo(String contractCode) {
|
||||
if (StringUtil.isBlank(contractCode)) {
|
||||
return null;
|
||||
}
|
||||
return contractManageMapper.selectOne(Wrappers.<ContractManage>lambdaQuery()
|
||||
.eq(ContractManage::getContractNo, contractCode.trim())
|
||||
.last("limit 1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 合同金蝶同步结果推送留痕(blade_hcs_check_log,biz_type=contract,合同未定位到时 bizId 为空,异常不影响主流程)
|
||||
*/
|
||||
private void writeKingdeeCallbackLog(ContractManage contractManage, String result, String msg) {
|
||||
try {
|
||||
HcsContractCheckLog checkLog = new HcsContractCheckLog();
|
||||
if (contractManage != null) {
|
||||
checkLog.setTenantId(contractManage.getTenantId());
|
||||
checkLog.setBizId(contractManage.getId());
|
||||
}
|
||||
checkLog.setBizType(HcsSyncConstant.BIZ_TYPE_CONTRACT);
|
||||
checkLog.setCheckType(HcsSyncConstant.CHECK_TYPE_KINGDEE);
|
||||
checkLog.setResult(result);
|
||||
checkLog.setMsg(StringUtil.left(msg, HcsSyncConstant.SYNC_MSG_MAX_LENGTH));
|
||||
checkLog.setCreateTime(LocalDateTime.now());
|
||||
hcsContractCheckLogMapper.insert(checkLog);
|
||||
} catch (Exception exception) {
|
||||
log.error("合同金蝶同步结果推送留痕写入失败:contractNo={}", contractManage == null ? null : contractManage.getContractNo(), exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 金蝶同步结果回填变更记录(changeRecordJson 追加一条;系统回调无登录用户,操作人记来源标识)
|
||||
*/
|
||||
private void appendKingdeeResultRecord(ContractManage contractManage, String changeContent) {
|
||||
List<Object> records = StringUtil.isBlank(contractManage.getChangeRecordJson())
|
||||
? new ArrayList<>() : new ArrayList<>(JSONUtil.toList(contractManage.getChangeRecordJson(), Object.class));
|
||||
Map<String, Object> record = new LinkedHashMap<>();
|
||||
record.put("changeDate", LocalDate.now().toString());
|
||||
record.put("handlerUserName", "合规系统回调");
|
||||
record.put("changeType", "金蝶同步结果");
|
||||
record.put("changeContent", changeContent);
|
||||
record.put("status", contractManage.getApprovalStatus());
|
||||
record.put("statusName", approvalStatusName(contractManage.getApprovalStatus()));
|
||||
records.add(record);
|
||||
contractManage.setChangeRecordJson(JSONUtil.toJsonStr(records));
|
||||
}
|
||||
|
||||
/**
|
||||
* 审批状态中文名(变更记录展示用,未匹配回退原值)
|
||||
*/
|
||||
private String approvalStatusName(String approvalStatus) {
|
||||
if (StringUtil.isBlank(approvalStatus)) {
|
||||
return null;
|
||||
}
|
||||
return switch (approvalStatus) {
|
||||
case "draft" -> "草稿";
|
||||
case "reviewing" -> "审批中";
|
||||
case "withdrawn" -> "已撤回";
|
||||
case "approved" -> "审批通过";
|
||||
case "rejected" -> "已驳回";
|
||||
case "change_reviewing" -> "变更审批中";
|
||||
case "change_approved" -> "变更审批通过";
|
||||
default -> approvalStatus;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送合同到 HCS:特批挂起门禁 → 风险校验(仅留痕,高风险不再阻断)→ 附件转传 → 判重 → 起草/更新 → 回填合规 fdId 置 synced
|
||||
* → 履约计划行级同步(C103-9,先于特批挂起)→ 高风险/黑名单客商合同挂起"特批审核"等待合规特批结果(报文随 fdSepcailContract=true,外部客商管控)
|
||||
|
||||
+10
-2
@@ -237,13 +237,15 @@ blade:
|
||||
- /feign/client/businessProcess/getProcessInfo
|
||||
- /feign/client/customerArchive/syncProcessNode
|
||||
- /feign/client/mkProcess/**
|
||||
# HCS 合同/付款特批结果回传 + 项目金蝶同步结果回传:合规系统经 iPaaS 网关无令牌调用,免登免授权
|
||||
# HCS 合同/付款特批结果回传 + 项目/合同金蝶同步结果回传:合规系统经 iPaaS 网关无令牌调用,免登免授权
|
||||
- /blade-transport/hcs/contractLegal/result
|
||||
- /hcs/contractLegal/result
|
||||
- /blade-transport/hcs/paymentLegal/result
|
||||
- /hcs/paymentLegal/result
|
||||
- /blade-transport/hcs/projectLegal/result
|
||||
- /hcs/projectLegal/result
|
||||
- /blade-transport/hcs/contractKingdee/result
|
||||
- /hcs/contractKingdee/result
|
||||
#授权认证配置
|
||||
auth:
|
||||
- method: ALL
|
||||
@@ -271,7 +273,7 @@ blade:
|
||||
- method: POST
|
||||
pattern: /kingdee-bfi/**
|
||||
expression: "permitAll()"
|
||||
# HCS 合同/付款特批结果回传 + 项目金蝶同步结果回传:合规系统经 iPaaS 网关无令牌调用,免登免授权
|
||||
# HCS 合同/付款特批结果回传 + 项目/合同金蝶同步结果回传:合规系统经 iPaaS 网关无令牌调用,免登免授权
|
||||
- method: POST
|
||||
pattern: /blade-transport/hcs/contractLegal/result
|
||||
expression: "permitAll()"
|
||||
@@ -290,6 +292,12 @@ blade:
|
||||
- method: POST
|
||||
pattern: /hcs/projectLegal/result
|
||||
expression: "permitAll()"
|
||||
- method: POST
|
||||
pattern: /blade-transport/hcs/contractKingdee/result
|
||||
expression: "permitAll()"
|
||||
- method: POST
|
||||
pattern: /hcs/contractKingdee/result
|
||||
expression: "permitAll()"
|
||||
#基础认证配置
|
||||
basic:
|
||||
- method: ALL
|
||||
|
||||
Reference in New Issue
Block a user