🐛 修复开票申请A303-4预检命中即整单返回导致多张发票张次无法断点续推

This commit is contained in:
刘泉佳
2026-11-04 01:28:52 +08:00
parent 2d0c4a4b26
commit 0818e493d3
@@ -782,31 +782,40 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
// 每张发票的金蝶业务单据编号(A303-1 billno 候选键,须唯一):单张=开票申请单号(兼容存量),多张=开票申请单号-张次序号
List<String> sheetBillNos = sheets.stream().map(sheet -> this.sheetBillNo(entity, sheet, sheets.size())).toList();
// A303-4 幂等预检:按全部候选 billno 查询金蝶是否已生成开票申请单(防上次推送成功但本地回滚的断链重推),
// 已生成的张次幂等跳过,未生成的张次重新推送
// 实测返回 billno 与推送值完全一致,按 billno 精确匹配;部分张次已生成时不可整单提前返回,须断点续推剩余张次
BfiInvoiceApplyQueryDTO idempotentQuery = new BfiInvoiceApplyQueryDTO();
idempotentQuery.setPageNo(1);
idempotentQuery.setPageSize(Math.max(sheets.size(), 10));
idempotentQuery.setBillno(sheetBillNos);
Set<String> existSheetBillNos = new LinkedHashSet<>();
Map<String, BfiInvoiceApplyVO> existApplyByBillNo = new LinkedHashMap<>();
BfiPageVO<BfiInvoiceApplyVO> existPage = bfiService.queryInvoiceApply(idempotentQuery);
if (existPage != null && Func.isNotEmpty(existPage.getRows())) {
for (BfiInvoiceApplyVO existApply : existPage.getRows()) {
if (existApply != null && Func.isNotBlank(existApply.getBillno())
&& sheetBillNos.contains(existApply.getBillno())) {
existSheetBillNos.add(existApply.getBillno());
// 金蝶已生成:直接回填视为同步成功(勾稽纠偏),星瀚内码一并回填(A902 附件上传定位用)
log.info("开票申请[{}]经 A303-4 查得金蝶开票申请单已生成(单据编号[{}],星瀚内码[{}]),跳过重复推送直接回填",
existApplyByBillNo.put(existApply.getBillno(), existApply);
log.info("开票申请[{}]经 A303-4 查得金蝶开票申请单已生成(单据编号[{}],星瀚内码[{}]),幂等跳过推送",
entity.getApplicationNo(), existApply.getBillno(), existApply.getId());
entity.setKingdeeBillNo(existApply.getBillno());
entity.setKingdeeBillId(existApply.getId() == null ? null : String.valueOf(existApply.getId()));
entity.setKingdeeStatus(KingdeeBfiConstant.KINGDEE_STATUS_SYNCED);
entity.setSyncedTime(LocalDateTime.now());
updateById(entity);
record(entity.getId(), "sync", "同步金蝶(勾稽回填)", TransportBusiConstant.APPROVED, TransportBusiConstant.APPROVED, null, existApply.getBillno());
return existApply.getBillno();
}
}
}
// 全部张次金蝶均已生成:直接勾稽回填视为同步成功(星瀚内码一并回填,A902 附件上传定位用)
if (!existApplyByBillNo.isEmpty() && existApplyByBillNo.keySet().containsAll(sheetBillNos)) {
entity.setKingdeeBillNo(String.join(",", existApplyByBillNo.keySet()));
entity.setKingdeeBillId(existApplyByBillNo.values().stream()
.map(BfiInvoiceApplyVO::getId).filter(Objects::nonNull).findFirst().map(String::valueOf).orElse(null));
entity.setKingdeeStatus(KingdeeBfiConstant.KINGDEE_STATUS_SYNCED);
entity.setSyncedTime(LocalDateTime.now());
updateById(entity);
record(entity.getId(), "sync", "同步金蝶(勾稽回填)", TransportBusiConstant.APPROVED, TransportBusiConstant.APPROVED, null, entity.getKingdeeBillNo());
return entity.getKingdeeBillNo();
}
// 部分张次已生成:先回填星瀚内码,已生成张次在下方逐张循环幂等跳过,未生成张次继续推送
Set<String> existSheetBillNos = existApplyByBillNo.keySet();
if (Func.isBlank(entity.getKingdeeBillId())) {
entity.setKingdeeBillId(existApplyByBillNo.values().stream()
.map(BfiInvoiceApplyVO::getId).filter(Objects::nonNull).findFirst().map(String::valueOf).orElse(null));
}
// 组装 A303-1 开票申请单(字段映射见设计文档 6.3/6.4)
if (Func.isBlank(entity.getIssuerName())) {
throw new ServiceException("推送金蝶开票申请失败:开票单位(销方)为空");