Step-by-Step Guide — Follow each step exactly as written. All values are provided — do not improvise.

TC-BIL-008: Total Parity & Payment Reconciliation (Detailed)

Module: Billing & Invoicing — Totals / Payments

Primary Test User: treasurer@demo.membervu.com / Treasurer123! (Finance Manager); testmember@rcme.membervu.com / Member123! (member)

Priority: P1

URLs for this test:
Frontend: https://stg-rcme.membervu.com/login
Admin invoices: https://stg-rcme.membervu.com/admin/invoices
Finance dashboard: https://stg-rcme.membervu.com/admin/finance
Member invoices: https://stg-rcme.membervu.com/invoices
MailHog: https://stg-webmail.membervu.com
Payment gateway is INERT on staging (Paynamics). The multi-invoice payment initiation in Step 3 creates a real payment-initiation record but does NOT complete a live charge — verify the initiation/allocation records, not a captured payment.

Step 1: Set up an invoice with discount + line items + credits (BIL8-01/02/03)

StepAction (EXACT clicks/typing)Expected Result (EXACT text/behavior)Test Value
1Go to https://stg-rcme.membervu.com/login; sign in.Dashboard loads.treasurer@demo.membervu.com / Treasurer123!
2Sidebar → FinanceInvoices. Create a new manual invoice with 2 line items.Invoice created with itemized total = sum of line items.Line 1: Annual Dues ₱15,000.00 · Line 2: Late Fee ₱500.00 (total ₱15,500.00)
3Apply a FIXED discount of ₱1,500.00 to this invoice (Apply Discount modal).Net drops to ₱14,000.00.Discount ₱1,500.00, reason QA BIL-008 parity setup
4Record a partial manual payment of ₱6,000.00 against this invoice and approve it (settled allocation/credit).Invoice balance now ₱8,000.00 outstanding.₱6,000.00
5Note the invoice number and the exact figures: original ₱15,500.00 → net after discount ₱14,000.00 → balance after payment ₱8,000.00.Recorded for cross-check.

Step 2: Cross-check the SAME total across all 4 surfaces (BIL8-01/02/03)

StepActionExpected ResultTest Value
1Open this invoice's detail view (GET /api/billing/admin/invoices/:id).Shows original ₱15,500.00, discount −₱1,500.00, net ₱14,000.00, paid ₱6,000.00, balance ₱8,000.00.
2Go back to the invoice listing (GET /api/billing/invoices/tenant) and find this invoice's row.The listing row's amount/balance figures are IDENTICAL to detail — same cents, no rounding drift.
3Run a reporting export (Finance → Reports, or the CSV export on the invoice list) covering this invoice's period/source.The exported row for this invoice number shows the SAME total figures as detail/listing.
4Open the Finance dashboard (/admin/finance, GET /api/billing/admin/finance/summary) for the relevant period.The aggregate figures are consistent — this invoice's ₱6,000.00 collected and ₱8,000.00 outstanding contribute correctly to the summary totals (not double-counted, not omitted).
Data assertion: all four surfaces are fed by the same canonical projectInvoiceTotals projector (#443/#450). If ANY of the 4 shows a different total for this same invoice, that is a P1 money-parity defect — record which surface(s) diverged and the exact conflicting figures.

Step 3: Multi-invoice payment initiation (BIL8-04)

StepActionExpected ResultTest Value
1Log out; log in as the member. Go to My Invoices (/invoices).List of the member's own outstanding invoices.testmember@rcme.membervu.com / Member123!
2Select 2 or more outstanding invoices via checkboxes (if the UI supports multi-select) and initiate ONE payment via a wallet channel.UI calls POST /api/billing/member/invoices/bulk-pay/paynamics with an array of invoice IDs. GCash/Maya only — CREDITCARD is not offered for bulk pay (deferred, GR150).Channel: GCash or Maya
3Inspect the response / resulting records (admin view of payments, or API response).A single payment-initiation groups the invoices, but each selected invoice receives its OWN Allocation record with the correct per-invoice amount — no invoice left un-allocated, none double-allocated.
4Verify each invoice's balance individually.Each invoice's balance reflects exactly its own allocation — sum of all allocations across the selected invoices equals the total payment amount.

Step 4: Payment-confirmation email — reconcile job window (BIL8-05)

StepActionExpected ResultTest Value
1Complete a dues payment (manual payment approved by admin, or the online-record path).Payment status settles.
2Immediately check https://stg-webmail.membervu.com.Confirmation email may or may not have arrived yet — this is expected either way.
3If not present, wait up to ~10 minutes (the background reconcile job's cycle window) and re-check MailHog.The confirmation email arrives within the window. Backend field Payment.confirmationEmailSentAt gets populated (verifiable via admin payment detail if exposed, or by re-confirming the email content matches this payment).
4Only if the email is STILL missing after 10+ minutes, log it as a genuine miss.Do not file "email not sent" as a bug if checked before the 10-minute window elapses — that is a false positive per #118's documented reconcile cadence.

Step 5: Reject a manual payment — invoice stays listed + balance reverts (BIL8-06)

StepActionExpected ResultTest Value
1As member, submit a manual bank-transfer payment with proof against a fresh OUTSTANDING invoice (e.g. ₱10,000.00), for the full amount.Payment record created, status PENDING. Invoice remains outstanding (unsettled allocation doesn't reduce balance).₱10,000.00
2As Finance Manager, go to Finance → Payments, locate the pending payment, click Reject, enter a reason.POST /api/billing/admin/payments/:paymentId/reject200. Payment status becomes FAILED (verificationStatus: REJECTED).Reason QA BIL-008 reject test
3Go back to the invoice list (Outstanding filter).The invoice still appears in the list — it was NOT removed/hidden by the rejection.
4Open the invoice detail.Balance is restored to the full pre-payment amount — ₱10,000.00 outstanding, not a stale partial or ₱0. The backend re-runs recomputeAndPersistInvoiceStatus on rejection specifically so the stored status/outstanding-tab query reflects this correctly.

Step 6: Payment rows show both references (BIL8-07)

StepActionExpected ResultTest Value
1Open Finance → Payments list; locate any settled payment row (e.g. from Step 1).Row/detail displays the internal payment reference AND, where applicable, the gateway reference — both visible, not just one collapsing into the other.

CLEANUP