refactor: 规范金蝶应付单同步日志英文标点并补充预付信息关键日志
This commit is contained in:
+30
-10
@@ -100,6 +100,10 @@ import java.util.stream.Collectors;
|
|||||||
* + 结算合计费用项(手动添加的每行一条);
|
* + 结算合计费用项(手动添加的每行一条);
|
||||||
* 物料编码按装卸大类/项目业务模式/运单运输方式映射,编码维护在 Nacos 配置 thirdparty.bfi.material.*(见 {@link #resolveMaterialNumber});
|
* 物料编码按装卸大类/项目业务模式/运单运输方式映射,编码维护在 Nacos 配置 thirdparty.bfi.material.*(见 {@link #resolveMaterialNumber});
|
||||||
* 运输类分录数量取运输量(按税率拆行时每行都取运输量)、装卸类默认 1;单价按结算金额/数量反算。</p>
|
* 运输类分录数量取运输量(按税率拆行时每行都取运输量)、装卸类默认 1;单价按结算金额/数量反算。</p>
|
||||||
|
* <p>预付信息分录(preentry,见 {@link #resolvePreEntries}):存在预付款抵扣(进度预付/项目预付核销)时,
|
||||||
|
* 按金蝶付款处理单(cas_paybill)逐笔送出 y_billtype/y_billid/y_settleamt,同 y_billid 合并求和;
|
||||||
|
* 任一笔应抵扣预付无法定位金蝶付款处理单内码(未付款/内码未回写/实付不足)时抛异常拦截应付单推送,
|
||||||
|
* 失败落 kingdee_fail_reason,付款结果回写后由重推任务自动续推。</p>
|
||||||
*
|
*
|
||||||
* @author Chill
|
* @author Chill
|
||||||
*/
|
*/
|
||||||
@@ -283,7 +287,9 @@ public class KingdeeApBillSyncSupport {
|
|||||||
* 幂等跳过保存并返回已有单据编号(说明上次同步已保存成功、在后续环节中断,应续推而非拦截报错)。
|
* 幂等跳过保存并返回已有单据编号(说明上次同步已保存成功、在后续环节中断,应续推而非拦截报错)。
|
||||||
* 明细分录取页面结算明细(每行按 货物→费用大类→税率 拆分)+ 结算合计费用项(每行一条),结算金额逐行直送;
|
* 明细分录取页面结算明细(每行按 货物→费用大类→税率 拆分)+ 结算合计费用项(每行一条),结算金额逐行直送;
|
||||||
* 汇率日期/汇率取结算单页面维护值;付款计划 planentity 暂不传(启用方案见方法内注释),
|
* 汇率日期/汇率取结算单页面维护值;付款计划 planentity 暂不传(启用方案见方法内注释),
|
||||||
* 当前由金蝶按明细自动汇总生成
|
* 当前由金蝶按明细自动汇总生成;
|
||||||
|
* 预付信息分录 preentry 仅在真正新建应付单时解析(幂等跳过路径不做预付校验),
|
||||||
|
* 每条对应一张金蝶付款处理单(cas_paybill),取数口径见 {@link #resolvePreEntries}
|
||||||
*
|
*
|
||||||
* @param apBillSrcCode 财务应付单防重键(正式结算单号_结算明细单据号拼接)
|
* @param apBillSrcCode 财务应付单防重键(正式结算单号_结算明细单据号拼接)
|
||||||
* @param settlement 正式结算单(合同/汇率日期/汇率取数来源)
|
* @param settlement 正式结算单(合同/汇率日期/汇率取数来源)
|
||||||
@@ -299,7 +305,7 @@ public class KingdeeApBillSyncSupport {
|
|||||||
String existBillNo = context.apBillNoCache().computeIfAbsent(apBillSrcCode, code ->
|
String existBillNo = context.apBillNoCache().computeIfAbsent(apBillSrcCode, code ->
|
||||||
queryApBillExistNos(List.of(code)).getOrDefault(code, ""));
|
queryApBillExistNos(List.of(code)).getOrDefault(code, ""));
|
||||||
if (Func.isNotEmpty(existBillNo)) {
|
if (Func.isNotEmpty(existBillNo)) {
|
||||||
log.info("正式结算单[{}]金蝶财务应付单已生成(单据编号[{}]),幂等跳过 A102-2 保存", subject, existBillNo);
|
log.info("正式结算单[{}]金蝶财务应付单已生成(单据编号[{}]), 幂等跳过 A102-2 保存", subject, existBillNo);
|
||||||
return new BfiApBillPushOutcome(existBillNo, null, true);
|
return new BfiApBillPushOutcome(existBillNo, null, true);
|
||||||
}
|
}
|
||||||
ContractManage contract = requireContract(settlement.getContractId(), context);
|
ContractManage contract = requireContract(settlement.getContractId(), context);
|
||||||
@@ -410,14 +416,14 @@ public class KingdeeApBillSyncSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 推送入参摘要(联调排查:防重键、分录条数、页面维护的汇率口径)
|
// 推送入参摘要(联调排查:防重键、分录条数、页面维护的汇率口径)
|
||||||
log.info("推送金蝶财务应付单:正式结算单[{}],防重键[{}],明细分录{}条,预付信息{}条,汇率日期[{}],汇率[{}]",
|
log.info("推送金蝶财务应付单: 正式结算单[{}], 防重键[{}], 明细分录{}条, 预付信息{}条, 汇率日期[{}], 汇率[{}]",
|
||||||
subject, apBillSrcCode, detailentry.size(), preEntries.size(), param.getExratedate(), param.getExchangerate());
|
subject, apBillSrcCode, detailentry.size(), preEntries.size(), param.getExratedate(), param.getExchangerate());
|
||||||
|
|
||||||
BfiBillSaveResultVO saveResult = bfiService.saveApBill(param);
|
BfiBillSaveResultVO saveResult = bfiService.saveApBill(param);
|
||||||
// 应付单id不落库,后续如需可经 A102-4 按防重键(awrp_src_sys + awrp_src_code)查询
|
// 应付单id不落库,后续如需可经 A102-4 按防重键(awrp_src_sys + awrp_src_code)查询
|
||||||
requireBfiSaveSuccess(saveResult, "推送金蝶财务应付单");
|
requireBfiSaveSuccess(saveResult, "推送金蝶财务应付单");
|
||||||
String billNo = saveResult.getResult().get(0).getNumber();
|
String billNo = saveResult.getResult().get(0).getNumber();
|
||||||
log.info("金蝶财务应付单保存成功:正式结算单[{}],单据编号[{}],明细分录{}条", subject, billNo, detailentry.size());
|
log.info("金蝶财务应付单保存成功: 正式结算单[{}], 单据编号[{}], 明细分录{}条", subject, billNo, detailentry.size());
|
||||||
// 星瀚应付单内码随结果返回(A902 附件上传定位用)
|
// 星瀚应付单内码随结果返回(A902 附件上传定位用)
|
||||||
BfiBillSaveResultItemVO savedItem = saveResult.getResult().get(0);
|
BfiBillSaveResultItemVO savedItem = saveResult.getResult().get(0);
|
||||||
return new BfiApBillPushOutcome(savedItem.getNumber(), savedItem.getId() == null ? null : String.valueOf(savedItem.getId()), false);
|
return new BfiApBillPushOutcome(savedItem.getNumber(), savedItem.getId() == null ? null : String.valueOf(savedItem.getId()), false);
|
||||||
@@ -487,8 +493,14 @@ public class KingdeeApBillSyncSupport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (demandAmounts.isEmpty()) {
|
if (demandAmounts.isEmpty()) {
|
||||||
|
// 无预付抵扣(无核销行且预付记录已付金额均为0):不送 preentry,保持报文字段缺省
|
||||||
|
log.info("应付单预付信息归集: 正式结算单[{}], 无预付抵扣, 不送预付信息分录", settlement.getFormalSettlementNo());
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
|
// 预付抵扣归集摘要(联调排查: 项目预付按核销行、进度预付按预付记录已付金额归集到底层付款申请)
|
||||||
|
log.info("应付单预付信息归集: 正式结算单[{}], 应抵扣付款申请{}笔, 合计金额{}",
|
||||||
|
settlement.getFormalSettlementNo(), demandAmounts.size(),
|
||||||
|
demandAmounts.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||||
// 批量取付款申请与付款处理记录(仅保留带回金蝶付款处理单内码的记录),逐笔校验并分摊
|
// 批量取付款申请与付款处理记录(仅保留带回金蝶付款处理单内码的记录),逐笔校验并分摊
|
||||||
Map<Long, PaymentApplication> applications = this.paymentApplicationMapper.selectBatchIds(demandAmounts.keySet()).stream()
|
Map<Long, PaymentApplication> applications = this.paymentApplicationMapper.selectBatchIds(demandAmounts.keySet()).stream()
|
||||||
.collect(Collectors.toMap(PaymentApplication::getId, Function.identity(), (first, second) -> first));
|
.collect(Collectors.toMap(PaymentApplication::getId, Function.identity(), (first, second) -> first));
|
||||||
@@ -542,6 +554,9 @@ public class KingdeeApBillSyncSupport {
|
|||||||
String summary = blockReasons.size() > PREPAY_BLOCK_REASON_LIMIT
|
String summary = blockReasons.size() > PREPAY_BLOCK_REASON_LIMIT
|
||||||
? String.join(";", blockReasons.subList(0, PREPAY_BLOCK_REASON_LIMIT)) + ";等" + blockReasons.size() + "笔预付无法抵扣"
|
? String.join(";", blockReasons.subList(0, PREPAY_BLOCK_REASON_LIMIT)) + ";等" + blockReasons.size() + "笔预付无法抵扣"
|
||||||
: String.join(";", blockReasons);
|
: String.join(";", blockReasons);
|
||||||
|
// 拦截关键日志:原因落盘供排查(异常文案同步落 kingdee_fail_reason,付款结果回写后由重推任务自动续推)
|
||||||
|
log.warn("应付单预付信息校验未通过, 拦截应付单推送: 正式结算单[{}], 应抵扣付款申请{}笔, 原因: {}",
|
||||||
|
settlement.getFormalSettlementNo(), demandAmounts.size(), summary);
|
||||||
throw new ServiceException("推送金蝶财务应付单失败:" + summary);
|
throw new ServiceException("推送金蝶财务应付单失败:" + summary);
|
||||||
}
|
}
|
||||||
List<BfiApBillSavePreEntryDTO> preEntries = new ArrayList<>();
|
List<BfiApBillSavePreEntryDTO> preEntries = new ArrayList<>();
|
||||||
@@ -554,6 +569,11 @@ public class KingdeeApBillSyncSupport {
|
|||||||
log.info("应付单预付信息分录: 正式结算单[{}], 来源[{}], y_billid={}, y_settleamt={}",
|
log.info("应付单预付信息分录: 正式结算单[{}], 来源[{}], y_billid={}, y_settleamt={}",
|
||||||
settlement.getFormalSettlementNo(), sourcesByBillId.get(billId), billId, settleAmount);
|
settlement.getFormalSettlementNo(), sourcesByBillId.get(billId), billId, settleAmount);
|
||||||
});
|
});
|
||||||
|
// 分录解析摘要:同一付款申请跨多预结算分摊后落在同一付款处理单的金额已按 y_billid 合并
|
||||||
|
log.info("应付单预付信息解析完成: 正式结算单[{}], 应抵扣付款申请{}笔, 生成分录{}条, 合计金额{}",
|
||||||
|
settlement.getFormalSettlementNo(), demandAmounts.size(), preEntries.size(),
|
||||||
|
preEntries.stream().map(BfiApBillSavePreEntryDTO::getYSettleamt)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||||
return preEntries;
|
return preEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -635,7 +655,7 @@ public class KingdeeApBillSyncSupport {
|
|||||||
+ "]无结算明细与结算合计费用项,无法解析分录");
|
+ "]无结算明细与结算合计费用项,无法解析分录");
|
||||||
}
|
}
|
||||||
// 分录解析摘要(联调排查:分录数=结算明细拆分行+手动添加的结算合计费用项,物料/分录标识逐条见下方分录生成日志)
|
// 分录解析摘要(联调排查:分录数=结算明细拆分行+手动添加的结算合计费用项,物料/分录标识逐条见下方分录生成日志)
|
||||||
log.info("金蝶应付单分录解析完成:正式结算单[{}],结算明细{}条 + 手工结算合计{}条 = 共{}条分录",
|
log.info("金蝶应付单分录解析完成: 正式结算单[{}], 结算明细{}条 + 手工结算合计{}条 = 共{}条分录",
|
||||||
settlement.getFormalSettlementNo(), settlementDetails.size(), manualSummaryFees.size(), entryGroups.size());
|
settlement.getFormalSettlementNo(), settlementDetails.size(), manualSummaryFees.size(), entryGroups.size());
|
||||||
return entryGroups;
|
return entryGroups;
|
||||||
}
|
}
|
||||||
@@ -680,7 +700,7 @@ public class KingdeeApBillSyncSupport {
|
|||||||
context.taxRateByRule(), rowAmount);
|
context.taxRateByRule(), rowAmount);
|
||||||
if (splits.isEmpty()) {
|
if (splits.isEmpty()) {
|
||||||
// 0元货物行(费用项与结算金额均为0)跳过不生成0元分录
|
// 0元货物行(费用项与结算金额均为0)跳过不生成0元分录
|
||||||
log.info("金蝶应付单分录生成:来源[{}],费用项与结算金额均为0,跳过该货物行", sourceDesc);
|
log.info("金蝶应付单分录生成: 来源[{}], 费用项与结算金额均为0, 跳过该货物行", sourceDesc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 运输类数量:取运单运输量(未维护兜底 1)
|
// 运输类数量:取运单运输量(未维护兜底 1)
|
||||||
@@ -707,7 +727,7 @@ public class KingdeeApBillSyncSupport {
|
|||||||
String entryCode = entryCodePrefix + "-" + split.getCategory().getLabel() + split.taxRateSuffix();
|
String entryCode = entryCodePrefix + "-" + split.getCategory().getLabel() + split.taxRateSuffix();
|
||||||
entryGroups.add(new BfiEntryGroup(materialNumber, entryCode, quantity, price, amount,
|
entryGroups.add(new BfiEntryGroup(materialNumber, entryCode, quantity, price, amount,
|
||||||
amountNoTax, cargoName, vehicleNo, context.settlement().getId()));
|
amountNoTax, cargoName, vehicleNo, context.settlement().getId()));
|
||||||
log.info("金蝶应付单分录生成:来源[{}],分录标识[{}],物料编码[{}],数量[{}],单价[{}],含税金额[{}],不含税金额[{}]",
|
log.info("金蝶应付单分录生成: 来源[{}], 分录标识[{}], 物料编码[{}], 数量[{}], 单价[{}], 含税金额[{}], 不含税金额[{}]",
|
||||||
sourceDesc, entryCode, materialNumber, quantity, price, amount, amountNoTax);
|
sourceDesc, entryCode, materialNumber, quantity, price, amount, amountNoTax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -741,7 +761,7 @@ public class KingdeeApBillSyncSupport {
|
|||||||
+ (Func.isBlank(feeItem) ? feeType : feeType + "-" + feeItem);
|
+ (Func.isBlank(feeItem) ? feeType : feeType + "-" + feeItem);
|
||||||
entryGroups.add(new BfiEntryGroup(materialNumber, entryCode, quantity, price, amount,
|
entryGroups.add(new BfiEntryGroup(materialNumber, entryCode, quantity, price, amount,
|
||||||
null, null, null, settlement.getId()));
|
null, null, null, settlement.getId()));
|
||||||
log.info("金蝶应付单分录生成:来源[{}],分录标识[{}],物料编码[{}],数量[{}],单价[{}],含税金额[{}]",
|
log.info("金蝶应付单分录生成: 来源[{}], 分录标识[{}], 物料编码[{}], 数量[{}], 单价[{}], 含税金额[{}]",
|
||||||
sourceDesc, entryCode, materialNumber, quantity, price, amount);
|
sourceDesc, entryCode, materialNumber, quantity, price, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -840,7 +860,7 @@ public class KingdeeApBillSyncSupport {
|
|||||||
} catch (RuntimeException ignored) {
|
} catch (RuntimeException ignored) {
|
||||||
// 计费方案 JSON 兼容历史数据,解析失败按未配置处理
|
// 计费方案 JSON 兼容历史数据,解析失败按未配置处理
|
||||||
}
|
}
|
||||||
log.info("合同[{}]计费方案解析:{}项费用类型/费用项配置税率{}", contract.getContractNo(), taxRateByRule.size(), taxRateByRule);
|
log.info("合同[{}]计费方案解析: {}项费用类型/费用项配置税率{}", contract.getContractNo(), taxRateByRule.size(), taxRateByRule);
|
||||||
return taxRateByRule;
|
return taxRateByRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1090,7 +1110,7 @@ public class KingdeeApBillSyncSupport {
|
|||||||
}
|
}
|
||||||
loaded.putIfAbsent(feeItem.getName().trim(), feeItem.getFeeCategory().trim());
|
loaded.putIfAbsent(feeItem.getName().trim(), feeItem.getFeeCategory().trim());
|
||||||
}
|
}
|
||||||
log.info("费用项档案加载:{}项(费用项名称 -> 费用大类编码)", loaded.size());
|
log.info("费用项档案加载: {}项(费用项名称 -> 费用大类编码)", loaded.size());
|
||||||
cache.putAll(loaded);
|
cache.putAll(loaded);
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user