Skip to content

Guard payment/scholarship/CE ticket callouts against missing event config#1992

Merged
maebeale merged 2 commits into
mainfrom
maebeale/callout-visibility-guards
Jul 15, 2026
Merged

Guard payment/scholarship/CE ticket callouts against missing event config#1992
maebeale merged 2 commits into
mainfrom
maebeale/callout-visibility-guards

Conversation

@maebeale

@maebeale maebeale commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

🤖 suggested review level: 3 Read 📖 small, contained visibility guards on four built-in callouts + one editor badge

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

  • A published built-in callout can still never reach the ticket when the event isn't configured for it. This makes that explicit instead of silently misleading admins.
  • Payment card hidden on a free event; scholarship card hidden when the event has no scholarship form; CE card hidden when the event offers no CE hours; videoconference card hidden when the event has no join link.
  • In the callout editor, an amber "won't show" badge sits next to the title of any published built-in whose event config is missing, explaining why.

How did you approach the change?

  • One shared BuiltinCalloutCards.config_gap(event, builtin_key) returns the reason a card can't show; the card builders guard on it and the editor badge reuses it, so the ticket guard and editor can't drift.
  • Badge rendered via a new RegistrationTicketCalloutDecorator#ticket_suppression_reason (nil when the callout will show, is hidden, or is custom).

Anything else to add?

  • Rebased onto main (post the "de-magic the callout naming" refactor Materialize built-in callouts on Event New; de-magic the callout naming #1977): uses BuiltinCalloutCards / builtin_key.
  • The scholarship guard keys on the event having a scholarship_form (not general scholarship-eligibility), per the ask; existing specs that exercised a requested scholarship without a form now seed one.
  • Deliberately excluded the certificate callout (hidden by per-registrant state — event ended/attended/paid — not misconfiguration, so a "won't show" badge would mislead).

Copilot AI review requested due to automatic review settings July 15, 2026 04:17

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 July 15, 2026 04:48
@maebeale maebeale force-pushed the maebeale/callout-visibility-guards branch from 502be41 to 7aa28cc Compare July 15, 2026 04:54
Copilot AI review requested due to automatic review settings July 15, 2026 04: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.

A published built-in callout still can't reach the ticket when the event
lacks what the card depends on — a free event has no payment card, an event
with no scholarship form has no scholarship card, and an event that offers no
CE hours has no CE card. Enforce those gaps in the card builders (one shared
BuiltinCalloutCards.config_gap so the ticket guard and editor can't drift) and
surface the reason as an amber "won't show" badge next to the callout title in
the editor, so admins aren't misled by a published toggle that has no effect.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@maebeale maebeale force-pushed the maebeale/callout-visibility-guards branch from 7aa28cc to 0a89df3 Compare July 15, 2026 04:58
The videoconference card already returns nil when the event has no
videoconference URL; route that through config_gap too so a published
videoconference callout on an event without a link gets the same amber
"won't show" badge in the editor as the payment/scholarship/CE built-ins.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 15, 2026 05:00

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 merged commit 78b6657 into main Jul 15, 2026
2 of 3 checks passed
@maebeale maebeale deleted the maebeale/callout-visibility-guards branch July 15, 2026 05:10
maebeale added a commit that referenced this pull request Jul 15, 2026
#1992's config_gap hides a built-in card whose event lacks the config it needs
(a cost, scholarship form, CE hours). On the sample ticket that suppressed
published cards the admin wants to preview, so a BuiltinCalloutCards preview
flag now skips the gap — the admin can see and click through the card while
still finishing the event's setup. Real tickets are unchanged (the gap still
applies).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
maebeale added a commit that referenced this pull request Jul 15, 2026
…f event config

#1992 added config_gap guards to the callout card builders but didn't exempt the
admin sample-ticket preview, so its 'every option turned on' view could no longer
show the scholarship / CE cards on an event lacking a scholarship form or CE hours
(and events_spec's sample_ticket ?options=all has failed since). The preview
illustrates a hypothetical registrant's options, so it now bypasses config_gap for
those two cards while a real ticket still applies it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
maebeale added a commit that referenced this pull request Jul 15, 2026
…olumns (#1996)

* Move FAQ + scholarship callout pages onto the shared _callout_page layout

Removes the duplicated back-eyebrow + branded-header chrome both pages
hand-rolled. Scholarship now renders through the shared layout, so it picks
up @builtin_intro (the materialized row's 'Callout page text'), which the
old bespoke markup silently dropped.

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

* Consolidate CE + art supplies onto callout rows; drop legacy Event columns

Finishes migrating the CE and art-supplies built-ins fully onto their
materialized callout rows, and deletes the two now-orphaned standalone pages.

- Rename the event_details built-in to art_supplies and make it a *content*
  callout, so it renders on the generic callout page (like handouts/FAQ) with
  no dedicated action/view. Default title 'Art supplies & what to bring'.
- Drop the legacy Event columns event_details(_label) and ce_hours_details(_label)
  (two reversible migrations, no backfill). The heading + copy live on the row now;
  the CE heading reads from the row via Event#ce_hours_label (used by the CE card,
  the CE page, and the CE-deadlines mailer).
- Delete the orphaned events#ce_hours / events#details pages, routes, controller
  actions, policy rules, and their specs — superseded by the callout pages.
- Remove the dead editor branch, the event_details_card builder, and the now-unused
  _builtin_callout_card partial.
- Seed the built-in callouts on every dev event and move the demo CE / art-supplies
  copy onto their rows.

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

* Update AGENTS.md for art_supplies content callout + dropped columns

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

* Show scholarship + CE cards in the sample-ticket preview regardless of event config

#1992 added config_gap guards to the callout card builders but didn't exempt the
admin sample-ticket preview, so its 'every option turned on' view could no longer
show the scholarship / CE cards on an event lacking a scholarship form or CE hours
(and events_spec's sample_ticket ?options=all has failed since). The preview
illustrates a hypothetical registrant's options, so it now bypasses config_gap for
those two cards while a real ticket still applies it.

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
maebeale added a commit that referenced this pull request Jul 15, 2026
… specs

- Remove EventRegistration#checked_in? — a stub with no backing column and
  no history of ever being implemented; deletes the unreachable "Checked in"
  badge branch on the ticket too. Day 1/Day N attendance already covers this
  via completed_day_N.
- Fix a real double-query on every ticket render: registration_ticket_callouts
  was queried once in the view and again in BuiltinCalloutCards#materialized?,
  plus a resources.any? query per visible callout. Preload
  event: { registration_ticket_callouts: :resources } and read the loaded
  association in Ruby instead of re-scoping it.
- Move HANDOUT_RESOURCE_TITLES from Events::CalloutsController into
  BuiltinCallouts, which actually owns the callout catalog; the controller
  had it backwards.
- Delete BuiltinCallouts.seedable_keys — dead code with no callers anywhere.
- Add request specs for CalloutsController's three previously-uncovered
  actions (certificate, update_ce_license, request_ce), and a spec pinning
  that the sample-ticket preview's config_gap bypass only applies to
  scholarship/CE (registrant-level), never payment/videoconference
  (event-level) — guards against a repeat of the #1992/#1996 regression.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
maebeale added a commit that referenced this pull request Jul 15, 2026
… specs (#1999)

- Remove EventRegistration#checked_in? — a stub with no backing column and
  no history of ever being implemented; deletes the unreachable "Checked in"
  badge branch on the ticket too. Day 1/Day N attendance already covers this
  via completed_day_N.
- Fix a real double-query on every ticket render: registration_ticket_callouts
  was queried once in the view and again in BuiltinCalloutCards#materialized?,
  plus a resources.any? query per visible callout. Preload
  event: { registration_ticket_callouts: :resources } and read the loaded
  association in Ruby instead of re-scoping it.
- Move HANDOUT_RESOURCE_TITLES from Events::CalloutsController into
  BuiltinCallouts, which actually owns the callout catalog; the controller
  had it backwards.
- Delete BuiltinCallouts.seedable_keys — dead code with no callers anywhere.
- Add request specs for CalloutsController's three previously-uncovered
  actions (certificate, update_ce_license, request_ce), and a spec pinning
  that the sample-ticket preview's config_gap bypass only applies to
  scholarship/CE (registrant-level), never payment/videoconference
  (event-level) — guards against a repeat of the #1992/#1996 regression.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
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.

2 participants