Release Notes — Jun 15, 2026 — Accounting milestone lands on stage

🎉 Major release — not a patch. The dev→prod release !136 carries the entire Accounting / Paynamics milestone (the long-running mile/accounting branch, merged to dev via !129) plus 5 targeted bug fixes. For testers this means a large block of finance/billing functionality that the previous notes flagged as ⛔ "not on stage" is now live on stage (dev = staging) and should get a full regression pass — invoices, line items, discounts, late fees, manual payments, proof of payment, treasury, dues. Verified merged to dev on 2026-06-15 (merge 377ef437).
⚠️ Critical scoping — read before planning.
Supersedes earlier "not on stage" warnings. The Jun 10–11 and Jun 12 notes both carried a ⛔ Still NOT on stage box listing #148, #151, #152, #153, #158 (treasury / reactivate-expiry / discount / late-fee). #152, #153, #158 (and the related #178, #213) are now on stage via this release. OQ-RET-16 / #151 is also fixed (see Membership below). Treasury now loads for all roles (#262). Re-test those items per this note.

💰 Accounting milestone (!129) — primary regression surface

A1 · Invoices & line items P0

#ChangeWhat to verify on stage
#213Relational invoice line items — add / edit / remove line items; itemized render & totals. (Previously the "Add line item" action did nothing.)Create an invoice → add multiple line items → totals recalc; itemized print view renders. ⚠️ Known limit: the update-existing-line-item path on an already-saved invoice is marked unwired in the #213 review — adding on creation works; editing line items on a saved invoice may not persist. Report what you see, but this gap is expected. Zero-total itemized invoices are rejected.
#152Invoice discounts with provenance — original amount, discount amount, reason, who/when.Apply a discount to an invoice → original vs discounted amount both shown + reason + audit/activity trail entry. Status transitions still work (DRAFT→ISSUED→PARTIALLY_PAID→PAID/OVERDUE/VOID).

A2 · Late-fee engine & config P1

#ChangeWhat to verify on stage
#178Late-fee config now persists in dues-settings update (the PUT previously stripped the fields, so config was unreachable).Dues settings → enable late fee (enabled / percent / flat / max) → save and reload; the config persists (old bug dropped it on save). Config UI lives on the live DuesSettingsTab (#261 moved it off a dead page).
#153 / #158Late-fee assessment engine — late fee on remaining balance, generated as a child invoice, with a unique-index guard against duplicates.An overdue invoice generates a late-fee child invoice once (no duplicate on re-run — there's a unique index). Disable late fee → no new assessment. (See Dues / Billing.)

A3 · Payments — manual / record / proof P1

AreaWhat to verify on stage
Record paymentRecord a manual / cash / bank payment against an invoice → allocation applied, balance reduces; partial + full; bulk payment. Upload & view proof of payment; reversal/refund states render. SimulatePayment still works as the inert-gateway substitute.

A4 · Treasury & reconciliation P1

#ChangeWhat to verify on stage
#262Treasury no longer crashes — backend DTO fields now mapped to the frontend view type (was toLowerCase on an undefined payment stream)./admin/treasury loads for all roles (Admin, Treasurer, Finance Mgr…) without crashing. Log an external payment; reconciliation table renders mixed payment streams; PayBiz table renders empty-but-stable (gateway inert).

A5–A7 · Finance dashboards · super-admin PayBiz config · events/dues P2

AreaWhat to verify on stage
Finance dashboardsFinance & Executive dashboards load with correct totals; invoice-status chart reflects state; quick-action links route correctly.
Super-admin PayBiz config (admin portal stg-admin.membervu.com)Open a tenant → PayBiz config tab renders; split-agreement % / fixed fields save & persist; URL-attestation guidance shows. Config is dormant (gateway inert) — verify it persists without enabling live payments.
Events / duesFree event registration still works end-to-end; a PAY_NOW event's checkout page renders but does not attempt the live gateway; dues creation works. Events are now ticket-aware (#166); suspend now revokes sessions (#167).

A8 · Security / session P1 — watch for regressions

ChangeWhat to verify on stage
Token invalidation (User.tokenVersion), public invoice link expiry (Invoice.publicTokenExpiry), and rate-limit hardening (rate limiting cannot be disabled in prod — VAPT F-24).Existing sessions behave normally; public invoice links work and expire appropriately; login / forgot-password rate limiting is still active (don't expect DISABLE_RATE_LIMIT to bypass it).

👥 Membership — OQ-RET-16 / #151 fixed

#FixWhat to verify on stage
#151 (OQ-RET-16)Reactivate now sets a future expiry. reactivateMembership previously only set status=ACTIVE and left membershipExpiresAt untouched (member could re-expire on the next renewal run). It now sets membershipExpiresAt to ~1 year from now and restores roles.Reactivate an EXPIRED or SUSPENDED member (Actions ▾ → Change Status → Reactivate/Activate) → status ACTIVE and a new expiry ~1 year out. Behaviour change: tests that previously asserted "no new expiry on reactivation" must be updated. (Updated in the Membership test plan.)

🐛 Targeted bug fixes

#AreaWhat to verify on stage
#262Treasury/admin/treasury loads without crashing for all roles. (Covered in A4.)
#213Invoices"Add line item" works. (Covered in A1, with the update-path caveat.)
#250Tenant URLsOn a tenant subdomain, the forgot-password email (plus magic-link / activation / invoice emails) use the correct tenant host — adopts buildTenantOrigin at 6 remaining getFrontendUrl sites. Trigger forgot-password on stg-rcme; the link host is stg-rcme.membervu.com. (Completes the #236/#237 sweep.) Check the body in stg-webmail.membervu.com.
#251Public eventsOpen a public event page as an anonymous visitor → attendee avatars load (were broken via the private /secure-images route; now served via the public /images route, scoped to the event's own tenant). Privacy check: only intended avatars show, none from other tenants.
#254Email unsubscribeClick the unsubscribe link in a broadcast/notification email → UnsubscribePage resolves the correct tenant (link params realigned to tenant slug; memberId dropped) and unsubscribes successfully. (Pairs with the Communications §6 note about broadcast unsubscribe URLs.)
#249NotificationsIn approval-workflow notification recipient config, a malformed / markup local-part email (e.g. <script>…@x.com) is rejected (tightened validation). Low severity.

ℹ️ No tester impact (FYI)

Suggested regression plan shape

  1. P0: Invoices + line items + discounts (A1); bug fixes #262 / #213 / #250 / #251 / #254.
  2. P1: Late fees (A2), manual payments + proof (A3), treasury (A4), security/session (A8), #151 reactivate-expiry.
  3. P2: Finance dashboards (A5), super-admin PayBiz config (A6), events/dues (A7), #249.
  4. Skip: live Paynamics gateway checkout / webhooks / split-pay (inert — not in this release).

Source of truth: MR !136 + linked issues in membervu/membervu-pm. Stage builds from dev — accounting milestone (merge 377ef437) and all 5 bug fixes (#262 fb648dd4, #250 18ceb7b3, #251 b255f62f, #254 09b9a7d4, #249 46c00a97) and #151 reactivate-expiry verified present on dev on 2026-06-15. Gateway flows are inert in every QA environment.