⚡ 金蝶应付单分录新增明细单价推送,取数去掉结算明细行兜底改为缺失即报错

This commit is contained in:
刘泉佳
2026-09-18 19:37:27 +08:00
parent 17b8da0a65
commit 63b2e89cb6
@@ -1134,6 +1134,8 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
entry.setMeasureunitNumber(entryGroup.measureunitNumber()); entry.setMeasureunitNumber(entryGroup.measureunitNumber());
// 【必填】数量:该行运输数量,无吨位数据时兜底 1 // 【必填】数量:该行运输数量,无吨位数据时兜底 1
entry.setQuantity(entryGroup.quantity().compareTo(BigDecimal.ZERO) > 0 ? entryGroup.quantity() : BigDecimal.ONE); entry.setQuantity(entryGroup.quantity().compareTo(BigDecimal.ZERO) > 0 ? entryGroup.quantity() : BigDecimal.ONE);
// 明细.单价:该行运输单价(费用明细 unit_price;单据头 ispricetotal=true 录入总价,单价仅作参考)
entry.setPrice(entryGroup.price());
// 应付金额(含税):该行应付货物费用行调整后总金额(含税) // 应付金额(含税):该行应付货物费用行调整后总金额(含税)
entry.setEPricetaxtotal(entryGroup.amount()); entry.setEPricetaxtotal(entryGroup.amount());
// 金额(不含税):该行结算金额(不含税)(应付费用行无不含税字段,经结算货物费用行回链) // 金额(不含税):该行结算金额(不含税)(应付费用行无不含税字段,经结算货物费用行回链)
@@ -1275,13 +1277,14 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
* *
* @param materialNumber 物料编码(货物类型档案货物编码) * @param materialNumber 物料编码(货物类型档案货物编码)
* @param measureunitNumber 计量单位编码(运费计算单位,档案暂无编码字段暂传单位名称) * @param measureunitNumber 计量单位编码(运费计算单位,档案暂无编码字段暂传单位名称)
* @param entryCode 分录唯一标识(awrp_entry_code):费用明细行id(兜底结算明细行id),同行多货物类型拆分时追加序号 * @param entryCode 分录唯一标识(awrp_entry_code):费用明细行id,同行多货物类型拆分时追加序号
* @param quantity 该行运输数量 * @param quantity 该行运输数量
* @param price 该行运输单价(费用明细 unit_price)
* @param amount 该行金额(含税),对应明细应付金额 e_pricetaxtotal * @param amount 该行金额(含税),对应明细应付金额 e_pricetaxtotal
* @param amountNoTax 该行金额(不含税),对应明细金额 e_amount * @param amountNoTax 该行金额(不含税),对应明细金额 e_amount
*/ */
private record BfiEntryGroup(String materialNumber, String measureunitNumber, String entryCode, private record BfiEntryGroup(String materialNumber, String measureunitNumber, String entryCode,
BigDecimal quantity, BigDecimal amount, BigDecimal amountNoTax) { BigDecimal quantity, BigDecimal price, BigDecimal amount, BigDecimal amountNoTax) {
} }
/** /**
@@ -1310,7 +1313,7 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
* 每货物一条)——货物类型/计量单位/运输数量/含税金额直接取应付费用行(含税金额取调整后总金额 after_amount); * 每货物一条)——货物类型/计量单位/运输数量/含税金额直接取应付费用行(含税金额取调整后总金额 after_amount);
* 应付费用行无不含税字段,不含税金额经结算货物费用行 sourceFeeId 回链(直接选明细路径 sourceFeeId=应付费用行id, * 应付费用行无不含税字段,不含税金额经结算货物费用行 sourceFeeId 回链(直接选明细路径 sourceFeeId=应付费用行id,
* 预结算合并路径 sourceFeeId=预结算费用行id,经预结算费用行 sourceFeeId 回溯应付费用行id); * 预结算合并路径 sourceFeeId=预结算费用行id,经预结算费用行 sourceFeeId 回溯应付费用行id);
* 结算明细无应付费用行时兜底结算明细行(金额取结算金额)。物料编码:货物类型(支持“、”分隔多类型) * 结算明细对应应付明细无货物费用行时直接报错拦截(取数必须来自应付费用明细,无兜底)。物料编码:货物类型(支持“、”分隔多类型)
* 匹配货物类型档案货物编码;分录唯一标识(awrp_entry_code)取费用明细行id(雪花id天然唯一,满足 A103-1 * 匹配货物类型档案货物编码;分录唯一标识(awrp_entry_code)取费用明细行id(雪花id天然唯一,满足 A103-1
* 对方系统唯一行id不能重复;A103-1 与应付单的勾稽关联走 awrp_finapbill_entryid=付款计划 * 对方系统唯一行id不能重复;A103-1 与应付单的勾稽关联走 awrp_finapbill_entryid=付款计划
* awrp_entry_code_p,与本标识无关);分录金额不按申请付款金额分摊。</p> * awrp_entry_code_p,与本标识无关);分录金额不按申请付款金额分摊。</p>
@@ -1326,7 +1329,7 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
// 去重收集结算明细单据号(保持行序),用于拼接财务应付单外部系统来源单据号 // 去重收集结算明细单据号(保持行序),用于拼接财务应付单外部系统来源单据号
List<String> documentNos = settlementDocumentNos(settlementDetails); List<String> documentNos = settlementDocumentNos(settlementDetails);
Map<String, String> cargoCodeByName = cargoCodeByName(context); Map<String, String> cargoCodeByName = cargoCodeByName(context);
// 应付明细id->应付货物费用行(分录主取数来源) // 应付明细id->应付货物费用行(分录取数来源,无兜底)
Map<Long, List<ReceivablePayableCargoFee>> payableFeesByDetailId = payableCargoFeesByDetailId(settlementDetails); Map<Long, List<ReceivablePayableCargoFee>> payableFeesByDetailId = payableCargoFeesByDetailId(settlementDetails);
// 应付费用行id->结算金额(不含税):应付费用行无不含税字段,经结算货物费用行 sourceFeeId 回链 // 应付费用行id->结算金额(不含税):应付费用行无不含税字段,经结算货物费用行 sourceFeeId 回链
Map<Long, BigDecimal> noTaxByPayableFeeId = settlementNoTaxByPayableFeeId(settlementDetails); Map<Long, BigDecimal> noTaxByPayableFeeId = settlementNoTaxByPayableFeeId(settlementDetails);
@@ -1334,27 +1337,19 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
for (FormalSettlementDetail settlementDetail : settlementDetails) { for (FormalSettlementDetail settlementDetail : settlementDetails) {
List<ReceivablePayableCargoFee> payableFees = List<ReceivablePayableCargoFee> payableFees =
payableFeesByDetailId.getOrDefault(settlementDetail.getSourceDetailId(), List.of()); payableFeesByDetailId.getOrDefault(settlementDetail.getSourceDetailId(), List.of());
if (Func.isNotEmpty(payableFees)) { if (Func.isEmpty(payableFees)) {
for (ReceivablePayableCargoFee payableFee : payableFees) { throw new ServiceException("推送金蝶财务应付单失败:结算明细[" + Func.toStr(settlementDetail.getDocumentNo())
appendEntryGroups(entryGroups, cargoCodeByName, payableFee.getCargoType(), + "]对应应付明细无货物费用行,分录取数必须来自应付费用明细,请先维护费用数据");
resolveMeasureunitNumber(payableFee.getPriceUnit(), payableFee.getQuantityUnit()), }
payableFee.getId(), for (ReceivablePayableCargoFee payableFee : payableFees) {
money(payableFee.getAfterAmount()), appendEntryGroups(entryGroups, cargoCodeByName, payableFee.getCargoType(),
noTaxByPayableFeeId.getOrDefault(payableFee.getId(), BigDecimal.ZERO), resolveMeasureunitNumber(payableFee.getPriceUnit(), payableFee.getQuantityUnit()),
money(payableFee.getTransportQuantity()), payableFee.getId(), money(payableFee.getUnitPrice()),
"应付货物费用[" + Func.toStr(payableFee.getCargoName()) + " 第" + Func.toStr(payableFee.getLineNo()) + "行]"); money(payableFee.getAfterAmount()),
} noTaxByPayableFeeId.getOrDefault(payableFee.getId(), BigDecimal.ZERO),
} else { money(payableFee.getTransportQuantity()),
appendEntryGroups(entryGroups, cargoCodeByName, settlementDetail.getCargoType(), "应付货物费用[" + Func.toStr(payableFee.getCargoName()) + " 第" + Func.toStr(payableFee.getLineNo()) + "行]");
resolveMeasureunitNumber(null, settlementDetail.getQuantityUnit()),
settlementDetail.getId(),
money(settlementDetail.getSettlementAmountTax()), money(settlementDetail.getSettlementAmountNoTax()),
money(settlementDetail.getTransportQuantity()),
"结算明细[" + Func.toStr(settlementDetail.getDocumentNo()) + " 第" + Func.toStr(settlementDetail.getLineNo()) + "行]");
} }
}
if (entryGroups.isEmpty()) {
throw new ServiceException("推送金蝶财务应付单失败:结算明细未解析出任何分录,请检查货物类型维护");
} }
return new BfiEntryGroupResult(entryGroups, documentNos); return new BfiEntryGroupResult(entryGroups, documentNos);
} }
@@ -1431,21 +1426,22 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
} }
/** /**
* 单条来源行(应付货物费用行或结算明细行)生成不聚合分录(每行一条); * 单条应付货物费用行生成不聚合分录(每行一条);
* 一行含多种货物类型时按类型拆为多条,金额与数量按份数均分(尾差计入最后一份) * 一行含多种货物类型时按类型拆为多条,金额与数量按份数均分(尾差计入最后一份)
* *
* @param entryGroups 分录集合(保持行序) * @param entryGroups 分录集合(保持行序)
* @param cargoCodeByName 货物类型名称->货物编码映射 * @param cargoCodeByName 货物类型名称->货物编码映射
* @param cargoType 货物类型(支持“、”分隔多类型) * @param cargoType 货物类型(支持“、”分隔多类型)
* @param measureunitNumber 计量单位编码(运费计算单位,档案暂无编码字段暂传单位名称) * @param measureunitNumber 计量单位编码(运费计算单位,档案暂无编码字段暂传单位名称)
* @param sourceRowId 来源行id(应付货物费用行id,兜底结算明细行id),雪花id天然唯一 * @param sourceRowId 应付货物费用行id,雪花id天然唯一
* @param price 该行运输单价(费用明细 unit_price)
* @param amount 该行金额(含税) * @param amount 该行金额(含税)
* @param amountNoTax 该行金额(不含税) * @param amountNoTax 该行金额(不含税)
* @param quantity 该行运输数量 * @param quantity 该行运输数量
* @param sourceDesc 来源行描述,用于异常提示 * @param sourceDesc 来源行描述,用于异常提示
*/ */
private void appendEntryGroups(List<BfiEntryGroup> entryGroups, Map<String, String> cargoCodeByName, private void appendEntryGroups(List<BfiEntryGroup> entryGroups, Map<String, String> cargoCodeByName,
String cargoType, String measureunitNumber, Long sourceRowId, String cargoType, String measureunitNumber, Long sourceRowId, BigDecimal price,
BigDecimal amount, BigDecimal amountNoTax, BigDecimal quantity, String sourceDesc) { BigDecimal amount, BigDecimal amountNoTax, BigDecimal quantity, String sourceDesc) {
List<String> cargoNames = splitCargoTypes(cargoType); List<String> cargoNames = splitCargoTypes(cargoType);
if (Func.isBlank(measureunitNumber)) { if (Func.isBlank(measureunitNumber)) {
@@ -1464,10 +1460,10 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
} }
String entryCode = cargoNames.size() > 1 ? rowEntryCode + "-" + (index + 1) : rowEntryCode; String entryCode = cargoNames.size() > 1 ? rowEntryCode + "-" + (index + 1) : rowEntryCode;
entryGroups.add(new BfiEntryGroup(materialNumber, measureunitNumber, entryCode, entryGroups.add(new BfiEntryGroup(materialNumber, measureunitNumber, entryCode,
quantityShares.get(index), amountShares.get(index), amountNoTaxShares.get(index))); quantityShares.get(index), price, amountShares.get(index), amountNoTaxShares.get(index)));
log.info("金蝶应付单分录生成:来源[{}],分录标识[{}],物料编码[{}],计量单位[{}],数量[{}],含税金额[{}],不含税金额[{}]", log.info("金蝶应付单分录生成:来源[{}],分录标识[{}],物料编码[{}],计量单位[{}],数量[{}],单价[{}],含税金额[{}],不含税金额[{}]",
sourceDesc, entryCode, materialNumber, measureunitNumber, sourceDesc, entryCode, materialNumber, measureunitNumber,
quantityShares.get(index), amountShares.get(index), amountNoTaxShares.get(index)); quantityShares.get(index), price, amountShares.get(index), amountNoTaxShares.get(index));
} }
} }