# T585 — followup-model-repository-and-hooks > Status: `done` > Milestone: `M5` > Kind: `feat` > Est. change: `~170 lines` ## Goal 完成後系統應:FollowUp domain/repository 就位,且在送出回覆或階段進入 `engaged`/`dm_sent` 時自動建立(`due_at = 最後接觸 + N 天`)。 ## Depends on - T550、T566 ## Inputs - Spec:`../spec.md` §3.5、§4.7.1、§8(`crm_followups`) ## Outputs ### 程式變更(預期路徑) | 路徑 | 動作 | 說明 | |------|------|------| | `apps/backend/internal/module/crm/domain/followup.go` | add | 狀態 `scheduled|notified|done|snoozed|escalated`+`notified_count` | | `apps/backend/internal/module/crm/repository/followup_mongo.go` | add | Upsert、ListDue(now)、ListByOwner、UpdateStatus | | `apps/backend/internal/module/crm/repository/followup_memory.go` | add | 測試用 | | `apps/backend/internal/module/crm/usecase/followup.go` | add | 建立/重算 `due_at`;hook 於 stage 轉移與回覆送出 | ### 行為變更 - 每個 Contact 同時最多一筆活躍 FollowUp(`scheduled`/`notified`/`snoozed`)。 - 天數取 Contact `follow_up_days`(預設 3)。 - 階段推進到 `replied` 或更後 → FollowUp 轉 `done`。 ## Out of scope - 掃描 Job 與通知(T586) - API(T587) ## Acceptance - [x] unit test:送出回覆 → 建立 `scheduled`,`due_at` 為最後接觸 +3 天 - [x] 階段轉 `replied` → 自動 `done` - [x] 指令: ```bash cd apps/backend && go test ./internal/module/crm/... -count=1 ```