TC-MEM-008: Membership Periods & Status Engine

Module: Membership Management โ€” Billing Periods (#504) + Unified Status-Transition Engine (#447/#453) + Manual-Dues Activation (#527)

Priority: P1

Backend: services/membership/membershipStatus.service.ts (transitions + computeMembershipExpiry()), services/membership/onDuesInvoicePaid.ts, paymentHandlers.ts (approveManualPaymentHandler), utils/validation.ts (createMembershipTypeSchema).

๐Ÿ†• New this pass: QUARTERLY + LIFETIME membership periods (#504), a unified status-transition engine with per-transition source-state guards (#447/#453), and manual bank-transfer dues approval now activating the member in the same step (#527). See index ยง2/ยง2a for full detail; this TC drives the scenarios end-to-end.

Objectives

Scenario Summary

#ScenarioExpected
1Create QUARTERLY membership type201; period: "QUARTERLY" persisted; selectable in the form.
2Create LIFETIME membership type201; period: "LIFETIME" persisted; price label reads "One-time Price".
3LIFETIME member activation (dues paid or approval skip-dues)membershipExpiresAt = null in the DB; activation email renders "Lifetime (no expiry)" โ€” no exception, no blank/garbled field.
4QUARTERLY member activationmembershipExpiresAt = activation date + exactly 3 calendar months.
5Valid transitions (approve, reject, suspend, deactivate, reactivate, expire)Each succeeds per the guard table in index ยง2.
6Invalid transitions (e.g. suspend a REJECTED member, approve an ACTIVE member, deactivate a SUSPENDED member)success:false / 400 with a "Cannot <action> member with status X" message โ€” no state change.
7Expiry identical across pathsApproval (skip-dues), dues-invoice-paid, and admin-reactivate all compute the same expiry date for the same period + duesPeriod + from-date.
8Manual bank-transfer dues approval (#527)Approving a PENDING bank-transfer payment on a DUES invoice flips the member PENDING_PAYMENT โ†’ ACTIVE immediately; membershipStartDate + membershipExpiresAt are set in the same request โ€” assert both the status field AND the dates.

See the detailed walkthrough for exact steps, URLs, and test data.

Notes