# T586 — job-radar-followup-scan-and-notify

> Status: `done`  
> Milestone: `M5`  
> Kind: `feat`  
> Est. change: `~180 lines`

## Goal

完成後系統應：`radar_followup_scan` 日排程掃到期 FollowUp → 轉 `notified` ＋發站內通知，落地 Contact 詳情。

## Depends on

- T585

## Inputs

- Spec：`../spec.md` §4.7.2、§4.7.3、§5.4、§9.4（FU-01）
- 既有：`cmd/worker/main.go` maintenance tick＋`redislock`、`internal/module/notification/**`

## Outputs

### 程式變更（預期路徑）

| 路徑 | 動作 | 說明 |
|------|------|------|
| `apps/backend/internal/module/job/domain/job.go` | edit | 新增 `TemplateRadarFollowupScan = "radar_followup_scan"` |
| `apps/backend/internal/module/crm/usecase/followup_scan.go` | add | 掃 `ListDue` → 轉 `notified`＋`notified_count++` → 發通知 |
| `apps/backend/cmd/worker/main.go` | edit | maintenance 內日排程呼叫（Redis lock 保護）＋ template 分派 |

### 行為變更

- 通知沿用既有 `notifications`，`ref_type=contact`，點擊落地 `/app/crm/:contactId`。
- 同一 FollowUp 同一天不重複通知。
- 多實例只有一台執行；掃描寫日誌（處理筆數、通知筆數）。

## Out of scope

- escalate 規則（T587）
- AI 追蹤訊息（T588）

## Acceptance

- [x] FU-01：3 天無動作 → `notified`＋通知存在且落地正確
- [x] 兩實例同時跑不重複通知
- [x] 指令：

```bash
cd apps/backend && go test ./internal/module/crm/... ./internal/module/notification/... -count=1 && make build
```
