diff --git a/T-278.-.md b/T-278.-.md new file mode 100644 index 0000000..76acd42 --- /dev/null +++ b/T-278.-.md @@ -0,0 +1,78 @@ + +> 同步来源:[`docs/tasks/T-278.md`](/chengma/mroubao/src/commit/afc651f75a3abc2676bb13aa8a80f6aa6a25a72e/docs/tasks/T-278.md) · commit `afc651f75a3a` + +--- +id: T-278 +title: 任务价格为空时使用冻结的低价采购上限 +phase: 2 +deps: + - T-277 +status: DONE +created: 2026-08-01 +context_ref: 757a522 +work_branch: null +write_paths: + - docs/tasks/T-278.md + - docs/current-state.md + - docs/04-architecture.md + - docs/05-coding-rules.md + - docs/api.md + - backend-api/migrations/** + - backend-api/internal/** + - backend-api/.env.example + - android-buyer/app/src/main/** + - android-buyer/app/src/test/** +--- + +## 问题 / 背景 + +候选价格可能为空或只是搜索结果展示价。现有 Android 策略在采购任务未设置最高总预算时, +要求下单时的规格单价必须和候选价格文本完全相同;候选价格为空会让已人工确认的商品永远 +无法进入订单确认页。直接取消价格判断又会失去自动采购的金额安全边界。 + +## 行为契约 + +1. 采购任务设置 `max_budget` 时,以该最高总预算作为订单总额上限;未设置时,以后台 + `CMROUBAO_DEFAULT_ORDER_TOTAL_CAP_CENTS` 配置作为低价采购上限,默认 `20000` 分。 +2. 创建人工确认授权时,把最终上限和来源 + `TASK_MAX_BUDGET|DEFAULT_LOW_PRICE_CAP` 冻结到授权记录和设备命令;配置后续变化不影响 + 已创建授权。 +3. 设备命令 schema 升级,上限参与 `command_sha256`;App 不从任务缓存自行推导默认值。 +4. 候选 `price_text` 只作为观察数据,不再要求和当前规格价格完全相等,也不作为授权上限。 +5. App 仍必须在规格选择后读取唯一、已验证的当前单价,并在订单确认页读取总价; + `当前单价 × 数量`、确认页总价和冻结上限必须同时一致/满足,任何缺失、歧义、溢出或超额 + 均失败关闭。 +6. 后端接收 dry-run 时再次校验总价不超过授权记录中的冻结上限,不能只信任手机校验。 + +## 方案 + +1. 配置层增加整数分单位的默认总额上限,限制在合理范围,并允许从现有 `.env` 读取。 +2. migration 为 `order_authorizations` 增加非空总额上限及来源;历史授权按保守方式迁移, + down migration 对非默认数据失败关闭。 +3. 授权仓储根据任务预算或服务配置生成冻结值,设备命令、哈希、HTTP JSON 和 Android + 安全存储透传该值。 +4. 重写 Android 价格策略和 Go dry-run 仓储校验,补充空候选价格、任务预算、默认上限、 + 超额、篡改哈希及迁移回归测试。 + +## 验收要点 + +- [x] 任务有预算时,命令冻结任务预算并标记 `TASK_MAX_BUDGET`。 +- [x] 任务无预算且候选价格为空时,仍可按默认 200 元上限执行 dry-run。 +- [x] 候选价格变化不阻止执行,但当前规格价格缺失或歧义仍阻止执行。 +- [x] 当前总价或订单确认总价超过冻结上限时,App 和后端均拒绝。 +- [x] 上限和来源参与命令哈希及持久化,重启和配置变化不改变旧授权。 +- [x] migration up/down/up、Go 全量测试、Android 双变体单测、lint 和构建通过。 + +## 边界 + +- 本任务不修复确认商品链接身份复核、订单 dry-run 的 VLM 规格兜底或终态失败上报, + 由 T-279 完成。 +- 不允许价格不可读时自动下单,不允许模型独立生成金额。 +- 不自动点击支付,最终仍停留在拼多多待支付订单。 + +## 执行记录 + +- 2026-08-01:按“价格为空时取消候选价等值判断,但保留冻结总额上限”的方案创建任务, + 状态 `TODO`。 +- 2026-08-01:完成 v22 授权上限持久化、schema v3 命令、双端金额校验和 Admin 展示; + Go 全量测试/vet、Android Debug/Release 共 942 项测试、lint 和构建通过,状态 `DONE`。