# T571 — contact-merge-unmerge-owner-guard > Status: `done` > Milestone: `M4` > Kind: `feat` > Est. change: `~180 lines` ## Goal 完成後系統應:可手動合併/取消合併聯絡人,時間軸保留兩邊,跨 owner 一律拒絕。 ## Depends on - T565、T566 ## Inputs - Spec:`../spec.md` §4.6.3、§5.6、§9.4(CR-06、CR-07) ## Outputs ### 程式變更(預期路徑) | 路徑 | 動作 | 說明 | |------|------|------| | `apps/backend/generate/api/crm.api` | edit | merge/unmerge req/resp | | `apps/backend/internal/logic/crm/mergeContactLogic.go` | edit | 合併端點 | | `apps/backend/internal/module/crm/usecase/merge.go` | add | 搬移 `opportunity_ids`/touches 歸屬、記 `merged_from[]`、被併方標記為已併 | ### 行為變更 - 合併方向:目標 Contact 保留,來源 Contact 標記為已併並不再出現在列表。 - 時間軸合併後**兩邊紀錄都看得到**,各筆保留原本的來源平台資訊。 - 跨平台**不自動合併**,只有手動這一條路。 - 跨 owner 合併回明確越權錯誤。 - `unmerge` 還原被併方與其原有 touches/商機歸屬。 ## Out of scope - 自動身分推測(spec §7 明確禁止) - 前端合併 UI(併入 T575) ## Acceptance - [x] CR-06:兩個不同平台 Contact 合併成功,時間軸含兩邊 - [x] CR-07:跨 owner 合併回越權錯誤 - [x] unmerge 後兩筆資料回到合併前狀態 - [x] 指令: ```bash cd apps/backend && make gen-api && go test ./internal/module/crm/... ./internal/logic/crm/... -count=1 ```