2026-08-04 16:38:29 +08:00
|
|
|
|
---
|
|
|
|
|
|
id: T-209
|
|
|
|
|
|
title: 把核心 schema / 状态机迁移为单趟模型
|
|
|
|
|
|
phase: 2
|
|
|
|
|
|
deps: [T-004, T-111]
|
2026-08-04 17:01:35 +08:00
|
|
|
|
status: DONE
|
2026-08-04 16:38:29 +08:00
|
|
|
|
created: 2026-08-04
|
|
|
|
|
|
vikunja_task_id: 29
|
|
|
|
|
|
context_ref: da540bf
|
|
|
|
|
|
work_branch: task/t-209-single-pass-schema
|
|
|
|
|
|
needs_device: false
|
|
|
|
|
|
needs_human_review: false
|
|
|
|
|
|
write_paths:
|
|
|
|
|
|
- docs/tasks/T-209.md
|
|
|
|
|
|
- admin/migrations/**
|
|
|
|
|
|
- admin/internal/migrations/**
|
|
|
|
|
|
- admin/internal/domain/**
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-08-04 17:15:12 +08:00
|
|
|
|
<!-- BEGIN VIKUNJA EXPORT id=29 synced=2026-08-04T09:15:04Z sha256=162d329ca4dac4535882e84fa12b73e5023a4c04e75a2c32548e7b3b84be8abb -->
|
2026-08-04 16:38:29 +08:00
|
|
|
|
## 问题 / 背景
|
|
|
|
|
|
|
|
|
|
|
|
T-111 已把业务契约改为管理员点击“开始采购”即授权桌面端在同一趟创建待付款订单;现有 SQLite v1 与领域模型仍是旧两趟结构,包含 spec_trials、authorized_unit_price 及 WAITING_CONFIRMATION/PENDING_RETRIAL/AUTHORIZED/RUNNING 等旧状态。T-203 不能在旧结构上继续实现。
|
|
|
|
|
|
|
|
|
|
|
|
## 关联需求与交互
|
|
|
|
|
|
|
|
|
|
|
|
T-111;F-004、F-005、F-008、F-017、F-018;docs/04-architecture.md 第四、五节;不包含页面选择器或真机操作。
|
|
|
|
|
|
|
|
|
|
|
|
## 方案
|
|
|
|
|
|
|
|
|
|
|
|
1. 保留 00001_core_data.sql 作为不可变迁移历史,新增 00002 单趟模型迁移;迁移只允许保留既有 MANUAL+DRAFT 任务,发现任一旧 spec_trials/authorization/submission 数据或非 DRAFT 任务即整体失败并回滚,不能猜测映射。
|
|
|
|
|
|
2. 重建 tasks 的状态约束为 DRAFT、PENDING、CLAIMED、ORDERING、NEEDS_MANUAL、WAITING_PAYMENT、RECONCILIATION_REQUIRED、SUCCEEDED、FAILED、CANCELED;保留 DRAFT 内容、版本与时间。
|
|
|
|
|
|
3. 删除旧 spec_trials 结构;重建 order_authorizations,锁定 task_version/start_key/goods_id/颜色/尺码/数量/total_price_cap,状态仅 ACTIVE/CLAIMED/FENCED/CONSUMED/EXPIRED/ABANDONED,不保存 observed/authorized unit price。
|
|
|
|
|
|
4. 新增 purchase_attempts 保存 claim generation、三闸门摘要和固定 failure code;重建 order_submissions,原子关联同一 task/authorization/attempt,保存 gate1、gate2、quantity、confirm amount,并限制一份授权/attempt 最多一条围栏。
|
|
|
|
|
|
5. 同步 Go 领域实体和 fail-closed 状态机;围栏前允许安全失败/重置,FENCED 后授权只能 CONSUMED,提交结果不明只能调和同一记录,任何未列出转移拒绝。
|
|
|
|
|
|
6. Down 迁移同样只在没有新业务执行数据且任务仍可无损回退时执行,否则失败并保持 v2;覆盖 up/down、幂等、DRAFT 保留、未知旧数据回滚、外键/唯一约束、金额 TEXT、状态转移与旧标识符消失测试。
|
|
|
|
|
|
|
|
|
|
|
|
## 验收要点
|
|
|
|
|
|
|
|
|
|
|
|
- 新 migration 不修改 00001;从空 v1 和仅含 DRAFT 的 v1 升级成功,DRAFT 字段逐项不变。
|
|
|
|
|
|
- 任一旧执行/授权/提交记录或非 DRAFT 状态都使升级失败,版本和原数据保持 v1;没有半迁移。
|
|
|
|
|
|
- 新 schema 无 spec_trials、authorized_unit_price、spec_trial_id、command_id、dry_run_id;包含 purchase_attempts 与架构规定的关系、唯一性、金额字符串和状态 CHECK。
|
|
|
|
|
|
- 领域模型不再暴露旧两趟状态;未知状态或未列出的转移全部失败。第一趟试选/下单函数均不在本任务范围。
|
|
|
|
|
|
- go test ./...、go test -race ./...、go vet ./...、go build ./...、完整 init.ps1、上下文校验和 diff-check 通过。
|
|
|
|
|
|
|
|
|
|
|
|
## 执行记录
|
|
|
|
|
|
|
2026-08-04 17:15:12 +08:00
|
|
|
|
### 2026-08-04T09:14:34Z · ila
|
|
|
|
|
|
|
|
|
|
|
|
2026-08-04 完成 T-209:SQLite v2 单趟 schema、领域状态机、迁移 up/down 与 fail-closed 护栏已实现。任务提交 e04f05b,合并提交 f85ef5f;主 agent 独立执行完整 init.ps1、Go test/race/vet/build、上下文校验与 diff-check 均通过。本地任务状态已置 DONE,主线已推送。
|
2026-08-04 16:38:29 +08:00
|
|
|
|
<!-- END VIKUNJA EXPORT -->
|
|
|
|
|
|
|
|
|
|
|
|
## 边界
|
|
|
|
|
|
|
|
|
|
|
|
- 本任务只迁移数据结构和纯领域状态机,不实现管理员“开始采购”HTTP/usecase、设备领取、租约、
|
|
|
|
|
|
attempt 写入 API、截图上传、提交围栏 API、页面自动化或任何真机动作;这些能力仍分别属于
|
|
|
|
|
|
T-203、T-205、T-208 与 Phase 3/4 任务。
|
|
|
|
|
|
- 不修改已经发布的 `00001_core_data.sql`;只能追加 `00002`。Up/Down 都必须置于单个事务,前置
|
|
|
|
|
|
检查失败时版本、schema 和数据原样保留,不能删除、转换或猜测任何旧执行记录。
|
|
|
|
|
|
- Up 只允许空库或仅含可无损保留的 `MANUAL + DRAFT` 任务。任一 `spec_trials`、旧
|
|
|
|
|
|
`order_authorizations`、旧 `order_submissions` 数据,或任一非 DRAFT / 非 MANUAL 任务均拒绝升级。
|
|
|
|
|
|
- Down 只允许没有授权、attempt、submission 且全部任务都能无损回到 v1 DRAFT 的 v2 数据库;否则
|
|
|
|
|
|
拒绝回退。迁移测试不得为通过而临时关闭外键后漏恢复,也不得留下临时表或 guard 表。
|
|
|
|
|
|
- 金额继续只用严格正十进制 `TEXT`;不得引入浮点数。新授权只锁定 `total_price_cap`,不得重新加入
|
|
|
|
|
|
`authorized_unit_price`、观察价格或 `spec_trial_id`。
|
|
|
|
|
|
- `FENCED` 授权不得回到可领取、可过期或可放弃状态;围栏后的提交只能记录明确提交或进入同一记录
|
|
|
|
|
|
调和,不能提供重试、释放或第二次点击的状态转移。
|
|
|
|
|
|
- 本任务不实现、不引用点击“提交订单”的函数,更不涉及支付、免密支付、先用后付或任何扣款动作。
|