From 34a128a4cbdf68127145d389f38e63a6fe02c53c Mon Sep 17 00:00:00 2001 From: maebeale Date: Mon, 22 Jun 2026 08:46:56 -0400 Subject: [PATCH] Hide scholarship/CE registration boxes when they don't apply The registration edit form always showed the Scholarship and CE credits boxes, even for free events (where there's no fee to subsidize) and events that don't grant continuing education credits. That implied actions that don't apply and crowded the row. - Add ce_credits_eligible to Event (default true) so organizers can flag whether an event grants CE credits; surface the checkbox on the event form. - On the registration form, hide the scholarship box for free events and the CE box when the event isn't CE-eligible. - Let the organizations box absorb the freed columns: half width with both boxes, three-quarters with one, full width with none. Co-Authored-By: Claude Opus 4.8 --- app/policies/event_policy.rb | 1 + app/views/event_registrations/_form.html.erb | 19 +++++++-- app/views/events/_form.html.erb | 7 ++++ ...20000_add_ce_credits_eligible_to_events.rb | 9 ++++ db/schema.rb | 3 +- spec/models/event_spec.rb | 6 +++ spec/system/event_registration_edit_spec.rb | 41 +++++++++++++++++++ 7 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 db/migrate/20260622120000_add_ce_credits_eligible_to_events.rb diff --git a/app/policies/event_policy.rb b/app/policies/event_policy.rb index e345eb5352..2367280a8d 100644 --- a/app/policies/event_policy.rb +++ b/app/policies/event_policy.rb @@ -126,6 +126,7 @@ def google_analytics? :autoshow_pre_date_text, :autoshow_registration_close, :public_registration_enabled, + :ce_credits_eligible, :signed_in_one_click_enabled, :autoshow_registration_details, :hint_dates, diff --git a/app/views/event_registrations/_form.html.erb b/app/views/event_registrations/_form.html.erb index 13a1091ad2..e3412a68fe 100644 --- a/app/views/event_registrations/_form.html.erb +++ b/app/views/event_registrations/_form.html.erb @@ -133,12 +133,21 @@ - <%# ---- Organizations, scholarship, and continuing education — one row ---- %> + <%# ---- Organizations, scholarship, and continuing education — one row. + Scholarship only applies to paid events; CE credits only to events the + organizer flagged as eligible. Organizations fills whatever the hidden + boxes leave behind: it starts at two of four columns and absorbs one + more column for each box that's hidden. ---- %> + <% paid_event = f.object.event.cost_cents.to_i.positive? %> + <% show_scholarship = paid_event %> + <% show_ce = f.object.event.ce_credits_eligible? %> + <% org_span = 2 + (show_scholarship ? 0 : 1) + (show_ce ? 0 : 1) %> + <% org_span_class = { 2 => "sm:col-span-2", 3 => "sm:col-span-3", 4 => "sm:col-span-4" }.fetch(org_span) %> <% active_orgs = f.object.registrant.affiliations.select { |a| !a.inactive? && (a.end_date.nil? || a.end_date >= Date.current) }.map(&:organization).compact.uniq.sort_by(&:name) %> <% connected_org_ids = f.object.organizations.map(&:id) %> <% addable_orgs = active_orgs.reject { |org| connected_org_ids.include?(org.id) } %>
-
+
@@ -208,12 +217,15 @@
- <%= render "scholarship", event_registration: f.object, scholarship: f.object.scholarships.first %> + <% if show_scholarship %> + <%= render "scholarship", event_registration: f.object, scholarship: f.object.scholarships.first %> + <% end %> <%# ---- CE credits — toggled "Requested" flag, plus the registrant's CE details (license number + requested hours) and what they owe at the default hourly rate, recomputed live by the ce-credit-requested controller. The details collapse when CE isn't requested. ---- %> + <% if show_ce %>
@@ -274,6 +286,7 @@
+ <% end %> <% if f.object.payment_unresolved? %> diff --git a/app/views/events/_form.html.erb b/app/views/events/_form.html.erb index b5790dc9fe..0abe1a2e27 100644 --- a/app/views/events/_form.html.erb +++ b/app/views/events/_form.html.erb @@ -163,6 +163,13 @@

