76 lines
3.3 KiB
Markdown
76 lines
3.3 KiB
Markdown
# T500 — api-shells-radar-crm-goctl
|
||
|
||
> Status: `done`(2026-07-31)
|
||
> Milestone: `M0`
|
||
> Kind: `feat`
|
||
> Est. change: `~180 lines`
|
||
|
||
## Goal
|
||
|
||
完成後系統應:`radar` 與 `crm` 兩個 group 的路由由 goctl 產出並可打通,所有尚未實作的能力回**明確未就緒錯誤**(禁止 `102000` 空成功)。
|
||
|
||
## Depends on
|
||
|
||
- —
|
||
|
||
## Inputs
|
||
|
||
- Spec:`../spec.md` §5.1、§5.2、§5.6
|
||
- 既有契約檔範例:`apps/backend/generate/api/growth.api`、`scout` 相關段落
|
||
- `AGENTS.md`:後端一律 goctl,禁止手寫 handler/routes
|
||
|
||
## Outputs
|
||
|
||
### 程式變更(預期路徑)
|
||
|
||
| 路徑 | 動作 | 說明 |
|
||
|------|------|------|
|
||
| `apps/backend/generate/api/radar.api` | add | service-profile/watches/today/opportunities/sweeps 全部 route 與 type |
|
||
| `apps/backend/generate/api/crm.api` | add | contacts/followups/stats 全部 route 與 type |
|
||
| `apps/backend/generate/api/gateway.api` | edit | import 兩個新契約檔 |
|
||
| `apps/backend/internal/handler/**`、`routes.go` | generated | `make gen-api` 產出,**不手寫** |
|
||
| `apps/backend/internal/logic/radar/**` | add | logic 殼,一律回未就緒錯誤 |
|
||
| `apps/backend/internal/logic/crm/**` | add | logic 殼,一律回未就緒錯誤 |
|
||
|
||
### 行為變更
|
||
|
||
- 新路由存在且需 Bearer JWT,`owner_uid` 取登入 uid。
|
||
- 未實作能力回明確 error code/message(例:`radar capability not ready`),**不是** `102000` + 空 `data`。
|
||
|
||
### API / 契約
|
||
|
||
- 依 spec §5.2 全表建立 route;`P1` 的 `/api/v1/radar/import` 先不建。
|
||
- 列表型 request 一律 `page`/`pageSize`(`pageSize ≤ 50`),response `pagination` + `list`。
|
||
- 時間欄位一律 `int64` unix nanoseconds。
|
||
|
||
## Out of scope
|
||
|
||
- 任何業務邏輯與 Mongo 讀寫(T510 起)
|
||
- Mongo 索引(T501)
|
||
- 前端接線(T502)
|
||
|
||
## Acceptance
|
||
|
||
- [x] `make gen-api` 後 `git status` 顯示 handler/routes 為產生物,非手改
|
||
- [x] 每個新 route 回未就緒錯誤且**非** `102000`(以 34 個 capability 測試取代 curl,斷言 HTTP 501+`code≠102000`+`data=nil`)
|
||
- [x] 指令:
|
||
|
||
```bash
|
||
cd apps/backend && make gen-api && make build && go test ./... -count=1
|
||
```
|
||
|
||
## Notes
|
||
|
||
route 命名避免與既有 `/api/v1/scout` 衝突;`promote` 掛在既有 scout group(T600)。
|
||
|
||
### 實作結果(2026-07-31)
|
||
|
||
- 新增 34 個 route:`radar` 20、`crm` 14;`internal/handler/{radar,crm}` 與 `routes.go` 全為 goctl 產出。
|
||
- 未就緒語意:`radarDomain.ErrNotReady`/`crmDomain.ErrNotReady` → `internal/response` 映射 **HTTP 501 / code 501010**;各 logic 以 `notReady("<capability>")` 標明是哪個能力。
|
||
- 一併定義兩個 module 的 `ErrNotFound`/`ErrForbidden`/`ErrValidation`(`400100`)sentinel 與映射,供 M1 起直接使用,避免每則 task 重複改 `response.go`。
|
||
- **超出 spec §5.2 表格的兩個 route**(刻意加入,非漏審):
|
||
- `GET /api/v1/radar/opportunities/:id/replies` — RP-01「查 replies 只有 public_comment」需要讀取端點。
|
||
- `POST /api/v1/crm/contacts/:id/unmerge` — spec §4.6.3 與 T571 都要求 unmerge。
|
||
- 送出回覆端點**未**建立,依原計畫留給 T550。
|
||
- `routes.go` 另有一處無害變動:兩個同前綴 `/api/v1/media` 區塊的輸出順序被 goctl 互換,`rest.WithJwt` 仍附在 `generate-image` 區塊,全檔 19 處計數不變。
|