thread-master/docs/product/demand-radar/tasks/T511-service-profile-api-ge...

2.9 KiB
Raw Permalink Blame History

T511 — service-profile-api-get-put

Status: done2026-07-31
Milestone: M1
Kind: feat
Est. change: ~160 lines

Goal

完成後系統應:GETPUT /api/v1/radar/service-profile 真實可用,欄位完整往返並以 owner_uid 隔離。

Depends on

  • T500、T510

Inputs

  • Spec../spec.md §4.1、§5.1、§5.6、§9.1SP-02
  • 既有 logic 模式:apps/backend/internal/logic/scout/**

Outputs

程式變更(預期路徑)

路徑 動作 說明
apps/backend/generate/api/radar.api edit service-profile reqresp 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 一律取 JWTrequest 帶的 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

  • SP-02填寫後 GET 欄位完整、forbidden[] 可讀
  • 別人的 uid 無法讀寫(回越權錯誤)
  • 指令:
cd apps/backend && make gen-api && go test ./internal/logic/radar/... -count=1 && make build

Notes2026-07-31

路徑 動作
internal/logic/radarmap/map.go adddomain ↔ types 映射,含 Pagination helper
internal/logic/radar/owner.go addownerUID:一律取 JWTrequest 帶的 uid 忽略)
internal/logic/radar/{get,upsert}_service_profile_logic.go edit
internal/svc/service_context.go editRadar *radarUC.Service
internal/middleware/auth.go edit新增 WithUID,見下)
internal/logic/radar/service_profile_logic_test.go add5 則)
  • generate/api/radar.api 未改T500 定的 reqresp 型別已足夠,不需要重跑契約。
  • 未建檔回 exists=false 的 200不是 404。 表單得先開得起來才有東西填;誠實之處在 exists 欄位,而不是用錯誤碼表達。空陣列而非 null,前端不必每個欄位判空。
  • 驗證錯誤映射成 400100cleanBizMessage 會把 radar validation: 前綴切掉所以前端拿到的是「services[0].name required」這種能對到欄位的訊息。
  • middleware.WithUID 是新增的匯出入口。 ctxUID 是私有型別,沒有它就只能繞過 UIDFrom 來測,那測到的就不是真的授權路徑。測試證明別人的 uid 讀不到也寫不壞自己的檔案。