diff --git a/app/services/event_attendance_report.rb b/app/services/event_attendance_report.rb index 14ebce83b9..9008da8025 100644 --- a/app/services/event_attendance_report.rb +++ b/app/services/event_attendance_report.rb @@ -38,11 +38,12 @@ def hours_awarded end def paying? - ce_registration.nil? || (ce_registration.counted? && ce_registration.payment_access_granted?) + ce_registration.nil? || ce_registration.access_granted? end end - # `paying_only:` narrows the CE report to counted licences paid or intending to pay. + # `paying_only:` narrows the CE report to licences that can sign in: paid or intending to + # pay and not denied, even past the CE payment deadline. def initialize(event, ce_only: false, paying_only: false) @event = event @ce_only = ce_only diff --git a/db/seeds/features/2026-11-02-ce-reports-drop-lapsed-ce.yml b/db/seeds/features/2026-11-02-ce-reports-drop-lapsed-ce.yml index 3d87bfc483..336b77e654 100644 --- a/db/seeds/features/2026-11-02-ce-reports-drop-lapsed-ce.yml +++ b/db/seeds/features/2026-11-02-ce-reports-drop-lapsed-ce.yml @@ -6,9 +6,9 @@ pr_number: 2934 action_path: "/events" summary: >- Once an event's CE payment deadline passes, CE that isn't paid in full stops - counting in reports: the CE timesheets, the dashboard's CE fees card and CE - pie, and the revenue report. Denied CE is left out the same way. + counting in reports: the dashboard's CE fees card and CE pie, and the revenue + report. Denied CE is left out the same way. pro_tips: - "Money already collected still counts as paid, even on CE that stopped counting." - - "Intending to pay keeps CE on the timesheets only until the deadline." + - "CE timesheets still list CE marked intending to pay after the deadline, since those registrants can still sign in." - "Events without a CE payment deadline keep counting unpaid CE." diff --git a/spec/requests/events/attendance_spec.rb b/spec/requests/events/attendance_spec.rb index 7dc2b8578b..51bd4ae2b1 100644 --- a/spec/requests/events/attendance_spec.rb +++ b/spec/requests/events/attendance_spec.rb @@ -56,6 +56,20 @@ def log_ce_time! expect(response.body).to include("AAA111", "UNPAID1") end + it "keeps CE intending to pay on the default view after the CE payment deadline passes" do + event.update!(ce_payment_due_deadline: 1.day.ago) + intending = create(:professional_license, person: registration.registrant, number: "INTENDS1") + create(:continuing_education_registration, event_registration: registration, professional_license: intending, intends_to_pay: true) + unpaid = create(:professional_license, person: registration.registrant, number: "UNPAID1") + create(:continuing_education_registration, event_registration: registration, professional_license: unpaid) + + get attendance_event_path(event, ce: "true") + expect(response.body).to include("INTENDS1") + expect(response.body).not_to include("UNPAID1") + toggle = Capybara.string(response.body).find("nav[aria-label='CE payment filter']") + expect(toggle).to have_link("Paid or intends to pay (1)") + end + it "says when nobody has paid or intends to pay for CE yet" do license = create(:professional_license, person: registration.registrant, number: "UNPAID1") create(:continuing_education_registration, event_registration: registration, professional_license: license) diff --git a/spec/requests/events/signins_spec.rb b/spec/requests/events/signins_spec.rb index b9d08fabb6..46c3a33e03 100644 --- a/spec/requests/events/signins_spec.rb +++ b/spec/requests/events/signins_spec.rb @@ -102,6 +102,20 @@ def header_text expect(Capybara.string(response.body)).to have_link(href: attendance_event_path(ce_event, ce: "true", ce_payment: "all", return_to: "signins")) end + it "keeps CE intending to pay on the default view after the CE payment deadline passes" do + ce_event = training(title: "CE training", abbreviation: "CE-1", ce: true) + ce_event.update!(ce_payment_due_deadline: 1.day.ago) + log_time!(ce_event, name: "Erin", ce: true, paid: false) + .continuing_education_registrations.first.update!(intends_to_pay: true) + log_time!(ce_event, name: "Dana", ce: true, paid: false) + + get signins_events_path + expect(response.body).to include("LIC-Erin") + expect(response.body).not_to include("LIC-Dana") + toggle = Capybara.string(response.body).find("nav[aria-label='CE payment filter']") + expect(toggle).to have_link("Paid or intends to pay (1)") + end + it "says when no CE registration in scope is paid or intending to pay yet" do log_time!(training(title: "CE training", abbreviation: "CE-1", ce: true), name: "Dana", ce: true, paid: false) get signins_events_path diff --git a/spec/services/event_attendance_report_spec.rb b/spec/services/event_attendance_report_spec.rb index 29b07e43aa..c7d9f20e51 100644 --- a/spec/services/event_attendance_report_spec.rb +++ b/spec/services/event_attendance_report_spec.rb @@ -182,10 +182,10 @@ def row_for(registration) expect(report.all_rows.map(&:license_number)).to eq(%w[AAA111 BBB222]) end - it "drops a licence still intending to pay once the CE payment deadline passes" do + it "keeps a licence intending to pay after the CE payment deadline passes" do bob.continuing_education_registrations.first.update!(intends_to_pay: true) event.update!(ce_payment_due_deadline: 1.day.ago) - expect(described_class.new(event, ce_only: true, paying_only: true).rows.map(&:license_number)).to eq([ "AAA111" ]) + expect(described_class.new(event, ce_only: true, paying_only: true).rows.map(&:license_number)).to eq(%w[AAA111 BBB222]) end it "keeps a person's paid licence when their second is unpaid" do