rejectIfActiveReturnMatch (app/goauto/purchase/return_match_block.go)
is called from Service.create right after the SYB row is locked: a
SYB product with an active (matched or confirmed) return_match row is
rejected with CodeReturnMatched. Since BatchCreate already calls
Service.Create per row and treats a create error as a per-row skip,
this single insertion point covers both single and batch creation —
batch creation skips only the blocked rows and reports
CodeReturnMatched, it does not fail the whole batch. A query error
here is treated as internal() and never silently allows creation.
Process stage computation (process_stage.go) gains two new stages,
ProcessStageReturnPending (退货待确认) and ProcessStageReturnUsed
(已用退货), sourced from a new bounded dataset.activeReturnMatchBySYB
query in loadBatchPreviewDataset (batch.go); with zero return_match
rows this query returns nothing and every other stage branch is
unchanged (updated the batch preview bounded-query-count assertion in
batch_test.go from 8 to 9 to reflect the new, still-bounded query).
Regression coverage (return_match_block_test.go): single create
rejected for matched and for confirmed match, cancelled match does
not block, batch create creates the clean row and skips only the
matched row with CodeReturnMatched, and a zero-return-match baseline
still succeeds unchanged (acceptance item 11).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NTDbDcwbDw1TSAcE6wfh2F