Each click of 「匹配退货」 now writes a return_match_batch row: operator, time, submitted/matched/skipped counts and the per-SYB-product result (in submission order), plus the error if the batch aborted. Recording happens after the per-row transactions commit, so a logging failure is logged server-side instead of failing an already-applied match. GET /return-matches/batches and /return-matches/batches/:batchId expose the records. Migration version 1789800800000 creates the table. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTDbDcwbDw1TSAcE6wfh2F