Add Event ready / Completed readiness filters to registrants roster#1925
Conversation
| # lands (CE payment, certificate-sent tracking). --- | ||
|
|
||
| # TODO: no CE payment is tracked yet, so nobody is CE-paid. | ||
| def ce_paid? |
There was a problem hiding this comment.
🤖 From Claude: These three are deliberate stubs — CE-paid and both certificate_sent_at fields don't exist yet. Until they land, "Completed" reads false for everyone (by design). Flip each to the real predicate when its feature merges; completion should require both the registration and CE certificate-sent fields.
| @readiness = @event_registrations.to_h do |registration| | ||
| [ registration.id, EventRegistrationReadiness.new(registration, submitted_org_name: @submitted_org_names[registration.registrant_id]) ] | ||
| end | ||
| if params[:event_ready].in?(%w[ ready not_ready ]) |
There was a problem hiding this comment.
🤖 From Claude: Readiness is filtered in Ruby on the already-loaded roster (no pagination on this page) rather than as a SQL scope, since the same per-row computation also drives the badge tooltips. It sits after the active/inactive counts, matching how the existing attendance_status filter is also excluded from those tab counts.
| # and its matching filter. Completion is the final state and wins; otherwise an | ||
| # outstanding pre-event to-do means "not ready", and a clear checklist means | ||
| # "ready" for the event. | ||
| def status |
There was a problem hiding this comment.
🤖 From Claude: Precedence is deliberate: completion wins over the pre-event checklist (a finished registrant shouldn't read "Not ready" just because, say, a balance was never reconciled), then an outstanding pre-event item is "not ready", and a clear checklist is "ready". The roster shows one badge from this and the filter matches it word-for-word.
9769887 to
36efab7
Compare
There was a problem hiding this comment.
Pull request overview
Adds a single, combined registrant lifecycle Status (badge + filter) to the event registrants roster, backed by a new EventRegistrationReadiness service that centralizes readiness/completion logic and exposes human-readable issues/reasons for tooltips and filtering.
Changes:
- Introduces
EventRegistrationReadinessPORO to compute:not_ready,:ready,:certificate_due,:completedplus issue/reason strings. - Updates Events registrants roster UI to display a new far-right Status column and adds a matching “Status” filter.
- Adds service + request specs covering the readiness logic and the roster/filter rendering behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
app/services/event_registration_readiness.rb |
New readiness/completion PORO used by the roster for status/tooltip/filter decisions. |
app/controllers/events_controller.rb |
Preloads needed associations, batches submitted org names, builds readiness objects, and applies readiness filtering in-memory. |
app/views/events/_registrants_search.html.erb |
Adds the “Status” (readiness) filter select. |
app/views/events/_registrants_results.html.erb |
Adds sortable Status column and renders the readiness badge per row; moves submitted org name mapping to controller-provided ivar. |
app/views/event_registrations/_readiness_badge.html.erb |
New badge partial rendering the status pill + tooltip + optional subtext. |
spec/services/event_registration_readiness_spec.rb |
Unit coverage for readiness/completion checks, status, and reason/issue outputs. |
spec/requests/events_spec.rb |
Request coverage ensuring the roster renders statuses and that readiness filtering works (including invalid filter handling). |
AGENTS.md |
Updates service/spec counts and documents the new service. |
| def scholarship_uncreated? | ||
| registration.scholarship_requested? && !registration.scholarship? | ||
| end | ||
|
|
||
| def scholarship_tasks_incomplete? | ||
| registration.scholarship? && !registration.scholarship_tasks_met? | ||
| end | ||
|
|
| def status | ||
| return :completed if completed? | ||
| return :not_ready unless event_ready? | ||
| return :certificate_due if certifiable? | ||
| :ready |
Squashed for re-integration onto main (which since merged the CE + certificate system). Reworked in the rebase resolution. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
36efab7 to
75dc87d
Compare
| <% readiness = @readiness[registration.id] %> | ||
| <td class="px-4 py-2 text-sm text-center" data-sort-value="<%= readiness.status %>"> | ||
| <%= render "event_registrations/readiness_badge", | ||
| status: readiness.status, |
- "Org validation" now fires purely on whether an organization is linked (pending or none). A linked org clears it — a registrant with an org no longer reads "Not ready" just for lacking a Facilitator affiliation. - The Status column sorts by lifecycle rank then reason (a "rank|reason" key sorted client-side), so same-status rows group by reason. - Moved the Edit action to the far-right column, after Status. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🤖 PR, suggested 👤 review level: 📖 Read — readiness PORO + one Status column/filter on the registrants roster; no migrations
What is the goal of this PR and why is this important?
How did you approach the change?
EventRegistrationReadinessPORO computes both checklists + a combinedstatus, returning the specific outstanding reasons so the badge tooltip/subtext and the filter share one source of truth. Reads only preloaded associations (no N+1).Registerable—paid_in_full?andcertificate_sent?on both the registration and itscontinuing_education_registrations(no more stubs).Anything else to add?