Files
cmroubao/docs/tasks/T-245.md
T

108 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: T-245
title: 创建采购需求时采用 ERP 商品图
phase: 2
deps:
- T-243
- T-244
status: DONE
created: 2026-07-29
context_ref: 9195019
work_branch: null
write_paths:
- docs/tasks/T-245.md
- docs/current-state.md
- backend-api/migrations/00017_procurement_reference_sources.sql
- backend-api/internal/domain/**
- backend-api/internal/usecase/**
- backend-api/internal/repository/sqlite/**
- backend-api/internal/transport/httpapi/**
- backend-api/internal/transport/webui/**
- backend-api/cmd/api/**
---
## 需求 / 背景
货运详情已经展示并缓存 ERP 商品图片,但采购人员确认“仍需采购”后,采购需求固定进入
`NEEDS_IMAGE`,还要重新选择并上传同一张图片。ERP 图片与当前货运商品直接关联,通常是
图片搜索最准确、操作成本最低的默认参考图。
现有货运缓存图和采购参考资产属于不同生命周期:`freight_item_images` 会随重新同步、图片
变化或货运删除而替换/清理;采购任务则通过 `assets / TASK_REFERENCE` 保存不可变参考图。
因此不能让采购任务直接共享货运图片的 `storage_key`。
## 修订契约
- ADMIN 显式确认创建采购需求时,若当前商品资料完整且对应缓存图为 `READY`,系统自动将
本地缓存 JPEG 复制并重新校验为独立 `TASK_REFERENCE` asset,需求直接进入 `READY`。
- 自动采用图片只读取 `CMROUBAO_ASSET_DIR` 中已验证的本地缓存,不在创建需求请求中访问
ERP,也不依赖 ERP 会话、OCR 或网络。
- ERP 图片不存在、`MISSING` 或 `FAILED` 时正常创建 `NEEDS_IMAGE` 需求,继续提供人工上传。
- 标题、SKU、数量或来源取消造成资料阻塞时保持 `BLOCKED`,不创建参考资产。
- 同商品 revision 的重复创建保持幂等;既有 `NEEDS_IMAGE` 且来源未变化时,如果 ERP 图片
后来变为 `READY`,重复操作可原子升级为 `READY`。
- 自动图片必须在事务提交时仍与当前商品、图片引用、SHA-256 和 storage key 一致;并发
来源变化或图片替换时回滚,复制文件通过补偿清理,不留下 asset 或半绑定需求。
- 自动采用后的参考图记录来源 `ERP_FREIGHT_IMAGE`、原图片数字引用和 SHA-256;人工上传
记录 `MANUAL_UPLOAD`。
- 采购任务生成前允许人工上传替换参考图。替换自动 ERP 参考图时,事务删除旧自动 asset,
提交后清理其独立文件;任务已生成后继续禁止替换。
## 方案
1. v17 增加 `procurement_reference_sources`,以采购需求 ID 为主键保存来源、ERP 图片引用、
原图片 SHA-256 和绑定时间;现有已绑定参考图回填为 `MANUAL_UPLOAD`。Down 在存在来源
记录时 fail-closed,避免静默丢失审计。
2. 为 `ProcurementService` 增加可选本地参考图 store;生产组合传入现有 asset store,
未配置的纯仓储测试保持原 `NEEDS_IMAGE` 行为。
3. 创建需求时先构造来源快照和阻塞状态。非阻塞时读取当前 `READY` 图片元数据并打开本地
文件,经现有 `Put` 再次执行完整 JPEG 解码、尺寸/像素、20 MB 和 SHA-256 校验,生成
独立 storage key 与 asset 候选。
4. SQLite immediate 事务统一校验商品 revision/hash、缓存图引用/hash/key,插入 asset、
采购需求和 ERP 来源记录;对既有 `NEEDS_IMAGE` 执行相同原子升级。事务未使用复制文件
时,由用例幂等删除。
5. 人工绑定事务允许 `NEEDS_IMAGE -> READY` 或替换尚未生成任务的 `READY` 引用,来源记录
统一改为 `MANUAL_UPLOAD`。只删除无上传幂等记录的旧 ERP 自动 asset,文件在提交后清理。
6. Admin API 返回 `reference_origin`;SSR 显示“已使用 ERP 商品图”或“已上传参考图”,
`READY` 状态同时提供“生成采购任务”和“更换参考图”。
7. 任务仍只携带现有 `image_asset_id`,Roubao 领取、下载和图片搜索协议不变。
## 验收要点
- [x] 当前商品有 `READY` ERP 图时,创建需求返回 `READY`、独立 asset 和
`ERP_FREIGHT_IMAGE` 来源。
- [x] 自动 asset 使用不同 storage key;货运缓存图替换不会破坏采购参考图。
- [x] 无可用 ERP 图时返回 `NEEDS_IMAGE`,人工上传路径不回归。
- [x] 资料阻塞时不复制文件、不创建 asset,状态保持 `BLOCKED`。
- [x] 重复创建不产生重复需求/asset;既有 `NEEDS_IMAGE` 可在图片恢复后升级。
- [x] 商品或图片并发变化时无采购 asset、来源记录或孤立复制文件。
- [x] `READY` 需求可人工替换;旧 ERP 自动 asset/文件被清理,任务创建后禁止替换。
- [x] API/SSR 展示参考图来源,生成的采购任务和 Roubao 图片契约不变化。
- [x] 已自动绑定参考图的货运单继续受 T-243 删除保护。
- [x] v17 上下迁移、标准 Go 测试、race、vet 和三个入口构建通过。
## 边界
- 不在采购需求创建时请求 ERP,不把 ERP URL 暴露给 Admin 或 Roubao。
- 不直接共享货运图片 storage key,不引入跨表隐式文件引用。
- 不自动生成采购任务;采购人员仍需明确点击“生成采购任务”。
- 不在任务生成后替换参考图,不改写已有任务快照。
- 不自动为既有 `NEEDS_IMAGE` 批量回填;由详情操作显式触发升级。
- 不增加通用 asset 回收站或全局引用计数;人工上传产生的历史未绑定 asset 继续沿用现状。
- 不记录图片正文、ERP Cookie/Token 或真实订单、商品、店铺和图片 ID。
## 执行记录
- 2026-07-29:审计确认当前 `CreateRequest` 对非阻塞商品固定写入 `NEEDS_IMAGE`;ERP
缓存图只有 `freight_item_images` 记录,而采购任务要求 `assets` 外键。确定采用独立
文件/asset 快照,不共享可变货运 storage key;Roubao 协议无需变化。
- 2026-07-29:v17 已增加参考图来源记录;生产组合启用本地 ERP 缓存图复制。SQLite
事务复核商品 revision/hash 和图片引用/hash/key 后,原子写 asset、需求及来源;重复
创建可升级既有 `NEEDS_IMAGE`,未使用或失败的复制文件由用例补偿清理。
- 2026-07-29:人工绑定已支持任务生成前替换自动参考图,提交后清理旧自动 asset/文件;
API 返回 `reference_origin`,货运详情显示来源并提供“更换参考图”。任务仍使用既有
`image_asset_id`,未改变 Roubao 协议。
- 2026-07-29:`go test ./...`、`go test -race ./...`、`go vet ./...` 通过;
`go build ./cmd/api`、`go build ./cmd/authctl`、`go build ./cmd/migrate` 通过。
测试仅使用运行时生成图片和脱敏 ID,未访问真实 ERP。