Cost <%= f.object.errors[:cost].join(", ") %>

<% end %> + +
+ <%= f.input :ce_credits_eligible, + as: :boolean, + label: "Eligible for continuing education credits", + hint: "When unchecked, the CE credits box is hidden on registrations." %> +
diff --git a/db/migrate/20260622120000_add_ce_credits_eligible_to_events.rb b/db/migrate/20260622120000_add_ce_credits_eligible_to_events.rb new file mode 100644 index 0000000000..f41e3a4fc2 --- /dev/null +++ b/db/migrate/20260622120000_add_ce_credits_eligible_to_events.rb @@ -0,0 +1,9 @@ +class AddCeCreditsEligibleToEvents < ActiveRecord::Migration[8.1] + def up + add_column :events, :ce_credits_eligible, :boolean, default: true, null: false + end + + def down + remove_column :events, :ce_credits_eligible, if_exists: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 87e2573c42..3580eb5114 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.1].define(version: 2026_06_21_213947) do +ActiveRecord::Schema[8.1].define(version: 2026_06_22_120000) do create_table "action_text_mentions", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| t.bigint "action_text_rich_text_id", null: false t.datetime "created_at", null: false @@ -517,6 +517,7 @@ t.boolean "autoshow_title", default: true, null: false t.boolean "autoshow_videoconference_label", default: true, null: false t.boolean "autoshow_videoconference_link", default: true, null: false + t.boolean "ce_credits_eligible", default: true, null: false t.text "ce_hours_details" t.string "ce_hours_details_label", default: "CE hours", null: false t.integer "cost_cents" diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index 19903ba5d3..0bcfc7d306 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -8,6 +8,12 @@ it { should validate_numericality_of(:cost_cents).is_greater_than_or_equal_to(0).allow_nil } end + describe "ce_credits_eligible" do + it "defaults to true" do + expect(build(:event).ce_credits_eligible).to be true + end + end + describe "destroying with form submissions" do it "is blocked and keeps the submission when the event has one" do event = create(:event) diff --git a/spec/system/event_registration_edit_spec.rb b/spec/system/event_registration_edit_spec.rb index 216bca7b60..db62cdfe02 100644 --- a/spec/system/event_registration_edit_spec.rb +++ b/spec/system/event_registration_edit_spec.rb @@ -234,6 +234,47 @@ end end + describe "conditional Organizations / scholarship / CE boxes" do + it "shows scholarship and CE boxes for a paid, CE-eligible event with organizations at half width" do + sign_in(admin) + visit edit_event_registration_path(registration) + + expect(page).to have_css("h2", text: "Scholarship") + expect(page).to have_css("h2", text: "CE credits") + expect(page).to have_css("section.sm\\:col-span-2", text: "Registration organizations") + end + + it "hides the scholarship box for a free event and widens organizations" do + event.update!(cost_cents: 0) + sign_in(admin) + visit edit_event_registration_path(registration) + + expect(page).to have_no_css("h2", text: "Scholarship") + expect(page).to have_css("h2", text: "CE credits") + expect(page).to have_css("section.sm\\:col-span-3", text: "Registration organizations") + end + + it "hides the CE box when the event is not CE-eligible and widens organizations" do + event.update!(ce_credits_eligible: false) + sign_in(admin) + visit edit_event_registration_path(registration) + + expect(page).to have_css("h2", text: "Scholarship") + expect(page).to have_no_css("h2", text: "CE credits") + expect(page).to have_css("section.sm\\:col-span-3", text: "Registration organizations") + end + + it "fills the full row with organizations for a free, non-CE-eligible event" do + event.update!(cost_cents: 0, ce_credits_eligible: false) + sign_in(admin) + visit edit_event_registration_path(registration) + + expect(page).to have_no_css("h2", text: "Scholarship") + expect(page).to have_no_css("h2", text: "CE credits") + expect(page).to have_css("section.sm\\:col-span-4", text: "Registration organizations") + end + end + describe "delete button" do it "deletes the registration" do sign_in(admin)