Release Notes — Jul 7, 2026 — on stage (dev accumulation since Jul 6)

What this release is. A single backend hardening MR merged to dev (→ staging) since the Jul 6 accumulation (!281)membervu/membervu-saas!282 (closes membervu-pm#620). This is a stage/dev accumulation, not a prod promotion — verify on staging (https://stg-rcme.membervu.com; admin portal https://stg-admin.membervu.com). Headline: the concurrency-safe invoice-number fix from #613 (dues path, shipped Jul 6) is now extended to the event-registration invoice and donation / manual invoice paths, so those two money paths no longer risk a duplicate-invoice-number 500 under a race.

⚙️ Before you start — environment & logins

SurfaceURLLogin to use
Org portal (tenant)stg-rcme.membervu.comAdmin admin@rcme.membervu.com / Admin123!; Treasurer treasurer@demo.membervu.com / Treasurer123!
Member viewstg-rcme.membervu.comMember testmember@rcme.membervu.com / Member123!
Super-admin portalstg-admin.membervu.comSuper Admin superadmin@zeniark.com / SuperAdmin123!
Email inbox (MailHog)stg-webmail.membervu.com
Scope notes — read before testing.

💳 Billing — concurrency-safe invoice numbers on event & donation invoices — #620 (!282)

Context (why this matters). On Jul 6, #613 made the dues invoice-number generator retry correctly on a duplicate-number collision (the retry had been silently dead under the new Prisma 7 database driver). #620 is the follow-up that extends that same fix to the other two money paths — event-registration invoices and donation / manual invoices — which were still running the old, dead retry check.
#ChangeWhat to verify on stage
#620 money · concurrency · P2 Event & donation invoice numbers are now collision-safe. The duplicate-invoice-number retry guard on the event-registration invoice and donation / manual invoice creation paths was dead at runtime under the Prisma 7 driver (it checked a field the driver no longer populates), so a simultaneous double-create could 500 on a duplicate number. The collision is now detected correctly, and where the operation owns its own transaction it retries with a fresh number (same shared helper the dues path uses). Normal path (must not regress):
  • Register for a paid event as a member → the registration succeeds and produces an invoice with a valid, unique invoice number (prefix EVT-…). Repeat a few times → every invoice number is distinct.
  • Record a donation (and a manual / offline "Record Payment" invoice) → each gets its own distinct invoice number; no duplicate-number or constraint error.
Optional concurrency probe (if you can): have two testers register for the same event at the same moment (or fire two donation submits back-to-back) → both invoices are created with different numbers; neither returns a server error about a duplicate/constraint.
⚠ Known residual (by design in this MR). For call sites where invoice creation is bundled into a larger caller-owned database transaction, an in-place auto-retry is not safe (Postgres aborts the whole transaction on the first collision). In that case #620 now correctly detects the collision and returns a clear, typed error instead of silently continuing — full caller-side retry for those paths is a separate, larger refactor and is out of scope for this ticket. Practical impact for testers: in the extremely rare simultaneous-collision case on a bundled path you may still see a single clean error rather than an automatic retry — this is expected, not a new bug. Report any duplicate invoice numbers that do slip through against #620.

🚀 Deploy & regression notes

Source of truth: membervu/membervu-pm#620 · merged via membervu/membervu-saas!282 to dev on 2026-07-07. Stage builds from dev.