From 459b422a59a249a61e1be578bb1a3a4bff8dcfed Mon Sep 17 00:00:00 2001 From: Thomas Leese Date: Thu, 18 Sep 2025 17:11:35 +0100 Subject: [PATCH 1/2] Warn users about deadline passed early This moves when we show users about whether the consent form deadline has passed to an earlier point in the journey, meaning they're not forced to go through the entire journey before being told to book a clinic appointment. Jira-Issue: MAV-2036 --- .../consent_forms/base_controller.rb | 22 ++++++++++++++----- .../consent_forms_controller.rb | 11 ++-------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/app/controllers/parent_interface/consent_forms/base_controller.rb b/app/controllers/parent_interface/consent_forms/base_controller.rb index ab99e17a65..072bdf5e08 100644 --- a/app/controllers/parent_interface/consent_forms/base_controller.rb +++ b/app/controllers/parent_interface/consent_forms/base_controller.rb @@ -11,6 +11,7 @@ class ConsentForms::BaseController < ApplicationController prepend_before_action :set_session prepend_before_action :set_consent_form before_action :authenticate_consent_form_user! + before_action :check_if_past_deadline! before_action :set_privacy_policy_url private @@ -61,12 +62,6 @@ def set_subteam end end - def authenticate_consent_form_user! - unless session[:consent_form_id] == @consent_form.id - redirect_to @header_path - end - end - def set_header_path @header_path = start_parent_interface_consent_forms_path( @@ -99,5 +94,20 @@ def set_service_guide_url def set_privacy_policy_url @privacy_policy_url = @team.privacy_policy_url end + + def authenticate_consent_form_user! + unless session[:consent_form_id] == @consent_form.id + redirect_to @header_path + end + end + + def check_if_past_deadline! + return if @session.open_for_consent? + + redirect_to deadline_passed_parent_interface_consent_forms_path( + @session.slug, + @programmes.map(&:type).join("-") + ) + end end end diff --git a/app/controllers/parent_interface/consent_forms_controller.rb b/app/controllers/parent_interface/consent_forms_controller.rb index e38620acbb..46cedb990e 100644 --- a/app/controllers/parent_interface/consent_forms_controller.rb +++ b/app/controllers/parent_interface/consent_forms_controller.rb @@ -7,9 +7,9 @@ class ConsentFormsController < ConsentForms::BaseController skip_before_action :set_consent_form, only: %i[start create deadline_passed] skip_before_action :authenticate_consent_form_user!, only: %i[start create deadline_passed] + skip_before_action :check_if_past_deadline!, only: :deadline_passed - before_action :clear_session_edit_variables, only: %i[confirm] - before_action :check_if_past_deadline, except: %i[deadline_passed] + before_action :clear_session_edit_variables, only: :confirm def start end @@ -65,12 +65,5 @@ def record def clear_session_edit_variables session.delete(:follow_up_changes_start_page) end - - def check_if_past_deadline - return if @session.open_for_consent? - redirect_to action: :deadline_passed, - programme_types: @programmes.map(&:type).join("-"), - session_slug: @session.slug - end end end From c5a5879ea866b31786bdc21e595bd7d8ee56136d Mon Sep 17 00:00:00 2001 From: Thomas Leese Date: Thu, 18 Sep 2025 17:42:54 +0100 Subject: [PATCH 2/2] Improve how session is chosen for consent form This ensures that when filling in a consent form where there exists multiple sessions with the same programmes at the same location, we pick the one that is most approriate based on which one has dates in the future. Jira-Issue: MAV-2036 --- .../app_consent_confirmation_component.rb | 8 +- .../concerns/consent_form_mailer_concern.rb | 3 +- app/controllers/consent_forms_controller.rb | 3 +- .../consent_forms/base_controller.rb | 2 +- app/jobs/consent_form_matching_job.rb | 21 ++-- app/lib/govuk_notify_personalisation.rb | 4 +- app/models/consent_form.rb | 48 ++++---- spec/features/parental_consent_clinic_spec.rb | 16 ++- ...l_consent_school_session_completed_spec.rb | 113 ++++-------------- 9 files changed, 82 insertions(+), 136 deletions(-) diff --git a/app/components/app_consent_confirmation_component.rb b/app/components/app_consent_confirmation_component.rb index b26e441c73..1044e80039 100644 --- a/app/components/app_consent_confirmation_component.rb +++ b/app/components/app_consent_confirmation_component.rb @@ -37,6 +37,8 @@ def full_name end def panel_text + location = (@consent_form.session.school? ? " at school" : "") + if response_given? if @consent_form.health_answers_require_triage? <<-END_OF_TEXT @@ -45,12 +47,12 @@ def panel_text your answers and get in touch again soon. END_OF_TEXT else - "#{full_name} is due to get the #{given_vaccinations} at school" + + "#{full_name} is due to get the #{given_vaccinations}#{location}" + (session_dates.present? ? " on #{session_dates}" : "") end else "You’ve told us that you do not want #{full_name} to get the" \ - " #{refused_vaccinations} at school" + " #{refused_vaccinations}#{location}" end end @@ -86,7 +88,7 @@ def given_vaccinations_are def session_dates @consent_form - .actual_session + .session .today_or_future_dates .map { it.to_fs(:short_day_of_week) } .to_sentence(two_words_connector: " or ", last_word_connector: " or ") diff --git a/app/controllers/concerns/consent_form_mailer_concern.rb b/app/controllers/concerns/consent_form_mailer_concern.rb index 2b62ab4e32..76827e37c3 100644 --- a/app/controllers/concerns/consent_form_mailer_concern.rb +++ b/app/controllers/concerns/consent_form_mailer_concern.rb @@ -14,8 +14,7 @@ def send_consent_form_confirmation(consent_form) consent_form:, programmes: ) - elsif consent_form.actual_session.clinic? || - consent_form.actual_session.completed? + elsif consent_form.session.clinic? || consent_form.session.completed? EmailDeliveryJob.perform_later( :consent_confirmation_clinic, consent_form:, diff --git a/app/controllers/consent_forms_controller.rb b/app/controllers/consent_forms_controller.rb index 6f50912688..953f7d9862 100644 --- a/app/controllers/consent_forms_controller.rb +++ b/app/controllers/consent_forms_controller.rb @@ -40,8 +40,7 @@ def update_match .sessions .includes(:location_programme_year_groups, :programmes) .has_programmes(@consent_form.programmes) - .find_by(academic_year: AcademicYear.pending) || - @consent_form.original_session + .find_by(academic_year: AcademicYear.pending) || @consent_form.session programme = session.programmes_for(patient: @patient).first diff --git a/app/controllers/parent_interface/consent_forms/base_controller.rb b/app/controllers/parent_interface/consent_forms/base_controller.rb index 072bdf5e08..a7793d3733 100644 --- a/app/controllers/parent_interface/consent_forms/base_controller.rb +++ b/app/controllers/parent_interface/consent_forms/base_controller.rb @@ -31,7 +31,7 @@ def set_session if params[:session_slug] @session = Session.find_by!(slug: params[:session_slug]) elsif @consent_form.present? - @session = @consent_form.original_session + @session = @consent_form.session end end diff --git a/app/jobs/consent_form_matching_job.rb b/app/jobs/consent_form_matching_job.rb index c2e5f1b5b4..a5e4225114 100644 --- a/app/jobs/consent_form_matching_job.rb +++ b/app/jobs/consent_form_matching_job.rb @@ -14,10 +14,10 @@ def perform(consent_form) # Match if we find a patient with the PDS NHS number return if match_with_exact_nhs_number - # Look for patients in the original session with no NHS number - if session_patients.count == 1 + # Look for patients in the original location with no NHS number + if location_patients.count == 1 # If we found exactly one, match the consent form to this patient - match_patient(session_patients.first) + match_patient(location_patients.first) end # Look for patients in any session with matching details @@ -65,11 +65,16 @@ def match_with_exact_nhs_number @consent_form.match_with_patient!(patient, current_user: nil) end - def session_patients - @session_patients ||= - @consent_form - .original_session - .patients + def location_patients + @location_patients ||= + Patient + .joins(:patient_locations) + .where( + patient_locations: { + location: @consent_form.location, + academic_year: @consent_form.academic_year + } + ) .includes(:school, :parents) .match_existing(nhs_number: nil, **query) end diff --git a/app/lib/govuk_notify_personalisation.rb b/app/lib/govuk_notify_personalisation.rb index 5bb62f43f2..430bf79620 100644 --- a/app/lib/govuk_notify_personalisation.rb +++ b/app/lib/govuk_notify_personalisation.rb @@ -26,9 +26,7 @@ def initialize( @programmes = programmes.presence || consent_form&.programmes.presence || [consent&.programme || vaccination_record&.programme].compact - @session = - session || consent_form&.actual_session || - consent_form&.original_session || vaccination_record&.session + @session = session || consent_form&.session || vaccination_record&.session @team = session&.team || consent_form&.team || consent&.team || vaccination_record&.team diff --git a/app/models/consent_form.rb b/app/models/consent_form.rb index 9935cd541b..7d1db52752 100644 --- a/app/models/consent_form.rb +++ b/app/models/consent_form.rb @@ -353,28 +353,32 @@ def reason_notes_must_be_provided? reason.in?(Consent::REASON_FOR_REFUSAL_REQUIRES_NOTES) end - def original_session - # The session that the consent form was filled out for. - @original_session ||= - Session - .joins(:programmes) - .where(programmes:) - .preload(:programmes) - .find_by(academic_year:, location:, team:) - end - - def actual_session - # The session that the patient is expected to be seen in. - @actual_session ||= - (location_is_clinic? && original_session) || - ( - school && - school - .sessions - .has_programmes(programmes) - .includes(:session_dates) - .find_by(academic_year:) - ) || team.generic_clinic_session(academic_year:) + def session + # This tries to find the most approriate session for this consent form. + # It's used when generating links to patients in a session, or when + # deciding which dates to show in an email. Under the hood, patients + # belong to locations, not sessions. + # + # Although unlikely to happen in production, there can be a scenario + # where multiple sessions at the same location offer the same programmes. + # In this case, we have to make a guess about which is the most relevant + # session. + + @session ||= + begin + session_location = school || location + + sessions_to_search = + Session.has_programmes(programmes).where( + academic_year:, + location: session_location, + team: + ) + + sessions_to_search.find { !it.completed? } || + sessions_to_search.first || + team.generic_clinic_session(academic_year:) + end end def find_or_create_parent_with_relationship_to!(patient:) diff --git a/spec/features/parental_consent_clinic_spec.rb b/spec/features/parental_consent_clinic_spec.rb index 6eb1ba7b86..7ed67cbf14 100644 --- a/spec/features/parental_consent_clinic_spec.rb +++ b/spec/features/parental_consent_clinic_spec.rb @@ -27,7 +27,7 @@ then_i_can_check_my_answers when_i_submit_the_consent_form - then_i_see_a_confirmation_page + then_i_see_a_confirmation_page_in_school when_the_nurse_checks_the_school_moves then_the_nurse_should_see_one_move @@ -57,7 +57,7 @@ then_i_can_check_my_answers when_i_submit_the_consent_form - then_i_see_a_confirmation_page + then_i_see_a_confirmation_page_in_clinic when_the_nurse_checks_the_school_moves then_the_nurse_should_see_one_move @@ -87,7 +87,7 @@ then_i_can_check_my_answers when_i_submit_the_consent_form - then_i_see_a_confirmation_page + then_i_see_a_confirmation_page_in_clinic when_the_nurse_checks_the_school_moves then_the_nurse_should_see_no_moves @@ -229,9 +229,15 @@ def when_i_submit_the_consent_form click_on "Confirm" end - def then_i_see_a_confirmation_page - # TODO: "will get their HPV vaccination at the clinic" + def then_i_see_a_confirmation_page_in_school + expect(page).to have_content("is due to get the HPV vaccination at school") + + perform_enqueued_jobs # match consent form with patient + end + + def then_i_see_a_confirmation_page_in_clinic expect(page).to have_content("is due to get the HPV vaccination") + expect(page).not_to have_content("at school") perform_enqueued_jobs # match consent form with patient end diff --git a/spec/features/parental_consent_school_session_completed_spec.rb b/spec/features/parental_consent_school_session_completed_spec.rb index 09a6f1b58a..95a167c5fa 100644 --- a/spec/features/parental_consent_school_session_completed_spec.rb +++ b/spec/features/parental_consent_school_session_completed_spec.rb @@ -9,24 +9,21 @@ given_an_hpv_programme_is_underway when_i_go_to_the_consent_form - when_i_fill_in_my_childs_name_and_birthday - - when_i_give_consent - and_i_answer_no_to_all_the_medical_questions - then_i_can_check_my_answers - - when_i_submit_the_consent_form - then_i_get_a_confirmation_email + and_i_fill_in_my_childs_name_and_birthday + and_i_try_to_give_consent + then_i_see_that_consent_is_closed end def given_an_hpv_programme_is_underway @programme = create(:programme, :hpv) @team = create(:team, :with_one_nurse, programmes: [@programme]) - subteam = create(:subteam, team: @team) + @subteam = create(:subteam, team: @team) - @scheduled_school = create(:school, :secondary, name: "School 1", subteam:) - @completed_school = create(:school, :secondary, name: "School 2", subteam:) + @scheduled_school = + create(:school, :secondary, name: "School 1", subteam: @subteam) + @completed_school = + create(:school, :secondary, name: "School 2", subteam: @subteam) @scheduled_session = create( @@ -46,29 +43,7 @@ def given_an_hpv_programme_is_underway location: @completed_school ) - @child = create(:patient, session: @scheduled_session) - end - - def when_a_nurse_checks_consent_responses - sign_in @team.users.first - visit "/dashboard" - - click_on "Programmes", match: :first - click_on "HPV" - within ".app-secondary-navigation" do - click_on "Sessions" - end - click_on "Pilot School" - click_on "Consent" - end - - def then_there_should_be_no_consent_for_my_child - expect(page).to have_content("No response") - - check "No response" - click_on "Update results" - - expect(page).to have_content(@child.full_name) + @patient = create(:patient, session: @scheduled_session) end def when_i_go_to_the_consent_form @@ -78,76 +53,34 @@ def when_i_go_to_the_consent_form ) end - def when_i_give_consent - choose "No, they go to a different school" - click_on "Continue" - - select @completed_school.name - click_on "Continue" - - expect(page).to have_content("About you") - fill_in "Full name", with: "Jane #{@child.family_name}" - choose "Mum" # Your relationship to the child - fill_in "Email address", with: "jane@example.com" - fill_in "Phone number", with: "07123456789" - check "Tick this box if you’d like to get updates by text message" - click_on "Continue" - - expect(page).to have_content("Phone contact method") - choose "I do not have specific needs" - click_on "Continue" - - expect(page).to have_content("Do you agree") - choose "Yes, I agree" - click_on "Continue" - - expect(page).to have_content("Home address") - fill_in "Address line 1", with: "1 Test Street" - fill_in "Address line 2 (optional)", with: "2nd Floor" - fill_in "Town or city", with: "Testville" - fill_in "Postcode", with: "TE1 1ST" - click_on "Continue" - end - - def when_i_fill_in_my_childs_name_and_birthday + def and_i_fill_in_my_childs_name_and_birthday click_on "Start now" expect(page).to have_content("What is your child’s name?") - fill_in "First name", with: @child.given_name - fill_in "Last name", with: @child.family_name + fill_in "First name", with: @patient.given_name + fill_in "Last name", with: @patient.family_name choose "No" # Do they use a different name in school? click_on "Continue" expect(page).to have_content("What is your child’s date of birth?") - fill_in "Day", with: @child.date_of_birth.day - fill_in "Month", with: @child.date_of_birth.month - fill_in "Year", with: @child.date_of_birth.year + fill_in "Day", with: @patient.date_of_birth.day + fill_in "Month", with: @patient.date_of_birth.month + fill_in "Year", with: @patient.date_of_birth.year click_on "Continue" end - def and_i_answer_no_to_all_the_medical_questions - until page.has_content?("Check and confirm") - choose "No" - click_on "Continue" - end - end - - def then_i_can_check_my_answers - expect(page).to have_content("Check and confirm") - expect(page).to have_content( - "Child’s name#{@child.full_name(context: :parents)}" - ) - end + def and_i_try_to_give_consent + choose "No, they go to a different school" + click_on "Continue" - def when_i_submit_the_consent_form - click_on "Confirm" + select @completed_school.name + click_on "Continue" end - def then_i_get_a_confirmation_email + def then_i_see_that_consent_is_closed + expect(page).to have_content("The deadline for responding has passed") expect(page).to have_content( - "#{@child.full_name(context: :parents)} is due to get the HPV vaccination at school" + "Contact #{@subteam.email} to book a clinic appointment." ) - - expect_email_to("jane@example.com", :consent_confirmation_clinic) end end