Service (app/goauto/returnmatch/service.go) wires the pure matching
functions to the database:
- BatchMatch: manual-only trigger (no scheduler, not called from
yeeke sync or SYB import) for ticked SYB product rows. Filters to
the participating process stages (待人工处理 excluded per the
confirmed rule), loads the available return pool (no active match,
non-nil future destroy deadline) via purchase.ProcessStages +a
join query, runs SelectMatches, and inserts one return_match row per
outcome. A unique-constraint violation on insert (lost race) is
reported per-row as a conflict skip, never fails the whole batch.
- Confirm/Cancel: state transitions with row locking; Cancel clears
both Active* columns so the same pair can be rematched later.
- Remark, List (by SYB product id / return item id / status) and
Detail for both admin pages' filter/column needs.
Handler + router (app/goauto/returnmatch/{handler,router}.go) expose
POST /api/admin/v1/return-matches/batch-match, GET .../return-matches,
GET .../return-matches/:id, POST .../:id/{confirm,cancel,remark}.
Write actions require admin/purchaser (same requireCanPurchase gate
already used by yeeke.Handler.TriggerSync); list/detail are read-only
for any authenticated user. Registered in
app/admin/router/init_router.go.
Tests cover end-to-end batch match, expired-deadline exclusion,
multi-colour cross-pairing through the DB path, 待人工处理 exclusion,
confirm-then-cancel restoring availability and rematch-ability, and a
concurrent-insert test asserting exactly one winner against the
unique constraint.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NTDbDcwbDw1TSAcE6wfh2F