72 lines
2.9 KiB
Markdown
72 lines
2.9 KiB
Markdown
# T511 — service-profile-api-get-put
|
||
|
||
> Status: `done`(2026-07-31)
|
||
> Milestone: `M1`
|
||
> Kind: `feat`
|
||
> Est. change: `~160 lines`
|
||
|
||
## Goal
|
||
|
||
完成後系統應:`GET`/`PUT /api/v1/radar/service-profile` 真實可用,欄位完整往返並以 `owner_uid` 隔離。
|
||
|
||
## Depends on
|
||
|
||
- T500、T510
|
||
|
||
## Inputs
|
||
|
||
- Spec:`../spec.md` §4.1、§5.1、§5.6、§9.1(SP-02)
|
||
- 既有 logic 模式:`apps/backend/internal/logic/scout/**`
|
||
|
||
## Outputs
|
||
|
||
### 程式變更(預期路徑)
|
||
|
||
| 路徑 | 動作 | 說明 |
|
||
|------|------|------|
|
||
| `apps/backend/generate/api/radar.api` | edit | service-profile req/resp type 定稿 |
|
||
| `apps/backend/internal/logic/radar/getServiceProfileLogic.go` | edit | 讀取;未建立回明確「尚未建立」狀態 |
|
||
| `apps/backend/internal/logic/radar/putServiceProfileLogic.go` | edit | 整份 upsert+驗證錯誤映射 |
|
||
| `apps/backend/internal/svc/servicecontext.go` | edit | 掛入 radar usecase |
|
||
|
||
### 行為變更
|
||
|
||
- 成功 `102000`;驗證失敗回明確 message(欄位名+原因),非空成功。
|
||
- 只能讀寫自己的檔案;`owner_uid` 一律取 JWT,request 帶的 uid 忽略。
|
||
|
||
### API / 契約
|
||
|
||
- `GET` 回 `{ exists, services[], cases[], forbidden[], faq[], service_areas[], remote_ok, availability, tone_note, updated_at }`。
|
||
- `PUT` 回更新後全量。
|
||
|
||
## Out of scope
|
||
|
||
- 前端畫面(T515)
|
||
- watch 前置條件檢查(T513)
|
||
|
||
## Acceptance
|
||
|
||
- [x] SP-02:填寫後 `GET` 欄位完整、`forbidden[]` 可讀
|
||
- [x] 別人的 uid 無法讀寫(回越權錯誤)
|
||
- [x] 指令:
|
||
|
||
```bash
|
||
cd apps/backend && make gen-api && go test ./internal/logic/radar/... -count=1 && make build
|
||
```
|
||
|
||
## Notes(2026-07-31)
|
||
|
||
| 路徑 | 動作 |
|
||
|------|------|
|
||
| `internal/logic/radarmap/map.go` | add(domain ↔ types 映射,含 `Pagination` helper) |
|
||
| `internal/logic/radar/owner.go` | add(`ownerUID`:一律取 JWT,request 帶的 uid 忽略) |
|
||
| `internal/logic/radar/{get,upsert}_service_profile_logic.go` | edit |
|
||
| `internal/svc/service_context.go` | edit(掛 `Radar *radarUC.Service`) |
|
||
| `internal/middleware/auth.go` | edit(新增 `WithUID`,見下) |
|
||
| `internal/logic/radar/service_profile_logic_test.go` | add(5 則) |
|
||
|
||
- `generate/api/radar.api` **未改**:T500 定的 req/resp 型別已足夠,不需要重跑契約。
|
||
- **未建檔回 `exists=false` 的 200,不是 404。** 表單得先開得起來才有東西填;誠實之處在 `exists` 欄位,而不是用錯誤碼表達。空陣列而非 `null`,前端不必每個欄位判空。
|
||
- **驗證錯誤映射成 400100**,`cleanBizMessage` 會把 `radar validation: ` 前綴切掉,所以前端拿到的是「services[0].name required」這種能對到欄位的訊息。
|
||
- **`middleware.WithUID` 是新增的匯出入口。** `ctxUID` 是私有型別,沒有它就只能繞過 `UIDFrom` 來測,那測到的就不是真的授權路徑。測試證明別人的 uid 讀不到也寫不壞自己的檔案。
|