Skip to content

Track event-reg transfers via a back-link (fix lost attendance on transfer-in) - #2044

Open
maebeale wants to merge 11 commits into
mainfrom
maebeale/issue-1944
Open

Track event-reg transfers via a back-link (fix lost attendance on transfer-in)#2044
maebeale wants to merge 11 commits into
mainfrom
maebeale/issue-1944

Conversation

@maebeale

@maebeale maebeale commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

🤖 suggested review level: 5 Inspect 🔬 self-FK + data migration, status-list change, transfer flow, and financials-on-source semantics across reporting

Closes #1944

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

  • Marking a registration transferred_in overwrote its attendance status, losing whether the person actually attended the event they transferred into.
  • Fix: track the transfer as a relationship, not a status. A transferred_from_registration_id self-FK lives on the incoming record; the out stays identifiable by its terminal transferred_out status. Chained transfers form a linked list back to the original.

The transfer flow

  • After a reg is marked Transferred out (from the edit-form save or the inline roster/onboarding Turbo badge), the admin lands on a transfer screen to pick the destination event (scoped to the same kind — facilitator training ↔ training), which creates or links the person's registration there.

Financials stay on the source registration

  • An incoming reg's scholarship/CE/payments remain on the source reg. The edit form shows a distinct, read-only "financials on the original registration" summary (payment/scholarship/CE) that links back to the source reg's section anchors, instead of its own editable cards.
  • A transferred-in reg no longer reads as owing this event: payment_status_label = "Transferred in", readiness stops flagging "Payment due", and payment access derives from the source.

Reporting

  • Totals stay on the original event (its dashboard/revenue are unchanged).
  • The new event excludes transferred-in regs from its financial totals (dashboard billable basis + revenue figures, held in parity) and from the bulk-payment allocation list — while still counting them in headcount/attendance.

Surfaced as a dimension (it's no longer a status)

  • Roster badge "In" marker, dashboard breakdown row (FK-counted) with drill-down, an "Attendance status → Transferred in" filter (roster + reminders), and a CSV "(transferred in)" annotation.

Known non-goals (flag if wanted)

  • The roster payment-status filter (unpaid) still buckets a transferred-in reg as unpaid.
  • The registrant-facing ticket invoice isn't suppressed for a transferred-in reg on a paid event.
  • Same-kind transfer scoping is enforced at the picker, not the POST endpoint.

Copilot AI lite review requested due to automatic review settings August 2, 2026 13:18

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.

Copilot AI review requested due to automatic review settings August 2, 2026 13:23

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 August 2, 2026 13:34
Copilot AI review requested due to automatic review settings August 2, 2026 13:37

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 force-pushed the maebeale/issue-1944 branch from abd066d to 3613ba0 Compare August 2, 2026 22:31
Copilot AI review requested due to automatic review settings August 2, 2026 22:31

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 force-pushed the maebeale/issue-1944 branch from 3613ba0 to b34dcfa Compare August 3, 2026 02:58
Copilot AI review requested due to automatic review settings August 3, 2026 02:58

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.

Copilot AI review requested due to automatic review settings August 3, 2026 03:13

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 force-pushed the maebeale/issue-1944 branch from 51c90b7 to 7711748 Compare August 4, 2026 05:12
Copilot AI review requested due to automatic review settings August 4, 2026 05:12

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.

Copilot AI review requested due to automatic review settings August 4, 2026 05:45

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.

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.

Copilot AI review requested due to automatic review settings August 10, 2026 03:07

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.

Copilot AI review requested due to automatic review settings August 10, 2026 15:35

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.

Copilot AI review requested due to automatic review settings August 10, 2026 20:19

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 force-pushed the maebeale/issue-1944 branch from c06f8a0 to 4df7226 Compare August 10, 2026 20:58
Copilot AI review requested due to automatic review settings August 10, 2026 20:58

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.

Copilot AI review requested due to automatic review settings August 10, 2026 21:04

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 and others added 11 commits August 11, 2026 02:46
Add transferred_from_registration_id (self-FK) so an incoming registration
points back at the one it transferred out of. The in-record keeps its own real
attendance status, fixing the loss of attendance data when it was marked
"transferred_in"; an out stays identifiable by its terminal status. Adds a
follow-up screen to record/link the destination after marking transferred out.

Closes #1944

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cover the transferred_from/to associations, transferred_in?/transfer_destination_pending?,
the post-save redirect to the transfer screen, and the transfer create/link flow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A facilitator training only transfers to another facilitator training, and a
non-training only to another non-training, so the destination picker matches
the source event's facilitator_training flag.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Integrates with main's dashboard status breakdown (#2041): transferred_in is no
longer an attendance status, so its row raised KeyError on
ATTENDANCE_STATUS_LABELS.fetch and drilled into an empty roster filter. Remove
the row and update the status-based specs accordingly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Transferred-in is now an FK-backed dimension (an incoming reg keeps its own
attendance status), so designate it wherever status is shown:
- roster badge gains an "In" marker alongside the real status
- dashboard attendance breakdown regains a transferred-in row, counted via the
  transfer link with a working drill-down
- the attendance-status filter (roster + reminder recipients) offers a
  "Transferred in" option, routed through the attendance_status scope to the FK
- CSV exports annotate the Status column with "(transferred in)"

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
An incoming registration's scholarship/CE/payments stay on the source reg it
transferred from. This makes that concrete across the app:

- Transfer follow-up now fires from every status-change entry point — the inline
  roster/onboarding Turbo badge, not just the edit-form save.
- The edit form shows a distinct, read-only "financials on the original
  registration" summary (payment/scholarship/CE) that links back to the source
  reg's section anchors, instead of its own editable cards. Added anchor ids to
  the scholarship and CE cards.
- A transferred-in reg no longer reads as owing this event: payment_status_label
  says "Transferred in", readiness stops flagging "Payment due", and payment
  access derives from the source.
- Reporting excludes transferred-in regs from the new event's financial totals
  (dashboard billable basis + revenue figures, kept in parity) and from the bulk
  payment allocation list, while still counting them in headcount/attendance.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A transferred-in reg's scholarship lives on the source, so the intended event
never showed them as a recipient. Add EventRegistration#effective_scholarship /
the dashboard's recipient recognition — scholarship_by_recipient, the recipient
count, and the recipients page — so they "get the hat" while the dollars stay on
the source (financial totals unchanged). The roster badge and the edit-form
summary now designate them a recipient and link to the actual award record.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Credit follows the person: a CE registration's hours are certified at the event
its home registration transferred to (else its own event), while the record +
payment stay on the source. Derive it from the transfer FK instead of a stored
column — certified_at_registration = event_registration.transferred_to_registration
|| event_registration; certified_ce_registrations is a has_many through the
transfer link. Certificate issuance and certificate_available? operate on the CE
a reg actually certifies (own + transferred-in), so the intended event can issue
the earned hours and the source no longer issues transferred-out hours. The
source CE card notes where the hours are certified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… exclusion

The event recipients card now flags a transferred-in scholarship recipient as
"Billed to original event" (recognized here, dollars on the source). Add a test
pinning that a transferred-out registration is excluded from the original
event's attendee count/attendance (it's an inactive status).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
@maebeale
maebeale force-pushed the maebeale/issue-1944 branch from 7d30f64 to 1d3ed18 Compare August 11, 2026 06:54
Copilot AI review requested due to automatic review settings August 11, 2026 06:54

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.

Event Reg - transferred in / transferred out

2 participants