feat: 审批通过提示拼接金蝶自动同步结果

This commit is contained in:
刘泉佳
2026-10-22 14:42:01 +08:00
parent 5b9a55d1b7
commit f3d899dcb8
6 changed files with 50 additions and 4 deletions
@@ -202,12 +202,16 @@ public class FormalSettlementController extends BladeController {
return approveResponse();
}
/** 审批接口统一响应:审批已生效,自动推送失败原因以警告文案返回(data=false 供前端区分提示样式) */
/** 审批接口统一响应:审批已生效,自动推送结果(成功单据号/失败原因)一并返回;失败用 data=false 供前端区分提示样式 */
private R approveResponse() {
String syncFailure = KingdeeApprovalSyncListener.pollSyncFailure();
String syncResult = KingdeeApprovalSyncListener.pollSyncResult();
if (syncFailure != null) {
return R.data(Boolean.FALSE, "审批通过,但自动同步金蝶失败:" + syncFailure);
}
if (syncResult != null) {
return R.success("审批通过,已同步金蝶:" + syncResult);
}
return R.success("审批通过");
}
@@ -134,12 +134,16 @@ public class InvoiceApplicationController extends BladeController {
return approveResponse();
}
/** 审批接口统一响应:审批已生效,自动推送失败原因以警告文案返回(data=false 供前端区分提示样式) */
/** 审批接口统一响应:审批已生效,自动推送结果(成功单据号/失败原因)一并返回;失败用 data=false 供前端区分提示样式 */
private R approveResponse() {
String syncFailure = KingdeeApprovalSyncListener.pollSyncFailure();
String syncResult = KingdeeApprovalSyncListener.pollSyncResult();
if (syncFailure != null) {
return R.data(Boolean.FALSE, "审批通过,但自动同步金蝶失败:" + syncFailure);
}
if (syncResult != null) {
return R.success("审批通过,已同步金蝶:" + syncResult);
}
return R.success("审批通过");
}
@@ -150,12 +150,16 @@ public class InvoiceReceiptController extends BladeController {
return approveResponse();
}
/** 审批接口统一响应:审批已生效,自动推送失败原因以警告文案返回(data=false 供前端区分提示样式) */
/** 审批接口统一响应:审批已生效,自动推送结果(成功单据号/失败原因)一并返回;失败用 data=false 供前端区分提示样式 */
private R approveResponse() {
String syncFailure = KingdeeApprovalSyncListener.pollSyncFailure();
String syncResult = KingdeeApprovalSyncListener.pollSyncResult();
if (syncFailure != null) {
return R.data(Boolean.FALSE, "审批通过,但自动同步金蝶失败:" + syncFailure);
}
if (syncResult != null) {
return R.success("审批通过,已同步金蝶:" + syncResult);
}
return R.success("审批通过");
}
@@ -99,12 +99,16 @@ public class PaymentApplicationController extends BladeController {
return approveResponse();
}
/** 审批接口统一响应:审批已生效,自动推送失败原因以警告文案返回(data=false 供前端区分提示样式) */
/** 审批接口统一响应:审批已生效,自动推送结果(成功单据号/失败原因)一并返回;失败用 data=false 供前端区分提示样式 */
private R approveResponse() {
String syncFailure = KingdeeApprovalSyncListener.pollSyncFailure();
String syncResult = KingdeeApprovalSyncListener.pollSyncResult();
if (syncFailure != null) {
return R.data(Boolean.FALSE, "审批通过,但自动同步金蝶失败:" + syncFailure);
}
if (syncResult != null) {
return R.success("审批通过,已同步金蝶:" + syncResult);
}
return R.success("审批通过");
}
@PostMapping("/return")
@@ -39,12 +39,16 @@ public class SettlementAdjustmentController extends BladeController {
String hint = service.approve(request);
// 未推送场景自动推送失败原因以警告文案返回(data=false 供前端区分提示样式)
String syncFailure = KingdeeApprovalSyncListener.pollSyncFailure();
String syncResult = KingdeeApprovalSyncListener.pollSyncResult();
if (Func.isNotBlank(syncFailure)) {
return R.data(Boolean.FALSE, "审批通过,但自动同步金蝶失败:" + syncFailure);
}
if (Func.isNotBlank(hint)) {
return R.data(Boolean.TRUE, "审批通过;" + hint);
}
if (Func.isNotBlank(syncResult)) {
return R.success("审批通过,已同步金蝶:" + syncResult);
}
return R.success("审批通过");
}
@PostMapping("/return") public R returnBill(@RequestBody SettlementAdjustmentStatusRequest request) { service.returnBill(request); return R.success("已驳回"); }
@@ -68,6 +68,9 @@ public class KingdeeApprovalSyncListener {
/** 当前审批请求线程的自动推送失败原因,供 Controller 取走提示前端(见类注释线程说明) */
private static final ThreadLocal<String> SYNC_FAILURE = new ThreadLocal<>();
/** 当前审批请求线程的自动推送成功结果(金蝶单据号/推送摘要),供 Controller 拼进提示文案 */
private static final ThreadLocal<String> SYNC_RESULT = new ThreadLocal<>();
/**
* 取走并清除当前审批请求的自动推送失败原因;null 表示推送成功或未触发推送。
* 须在 service.approve 返回后立即调用(监听器在审批事务提交时同步执行完毕)。
@@ -78,6 +81,23 @@ public class KingdeeApprovalSyncListener {
return failure;
}
/**
* 取走并清除当前审批请求的自动推送成功结果;null 表示推送失败或未触发推送。
* 与 {@link #pollSyncFailure()} 成对调用,避免线程复用导致结果串单。
*/
public static String pollSyncResult() {
String result = SYNC_RESULT.get();
SYNC_RESULT.remove();
return result;
}
/** 记录本次自动推送的成功结果,空值不记录(未触发推送/接口无返回) */
private static void recordResult(String result) {
if (result != null && !result.isBlank()) {
SYNC_RESULT.set(result);
}
}
/**
* 事务提交后同步推送。fallbackExecution=true 兜底:approve 未开启事务时事件不再被默认丢弃。
*
@@ -86,6 +106,7 @@ public class KingdeeApprovalSyncListener {
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true)
public void onBillApproved(KingdeeBillApprovedEvent event) {
SYNC_FAILURE.remove();
SYNC_RESULT.remove();
try {
switch (event.bizType()) {
case KingdeeBillApprovedEvent.BIZ_FORMAL_SETTLEMENT -> pushSettlement(event.id());
@@ -97,6 +118,7 @@ public class KingdeeApprovalSyncListener {
} catch (Exception exception) {
// 推送失败只记日志(失败状态已在推送方法内独立事务落库),不影响审批结果,交给重推任务与手动按钮兜底;
// 原因暂存线程变量,由审批 Controller 取走提示前端
SYNC_RESULT.remove();
log.error("审批通过自动同步金蝶失败 bizType={} id={}", event.bizType(), event.id(), exception);
String reason = exception.getMessage() == null ? "金蝶接口调用异常" : exception.getMessage();
// 手动按钮同文案已带"推送金蝶失败:"前缀,拼提示时去掉避免重复
@@ -110,6 +132,7 @@ public class KingdeeApprovalSyncListener {
}
log.info("正式结算单[{}]审批通过自动同步金蝶开始", id);
String billNo = formalSettlementService.syncKingdee(id);
recordResult(billNo);
log.info("正式结算单[{}]审批通过自动同步金蝶完成:billNo={}", id, billNo);
}
@@ -128,6 +151,7 @@ public class KingdeeApprovalSyncListener {
}
log.info("付款申请[{}]审批通过自动同步金蝶开始", id);
String kingdeeBillId = paymentApplicationService.syncKingdee(id);
recordResult(kingdeeBillId);
log.info("付款申请[{}]审批通过自动同步金蝶完成:kingdeeBillId={}", id, kingdeeBillId);
}
@@ -137,6 +161,7 @@ public class KingdeeApprovalSyncListener {
}
log.info("开票申请[{}]审批通过自动同步金蝶开始", id);
String billNo = invoiceApplicationService.syncKingdee(id);
recordResult(billNo);
log.info("开票申请[{}]审批通过自动同步金蝶完成:billNo={}", id, billNo);
}
@@ -146,6 +171,7 @@ public class KingdeeApprovalSyncListener {
}
log.info("收票登记[{}]审批通过自动推送金蝶收票单开始", id);
String summary = invoiceReceiptService.pushKingdeeReceivedInvoice(List.of(id), true);
recordResult(summary);
log.info("收票登记[{}]审批通过自动推送金蝶收票单完成:{}", id, summary);
}
}