diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/KingdeeApBillSyncSupport.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/KingdeeApBillSyncSupport.java index 181cc4be..f091b00f 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/KingdeeApBillSyncSupport.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/KingdeeApBillSyncSupport.java @@ -463,7 +463,9 @@ public class KingdeeApBillSyncSupport { List splits = splitFeeItems(parseFeeItems(feeItemsJson), context.feeCategoryByName(), context.taxRateByRule(), rowAmount); if (splits.isEmpty()) { - throw new ServiceException("推送金蝶失败:" + sourceDesc + "无费用项金额,无法拆分明细分录"); + // 0元货物行(费用项与结算金额均为0)跳过不生成0元分录 + log.info("金蝶应付单分录生成:来源[{}],费用项与结算金额均为0,跳过该货物行", sourceDesc); + return; } // 运输类数量:取运单运输量(未维护兜底 1) BigDecimal freightQuantity = transportQuantity != null && transportQuantity.compareTo(BigDecimal.ZERO) > 0 @@ -656,6 +658,10 @@ public class KingdeeApBillSyncSupport { continue; } BigDecimal amount = item.getValue() == null ? BigDecimal.ZERO : item.getValue(); + // 0元费用项跳过,不生成0元分录(金额缺失由运输类无税率组残差兜底) + if (amount.signum() == 0) { + continue; + } boolean loading = isLoadingCategory(item.getKey(), feeCategoryByName); BigDecimal taxRate = taxRateByRule == null ? null : taxRateByRule.get(item.getKey()); FeeLineSplit split = grouped.get(splitGroupKey(loading, taxRate)); diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/KingdeeEntrySplitTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/KingdeeEntrySplitTest.java index 1b34b596..9b0575b1 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/KingdeeEntrySplitTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/KingdeeEntrySplitTest.java @@ -136,4 +136,34 @@ class KingdeeEntrySplitTest { assertFalse(splits.get(1).isLoading()); assertEquals(new BigDecimal("100"), splits.get(1).getAmount()); } + + /** 0元费用项跳过:不生成0元分录(FJS2026101300005 结算单8条分录问题的回归用例) */ + @Test + void zeroAmountFeeItemsSkipped() { + Map feeItems = new LinkedHashMap<>(); + feeItems.put("运输费", new BigDecimal("3120")); + feeItems.put("附加运输补贴", BigDecimal.ZERO); + feeItems.put("装卸费", new BigDecimal("800")); + feeItems.put("仓储服务费", BigDecimal.ZERO); + Map taxRateByRule = Map.of( + "运输费", new BigDecimal("9"), + "附加运输补贴", new BigDecimal("6"), + "装卸费", new BigDecimal("6")); + List splits = KingdeeApBillSyncSupport.splitFeeItems(feeItems, Map.of(), taxRateByRule, new BigDecimal("3920")); + assertEquals(2, splits.size()); + assertFalse(splits.get(0).isLoading()); + assertEquals(new BigDecimal("3120"), splits.get(0).getAmount()); + assertTrue(splits.get(1).isLoading()); + assertEquals(new BigDecimal("800"), splits.get(1).getAmount()); + } + + /** 全部费用项为0且结算金额为0:拆分结果为空(调用方跳过该0元货物行) */ + @Test + void allZeroFeeItemsYieldEmptySplits() { + Map feeItems = new LinkedHashMap<>(); + feeItems.put("运输费", BigDecimal.ZERO); + feeItems.put("装卸费", BigDecimal.ZERO); + List splits = KingdeeApBillSyncSupport.splitFeeItems(feeItems, Map.of(), Map.of(), BigDecimal.ZERO); + assertTrue(splits.isEmpty()); + } }