Put the events in a test queue and release them one at a time. Start attempt A, hold its completion, start B, then deliver A's completion. Assert which attempt changes after each step, not just the final count.
Give attempts their own identity in the proposed interface, then replay the same sequence against the change. The coupon name can stay useful to people without doing the matching job on its own.
Also deliver A's completion twice. It should update A once without incrementing the count again or touching B. You've already got the awkward event queued, so that extra case is cheap.
Revised offline cases now keep A and B separate after reopening. An unmatched completion appears in review, not against the latest coupon. Controls still needs to check the real interface supplies the same identity.