docs: 金蝶仓储费用独立分录与仓储物料映射设计

This commit is contained in:
刘泉佳
2026-11-03 17:17:29 +08:00
parent 34c89bde9d
commit 8346ed5256
@@ -0,0 +1,130 @@
# 金蝶仓储费用独立分录与仓储物料映射设计(修订版)
> 日期:2026-11-03(修订:去掉名称关键字兜底;明确仅字典+Nacos 配置不生效,需最小代码改动)
> 范围:财务应付单(A102-2)、财务应收单(A302-2)、付款申请(A103-1)分录拆分口径(三方共用 `resolveEntryGroups`,一处改动三方生效)
> 关联文档:`2026-10-13-金蝶应付应收收票单明细分录拆分与物料映射逻辑梳理.md`
---
## 1. 背景与现状问题
当前分录拆分维度为 **货物 → 费用大类(装卸/运输)→ 税率**,费用大类只有二分类:
- 装卸大类:费用项档案分类编码 = A10
- 运输大类:**其余全部**(含仓储等)
| # | 场景 | 现状行为 | 问题 |
| --- | --- | --- | --- |
| 1 | 结算明细行的仓储费用项(如「仓储堆存保管费」,档案分类 A02) | 落入「运输费」组,映射运输物料(XDWL11010001 等),数量取运单运输量 | 物料错误、数量口径错误 |
| 2 | 结算合计手动添加的仓储费用 | 非运费类统一映射装卸物料 XDWL11002004 | 物料错误 |
数据事实(本地库 transport):业务字典 `fee_category` 无「仓储」编码(现有 A01/A02/A03/A04/A09/A10);档案「仓储堆存保管费」挂在 A02。
---
## 2. 为什么仅加字典 + Nacos 配置不生效(结论先行)
代码里仓储分支不存在,新增的字典编码与配置项没有消费方:
| # | 证据(`KingdeeApBillSyncSupport` / `BfiProperties`) | 后果 |
| --- | --- | --- |
| 1 | `BfiProperties.Material` 只有 `domestic`/`international`/`loading` 三个属性(BfiProperties.java L211-233),**无 `warehouse` 字段**;Spring 对未知配置项静默忽略 | Nacos 加 `material.warehouse` 为死配置,不报错也不生效 |
| 2 | `splitFeeItems` 大类判定仅 `isLoadingCategory`(A10)二分类(L682-712),仓储费用项仍落入运输费组 | 明细行仓储费照旧映射运输物料、数量取运输量 |
| 3 | `resolveMaterialNumber` 仅 装卸/国际/国内 三分支(L573-599);手动合计行非运费类固定走 `loading`(L546-547) | 手动仓储费照旧映射装卸物料 XDWL11002004 |
| 4 | 字典编码 A01/A10 为硬编码常量(L104-106),档案里的 A05 无代码比较它 | 字典加了也没有判定逻辑消费 |
因此:**字典 + Nacos 是必要的数据/配置部分,但必须配合最小代码改动**(约 6 处、20 行以内,见第 5 节)。
---
## 3. 需求口径
1. **仓储大类费用**:独立成组生成一行明细;同大类税率不同按税率拆多行
2. **结算合计手动添加费用**(manual_flag=1):每行单独一条分录(现状保留,仅物料映射修正)
3. **一车多货**:按货物拆分多行(现状保留,仓储同样适用)
4. **仓储物料编码**:`XDWL11002001`(Nacos `thirdparty.bfi.material.warehouse` 可覆盖)
---
## 4. 目标方案
### 4.1 大类判定(无关键字兜底,纯数据驱动)
- 费用项档案 `blade_fee_item.fee_category = A05` → 仓储大类(新增字典)
- **不做名称关键字兜底**:档案未配 A05 的费用项照旧走现有分类(运输/装卸),分类准确性由档案维护负责
- 代码侧仅新增常量 `FEE_CATEGORY_WAREHOUSE = "A05"` 与档案编码比较
### 4.2 拆分与合并(`splitFeeItems`)
- 分组键 `大类@税率` 扩为三态:`运输费@税率` / `仓储@税率` / `装卸@税率`
- 税率来源不变(合同计费方案),未配置归该大类无税率组;残差仍并入运输费无税率组
- 同货物行内同大类同税率合并一行、不同税率拆行 —— 满足需求 1
- 分录标识:`单据号-货物序号-仓储[-税率]`
- `FeeLineSplit.boolean loading` 升级为三态枚举 `FeeCategory{FREIGHT, WAREHOUSE, LOADING}`,保留 `isLoading()` 便捷方法
### 4.3 分录字段口径
| 分录字段 | 运输大类行 | 仓储大类行(新增) | 装卸大类行 | 结算合计手动费用行 |
| --- | --- | --- | --- | --- |
| 物料编码 | 国际/国内按运输方式映射 | **`material.warehouse`(XDWL11002001)** | `material.loading` | 运费类→同运输行;仓储类(档案A05)→`material.warehouse`;其余→`material.loading` |
| 数量 | 运单运输量(兜底1) | **1**(同装卸) | 1 | 1 |
| 运输货物/车号 | 货物名/车号 | 货物名/车号 | 同左 | 不传 |
| 不含税金额 | 仅运输类首行携带 | 不传(同装卸) | 不传 | 不传 |
| 分录标识 | 单据号-货物序号-运输费[-税率] | 单据号-货物序号-仓储[-税率] | 单据号-货物序号-装卸[-税率] | 结算单号-费用类型[-费用项] |
收票单(A303-2)按票行生成、不经 `splitFeeItems`,不受影响。
---
## 5. 改动清单
| # | 类型 | 位置 | 内容 |
| --- | --- | --- | --- |
| 1 | SQL | `doc/sql/transport/lqj/temp/`(可重复执行) | 字典 `fee_category` 新增 A05 仓储(见第 6 节) |
| 2 | SQL | 同上 | 档案修正:仓储类费用项 A02→A05(无兜底后此步为分类生效前提) |
| 3 | Nacos | `doc/nacos/blade-dev.yaml`、`doc/nacos/third-party-api.yaml` | `material.warehouse: XDWL11002001` |
| 4 | 代码 | `BfiProperties.Material` | +1 字段 `warehouse = "XDWL11002001"` |
| 5 | 代码 | `KingdeeApBillSyncSupport` | +常量 `FEE_CATEGORY_WAREHOUSE="A05"`;`splitFeeItems`/`splitGroupKey` 三分类;`appendCargoLines` 仓储行物料取 `warehouse`、数量 1;`appendSummaryEntry` 仓储判定映射仓储物料;`resolveMaterialNumber` +仓储分支(参数 boolean→大类枚举) |
| 6 | 代码 | `KingdeeEntrySplitTest` | 追加仓储用例(第 7 节) |
> 第 4、5 项为代码不可省的最小集;缺任一项则 XDWL11002001 永远不会被推送(见第 2 节)。
---
## 6. 数据脚本(可重复执行)
```sql
-- 1. 业务字典 fee_category 新增「仓储 A05」
INSERT INTO blade_dict_biz (id, tenant_id, parent_id, code, dict_key, dict_value, sort, remark, is_sealed, status, is_deleted)
SELECT 2084286398513100005, '000000', -1, 'fee_category', 'A05', '仓储', 1, '金蝶分录仓储大类', 0, 1, 0
FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM (SELECT 1 FROM blade_dict_biz WHERE code = 'fee_category' AND dict_key = 'A05' AND is_deleted = 0) t);
-- 2. 费用项档案:仓储类费用项归入 A05(无兜底方案下,分类生效的唯一数据来源)
UPDATE blade_fee_item
SET fee_category = 'A05'
WHERE is_deleted = 0
AND fee_category <> 'A05'
AND (name LIKE '%仓储%' OR name LIKE '%堆存%' OR name LIKE '%保管%');
```
> 字典 id 为手工雪花段,落地前校验不冲突;`blade_fee_item` 在 system 与 transport 两库均有,按实际部署库执行。
---
## 7. 测试用例(`KingdeeEntrySplitTest` 追加)
| 用例 | 输入要点 | 断言 |
| --- | --- | --- |
| 仓储同税率合并 | 同货物行:档案 A05 的仓储费 300 + 堆存费 200,税率 6% | 1 行仓储组金额 500 |
| 仓储不同税率拆行 | 仓储费 300@6% + 保管费 200@9%(均档案 A05) | 2 行,后缀 -6 / -9 |
| 仓储不混入运输组 | 运输费 1000@9% + 仓储费(档案A05) 500@6% | 2 行:运输组 1000、仓储组 500 |
| 档案未配 A05 不兜底 | 「仓储服务费」档案 A02 | 归运输组(无兜底,纯档案驱动) |
| 残差勾稽不变 | 运输费 2000@9% + 仓储费 500,结算金额 2520 | 残差 20 仍入运输无税率组 |
---
## 8. 待确认项
1. **仓储字典编码**:建议 A05(A05~A08 空缺),业务确认后定稿
2. **仓储行数量**:默认固定 1(同装卸);如需按吨/方计量另行明确
3. **档案批量 UPDATE**:按名称关键字一次性归仓,执行前需核对命中清单(含「保管」字样但非仓储的费用项需剔除)