thread-master/docs/product/demand-radar/tasks/T513-radar-watch-api-crud-q...

81 lines
3.9 KiB
Markdown
Raw Permalink Normal View History

2026-08-03 05:52:02 +00:00
# T513 — radar-watch-api-crud-quota-gate
> Status: `done`2026-07-31
> Milestone: `M1`
> Kind: `feat`
> Est. change: `~200 lines`
## Goal
完成後系統應watch CRUDpauseresumearchive API 可用,且**未建服務檔案不得建 active watch**、**超過方案 `max_active_watches` 明確拒絕**。
## Depends on
- T511、T512
## Inputs
- Spec`../spec.md` §3.1、§4.9、§5.2、§5.6、§9.1SP-01、RW-01、RW-02、RW-04
- 既有方案/配額讀取:`apps/backend/internal/module/usage/**`、`billing` plan 定義
## Outputs
### 程式變更(預期路徑)
| 路徑 | 動作 | 說明 |
|------|------|------|
| `apps/backend/generate/api/radar.api` | edit | watches reqresp type 定稿 |
| `apps/backend/internal/logic/radar/*Watch*Logic.go` | edit | listcreategetupdatedelete(archive)pauseresume |
| `apps/backend/internal/module/radar/usecase/watch_quota.go` | add | 方案上限查詢與判斷Free 1Starter 5Pro 20 |
| `apps/backend/internal/module/billing/**` 或方案常數檔 | edit | 新增 `max_active_watches`、`max_daily_opportunities` 欄位(**不改價格、不動 `soft_caps`** |
### 行為變更
- 建立或 resume 成 `active` 前檢查兩道閘服務檔案存在、active 數 < 上限
- 兩種拒絕皆為明確錯誤:前者 message 指向服務檔案;後者 message 含「目前上限 N」與升級提示。
- 既有超額者不強制降級(只擋新增)。
- `DELETE` 語意為封存(軟刪),非實刪。
### API / 契約
- `GET /watches` 支援 `page``pageSize`、`status` filter`pagination` + `list`
## Out of scope
- 手動觸發 sweepT533
- 關鍵字建議T514
## Acceptance
- [x] SP-01無服務檔案建 active watch → 明確錯誤且指向服務檔案
- [x] RW-01Free 已有 1 個 active再建 → 明確錯誤含上限與升級提示
- [x] RW-02RW-04pause 後不在 active 清單archive 後不可 resume
- [x] 指令:
```bash
cd apps/backend && make gen-api && go test ./internal/logic/radar/... ./internal/module/radar/... -count=1
```
## Notes
配額欄位加在既有方案定義上,**不要**新增第五個 usage meterRG-04
## Notes2026-07-31
| 路徑 | 動作 |
|------|------|
| `internal/module/usage/domain/usage.go` | edit`PlanDef` 加 `MaxActiveWatches``MaxDailyOpportunities`Free 1/5、Starter 5/30、Pro 20/100 |
| `internal/module/usage/usecase/service.go` | edit新增 `PlanFor` |
| `internal/module/radar/usecase/watch_quota.go` | add`PlanQuota` 介面、`FixedQuota`、`assertCanActivate` |
| `internal/logic/radar/{list,create,get,update,archive,pause,resume}_*_logic.go` | edit |
| `internal/svc/service_context.go` | edit`radarQuotaBridge` 橋接既有方案) |
| `internal/logic/radar/watch_logic_test.go` | add8 則) |
- **價格與 `soft_caps` 未動**,也沒有新增第五個 meter兩個新欄位只是方案的規模上限AI 判定與回覆仍計既有四個 meter。
- **配額介面留在 radar module實作橋接在 `internal/svc`。** radar 不反向依賴 usage module。
- **沒接上 `PlanQuota` 時退回最低方案15不是無上限。** 漏接線的後果應該是使用者看到上限提示來問,而不是所有人都拿到 Pro 的常駐監控量。
- **`resume` 會重驗兩道閘。** 暫停期間方案可能已降級,不重驗就等於「暫停再恢復」是繞過上限的後門。測試明確蓋住這條路。
- **既有超額訂閱不強制降級**spec §3.1):降級後只擋新增,已經在跑的照跑。
- **`DELETE` 是軟刪**archive 後列表仍看得到、`active_count` 不含它,歷史商機與統計不動。
- `GET /watches` 額外回 `active_count``max_active``profile_exists`,讓雷達頁在使用者按下建立之前就能顯示引導或升級提示,而不是等 POST 被拒才說。