thread-master/docs/product/demand-radar/tasks/T525-opportunity-model-repo...

2.3 KiB
Raw Blame History

T525 — opportunity-model-repository

Status: done
Milestone: M2
Kind: feat
Est. change: ~190 lines

Goal

完成後系統應Opportunity domain 與 repository 就位,狀態機依 spec §3.2,同 owner 同 external_id 去重且可記錄多個觸發 term。

Depends on

  • T501

Inputs

  • Spec../spec.md §3.2、§3.3、§8、§9.2OP-06、SW-06
  • 既有 module 模式:apps/backend/internal/module/scout/**

Outputs

程式變更(預期路徑)

路徑 動作 說明
apps/backend/internal/module/radar/domain/opportunity.go add structstatus 轉移+intent_band 由 score 推導8050reasons[] 五維度驗證
apps/backend/internal/module/radar/repository/opportunity_mongo.go add UpsertByExternalIDListByOwnerbandstatuswatch日期 filterCountTodayGetUpdateStatusSetOverride
apps/backend/internal/module/radar/repository/opportunity_memory.go add 測試用

行為變更

  • reasons[] 不足五維度時 repository 拒絕寫入回明確錯誤——OP-06。
  • UpsertByExternalID:命中既有則只把新的觸發 term 併入 matched_terms[],不重複建立、不重跑判定。
  • region_match 為三態 match|mismatch|unknownstatusjudging|qualified|rejected|accepted|dismissed
  • override{from_band, to_band, from_status, to_status, actor_uid, at}

Out of scope

  • 判定演算法T529與寫入流程T530
  • HTTP logicT545T546T547

Acceptance

  • unit test缺一條 reason 被拒;同 external_id 兩次 upsert 只有一筆且 matched_terms 有兩個
  • score 79→mid、80→high、49→low
  • 指令:
cd apps/backend && go test ./internal/module/radar/... -count=1

Notes

band 門檻 8050 為 spec 鎖定值,不可在此 task 調整。

實作落點

  • domain/opportunity.gostatus 轉移、BandFromScore8050ValidateReasons 五維度、UTCDayBounds
  • repository/opportunity_{memory,mongo}.goUpsertByExternalID 命中只併 matched_termsCountTodayListOpportunitiesSetOpportunityOverride
  • 測試:domain/opportunity_test.gorepository/opportunity_memory_test.go