# ADR-0004: bill-recon 价格模型对齐 WMS ShipCostCfg - **Status**: Accepted (大修 4 commit 落地 v0.5.0-alpha.11, 2026-04-28) - **Date**: 2026-04-27 - **Deciders**: PM (产品经理) + Flyto Agent core team - **Related code**: `platform/common/internal/billrecon/parser/adjustment.go`, `platform/common/internal/billrecon/llm/vision.go`, `platform/common/internal/billrecon/store/postgres.go`, `platform/common/internal/billrecon/workflow/engine.go`, `platform/common/internal/billrecon/web/server.go`, `platform/common/cmd/bill-recon-web/static/{app.js,index.html,style.css}` - **Related TODO**: bill-recon 8 sub-task (S1 schema migration / S2 parser struct / S3 store / S4 LLM prompt + parser / S5 workflow + web / S6 review UI / S7 测试 / S8 bill detail 页接新 schema) - **Reference**: WMS 数据字典 — `git.flytoex.net/AWS_Team/CloudWM/02_Design/` `CWM云仓数据库设计说明书.xlsx` Sheet `CWMACCT` `ShipCostCfgMaster` (L1) + `ShipCostCfg` (L21), `CostType=0=StandardCost / 1=AdjustedCost` ## 1. Context C6 (commit `6f40c9c`, alpha.6) 给 bill-recon 加了 vision 调价通知图抽取链路: 6 张内嵌图 → MiniMax vlm → 12 字段 `parser.Adjustment` (`EffectiveDate / Carrier / Regions / AdjustmentType / Details / Summary / TimeDimension` 等) → `price_adjustments` 表. alpha.10 review (commit `44b277d`) PM 看 review 表单时发现两个问题: 1. 表单字段全空 (regions / effective_date 等) — Go 默认 marshal 出 PascalCase, JS 用 snake_case 读, 永远 mismatch (alpha.6 遗留 bug). 2. 更深: PM 拉出飞驼内部 WMS 数据字典 (`CloudWM/02_Design/CWM云仓数据库 设计说明书.xlsx` Sheet `CWMACCT`), 指出当前 12 字段是看圆通调价图原文 自由设计的, 跟 WMS 现有承运商价格表 schema 大幅 mismatch. `parser.Adjustment` (alpha.6) vs `ShipCostCfgMaster + ShipCostCfg` (WMS) 5 关键 gap: | # | bill-recon (alpha.6) | WMS schema | 影响 | |---|---|---|---| | 1 | `Details / Summary` 自由文本 | `BaseWeight + BaseAmount + IncrementWeight + IncrementPrice` 结构化 (首重 + 续重定价) | 对账规则引擎当下没法直接用 LLM 抽出文本算价 | | 2 | `Regions []string` 数组 | 一行一省 `ProvinceName + CityName` (1 master : N detail) | 数据形态不一致, 反查 WMS 时 join 不上 | | 3 | 无 | `StandardCostSysNo` 指向 base 标准成本 | 调价是相对 base 的 delta, 当下抽出来无 anchor | | 4 | `Carrier="圆通"` 字符串 | `ShipTypeId / ShipTypeMSN` (物流 ID) | 反查 WMS 配置时按名字模糊匹配易错 | | 5 | 无 | `LimitTop / LimitBottom` (重量段) + `VWRate` (体积重比) + `Priority` (多调价同时生效优先级) | 阶梯 / 体积货 / 优先级冲突全无支持 | PM 拍板: 大修对齐 WMS, 不分阶段 ("马上大修, 完整实现"). ## 2. Decision `parser.Adjustment` (单一 struct + free-form 字段) → 重构为 `AdjustmentMaster` + `AdjustmentDetail` (1:N) 镜像 WMS `ShipCostCfgMaster + ShipCostCfg` (`CostType=1=AdjustedCost` 那一档). `price_adjustments` 表 drop, 新建 `ship_cost_cfg_master` + `ship_cost_cfg` 两表 (字段名直接镜像 WMS 字典, 含 PascalCase → snake_case SQL 列命名转换, e.g. `BaseWeight` → `base_weight`). LLM vlm prompt 重写按 WMS 字段名输出 (vlm 直接产 master 字段 + detail 数组). 抽不出 (调价通知通常是 delta 不是完整价目) 的字段落 NULL / 0, 用户在 chat UI 上对照原图手填或留空. UI review 卡片重做: 一张图 → 1 master 表单 (起止时间 / 物流 ID / 优先级 / 文件路径) + N 行 detail 子表 (省名 / 市名 / 重量段上下限 / 首重续重定价). ## 3. 4 commit chain (合并实施) 实际落地节奏从原计划 8 commit 收窄到 4 commit, 因为 schema / parser / store / llm / workflow / web 6 包紧耦合无法分拆 build 通 过, 强行拆只是中间态 broken; 用户 review (PM 浏览器实测) 也是按 端到端切换感知, 拆 8 个中间 cut 没价值. UI / bill detail 各自一 commit 因为前端独立编译. | # | Commit (hash 已回填) | 内容 | |---|---|---| | C1 | `199fd11` docs | 本 ADR + CHANGELOG (v0.5-dev 段) + TODO.md 立项 | | C2 | `045ec70` refactor | schema migration (`price_adjustments` drop + `ship_cost_cfg_master + ship_cost_cfg` 镜像 WMS) + parser (Adjustment 拆 Master+Detail+Bundle, 全字段 json tag snake_case) + store (`SaveShipCostCfg` + `ListShipCostCfg` + `CountShipCostCfgMaster`) + LLM (`ExtractShipCostCfg` + WMS 字段 prompt + `parseShipCostCfgContent`) + workflow (`AdjustmentExtractor` 新签名, `pendingBundles`, `runAdjustmentReview` 重写) + web (`bundleConfirmPayload` 新 wire + `handleAdjustmentsConfirm` 重写). 顺手关 alpha.6 PascalCase / snake_case marshal mismatch bug. 1173+/656− 行. | | C3 | `2ce9076` refactor | review UI 卡片重做: master 4 字段 + 3 高级折叠 + N 行 detail 子表 (省 / 市 / 重量段 / 首重续重定价 9 字段) + 加行删行 + status approve/reject. style.css 加 grid 布局 + 折叠按钮样式. | | C4 | `b314a2e` feat | bill detail 接 ListShipCostCfg: server.go 加 `adjustmentBundleDTO` + 扩 `handleGetBill` 返 `{ bill, adjustments[], warning? }`. app.js 加历史卡片 "详情" inline 切换 + `renderBillDetail` 渲染 meta + 每 bundle (image + master `