fix: 付款特批未通过前不推送履约数据,特批通过后自动补推

发起 C106-3 后挂起等待特批结果,审核期间仅回填整体同步状态,不再推送履约计划 C103-9 与履约记录 C108;
合规回调或人工确认特批通过后补推履约数据并联动金蝶,驳回不产生履约数据。
This commit is contained in:
刘泉佳
2026-10-23 17:22:18 +08:00
parent 9450f95bbc
commit 3ddf044810
@@ -49,10 +49,11 @@ import java.util.List;
/**
* HCS 付款链推送编排支撑组件(结算付款特批 C106-3/4 + 履约计划重推 C103-9 + 履约记录 C108-1/2 + 特批结果推送接收,设计文档 §5.0/§5.3/§5.5/§5.6)
* <p>
* 编排顺序:特批(提交时高风险/黑名单须特批附件或额度超额标记 need 时发起)→ 履约计划重推(付款审批款项金额累加行)→ 履约记录(审批通过新建 / 实际付款推进更新)。
* 编排顺序:特批(提交时高风险/黑名单须特批附件或额度超额标记 need 时发起)→ 特批通过后再推履约计划(付款审批款项金额累加行)→ 履约记录(审批通过新建 / 实际付款推进更新)。
* 特批审核期间(need/pushing/processing)仅发起/等待 C106,不推送履约计划与履约记录;驳回不产生履约数据。
* 特批流程ID 与履约记录ID 在各自 Support 内即时持久化;整体同步状态(hcs_sync_status)由本组件统一回写。
* 特批发起后 TMS 挂起 currentNode="特批审核",合规 paymentLegal/result 回调联动付款审批状态
* (通过恢复"审批通过"放行 / 驳回联动审批驳回走重新提交闭环),人工确认等效兜底。
* (通过恢复"审批通过"并补推履约数据 / 驳回联动审批驳回走重新提交闭环),人工确认等效兜底。
*
* @author Chill
*/
@@ -75,16 +76,31 @@ public class HcsPaymentSyncSupport {
private final ApplicationEventPublisher eventPublisher;
/**
* 推送付款申请到 HCS:特批(如需)→ 履约计划重推(C103-9 款项金额累加行)→ 履约记录(新建/更新)→ 回填整体同步状态
* 推送付款申请到 HCS:特批(need 时发起 C106-3 后挂起)→ 特批通过后履约计划重推(C103-9 款项金额累加行)→ 履约记录(新建/更新)→ 回填整体同步状态
*
* @param payment 付款申请单(approvalStatus=approved)
* @return 推送结果描述
*/
public String pushPayment(PaymentApplication payment) {
StringBuilder result = new StringBuilder();
// ① 结算付款特批:提交时高风险/黑名单(须特批附件)或额度超额(hcs_spec_status=need)且未发起时发起 C106-3
// ① 结算付款特批:提交时高风险/黑名单(须特批附件)或额度超额(hcs_spec_status=need)且未发起时发起 C106-3;
// 发起后挂起等待特批结果,履约计划与履约记录由特批通过后的 pushAfterSpecApproved 补推(驳回不产生履约数据)
if (HcsSyncConstant.SPEC_STATUS_NEED.equals(payment.getHcsSpecStatus())) {
result.append(hcsSpecPaySyncSupport.pushSpecPay(payment));
String specResult = hcsSpecPaySyncSupport.pushSpecPay(payment);
// C106-4 更新路径不改状态,统一归一为特批审核中,避免下轮扫描重复发起
if (HcsSyncConstant.SPEC_STATUS_NEED.equals(payment.getHcsSpecStatus())) {
payment.setHcsSpecStatus(HcsSyncConstant.SPEC_STATUS_PROCESSING);
payment.setCurrentNode(HcsSyncConstant.SPEC_REVIEW_NODE);
}
markSynced(payment, specResult);
return specResult;
}
// 特批审核中:仅等待合规回调/人工确认,不推送履约计划与履约记录
if (HcsSyncConstant.SPEC_STATUS_PUSHING.equals(payment.getHcsSpecStatus())
|| HcsSyncConstant.SPEC_STATUS_PROCESSING.equals(payment.getHcsSpecStatus())) {
String message = "付款特批审核中,待特批通过后推送履约数据";
markSynced(payment, message);
return message;
}
// ② 履约计划重推(C103-9 行级更新):付款审批通过累加款项金额置 row_op=update 的计划行,
// 凭已存合规阶段ID 重推;独立于履约记录开关,推送失败抛出由付款链置 failed 重试兜底
@@ -127,6 +143,22 @@ public class HcsPaymentSyncSupport {
return "履约规则无待同步行".equals(stageResult) ? "" : stageResult;
}
/**
* 特批通过后补推履约数据(C103-9 计划重推 + C108 履约记录):补推失败置 failed 留待人工重推兜底,
* 不阻断特批结果落库与金蝶补推
*
* @param payment 付款申请单(hcs_spec_status=approved)
*/
private void pushAfterSpecApproved(PaymentApplication payment) {
try {
this.pushPayment(payment);
} catch (Exception exception) {
String message = StringUtil.isBlank(exception.getMessage()) ? "履约数据推送异常" : exception.getMessage();
markFailed(payment, message);
log.error("付款特批通过后履约数据推送失败:paymentNo={},{}", payment.getPaymentNo(), message, exception);
}
}
/**
* 单条手动重推:重置为待同步并清零重试计数后立即推送(页面"推送合规/重推"按钮入口)
*
@@ -175,6 +207,10 @@ public class HcsPaymentSyncSupport {
syncPaymentOnSpecResult(payment, HcsSyncConstant.SPEC_STATUS_APPROVED.equals(result));
payment.setHcsSpecStatus(result);
paymentApplicationMapper.updateById(payment);
// 特批通过后补推履约计划与履约记录(驳回不产生履约数据),失败不阻断后续金蝶补推
if (HcsSyncConstant.SPEC_STATUS_APPROVED.equals(result)) {
this.pushAfterSpecApproved(payment);
}
publishKingdeeAutoSyncOnSpecApproved(payment, result);
log.info("HCS特批结果人工确认:paymentNo={},specFdId={},结果={}", payment.getPaymentNo(), payment.getHcsSpecFdId(), result);
return "特批结果已确认:" + result;
@@ -215,6 +251,10 @@ public class HcsPaymentSyncSupport {
syncPaymentOnSpecResult(payment, HcsSyncConstant.SPEC_STATUS_APPROVED.equals(status));
payment.setHcsSpecStatus(status);
paymentApplicationMapper.updateById(payment);
// 特批通过后补推履约计划与履约记录(驳回不产生履约数据),失败不阻断后续金蝶补推
if (HcsSyncConstant.SPEC_STATUS_APPROVED.equals(status)) {
this.pushAfterSpecApproved(payment);
}
publishKingdeeAutoSyncOnSpecApproved(payment, status);
log.info("付款特批结果推送处理完成:paymentNo={},结果={},reason={}", payment.getPaymentNo(), status, param.getReason());
return "特批结果已处理:" + status;