fix: 修复多张发票开票结果部分回写即推进开票完成导致剩余张次不再查询

This commit is contained in:
刘泉佳
2026-10-29 18:17:13 +08:00
parent 4d16030999
commit 3f23baccd8
@@ -1158,7 +1158,8 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
}
/**
* 金蝶开票结果回写主体:A303-5 分批查询开票申请发票结果落库并推进开票完成,
* 金蝶开票结果回写主体:A303-5 分批查询开票申请发票结果落库,
* 多张发票全部张次均有开票结果才推进开票完成(终态),部分回写保持已同步继续轮询剩余张次,
* 由 {@link #syncKingdeeInvoiceResult()} 在分布式锁保护下调用
*
* @return 执行摘要
@@ -1177,16 +1178,20 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
log.info("金蝶开票结果回写开始:待回写开票申请{}笔", applications.size());
// 按 serialNo(金蝶开票申请单编号)分批(≤50/批)调 A303-5,销方税号与 A303-1 同源(开票单位→客商档案),按税号分组查询
Map<String, InvoiceApplication> applicationBySerialNo = new LinkedHashMap<>();
Map<Long, List<String>> serialNosByApplicationId = new LinkedHashMap<>();
applications.forEach(application -> {
if (Func.isNotBlank(application.getKingdeeBillNo())) {
// 多张发票时申请单金蝶单号逗号拼接存储,拆分为逐张单号分别归集回写
for (String serialNo : application.getKingdeeBillNo().split(",")) {
if (Func.isNotBlank(serialNo)) {
applicationBySerialNo.putIfAbsent(serialNo.trim(), application);
serialNosByApplicationId.computeIfAbsent(application.getId(), key -> new ArrayList<>()).add(serialNo.trim());
}
}
}
});
// 已有开票结果的单号归集(含历史已落库),全部张次齐备才推进开票完成
Set<String> serialNosWithResult = new LinkedHashSet<>();
Map<String, CustomerArchive> sellerCache = new LinkedHashMap<>();
Map<String, List<String>> serialNosBySellerTaxNo = new LinkedHashMap<>();
int unresolved = 0;
@@ -1211,7 +1216,6 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
log.info("金蝶开票结果回写:按销方税号分组完成,共{}组,销方税号无法解析跳过{}笔", serialNosBySellerTaxNo.size(), unresolved);
int invoiceWritten = 0;
int failed = 0;
int invoicedCount = 0;
for (Map.Entry<String, List<String>> group : serialNosBySellerTaxNo.entrySet()) {
List<String> groupSerialNos = group.getValue();
for (int from = 0; from < groupSerialNos.size(); from += INVOICE_RESULT_QUERY_BATCH) {
@@ -1232,10 +1236,11 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
// 批量查询当前批次已落库的发票记录(按发票号索引,用于幂等去重与缺文件地址补齐)
Map<String, InvoiceApplicationInvoice> existingInvoiceMap = batchQueryExistingInvoices(batch);
log.debug("金蝶开票结果回写:批次已存在发票记录数={}", existingInvoiceMap.size());
// 收集待插入的发票记录、待补文件地址的已有发票记录和待更新的开票申请
// 已落库记录对应的单号视为已有开票结果(跨批次幂等归集)
existingInvoiceMap.values().forEach(record -> serialNosWithResult.add(Func.toStr(record.getSerialNo()).trim()));
// 收集待插入的发票记录和待补文件地址的已有发票记录
List<InvoiceApplicationInvoice> toInsertInvoices = new ArrayList<>();
List<InvoiceApplicationInvoice> toPatchInvoices = new ArrayList<>();
List<InvoiceApplication> toUpdateApplications = new ArrayList<>();
for (BfiInvoiceApplyOpenApiBillVO bill : result.getData()) {
String billNo = bill.getBillNo();
InvoiceApplication application = applicationBySerialNo.get(billNo);
@@ -1277,13 +1282,8 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
}
if (inserted > 0) {
invoiceWritten += inserted;
// 查到发票:开票申请单推进开票完成(终态)
application.setKingdeeStatus(KingdeeBfiConstant.KINGDEE_STATUS_INVOICED);
// HCS 开票登记待更新:扫描任务凭 hcs_fd_id 走 C111-3 回填票据日期(D12)
application.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
toUpdateApplications.add(application);
invoicedCount++;
log.info("金蝶开票结果回写:开票申请[{}]状态推进为invoiced,本次写入发票{}张", application.getApplicationNo(), inserted);
serialNosWithResult.add(billNo);
log.info("金蝶开票结果回写:单据编号[{}]写入发票{}张", billNo, inserted);
}
}
// 批量插入发票记录
@@ -1296,17 +1296,29 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
Db.updateBatchById(toPatchInvoices);
log.info("金蝶开票结果回写:批量补齐发票文件地址{}条", toPatchInvoices.size());
}
// 批量更新开票申请状态
if (!toUpdateApplications.isEmpty()) {
updateBatchById(toUpdateApplications);
log.info("金蝶开票结果回写:批量更新开票申请状态{}笔", toUpdateApplications.size());
}
} catch (Exception exception) {
failed++;
log.error("金蝶开票结果回写批次异常:serialNo=[{}]", batchSerialNos, exception);
}
}
}
// 全部张次均有开票结果才推进开票完成(终态),部分回写保持已同步继续轮询剩余张次
List<InvoiceApplication> toCompleteApplications = new ArrayList<>();
for (InvoiceApplication application : applications) {
List<String> applicationSerialNos = serialNosByApplicationId.get(application.getId());
if (Func.isEmpty(applicationSerialNos) || !serialNosWithResult.containsAll(applicationSerialNos)) {
continue;
}
application.setKingdeeStatus(KingdeeBfiConstant.KINGDEE_STATUS_INVOICED);
// HCS 开票登记待更新:扫描任务凭 hcs_fd_id 走 C111-3 回填票据日期(D12)
application.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
toCompleteApplications.add(application);
}
int invoicedCount = toCompleteApplications.size();
if (!toCompleteApplications.isEmpty()) {
updateBatchById(toCompleteApplications);
log.info("金蝶开票结果回写:批量推进开票完成{}笔", invoicedCount);
}
log.info("金蝶开票结果回写完成:待查开票申请{}笔(销方税号无法解析跳过{}笔),回写发票{}张(开票完成{}笔,失败批次{}个)",
applications.size(), unresolved, invoiceWritten, invoicedCount, failed);
return "金蝶开票结果回写完成:待查开票申请" + applications.size() + "笔(销方税号无法解析跳过" + unresolved