# T733 — radar product mappers filters

> Status: `done`  
> Milestone: `M3` · Phase C  
> Kind: `feat` · Est. change: `~170 lines`

## Goal

將 product watch／ProductMatch／primary／filters 正確映射到 goctl public types，不丟失舊欄位。

## Depends on

- T700、T730、T731、T732

## Inputs

- `apps/backend/internal/logic/radarmap/map.go`
- `apps/backend/internal/logic/radar/*list*`、`*get*`
- `../spec.md` §5.2

## Outputs

| 路徑 | 動作 | 說明 |
|------|------|------|
| `apps/backend/internal/logic/radarmap/map.go` | edit | watch／match／primary／snapshot mapper |
| `apps/backend/internal/logic/radar/list_watches_logic.go` | edit | context filters mapping |
| `apps/backend/internal/logic/radar/list_opportunities_logic.go` | edit | product／fit／state／sort filters mapping |
| mapper tests | add/edit | optional fields、legacy shape |

## Behavior

- nil slice 對外為穩定空陣列；legacy optional 欄位不造假。
- product filter 語意為存在該 match；primary fields 另回。
- pagination/envelope 沿用既有規則。

## Out of scope

- 查詢業務與排序實作（T753）
- frontend mapper（T760）

## Acceptance

- [x] 新舊 fixtures mapper snapshot 測試通過。

```bash
cd apps/backend && go test ./internal/logic/radarmap/... ./internal/logic/radar/... -count=1
```

Implementation result (2026-08-10): mapped watch context, ProductMatch
evidence/snapshots, primary fields, sweep counters, and product filters while
keeping legacy optional fields and stable non-nil arrays.
