Add downloadable receipt for paid bulk payments#2011
Conversation
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>
84961a2 to
318399f
Compare
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>
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>
jmilljr24
left a comment
There was a problem hiding this comment.
The receipt doesn't reflect who paid, it's showing who submitted the form. I don't know how critical it is, but I could see someone getting their receipt with wrong payer info and wanted it fixed.
Do we actually need a name/org on the receipt? Invoice makes sense but the receipt is completely transactional. This amount was paid to awbw for xyz. But I don't know if some business (payer) needs so see their name on a receipt.

| # payment is on file. Mirrors Registrations#receipt: gated on availability, | ||
| # redirecting back to the ticket while payment is still pending. | ||
| def receipt | ||
| authorize! :bulk_payment, to: :receipt? |
There was a problem hiding this comment.
| authorize! :bulk_payment, to: :receipt? | |
| authorize! :bulk_payment |
|
Also, being that the receipt is generated based on the event details, if a payment is made when an event is $1500 the receipt reflects that. If the event cost were to change (unlikely but out of principle) then receipt would then be updated. Shouldn't a receipt be static and captured at the time of payment? |
🤖 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?
How did you approach the change?
EventReceipt.from_bulk_paymentalongside the existingfrom_registration— one itemized line per attendee, the payer's single payment as the ledger entry.EventReceiptnow carries abalance_settlementflag: 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.bulk_payment/:slug/receiptroute/action/policy (direct action onBulkPaymentsController, matching how the registration receipt lives onRegistrationsController), gated onFormSubmission#bulk_payment_receipt_available?(a payment is on file); redirects back to the ticket while pending.events/receipts/_receipt+events/invoices/_actions(print-to-PDF) partials.AllocationLedgerLabelto label aPaymentdirectly (not only via an allocation), so invoice and receipt stay in sync.Ticket integration (rebased onto main's ticket redesign)
short_date_range, "Registrant details"); kept that redesign wholesale.Anything else to add?
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.