fix: 付款申请金蝶付款结果回写统一按金蝶单据号匹配, 修复来源单号含环境后缀导致回写匹配失败状态不推进问题

This commit is contained in:
刘泉佳
2026-11-06 16:44:53 +08:00
parent 3acd1afd66
commit 9f1b295c2f
@@ -134,6 +134,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -903,9 +904,9 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
* 手动指定付款单据号(paymentNos)时仅回写指定单据;生成失败单据一并纳入: * 手动指定付款单据号(paymentNos)时仅回写指定单据;生成失败单据一并纳入:
* 金蝶侧已生成说明上次推送实际成功(如下推超时但远端已落单、本地事务回滚), * 金蝶侧已生成说明上次推送实际成功(如下推超时但远端已落单、本地事务回滚),
* 查得即回填纠正为已生成,避免人工重推产生重复单据,未查得则保持生成失败等待人工重推; * 查得即回填纠正为已生成,避免人工重推产生重复单据,未查得则保持生成失败等待人工重推;
* ② A103-2 付款申请单查询回填:指定单据号时按金蝶单据号(billno)精确查询(无金蝶单据号兜底按来源单号), * ② A103-2 付款申请单查询回填:统一按金蝶单据号(billno,全局唯一)分批精确查询,
* 定时全量回写按 paymentNo(awrp_src_code)分批查询,同一来源单号取最近修改一条, * 同一金蝶单据号取最近修改一条,按金蝶单据号与本地 kingdee_bill_no 匹配回填
* 回填金蝶单号/内码/同步状态/已付金额并联动预结算与正式结算付款记录;未查得保持现状等待下一轮; * 金蝶单号/内码/同步状态/已付金额并联动预结算与正式结算付款记录;未查得保持现状等待下一轮;
* ③ A103-4 付款处理查询补付款记录:付款中/已付款单据 + 已付款无付款记录单据(补偿), * ③ A103-4 付款处理查询补付款记录:付款中/已付款单据 + 已付款无付款记录单据(补偿),
* 按付款组织 + awrp_sourcebillno(金蝶单据号)数组精确查询,双键勾稽后回填付款记录; * 按付款组织 + awrp_sourcebillno(金蝶单据号)数组精确查询,双键勾稽后回填付款记录;
* ④ 汇总执行摘要:各计数随流程累计,单笔失败仅计数不中断整轮 * ④ 汇总执行摘要:各计数随流程累计,单笔失败仅计数不中断整轮
@@ -931,22 +932,18 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
int updated = 0; int updated = 0;
int failed = 0; int failed = 0;
int paidCount = 0; int paidCount = 0;
Map<String, BfiPayApplyVO> payApplyMap = new HashMap<>(); // A103-2 查询结果按金蝶单据号(billno,全局唯一)归并缓存,本地 kingdee_bill_no 与之同源匹配
Map<String, BfiPayApplyVO> payApplyByBillNo = new HashMap<>();
if (!applications.isEmpty()) { if (!applications.isEmpty()) {
// ② A103-2 付款申请单查询:指定单据号时按金蝶单据号(billno)精确查询,无金蝶单据号的兜底按来源单号查询; // ② A103-2 付款申请单查询:统一按金蝶单据号(billno)分批精确查询,同一金蝶单据号取最近修改的一条;
// 定时全量回写按 paymentNo(awrp_src_code)分批查询,同一来源单号取最近修改的一条 // 来源单号 awrp_src_code 因历史版本逻辑与 Nacos 配置变更含环境后缀(如 xxx-local),不作为回写查询与匹配依据
List<String> billNos = applications.stream() List<String> billNos = applications.stream()
.map(PaymentApplication::getKingdeeBillNo).filter(Func::isNotEmpty).distinct().toList(); .map(PaymentApplication::getKingdeeBillNo).filter(Func::isNotEmpty).distinct().toList();
List<String> fallbackSrcCodes = applications.stream()
.filter(application -> Func.isEmpty(application.getKingdeeBillNo()))
.map(PaymentApplication::getPaymentNo).filter(Func::isNotEmpty).distinct().toList();
this.batchForeach(billNos, PAY_RESULT_QUERY_BATCH, this.batchForeach(billNos, PAY_RESULT_QUERY_BATCH,
batch -> payApplyMap.putAll(this.latestPayApplyBySrcCode(this.queryPayApplyPagesByBillNo(batch)))); batch -> payApplyByBillNo.putAll(this.latestPayApplyByKey(this.queryPayApplyPagesByBillNo(batch), BfiPayApplyVO::getBillno)));
this.batchForeach(fallbackSrcCodes, PAY_RESULT_QUERY_BATCH,
batch -> payApplyMap.putAll(this.latestPayApplyBySrcCode(this.queryPayApplyPages(batch))));
// 逐单回写:未查得保持现状等待下一轮,查得即回填(解锁仅由金蝶删单回调触发) // 逐单回写:未查得保持现状等待下一轮,查得即回填(解锁仅由金蝶删单回调触发)
for (PaymentApplication application : applications) { for (PaymentApplication application : applications) {
BfiPayApplyVO payApply = payApplyMap.get(application.getPaymentNo()); BfiPayApplyVO payApply = payApplyByBillNo.get(application.getKingdeeBillNo());
if (payApply == null) { if (payApply == null) {
continue; continue;
} }
@@ -967,7 +964,7 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
// 候选二:已付款终态但尚无真实付款记录的单据(上轮付款记录回填失败的补偿) // 候选二:已付款终态但尚无真实付款记录的单据(上轮付款记录回填失败的补偿)
Map<Long, PaymentApplication> recordCandidates = new LinkedHashMap<>(); Map<Long, PaymentApplication> recordCandidates = new LinkedHashMap<>();
for (PaymentApplication application : applications) { for (PaymentApplication application : applications) {
BfiPayApplyVO payApply = payApplyMap.get(application.getPaymentNo()); BfiPayApplyVO payApply = payApplyByBillNo.get(application.getKingdeeBillNo());
if (payApply != null && !KingdeeBfiConstant.BFI_PAY_STATUS_UNPAID.equals(payApply.getPaystatus())) { if (payApply != null && !KingdeeBfiConstant.BFI_PAY_STATUS_UNPAID.equals(payApply.getPaystatus())) {
recordCandidates.put(application.getId(), application); recordCandidates.put(application.getId(), application);
} }
@@ -984,7 +981,7 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
// 兜底按合同关联项目解析(已付款补偿候选不在本轮 A103-2 返回内,须走兜底) // 兜底按合同关联项目解析(已付款补偿候选不在本轮 A103-2 返回内,须走兜底)
Map<String, List<PaymentApplication>> orgGroups = new LinkedHashMap<>(); Map<String, List<PaymentApplication>> orgGroups = new LinkedHashMap<>();
for (PaymentApplication application : recordCandidates.values()) { for (PaymentApplication application : recordCandidates.values()) {
BfiPayApplyVO payApply = payApplyMap.get(application.getPaymentNo()); BfiPayApplyVO payApply = payApplyByBillNo.get(application.getKingdeeBillNo());
String orgNumber = payApply == null ? null : payApply.getPayorgNumber(); String orgNumber = payApply == null ? null : payApply.getPayorgNumber();
if (Func.isBlank(orgNumber)) { if (Func.isBlank(orgNumber)) {
try { try {
@@ -1174,28 +1171,30 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
* @return 最近修改的付款申请单,未查询到返回 null * @return 最近修改的付款申请单,未查询到返回 null
*/ */
/** /**
* A103-2 查询结果按来源单号归并:同一 awrp_src_code 取最近修改(modifytime 最大)的一条, * A103-2 查询结果按指定键归并:同一键取最近修改(modifytime 最大)的一条,
* 定时回写与恢复勾稽共用同一取数规则 * 定时回写(按金蝶单据号 billno)与推送幂等预检(按来源单号 awrp_src_code)共用同一取数规则
* *
* @param payApplies A103-2 分页查询全量结果 * @param payApplies A103-2 分页查询全量结果
* @return 来源单号 -> 最近修改的付款申请单 * @param keyGetter 归并键提取函数
* @return 归并键 -> 最近修改的付款申请单
*/ */
private Map<String, BfiPayApplyVO> latestPayApplyBySrcCode(List<BfiPayApplyVO> payApplies) { private Map<String, BfiPayApplyVO> latestPayApplyByKey(List<BfiPayApplyVO> payApplies, Function<BfiPayApplyVO, String> keyGetter) {
Map<String, BfiPayApplyVO> latestBySrcCode = new HashMap<>(); Map<String, BfiPayApplyVO> latestByKey = new HashMap<>();
for (BfiPayApplyVO payApply : payApplies) { for (BfiPayApplyVO payApply : payApplies) {
if (Func.isEmpty(payApply.getAwrpSrcCode())) { String key = keyGetter.apply(payApply);
if (Func.isEmpty(key)) {
continue; continue;
} }
BfiPayApplyVO existing = latestBySrcCode.get(payApply.getAwrpSrcCode()); BfiPayApplyVO existing = latestByKey.get(key);
if (existing == null || this.strCompare(payApply.getModifytime(), existing.getModifytime()) > 0) { if (existing == null || this.strCompare(payApply.getModifytime(), existing.getModifytime()) > 0) {
latestBySrcCode.put(payApply.getAwrpSrcCode(), payApply); latestByKey.put(key, payApply);
} }
} }
return latestBySrcCode; return latestByKey;
} }
private BfiPayApplyVO queryLatestPayApply(String paymentNo) { private BfiPayApplyVO queryLatestPayApply(String paymentNo) {
return this.latestPayApplyBySrcCode(this.queryPayApplyPages(List.of(paymentNo))).get(paymentNo); return this.latestPayApplyByKey(this.queryPayApplyPages(List.of(paymentNo)), BfiPayApplyVO::getAwrpSrcCode).get(paymentNo);
} }
/** /**