diff --git a/docs/tasks/T-239.md b/docs/tasks/T-239.md new file mode 100644 index 0000000..c7db137 --- /dev/null +++ b/docs/tasks/T-239.md @@ -0,0 +1,75 @@ +--- +id: T-239 +title: 冻结货运商品规格、原始价格与图片引用契约 +phase: 2 +deps: + - T-238 +status: TODO +created: 2026-07-29 +context_ref: 01be7e7 +work_branch: null +write_paths: + - docs/tasks/T-239.md + - docs/api.md + - docs/current-state.md + - backend-api/migrations/00015_freight_item_metadata.sql + - backend-api/internal/domain/freight.go + - backend-api/internal/platform/shunyunbao/normalizer.go + - backend-api/internal/platform/shunyunbao/*_test.go + - backend-api/internal/usecase/freight_* + - backend-api/internal/repository/sqlite/freight_* + - backend-api/internal/transport/httpapi/freight_handlers.go + - backend-api/internal/transport/webui/** +--- + +## 问题 / 背景 + +顺运宝货运详情已能导入商品标题、数量和 `productThumb` 引用,但采购使用的 SKU 仍优先取 +ERP `sku/variationSku`,与本项目需要按颜色、尺码硬匹配的 `productSpec` 不一致;ERP +`productPrice` 也没有进入本地货运契约。图片引用当前按任意标量接收,后续无法安全地用于固定 +图片 endpoint。 + +本机真实响应的结构化检查确认:`productSpec` 是采购所需规格,`productPrice` 当前样例为 +整数,`productThumb` 是正整数且不同于货运单 ID 和商品明细 ID。真实响应包含业务及个人 +数据,继续保持未跟踪且不得复制到 fixture、日志或提交。 + +## 关联需求与交互 + +- 货运商品的规格和采购 SKU 都取 ERP `productSpec`。 +- 保存 ERP `productPrice`,默认币种为 TWD,供货运详情和后续采购复核使用。 +- 保存 ERP `productThumb` 的规范化正整数引用,供后续后端拼接固定图片 URL。 +- 已生成采购任务保持不可变;新建采购需求使用新同步版本中的规格 SKU。 + +## 方案 + +1. normalizer 将 `productSpec` 同时写入 `product_spec` 和 `sku`;字段为空时保留空值,由既有 + 采购前置校验阻塞,不静默回退 `sku/variationSku`。 +2. 严格解析 `productPrice` 的整数、小数或数字字符串,不接受负数、指数、NaN、超过两位 + 小数或越界金额;未知值保存 `NULL`,不能误写为零。 +3. SQLite 使用 `original_unit_price_minor INTEGER NULL` 保存最小货币单位,并增加 + `original_currency TEXT NOT NULL DEFAULT 'TWD'`。金额和币种进入商品 canonical hash,变化 + 时递增 revision。 +4. `productThumb` 缺失时为 `NULL`;存在时必须是正整数并规范化为十进制字符串。禁止接受 + 完整 URL、负数、小数或任意文本。 +5. API 和 Web 适配层返回原始单价与币种,但本任务不下载图片、不展示外部 URL。 + +## 验收要点 + +- [ ] `productSpec` 同时成为货运商品的规格和采购 SKU,缺失时不使用其他 ERP SKU 猜测。 +- [ ] `productPrice` 的合法整数、小数和数字字符串精确转换为 TWD 最小单位。 +- [ ] 缺失价格为 `NULL`;负数、指数、超过两位小数和越界值拒绝为 ERP 协议错误。 +- [ ] `productThumb` 仅接受可规范化的正整数引用,且不与货运单 ID 混用。 +- [ ] 金额、币种和新 SKU 进入 canonical hash,并通过 SQLite 往返和 revision 测试。 +- [ ] API/Web 适配层能读取新增字段;既有采购快照和任务不可变语义不回归。 +- [ ] 标准 Go 测试、race、vet 和三个入口构建通过。 + +## 边界 + +- 本任务不请求 `/api/p/file`,不保存图片文件,也不修改页面视觉布局。 +- 不计算货运总价、税费、运费或采购预算;`productPrice` 仅标记为 ERP 原始单价。 +- 不提交真实 ERP 响应、账号、Cookie、Token、订单、收件人或商品业务数据。 + +## 执行记录 + +- 2026-07-29:创建任务。确认图片 URL 的查询参数必须来自商品 `productThumb`,不能使用 + 货运单或商品明细 ID;金额使用定点最小单位,图片网络获取拆分到后续任务。