From 2079da6195b9794a46cc6a1bbe436bf0fa33aa63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=B3=89=E4=BD=B3?= <1107186916@qq.com> Date: Tue, 29 Sep 2026 01:50:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BB=98=E6=AC=BE=E7=94=B3=E8=AF=B7?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=87=91=E8=9D=B6=E5=8D=95=E6=8D=AE=E6=B6=88?= =?UTF-8?q?=E5=A4=B1=E8=A7=A3=E9=94=81=E5=85=9C=E5=BA=95=EF=BC=88A103-2?= =?UTF-8?q?=E8=BF=9E=E7=BB=AD=E4=B8=A4=E8=BD=AE=E6=9F=A5=E8=AF=A2=E6=B6=88?= =?UTF-8?q?=E5=A4=B1=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 金蝶侧反审核删除付款申请单后,本地停留已生成/付款中且状态门禁禁止重推,单据卡死。 按 ADR-0005 新增 unlockBill():置生成失败、清空金蝶单据内码/编号(日志留档)、不自动重推; A103-2 定时回写对已推送单据连续两轮未查得(Redis 计数,TTL 覆盖三个回写周期)触发解锁; failed 单据不参与计数,Redis 异常放弃判定,重推链 A103-2 勾稽预检兜底防重复单据; B901 UNLOCK 回调后续接入复用同一 unlockBill() --- .../service/IPaymentApplicationService.java | 12 +++ .../impl/PaymentApplicationServiceImpl.java | 91 ++++++++++++++++++- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IPaymentApplicationService.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IPaymentApplicationService.java index fddbe20c..1b5ced1c 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IPaymentApplicationService.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IPaymentApplicationService.java @@ -73,6 +73,18 @@ public interface IPaymentApplicationService extends BaseService[生成失败],原单据编号[{}]/内码[{}]已留档并清空,不自动重推,等待人工核实后重新推送", + entity.getPaymentNo(), source, entity.getKingdeeStatus(), entity.getKingdeeBillNo(), entity.getKingdeeBillId()); + baseMapper.update(null, Wrappers.lambdaUpdate() + .eq(PaymentApplication::getId, id) + .in(PaymentApplication::getKingdeeStatus, KingdeeBfiConstant.KINGDEE_STATUS_SYNCED, KingdeeBfiConstant.KINGDEE_STATUS_PAYING) + .set(PaymentApplication::getKingdeeStatus, KingdeeBfiConstant.KINGDEE_STATUS_FAILED) + .set(PaymentApplication::getKingdeeBillId, null) + .set(PaymentApplication::getKingdeeBillNo, null)); + } + + /** + * A103-2 未查得已推送单据的兜底判定(ADR-0005"连续两轮查询消失"): + * 仅对已生成/付款中单据经 Redis 计数累计消失轮次(生成失败单据金蝶查不到属正常态,等待人工重推,不参与计数), + * 连续达到阈值即解锁置失败态;重推链 A103-2 勾稽预检兜底,误判场景(金蝶单据实际存在)自动回填不产生重复单据 + * + * @param application 本轮未查得的付款申请 + */ + private void handlePayApplyMissed(PaymentApplication application) { + if (Func.isBlank(application.getPaymentNo()) + || (!KingdeeBfiConstant.KINGDEE_STATUS_SYNCED.equals(application.getKingdeeStatus()) + && !KingdeeBfiConstant.KINGDEE_STATUS_PAYING.equals(application.getKingdeeStatus()))) { + return; + } + String missKey = payApplyMissKey(application.getId()); + Long rounds; + try { + rounds = bladeRedis.getStringRedisTemplate().opsForValue().increment(missKey); + bladeRedis.getStringRedisTemplate().expire(missKey, PAY_RESULT_MISS_KEY_TTL_SECONDS, TimeUnit.SECONDS); + } catch (Exception exception) { + // Redis 异常时放弃本轮判定:解锁是破坏性动作(清空金蝶单号),宁可延迟不可误判 + log.warn("付款申请[{}]A103-2 消失轮次累计失败,本轮跳过解锁判定", application.getPaymentNo(), exception); + return; + } + if (rounds != null && rounds >= PAY_RESULT_MISS_UNLOCK_ROUNDS) { + log.warn("付款申请[{}]A103-2 连续[{}]轮未查得金蝶付款申请单,判定金蝶侧已反审核删除,执行解锁", + application.getPaymentNo(), rounds); + self().unlockBill(application.getId(), "A103-2 连续" + rounds + "轮查询消失"); + } else { + log.warn("付款申请[{}]A103-2 未查得金蝶付款申请单(第[{}]轮),金蝶侧可能已反审核删除,下一轮复核", + application.getPaymentNo(), rounds); + } + } + + /** A103-2 消失轮次计数键 */ + private String payApplyMissKey(Long id) { + return PAY_RESULT_MISS_KEY_PREFIX + id; + } + + /** 清除 A103-2 消失轮次计数(金蝶重新查得或单据解锁后调用) */ + private void clearPayApplyMissKey(Long id) { + if (id == null) return; + try { + bladeRedis.getStringRedisTemplate().delete(payApplyMissKey(id)); + } catch (Exception exception) { + log.warn("付款申请[{}]清除 A103-2 消失轮次计数失败", id, exception); + } + } + @Override public List syncKingdeeBatch(List ids) { if (ids == null || ids.isEmpty()) throw new ServiceException("请至少选择一条审批通过的付款申请"); @@ -588,8 +671,12 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl