Endpoints: GET /api/campaigns/admin/donations/pending (queue) · approve/reject (see TC-FUND-001) · POST /api/billing/admin/campaigns/:id/close-out · GET .../close-out/donors.csv · POST .../close-out/thank-you.
Login as admin@rcme.membervu.com / Admin123! (finance admin) or treasurer@demo.membervu.com / Treasurer123! (FINANCE_MANAGER). At least one campaign with a PENDING donation (see TC-FUND-001).
Open Proof Review (/admin/campaigns/donations/pending).
GET /api/campaigns/admin/donations/pending — lists all tenant PENDING donations across all campaigns, oldest first, each row showing the donor, amount, and the uploaded proof image.
2
Approve or reject a row inline (no page navigation).
The row disappears from the queue immediately; the same approve/reject endpoints from TC-FUND-001 are used.
TC-FUND-ADMIN-02: Nav Badge Tracks Pending Count
Step
Action
Expected Result
1
Note the current "Proof Review" sidebar badge count. Create a new donation + proof upload (as donor, in a second session/tab).
Badge count increments by 1 (backed by listPendingDonations().total, key pendingProofDonations).
2
Approve or reject the new donation.
Badge count decrements by 1.
3
Log in as a role WITHOUT finance permissions and check the badge.
The badge shows 0 — a 403 on the underlying fetch is treated as 0, not surfaced as an error.
TC-FUND-ADMIN-03: Campaign Close-Out — Final Totals
Step
Action
Expected Result
1
On an ACTIVE campaign with a mix of APPROVED/PENDING/REJECTED donations, trigger Close-Out from the campaign detail page.
POST /api/billing/admin/campaigns/:id/close-out. FundraisingCampaign.status ACTIVE → CLOSED. Response finalTotal = SUM(Donation.amount WHERE approvalStatus = APPROVED) only — PENDING/REJECTED excluded. donationCount matches the number of APPROVED donations.
2
Re-trigger Close-Out on the now-CLOSED campaign.
Idempotent 200 no-op (NOT a 400) — same finalTotal/donationCount returned.
TC-FUND-ADMIN-04: Close-Out Donor CSV Export
Step
Action
Expected Result
1
Download GET .../close-out/donors.csv for the closed campaign.
CSV contains only APPROVED donations. Anonymous donation rows have name/email redacted to "Anonymous"/empty string.
TC-FUND-ADMIN-05: Close-Out Bulk Thank-You Email
Step
Action
Expected Result
1
Trigger POST .../close-out/thank-you.
Response shape {total,sent,skipped,failed}. Only APPROVED donors are emailed; anonymous donors with no linked member are skipped, not failed.
2
Check MailHog.
One thank-you email per non-anonymous APPROVED donor.
TC-FUND-ADMIN-06: Auto-Close on Deadline Does NOT Auto-Run Close-Out
Step
Action
Expected Result
1
Let (or force via a past endsAt) a campaign's deadline pass.
A sweep auto-transitions ACTIVE → CLOSED; the public donate button goes dark/disabled.
2
Check any donations that were PENDING near the deadline.
Close-out is NOT auto-run — those PENDING donations remain in the Proof Review queue and are still approvable by admin after auto-close.