From 7b7a40b94d30b77e3495691e4e0f9a3d30b2c1d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=B3=89=E4=BD=B3?= <1107186916@qq.com> Date: Wed, 23 Sep 2026 11:08:50 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E8=A1=A5=E5=85=85=E6=94=B6=E7=A5=A8?= =?UTF-8?q?=E5=8D=95=E6=8E=A8=E9=80=81=E9=87=91=E8=9D=B6=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E4=B8=8E=E6=89=B9=E9=87=8F=E6=8E=A8=E9=80=81?= =?UTF-8?q?=E5=85=B3=E9=94=AE=E7=8E=AF=E8=8A=82=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/InvoiceReceiptServiceImpl.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InvoiceReceiptServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InvoiceReceiptServiceImpl.java index 98758bab..ad1c345a 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InvoiceReceiptServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InvoiceReceiptServiceImpl.java @@ -491,6 +491,16 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl + * 编排流程:参数去重校验 → 批量组装推送计划(分摊/镜像/结算单/结算明细一次取回防 N+1)→ + * A102-4 应付单已生成预检 → A801-3 幂等预检(金蝶已有收票单则跳过保存续推指定)→ + * 逐单推送(单笔失败不中断整批)→ 汇总成功/失败笔数返回 + * + * @param ids 收票登记主键集合 + * @return 推送结果汇总(本批笔数、成功/失败笔数及失败原因明细) + */ @Override public String pushKingdeeReceivedInvoice(List ids) { if (Func.isEmpty(ids)) { @@ -500,26 +510,31 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl receipts = listByIds(distinctIds); if (receipts.size() != distinctIds.size()) { throw new ServiceException("部分收票登记不存在或已删除"); } // 批量组装推送计划:分摊关系/镜像/结算单/结算明细一次取回,避免逐单查库 N+1 + // 1) 收票登记与正式结算单的分摊关系(按登记id分组),用于"一票一应付"校验及防重键取数来源 Map> relationsByReceipt = settlementRelationMapper.selectList( Wrappers.lambdaQuery() .in(InvoiceReceiptSettlement::getInvoiceReceiptId, distinctIds) .orderByAsc(InvoiceReceiptSettlement::getCreateTime)).stream() .collect(Collectors.groupingBy(InvoiceReceiptSettlement::getInvoiceReceiptId)); + // 2) 票池镜像(A801-1 同步落库的发票数据),提供明细行 itemsJson、票种编码、购方单位等推送必填字段 List mirrorIds = receipts.stream().map(InvoiceReceipt::getKingdeeInvoicePoolId) .filter(Objects::nonNull).distinct().toList(); Map mirrorById = mirrorIds.isEmpty() ? Map.of() : invoicePoolMapper.selectBatchIds(mirrorIds).stream() .collect(Collectors.toMap(KingdeeInvoicePool::getId, Function.identity(), (first, second) -> first)); + // 3) 分摊关系指向的正式结算单,后续校验须为审批通过的应付类型结算单 List settlementIds = relationsByReceipt.values().stream().flatMap(List::stream) .map(InvoiceReceiptSettlement::getFormalSettlementId).filter(Objects::nonNull).distinct().toList(); Map settlementById = settlementIds.isEmpty() ? Map.of() : formalSettlementMapper.selectBatchIds(settlementIds).stream() .collect(Collectors.toMap(FormalSettlement::getId, Function.identity(), (first, second) -> first)); + // 4) 应付结算单的明细行(按行号升序),用于组装 A302-6 指定应付的防重键 apBillSrcCode List payableSettlementIds = settlementById.values().stream() .filter(settlement -> "payable".equals(settlement.getSettlementType())) .map(FormalSettlement::getId).toList(); @@ -529,19 +544,27 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl planByReceipt = new LinkedHashMap<>(); for (InvoiceReceipt receipt : receipts) { planByReceipt.put(receipt.getId(), buildReceivedInvoicePushPlan(receipt, relationsByReceipt.getOrDefault(receipt.getId(), List.of()), mirrorById, settlementById, detailsBySettlement)); } + long blockedCount = planByReceipt.values().stream().filter(plan -> plan.blockedReason() != null).count(); + log.info("推送金蝶收票单计划组装完成:本批 {} 笔,前置校验拦截 {} 笔", planByReceipt.size(), blockedCount); // A102-4 应付单已生成预检:本批防重键一次批量查询,缺单的登记逐单提示先完成付款侧同步 List apSrcCodes = planByReceipt.values().stream() .filter(plan -> plan.blockedReason() == null) .map(ReceivedInvoicePushPlan::apBillSrcCode).filter(Func::isNotBlank).distinct().toList(); Map apBillNoBySrcCode = apSrcCodes.isEmpty() ? Map.of() : kingdeeApBillSyncSupport.queryApBillExistNos(apSrcCodes); + log.info("推送金蝶收票单 A102-4 预检:待校验防重键 {} 个,已生成财务应付单 {} 个", apSrcCodes.size(), apBillNoBySrcCode.size()); // A801-3 幂等预检:按购方单位(接口必填)分组回看窗口翻页,本地按防重键匹配(金蝶已存在则跳过保存续推指定) Map kingdeeRowByInvoiceNo = queryKingdeeReceivedInvoiceRows(planByReceipt); + log.info("推送金蝶收票单 A801-3 预检:金蝶已存在收票单 {} 笔,命中单据将跳过保存续推指定", kingdeeRowByInvoiceNo.size()); KingdeeSyncContext context = KingdeeSyncContext.empty(); int success = 0; List failures = new ArrayList<>(); @@ -559,6 +582,7 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl