Skip to content

Add downloadable receipt for paid bulk payments#2011

Open
maebeale wants to merge 3 commits into
mainfrom
maebeale/bulk-payment-receipt
Open

Add downloadable receipt for paid bulk payments#2011
maebeale wants to merge 3 commits into
mainfrom
maebeale/bulk-payment-receipt

Conversation

@maebeale

@maebeale maebeale commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

🤖 suggested review level: 3 Read 📖 small backend flow mirroring the existing registration receipt; new presenter method + gated slug route

What is the goal of this PR and why is this important?

  • Bulk payers had only an invoice. Once their payment is recorded they now get a receipt (proof money changed hands) they can download for their records.

How did you approach the change?

  • Added EventReceipt.from_bulk_payment alongside the existing from_registration — one itemized line per attendee, the payer's single payment as the ledger entry.
  • A bulk payment has no owed-balance / paid-in-full concept, unlike a registration. EventReceipt now carries a balance_settlement flag: the shared receipt document shows the "Total charged / Balance due $0 / Paid in full" reconciliation only for registrations, and a plain "Amount paid" + "Payment received" for bulk payments.
  • New public, slug-based bulk_payment/:slug/receipt route/action/policy (direct action on BulkPaymentsController, matching how the registration receipt lives on RegistrationsController), gated on FormSubmission#bulk_payment_receipt_available? (a payment is on file); redirects back to the ticket while pending.
  • Reuses the shared events/receipts/_receipt + events/invoices/_actions (print-to-PDF) partials.
  • Refactored AllocationLedgerLabel to label a Payment directly (not only via an allocation), so invoice and receipt stay in sync.

Ticket integration (rebased onto main's ticket redesign)

  • Rebased onto main after the bulk-payment ticket redesign (Payer + payment-status headline, short_date_range, "Registrant details"); kept that redesign wholesale.
  • Folded the receipt in by turning main's standalone Invoice card into a Documents group: invoice (always) + receipt (green "View receipt" link once paid, locked "Available once your payment is received" card until then).

Anything else to add?

  • Specs: presenter (from_bulk_payment), request (receipt gating + amount-paid framing + ticket Documents card states), model predicate. Registration receipt path unchanged (still asserts "Paid in full"/"Balance due"). All green; RuboCop clean.
  • Gating is "any payment on file" (matches the ticket's existing "Payment received" signal) — flag if you'd prefer a stricter check.

Copilot AI review requested due to automatic review settings July 22, 2026 13:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Bulk payers previously had only an invoice; once a payment is on file they
now get a matching paid-in-full receipt from the ticket's Documents section,
mirroring the registration receipt flow. The receipt card is locked until a
payment is recorded, so the payer sees what unlocks it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@maebeale
maebeale force-pushed the maebeale/bulk-payment-receipt branch from 84961a2 to 318399f Compare July 22, 2026 13:41
Copilot AI review requested due to automatic review settings July 22, 2026 13:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@maebeale
maebeale marked this pull request as ready for review July 22, 2026 13:58
The old comment mostly restated the method body. Keep only the point a reader
can't infer: the gate is deliberately looser than the registration receipt's
paid-in-full check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 22, 2026 14:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

A bulk payment has no owed-balance concept, so its receipt shouldn't borrow the
registration receipt's "Total charged / Balance due / Paid in full" framing — it
just records whatever was paid. EventReceipt now carries a balance_settlement
flag; the shared receipt document shows the reconciliation summary + "Paid in
full" badge only when settling a balance (registrations), and a plain "Amount
paid" + "Payment received" for bulk payments.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 22, 2026 14:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants