Track event-reg transfers via a back-link (fix lost attendance on transfer-in) - #2044
Open
maebeale wants to merge 30 commits into
Open
Track event-reg transfers via a back-link (fix lost attendance on transfer-in)#2044maebeale wants to merge 30 commits into
maebeale wants to merge 30 commits into
Conversation
maebeale
marked this pull request as ready for review
August 2, 2026 13:34
maebeale
force-pushed
the
maebeale/issue-1944
branch
from
August 2, 2026 22:31
abd066d to
3613ba0
Compare
maebeale
force-pushed
the
maebeale/issue-1944
branch
from
August 3, 2026 02:58
3613ba0 to
b34dcfa
Compare
maebeale
force-pushed
the
maebeale/issue-1944
branch
from
August 4, 2026 05:12
51c90b7 to
7711748
Compare
maebeale
force-pushed
the
maebeale/issue-1944
branch
from
August 10, 2026 02:49
4360cb2 to
773cd02
Compare
maebeale
force-pushed
the
maebeale/issue-1944
branch
from
August 10, 2026 15:35
174e97a to
4fc99b9
Compare
Reflect where CE is certified rather than where it's billed: - Readiness certificate checks (pending/sent) use the certifiable set (earned here), so the intended event's roster shows the CE certificate pending and the source no longer does; payment/license checks stay on the home reg. - The registrants roster CE column shows a transferred-in reg's certified CE (linking to the record on the original) instead of offering "Create". - Add EventDashboard#transferred_in_recipient? (public) and use it for the recipient-card "billed to original event" note (fixes a private-method call). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both the original and the new event's registration have their own ticket, so a shared _transfer_notice partial explains on each where the money/scholarship/CE records live and where attendance + the certificate are earned. Rendered on the ticket and the payment, CE, scholarship, certificate, invoice, and receipt pages — surfaced to attendee and staff, linking to the paired registration's ticket. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A transfer-in is a temporary middle stop: when it's transferred out again (A→B→C), keep only the endpoints. Point the new reg at the original source and destroy the middle, so attendance and the transfer trail stay on the two real registrations. (#1944) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Transfers now match on-demand ↔ on-demand and scheduled ↔ scheduled (was facilitator-training kind). Picker hint + tests updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A transferred-in registration carries no money of its own — the balance, payments, invoice, receipt, and scholarship all live on the source it came from (the old event, where they actually paid). Route them there so the new ticket never re-bills a paid transfer, the invoice/receipt document the old cost, and the roster's unpaid filter buckets a transfer by the source's balance. Hide participation callouts on a transferred-out ticket (they withdrew) while keeping their financial/credit records, and block scholarship creation on a transfer-in at the URL, not just the UI. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A transfer now keeps two CE records instead of deriving certification across the link: the source keeps a paid, zero-hours stub (its payments count at the original event and it still surfaces in that event's CE searches), and the destination gets a live record carrying the hours and the outstanding balance, where new payments are received and the certificate is earned. Collapsing a double transfer relocates the middle record forward instead of destroying it; transferring back to the origin merges it into the stub. The destination record's cost is snapshotted from the source's balance and admin-locked, and manual CE creation on a transfer-in is blocked at the URL. CE reporting follows the record, so the stub counts at the original event and the carried record at the new one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A transfer keeps the registrant's agency context in both places, so the new reg should show the same linked orgs as the one they left — copied, not moved, so the source keeps its own. (#1944) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A reg marked transferred-out but with no destination recorded is a half-done task that's easy to lose track of; surface a warning triangle on the badge so an admin can spot and complete it. (#1944) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The transfer screen only vaguely said it "keeps the transfer history." An admin approving a transfer should know exactly what happens to the registrant's data first — that money/scholarship stay on the original event, orgs copy over, and CE hours move. A transfer-in being moved again also removes the middle registration, so warn about that explicitly in the chain-collapse case. (#1944) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A reg marked transferred-out with no destination recorded yet is an unfinished task, but readiness ignored it — a stale "Payment due" could mask it. Make it the highest-priority pre-event issue so the roster Status badge and readiness filter surface it. (#1944) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Transfers get done wrong, and there was no way to fix one. The interstitial becomes a "Manage transfer" hub reached from a roster status-badge chip (amber when a destination is still missing, purple once set) and an edit-form link, keeping the status dropdown a pure status control. From the hub an admin can change the destination event or undo the transfer entirely. Undo restores the reg to its pre-transfer status; for a completed transfer it also unlinks the destination (it becomes a normal standalone reg, nothing deleted) and re-merges the split CE back onto the source. Re-pointing to a new event reuses the same revert step before re-splitting. (#1944) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Confirms RevertTransfer re-merges a relocated CE record back onto the origin when undoing an A→B→C transfer that collapsed to two regs — origin restored, destination unlinked, no orphaned hours. (#1944) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
maebeale
force-pushed
the
maebeale/issue-1944
branch
from
August 18, 2026 11:50
71b6003 to
a776f29
Compare
Shorter, plainer bullets read more clearly for a low-tech admin. (#1944) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two side-by-side columns (this registration vs. the new one) read more clearly than a flat list. Also surface a "Manage transfer" link on the transferred-in reg's trail so the hub is reachable from either end. (#1944) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Carry days attended, expected payment method, buddy-pay, and the
recipients-page shout-out flag onto the new reg so it reflects where they
left off (money and CE resolve separately). Note the carried days under the
new reg's attendance checkboxes ("Day 1 completed in prior training"). (#1944)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dashboard shout-outs already scope to active_registrations, so a transferred-out (or no-show/cancelled) reg's shout-out never shows on the recipients page. With shout-out now copied forward, it surfaces on the new active reg instead. Add a test pinning the exclusion. (#1944) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A transferred-out reg is historical: its status, attendance, financials, linked orgs, and shout-out shouldn't change here — only comments and communications stay open, and undo runs through the Manage-transfer flow, not by editing fields. Enforce this server-side (restricted update params + action guards on the inline onboarding/certificate/attendance/org-link endpoints and the recipients shout-out) so a locked field is refused with a warning rather than silently dropped, and surface it in the UI: a lock banner and disabled fields on the edit form, disabled onboarding/roster inline controls. The scholarship, CE, and allocations pages stay reachable but show a caution banner, since an admin may still need to edit those deliberately. Also tighten the transfer interstitial consent copy, show the event's month and year to disambiguate same-titled trainings, rename the action to "Perform transfer", and fix the transferred-in CE card to offer the normal Add-CE control when the source had no CE (so CE decided now attaches to this reg). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…in reg A transferred-in reg's financials summary showed only the source's payment and scholarship, but the CE payment stays on the source too — so surface it (No CE / No CE payments / the amount), alongside the payment and scholarship it already shows. And when the source had no scholarship, show this reg's own editable scholarship card so an admin can award one here: a scholarship decided now belongs to this registration, the same way a CE decided now does. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
So facilitators/admins can see the transfer capability on /features once an admin syncs the catalog. (#1944) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…every callout page A transferred-out registrant should be pointed to their new registration, not transacting on the old ticket. Hide the "Pay with Credit Card" button (and its "access granted" pill) for a transferred-out reg — the join link and manage block were already hidden, this closes the last interactive gap; the new-reg banner already links onward. Also consolidate the transfer banner into the shared callout wrapper (`_callout_page`, guarded on @event_registration) so it appears at the top of every callout page a transferred in/out registrant can reach, and delete the four now-duplicate explicit renders (payment/scholarship/ce/certificate). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 suggested review level: 5 Inspect 🔬 self-FK + data migration, status-list change, transfer flow, two-record CE split, and financials-on-source semantics across reporting
Closes #1944
What is the goal of this PR and why is this important?
transferred_inoverwrote its attendance status, losing whether the person actually attended the event they transferred into.transferred_from_registration_idself-FK lives on the incoming record; the out stays identifiable by its terminaltransferred_outstatus. Chained transfers form a linked list back to the original.The transfer flow
Editing & undoing a transfer (Manage-transfer hub)
RevertTransfer): restores the reg to its pre-transfer status; for a completed transfer it also unlinks the destination (it becomes a normal standalone reg, nothing deleted) and re-merges the split CE back onto the source (TransferContinuingEducation#revert).Money & records resolve to the source registration
payment_status_label= "Transferred in", readiness stops flagging "Payment due", payment access derives from the source.Continuing education splits into two records (issue #1944)
Transferred-out ticket
Reporting
Surfaced as a dimension (it's no longer a status)
Locking a transferred-out registration
updateparams + guards on the inline onboarding / certificate / attendance / org-link endpoints and the recipients shout-out), so a locked field is refused with a warning, not silently dropped.<fieldset>s), disabled onboarding/roster inline controls, and hidden "Create user".Transferred-in editing & the consent screen
Transferred-out ticket: read-only + banner everywhere
_callout_page), so it appears on every callout page a transferred in/out registrant can reach, not just the financial ones. The four duplicate explicit renders were removed.