rubyforgood / rubyforgood/awbw

Transferred-in ticket: surface source financials and service them from the new registration

Open
#2,262 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement event mgmt scholarships
Dominant language
Ruby
Stars
15
Forks
26
Avg merge
12h 42m
Merged PRs (30d)
242

Description

Followup to the event-registration transfer work (#1944 / PR #2044). Start as a new branch off main after #2044 merges — not part of #2044.

Context

A transferred-in registration's registrant-facing ticket/callout pages don't correctly surface or service the money/scholarship that live on the source reg. The read-side "amount due" already delegates to the source; the gaps are the payment ledger, scholarship servicing, and a pay-flow that misfiles a payment onto the transferred-in reg without clearing the delegated balance.

Caveats (main moved since this was drafted):

  • Line numbers below are approximate — main advanced through #2237/#1993/#2178/#2258, so verify against current code (method names are stable).
  • #2178 (scholarship decline flow) is now merged and reworked the scholarship agreement into a tri-state agreement_response_status (pending/accepted/declined) + ScholarshipAgreementResponse history. Part 2 (scholarship servicing) must be built against that new model, not the old agreement_signed_at boolean.

The governing rule

Delegation to the source is conditional on the source actually having allocations/payments.

  • Source has payments → the financial record is anchored on the source. Show the source's ledger + delegated balance on the new ticket; to pay a remaining balance, send the registrant to the source reg's ticket (pay there, allocations stay on source). Never let a payment land on the transferred-in reg in this case.
  • Source has no payments → the math should all be on the new reg. The new reg owns its own cost/balance/allocations; the registrant pays on the new reg normally (no delegation). This also removes the misfiling risk.

Implementation seam: gate the existing transferred_in? delegation in EventRegistration (remaining_cost, paid_in_full?, payment_received?, payment_access_granted?, invoice_available?, etc.) on transferred_from_registration.allocations.exists? (or payments_sum.positive?). Add a predicate like source_holds_financials? = transferred_in? && source.allocations.exists? and key the delegations + the pay routing off it. Verify the invoice/receipt from_registration swap (app/presenters/event_invoice.rb, event_receipt.rb) respects the same condition.

Part 1 — Payment ledger

app/views/events/callouts/payment.html.erb (+ payment action, Events::CalloutsController):

  • Keep this reg's own allocations rendering as-is (the existing @allocations list).
  • If transferred-in AND the source has allocations, add a separate section below — "Payments on your original registration" — rendering source.allocations. Reuse the figures the admin summary already computes in app/views/event_registrations/_transferred_in_financials.html.erb (source.event.cost_cents, source.allocations_sum/payments_sum, due).
  • "Amount due" already correct via delegated remaining_cost — leave it, but it now follows the conditional-delegation rule.

Part 2 — Scholarship servicing

Let the registrant view + respond to the source's scholarship from the new ticket, showing the old reg's scholarship record.

  • scholarship action gate + @scholarship: resolve via the chain — EventRegistration#effective_scholarship (scholarships.first || transferred_from_registration&.effective_scholarship) instead of raw @event_registration.scholarships.first. Relax the gate so a transferred-in reg whose source has a scholarship isn't redirected away.
  • sign_agreement (and the new accept/decline flow from #2178): operate on the source's Scholarship record (same person).
  • scholarship_status_card builder (app/services/builtin_callout_cards.rb): use the effective scholarship for the card's gate + data.
  • Task completion stays admin-only (display only).
  • The scholarship view's admin "Edit scholarship" link should point at the source's scholarship record.

Part 3 — Pay-flow correctness

  • pay action + redirect_to_stripe_checkout (Events::RegistrationsController) and the webhook allocation (pay_charge_extensions.rb): when source_holds_financials?, route the checkout/allocation to the source reg (metadata event_registration_id = source), so paying clears the delegated balance. When the source holds no financials, the transferred-in reg pays itself (correct once remaining_cost no longer delegates in that case).
  • On the ticket/payment page, the pay button for a transferred-in reg with a source balance should link to the source's payment/ticket rather than posting to its own pay path.

Per-builtin (no change needed)

  • ce_hours — correct (hours ride on the new reg's own record).
  • certificate — correct (earned at the intended/new event).
  • videoconference / staff / handouts / faq — correct (this event's content); keep showing (they're attending here), unlike a transferred-out reg.
  • art_supplies — reserved key, unused; ignore.

Verification

  • Model specs for conditional delegation: transferred-in with source payments → delegates; with no source payments → own math.
  • Request specs: payment page shows the source-allocations section only when transferred-in + source has allocations; scholarship page renders + services the source's scholarship from the new slug; pay routing targets the correct reg.
  • ai/test_extra before opening the (draft) PR.

🤖 Filed by Claude for maebeale — followup to #1944.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

After #2044 merges, start in EventRegistration and inspect the existing transferred_in? delegation methods and the source financials partial. Then trace app/views/events/callouts/payment.html.erb, Events::CalloutsController, Events::RegistrationsController, event_invoice.rb, event_receipt.rb, builtin_callout_cards.rb, and pay_charge_extensions.rb. Add model and request specs for source-payment delegation, scholarship servicing, payment-page rendering, and pay routing, then run ai/test_extra; done means source-held payments and scholarships are serviced from the new ticket without misfiling payments.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby
Domain
backend, payments
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.