fix: 合同特批结果回传改按合规合同ID(hcs_fd_id)定位合同并联动审批状态

This commit is contained in:
刘泉佳
2026-10-23 15:57:51 +08:00
parent 7f68798505
commit f3699c9cf0
3 changed files with 41 additions and 64 deletions
@@ -292,13 +292,13 @@ public class HcsSyncController {
* <p>
* 免登免授权:blade.secure skip-url + auth permitAll 放行(doc/nacos/blade.yaml);
* iPaaS 网关注册映射:/gwzh/HTHG/contractLegal/result → /hcs/contractLegal/result;
* 报文 {sourceSystem, requestId=TMS合同ID, status=APPROVED/REJECTED, reason},
* approved 恢复流程展示,rejected 联动合同审批驳回。
* 报文 {sourceSystem, requestId=合规合同ID(hcs_fd_id), id, status=APPROVED/REJECTED, reason},
* 按 requestId=hcs_fd_id 定位合同,approved 恢复流程展示,rejected 联动合同审批驳回。
*/
@PostMapping("/contractLegal/result")
@ApiOperationSupport(order = 15)
@Operation(summary = "合同特批结果回传接收", description = "合规系统推送合同特批(金蝶同步)结果,按合同编号定位并联动特批状态,原文留痕")
public R<String> contractLegalResult(@RequestBody(required = false) HcsContractLegalResultDTO param) {
@Operation(summary = "合同特批结果回传接收", description = "合规系统推送合同特批结果,按合规合同ID(hcs_fd_id=requestId)定位并联动特批状态,原文留痕")
public R<String> contractLegalResult(@RequestBody(required = false) HcsLegalResultDTO param) {
return R.data(hcsContractSpecSyncSupport.handleLegalResult(param));
}
@@ -35,7 +35,7 @@ import org.springblade.core.tool.utils.StringUtil;
import org.springblade.hcs.config.HcsProperties;
import org.springblade.hcs.dto.HcsContractDetailQueryDTO;
import org.springblade.hcs.dto.HcsContractDetailVO;
import org.springblade.hcs.dto.HcsContractLegalResultDTO;
import org.springblade.hcs.dto.HcsLegalResultDTO;
import org.springblade.hcs.dto.HcsResult;
import org.springblade.hcs.feign.IHcsClient;
import org.springblade.transport.constant.HcsSyncConstant;
@@ -45,13 +45,9 @@ import org.springblade.transport.pojo.entity.ContractManage;
import org.springblade.transport.pojo.entity.HcsContractCheckLog;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* HCS 合同特批同步支撑组件(合规特批结果接收:contractLegal/result 推送 + C103-4 定时查询兜底 + 人工确认)。
@@ -61,7 +57,7 @@ import java.util.Map;
* 集团审批结果经合规 contractLegal/result 接口推送 TMS(替代未建设的 D103),或定时 C103-4 查询兜底联动 →
* approved 恢复流程,rejected 联动合同审批驳回。
* <p>
* 结果推送报文 {contractType, contractCode, requestId, success, reason, kingdeeId, sourceSystem=},原文留痕 blade_hcs_check_log。
* 结果推送报文 {sourceSystem, requestId=合规合同ID, id, status=APPROVED/REJECTED, reason},原文留痕 blade_hcs_check_log。
*
* @author Chill
*/
@@ -167,79 +163,56 @@ public class HcsContractSpecSyncSupport {
}
/**
* 合同特批结果接收处理(合规 contractLegal/result 推送,2026-10-13 按合规方最新字段表修正报文结构):
* 特批完成后合规侧同步金蝶并回调,报文 {contractType, contractCode, requestId, success, reason, kingdeeId, sourceSystem=};
* sourceSystem 须为 (不符抛"来源系统标识错误"异常);contractCode=TMS 合同编号定位(requestId 仅请求头回显不可定位);
* success=true 联动恢复"审批通过"(金蝶合同ID回填 kingdee_id);success=false 联动合同审批驳回走重新提交闭环(reason 随原文留痕)
* 合同特批结果接收处理(合规 contractLegal/result 推送,2026-10-23 按联调实际报文修正):
* 报文 {sourceSystem, requestId=合规合同ID, id, status=APPROVED/REJECTED, reason};
* sourceSystem 须与 third-party.hcs.src-system 一致(不符抛"来源系统标识错误"异常);
* requestId 即合规合同ID(与 id 同值),按 blade_contract_manage.hcs_fd_id 定位合同;
* approved 联动恢复"审批通过",rejected 联动合同审批驳回走重新提交闭环(reason 随原文留痕)
*
* @param param 合规推送报文
* @return 处理结果描述
*/
public String handleLegalResult(HcsContractLegalResultDTO param) {
// 来源系统校验:仅接受合规方约定的 ,防伪造回传
public String handleLegalResult(HcsLegalResultDTO param) {
// 来源系统校验:仅接受合规方约定的来源标识,防伪造回传
if (!StrUtil.equalsIgnoreCase(param == null ? null : param.getSourceSystem(), hcsProperties.getSrcSystem())) {
log.warn("合同特批结果推送来源系统标识错误:sourceSystem={}", param == null ? null : param.getSourceSystem());
throw new ServiceException("来源系统标识错误");
}
String raw = JSONUtil.toJsonStr(param);
ContractManage contractManage = locateContractByNo(param.getContractCode());
String requestId = param.getRequestId();
ContractManage contractManage = locateContractByFdId(requestId);
if (contractManage == null) {
log.warn("合同特批结果推送未定位到合同:contractCode={},报文已留痕", param.getContractCode());
log.warn("合同特批结果推送未定位到合同:requestId={},报文已留痕", requestId);
writeCallbackLog(null, HcsSyncConstant.CHECK_RESULT_SKIP, "合同特批结果推送未定位到合同:" + raw);
return "已留痕:未定位到合同(contractCode=" + param.getContractCode() + ")";
return "已留痕:未定位到合同(requestId=" + requestId + ")";
}
if (param.getSuccess() == null) {
log.warn("合同特批结果推送 success 字段缺失:contractNo={},报文已留痕", contractManage.getContractNo());
writeCallbackLog(contractManage, HcsSyncConstant.CHECK_RESULT_SKIP, "合同特批结果推送 success 字段缺失:" + raw);
return "已留痕:success 字段缺失(contractNo=" + contractManage.getContractNo() + ")";
String normalizedStatus = param.getStatus() == null ? "" : param.getStatus().trim();
if (!HcsSyncConstant.LEGAL_RESULT_APPROVED.equalsIgnoreCase(normalizedStatus)
&& !HcsSyncConstant.LEGAL_RESULT_REJECTED.equalsIgnoreCase(normalizedStatus)) {
log.warn("合同特批结果推送状态未识别:contractNo={},status={},报文已留痕", contractManage.getContractNo(), param.getStatus());
writeCallbackLog(contractManage, HcsSyncConstant.CHECK_RESULT_SKIP, "合同特批结果推送状态未识别:" + raw);
return "已留痕:状态字段未识别(contractNo=" + contractManage.getContractNo() + ")";
}
boolean success = param.getSuccess();
// 成功:特批完成且金蝶同步成功,恢复"审批通过";金蝶合同ID回填 kingdee_id 留痕保存
if (success) {
syncContractOnSpecResult(contractManage, true);
contractManage.setKingdeeId(param.getKingdeeId());
appendKingdeeResultRecord(contractManage, "金蝶同步成功:金蝶合同ID=" + param.getKingdeeId());
markSpec(contractManage, HcsSyncConstant.SPEC_STATUS_APPROVED,
"合同特批结果推送:金蝶同步成功,kingdeeId=" + param.getKingdeeId());
writeCallbackLog(contractManage, HcsSyncConstant.CHECK_RESULT_PASS, "合同特批结果推送:" + raw);
log.info("合同特批结果推送处理完成:contractNo={},结果=approved,kingdeeId={}", contractManage.getContractNo(), param.getKingdeeId());
return "特批结果已处理:approved";
}
// 失败:特批流程已完成但金蝶同步失败,联动合同审批驳回,走重新编辑→提交→审批→重新特批闭环(失败单独重试机制待联调确认)
syncContractOnSpecResult(contractManage, false);
appendKingdeeResultRecord(contractManage, "金蝶同步失败:" + param.getReason());
markSpec(contractManage, HcsSyncConstant.SPEC_STATUS_REJECTED, "合同特批结果推送:金蝶同步失败:" + param.getReason());
writeCallbackLog(contractManage, HcsSyncConstant.CHECK_RESULT_FAIL, "合同特批结果推送:" + raw);
log.info("合同特批结果推送处理完成:contractNo={},结果=rejected,reason={}", contractManage.getContractNo(), param.getReason());
return "特批结果已处理:rejected";
boolean approved = HcsSyncConstant.LEGAL_RESULT_APPROVED.equalsIgnoreCase(normalizedStatus);
// 特批结果联动合同审批状态(通过恢复展示,驳回联动审批驳回),随 markSpec 一并落库
syncContractOnSpecResult(contractManage, approved);
markSpec(contractManage, approved ? HcsSyncConstant.SPEC_STATUS_APPROVED : HcsSyncConstant.SPEC_STATUS_REJECTED,
"合同特批结果推送:" + normalizedStatus + (StringUtil.isBlank(param.getReason()) ? "" : ",reason=" + param.getReason()));
writeCallbackLog(contractManage, approved ? HcsSyncConstant.CHECK_RESULT_PASS : HcsSyncConstant.CHECK_RESULT_FAIL,
"合同特批结果推送:" + raw);
log.info("合同特批结果推送处理完成:contractNo={},结果={},reason={}", contractManage.getContractNo(), normalizedStatus, param.getReason());
return "特批结果已处理:" + (approved ? "approved" : "rejected");
}
/**
* 金蝶同步结果回填变更记录(changeRecordJson 追加一条;系统回调无登录用户,操作人记来源标识)
* 按合规合同ID定位合同(合规推送 requestId/id,即 blade_contract_manage.hcs_fd_id)
*/
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", HcsSyncConstant.approvalStatusName(contractManage.getApprovalStatus()));
records.add(record);
contractManage.setChangeRecordJson(JSONUtil.toJsonStr(records));
}
/**
* 按 ERP 合同编号定位合同(合规推送 contractCode,合同编号唯一)
*/
private ContractManage locateContractByNo(String contractCode) {
if (StringUtil.isBlank(contractCode)) {
private ContractManage locateContractByFdId(String requestId) {
if (StringUtil.isBlank(requestId)) {
return null;
}
return contractManageMapper.selectOne(Wrappers.<ContractManage>lambdaQuery()
.eq(ContractManage::getContractNo, contractCode.trim())
.eq(ContractManage::getHcsFdId, requestId.trim())
.last("limit 1"));
}
@@ -51,9 +51,13 @@ public class HcsLegalResultDTO implements Serializable {
*/
private String sourceSystem;
/**
* 业务单据ID(合同特批=TMS 合同ID,付款特批=TMS 付款申请ID)
* 定位单据ID(付款特批=TMS 付款申请ID;合同特批=合规合同ID,与 id 同值,按 blade_contract_manage.hcs_fd_id 匹配)
*/
private String requestId;
/**
* 合规侧单据ID(合同特批回传携带,与 requestId 同值=合规合同ID;付款特批回传不传,忽略)
*/
private String id;
/**
* 审批结果:APPROVED 通过 / REJECTED 驳回
*/