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

81 lines
3.9 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.

# 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/5Starter 5/30Pro 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 被拒才說