From a067875d65bf272a1fb3182f417cba4f0c13371d Mon Sep 17 00:00:00 2001 From: Thomas Leese Date: Fri, 22 Aug 2025 20:32:38 +0100 Subject: [PATCH 1/8] Update policies for healthcare assistances This updates the programme and session policy to ensure that if a user is a healthcare assistant they can only see sessions and programmes which support delegation, which at the moment is limited to flu. Jira-Issue: MAV-1353 --- app/policies/programme_policy.rb | 7 +++- app/policies/session_policy.rb | 6 +++- spec/policies/programme_policy_spec.rb | 32 +++++++++++++++++++ spec/policies/session_policy_spec.rb | 44 +++++++++++++++++++++++--- 4 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 spec/policies/programme_policy_spec.rb diff --git a/app/policies/programme_policy.rb b/app/policies/programme_policy.rb index 90ca12d5a5..e6b7cb86a9 100644 --- a/app/policies/programme_policy.rb +++ b/app/policies/programme_policy.rb @@ -9,7 +9,12 @@ def consent_form? = show? class Scope < ApplicationPolicy::Scope def resolve - scope.where(id: user.selected_team.programmes.ids) + scope + .joins(:team_programmes) + .where(team_programmes: { team: user.selected_team }) + .then do |scope| + user.is_healthcare_assistant? ? scope.supports_delegation : scope + end end end end diff --git a/app/policies/session_policy.rb b/app/policies/session_policy.rb index 3c2d9e2866..acfc8b073f 100644 --- a/app/policies/session_policy.rb +++ b/app/policies/session_policy.rb @@ -11,7 +11,11 @@ def make_in_progress? = edit? class Scope < ApplicationPolicy::Scope def resolve - scope.where(team: user.selected_team) + scope + .where(team: user.selected_team) + .then do |scope| + user.is_healthcare_assistant? ? scope.supports_delegation : scope + end end end end diff --git a/spec/policies/programme_policy_spec.rb b/spec/policies/programme_policy_spec.rb new file mode 100644 index 0000000000..6f36f2e663 --- /dev/null +++ b/spec/policies/programme_policy_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +describe ProgrammePolicy do + describe ProgrammePolicy::Scope do + describe "#resolve" do + subject { described_class.new(user, Programme).resolve } + + let(:flu_programme) { create(:programme, :flu) } + let(:hpv_programme) { create(:programme, :hpv) } + + let(:team) { create(:team, programmes: [flu_programme, hpv_programme]) } + + context "with an admin user" do + let(:user) { create(:admin, team:) } + + it { should contain_exactly(flu_programme, hpv_programme) } + end + + context "with a nurse user" do + let(:user) { create(:nurse, team:) } + + it { should contain_exactly(flu_programme, hpv_programme) } + end + + context "with a healthcare assistant user" do + let(:user) { create(:healthcare_assistant, team:) } + + it { should contain_exactly(flu_programme) } + end + end + end +end diff --git a/spec/policies/session_policy_spec.rb b/spec/policies/session_policy_spec.rb index 83c9054f9b..d93fffd38c 100644 --- a/spec/policies/session_policy_spec.rb +++ b/spec/policies/session_policy_spec.rb @@ -69,15 +69,51 @@ describe "#resolve" do subject { described_class.new(user, Session).resolve } - let(:programmes) { [create(:programme)] } - let(:team) { create(:team, programmes:) } let(:user) { create(:user, team:) } + let!(:flu_programme) { create(:programme, :flu) } + let!(:hpv_programme) { create(:programme, :hpv) } + let(:users_teams_session) { create(:session, team:, programmes:) } let(:another_teams_session) { create(:session, programmes:) } - it { should include(users_teams_session) } - it { should_not include(another_teams_session) } + let(:programmes) { [hpv_programme] } + let(:team) { create(:team, programmes:) } + + context "with a session part of the user's teams" do + let(:session) { create(:session, team:, programmes:) } + + context "and an admin user" do + let(:user) { create(:admin, team:) } + + it { should include(session) } + end + + context "and a nurse user" do + let(:user) { create(:nurse, team:) } + + it { should include(session) } + end + + context "and a healthcare assistant user" do + let(:user) { create(:healthcare_assistant, team:) } + + it { should_not include(session) } + + context "and a flu session" do + let(:programmes) { [flu_programme] } + + it { should include(session) } + end + end + end + + context "with a session not part of the user's teams" do + let(:session) { create(:session, programmes:) } + let(:user) { create(:user, team:) } + + it { should_not include(session) } + end end end end From 369095f048ebd90a916d0bddf4c6aa3cff21671d Mon Sep 17 00:00:00 2001 From: Thomas Leese Date: Mon, 25 Aug 2025 17:45:25 +0100 Subject: [PATCH 2/8] Add `Session#vaccine_methods_for` This adds a method which can be used to determine which vaccine methods are approriate for a user in a particular session. This will be used to limit which patients are shown to which users. Jira-Issue: MAV-1353 --- app/models/session.rb | 12 +++++++++++- spec/models/session_spec.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/app/models/session.rb b/app/models/session.rb index 1d7031bf8e..cf1f202a7d 100644 --- a/app/models/session.rb +++ b/app/models/session.rb @@ -204,7 +204,7 @@ def year_groups end def vaccine_methods - programmes.flat_map(&:vaccine_methods).uniq.sort + @vaccine_methods ||= programmes.flat_map(&:vaccine_methods).uniq.sort end def programmes_for(year_group: nil, patient: nil, academic_year: nil) @@ -217,6 +217,16 @@ def programmes_for(year_group: nil, patient: nil, academic_year: nil) end end + def vaccine_methods_for(user:) + if user.is_nurse? + vaccine_methods + elsif user.is_healthcare_assistant? && pgd_supply_enabled? + %w[nasal] + else + [] + end + end + def dates session_dates.map(&:value).compact end diff --git a/spec/models/session_spec.rb b/spec/models/session_spec.rb index e4cf9925b0..18ea1316ce 100644 --- a/spec/models/session_spec.rb +++ b/spec/models/session_spec.rb @@ -296,6 +296,32 @@ it { should contain_exactly("injection", "nasal") } end + describe "#vaccine_methods_for" do + subject { session.vaccine_methods_for(user:) } + + let(:programmes) { [create(:programme, :flu)] } + + let(:session) { create(:session, programmes:) } + + context "with a nurse" do + let(:user) { create(:nurse) } + + it { should match_array(%w[nasal injection]) } + end + + context "with a healthcare assistant" do + let(:user) { create(:healthcare_assistant) } + + it { should eq(%w[nasal]) } + end + + context "with an admin staff" do + let(:user) { create(:admin) } + + it { should be_empty } + end + end + describe "#today_or_future_dates" do subject(:today_or_future_dates) do travel_to(today) { session.today_or_future_dates } From 4b7e0d7e6ecec3159584c18b003dfed3c8a9742c Mon Sep 17 00:00:00 2001 From: Thomas Leese Date: Mon, 25 Aug 2025 19:56:41 +0100 Subject: [PATCH 3/8] Don't render vaccination section heading If the user is not allowed to perform a vaccination we should hide the heading as well as the form since it doesn't make sense to show the heading. Jira-Issue: MAV-1353 --- app/components/app_patient_session_record_component.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/components/app_patient_session_record_component.rb b/app/components/app_patient_session_record_component.rb index 33c1f94760..d5a5451f23 100644 --- a/app/components/app_patient_session_record_component.rb +++ b/app/components/app_patient_session_record_component.rb @@ -2,9 +2,8 @@ class AppPatientSessionRecordComponent < ViewComponent::Base erb_template <<-ERB -

<%= heading %>

- <% if helpers.policy(VaccinationRecord).new? %> +

<%= heading %>

<%= render AppVaccinateFormComponent.new(vaccinate_form) %> <% end %> ERB From 6cd3c601079088849ff9cad4a71b90c3bf9ca628 Mon Sep 17 00:00:00 2001 From: Thomas Leese Date: Mon, 25 Aug 2025 19:56:57 +0100 Subject: [PATCH 4/8] Refactor recording already vaccinated This moves the method related to determining whether the user is able to take this action in to the policy method, closer to where it would be used. Jira-Issue: MAV-1353 --- .../patient_sessions/programmes_controller.rb | 10 +++++----- app/models/patient_session.rb | 5 ----- app/policies/vaccination_record_policy.rb | 8 ++++++++ app/views/patient_sessions/_header.html.erb | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/app/controllers/patient_sessions/programmes_controller.rb b/app/controllers/patient_sessions/programmes_controller.rb index 1ee3bd5212..c75acd3bde 100644 --- a/app/controllers/patient_sessions/programmes_controller.rb +++ b/app/controllers/patient_sessions/programmes_controller.rb @@ -8,11 +8,11 @@ def show end def record_already_vaccinated - unless @patient_session.can_record_as_already_vaccinated?( - programme: @programme - ) - redirect_to session_patient_path and return - end + authorize VaccinationRecord.new( + patient: @patient, + session: @session, + programme: @programme + ) draft_vaccination_record = DraftVaccinationRecord.new(request_session: session, current_user:) diff --git a/app/models/patient_session.rb b/app/models/patient_session.rb index 712b37fa50..9660b70619 100644 --- a/app/models/patient_session.rb +++ b/app/models/patient_session.rb @@ -274,11 +274,6 @@ def destroy_if_safe! destroy! if safe_to_destroy? end - def can_record_as_already_vaccinated?(programme:) - !session.today? && - patient.vaccination_status(programme:, academic_year:).none_yet? - end - def programmes = session.programmes_for(patient:, academic_year:) def todays_attendance diff --git a/app/policies/vaccination_record_policy.rb b/app/policies/vaccination_record_policy.rb index 8148875788..d032c924ed 100644 --- a/app/policies/vaccination_record_policy.rb +++ b/app/policies/vaccination_record_policy.rb @@ -9,6 +9,11 @@ def new? create? end + def record_already_vaccinated? + user.is_nurse? && !session.today? && + patient.vaccination_status(programme:, academic_year:).none_yet? + end + def edit? user.is_nurse? && record.session_id.present? && record.performed_ods_code == user.selected_organisation.ods_code @@ -22,6 +27,9 @@ def destroy? user.is_superuser? end + delegate :patient, :session, :programme, to: :record + delegate :academic_year, to: :session + class Scope < ApplicationPolicy::Scope def resolve organisation = user.selected_organisation diff --git a/app/views/patient_sessions/_header.html.erb b/app/views/patient_sessions/_header.html.erb index 0cc87b922a..96a191679e 100644 --- a/app/views/patient_sessions/_header.html.erb +++ b/app/views/patient_sessions/_header.html.erb @@ -39,7 +39,7 @@ <% end %> <% end %> - <% if policy(VaccinationRecord).create? && @programme && @patient_session.can_record_as_already_vaccinated?(programme: @programme) %> + <% if @programme && policy(VaccinationRecord.new(patient: @patient, session: @session, programme: @programme)).record_already_vaccinated? %>
  • <%= link_to "Record as already vaccinated", session_patient_programme_record_already_vaccinated_path(@session, @patient, @programme) %> From cc36f0b8e45e1c35f75b254685c2b6810468bdf4 Mon Sep 17 00:00:00 2001 From: Thomas Leese Date: Mon, 25 Aug 2025 17:11:29 +0100 Subject: [PATCH 5/8] Pass VaccinationRecord instance to policy This allows us to check various properties on the vaccination record to support delegation where only certain users will be able to perform certain actions. Jira-Issue: MAV-1353 --- app/components/app_patient_session_record_component.rb | 6 +++++- app/controllers/draft_vaccination_records_controller.rb | 7 ++++++- .../patient_sessions/vaccinations_controller.rb | 6 +++++- app/models/draft_vaccination_record.rb | 6 +++++- app/views/patient_sessions/_header.html.erb | 8 ++++++-- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/app/components/app_patient_session_record_component.rb b/app/components/app_patient_session_record_component.rb index d5a5451f23..d2521f1463 100644 --- a/app/components/app_patient_session_record_component.rb +++ b/app/components/app_patient_session_record_component.rb @@ -2,7 +2,7 @@ class AppPatientSessionRecordComponent < ViewComponent::Base erb_template <<-ERB - <% if helpers.policy(VaccinationRecord).new? %> + <% if helpers.policy(vaccination_record).new? %>

    <%= heading %>

    <%= render AppVaccinateFormComponent.new(vaccinate_form) %> <% end %> @@ -32,6 +32,10 @@ def render? delegate :patient, :session, to: :patient_session delegate :academic_year, to: :session + def vaccination_record + VaccinationRecord.new(patient:, session:, programme:) + end + def default_vaccinate_form pre_screening_confirmed = patient.pre_screenings.today.exists?(programme:) diff --git a/app/controllers/draft_vaccination_records_controller.rb b/app/controllers/draft_vaccination_records_controller.rb index b3453d7da1..bc194a8510 100644 --- a/app/controllers/draft_vaccination_records_controller.rb +++ b/app/controllers/draft_vaccination_records_controller.rb @@ -193,7 +193,12 @@ def set_programme def set_vaccination_record @vaccination_record = - @draft_vaccination_record.vaccination_record || VaccinationRecord.new + @draft_vaccination_record.vaccination_record || + VaccinationRecord.new( + patient: @patient, + session: @session, + programme: @programme + ) end def set_steps diff --git a/app/controllers/patient_sessions/vaccinations_controller.rb b/app/controllers/patient_sessions/vaccinations_controller.rb index 03c173c2ed..8753287e76 100644 --- a/app/controllers/patient_sessions/vaccinations_controller.rb +++ b/app/controllers/patient_sessions/vaccinations_controller.rb @@ -9,7 +9,11 @@ class PatientSessions::VaccinationsController < PatientSessions::BaseController after_action :verify_authorized def create - authorize VaccinationRecord + authorize VaccinationRecord.new( + patient: @patient, + session: @session, + programme: @programme + ) draft_vaccination_record = DraftVaccinationRecord.new(request_session: session, current_user:) diff --git a/app/models/draft_vaccination_record.rb b/app/models/draft_vaccination_record.rb index 8e3d975b97..83dcf87d0d 100644 --- a/app/models/draft_vaccination_record.rb +++ b/app/models/draft_vaccination_record.rb @@ -187,7 +187,11 @@ def programme=(value) def session return nil if session_id.nil? - SessionPolicy::Scope.new(@current_user, Session).resolve.find(session_id) + SessionPolicy::Scope + .new(@current_user, Session) + .resolve + .includes(:programmes) + .find(session_id) end def session=(value) diff --git a/app/views/patient_sessions/_header.html.erb b/app/views/patient_sessions/_header.html.erb index 96a191679e..471c6ba2c5 100644 --- a/app/views/patient_sessions/_header.html.erb +++ b/app/views/patient_sessions/_header.html.erb @@ -9,9 +9,13 @@ ].compact) %> <% end %> -<% if policy(VaccinationRecord).new? && (outstanding_programmes = @patient_session.outstanding_programmes).any? %> +<% if (outstanding_programmes = @patient_session.outstanding_programmes).any? %> + <% programmes_can_record_vaccination = outstanding_programmes.filter do |programme| + policy(VaccinationRecord.new(patient: @patient, session: @session, programme:)).new? + end %> + <%= govuk_notification_banner(title_text: "Important") do |notification_banner| %> - <% notification_banner.with_heading(text: "You still need to record an outcome for #{outstanding_programmes.map(&:name).to_sentence}.") %> + <% notification_banner.with_heading(text: "You still need to record an outcome for #{programmes_can_record_vaccination.map(&:name).to_sentence}.") %> <% end %> <% end %> From 834a4bbb3670fe3997d65a74e886c81b9de0fdeb Mon Sep 17 00:00:00 2001 From: Thomas Leese Date: Mon, 25 Aug 2025 19:01:55 +0100 Subject: [PATCH 6/8] Restrict patients by user This makes it so that healthcare assistants don't have permission to record vaccinations against injection patients by hiding them from the "Record" tab. Jira-Issue: MAV-1353 --- app/controllers/sessions/record_controller.rb | 16 ++++ app/policies/vaccination_record_policy.rb | 20 ++-- app/views/sessions/record/show.html.erb | 2 +- config/initializers/inflections.rb | 1 + .../flu_vaccination_hca_pgd_supply_spec.rb | 93 +++++++++++++++++++ 5 files changed, 120 insertions(+), 12 deletions(-) create mode 100644 spec/features/flu_vaccination_hca_pgd_supply_spec.rb diff --git a/app/controllers/sessions/record_controller.rb b/app/controllers/sessions/record_controller.rb index ffbd77d3c7..de56fff23b 100644 --- a/app/controllers/sessions/record_controller.rb +++ b/app/controllers/sessions/record_controller.rb @@ -25,6 +25,22 @@ def show scope = scope.has_registration_status(%w[attending completed]) end + @vaccine_methods = @session.vaccine_methods_for(user: current_user) + + if @vaccine_methods != @session.vaccine_methods + scope = + if @vaccine_methods.empty? + scope.none + else + @vaccine_methods.reduce(scope) do |accumulator, vaccine_method| + accumulator.has_vaccine_method( + vaccine_method, + programme: @session.programmes + ) + end + end + end + patient_sessions = @form.apply(scope).consent_given_and_ready_to_vaccinate( programmes: @form.programmes, diff --git a/app/policies/vaccination_record_policy.rb b/app/policies/vaccination_record_policy.rb index d032c924ed..ebe1c66d53 100644 --- a/app/policies/vaccination_record_policy.rb +++ b/app/policies/vaccination_record_policy.rb @@ -2,12 +2,14 @@ class VaccinationRecordPolicy < ApplicationPolicy def create? - user.is_nurse? + user.is_nurse? || + ( + patient.approved_vaccine_methods(programme:, academic_year:) & + session.vaccine_methods_for(user:) + ).present? end - def new? - create? - end + def new? = create? def record_already_vaccinated? user.is_nurse? && !session.today? && @@ -15,17 +17,13 @@ def record_already_vaccinated? end def edit? - user.is_nurse? && record.session_id.present? && + user.is_nurse? && record.recorded_in_service? && record.performed_ods_code == user.selected_organisation.ods_code end - def update? - edit? - end + def update? = edit? - def destroy? - user.is_superuser? - end + def destroy? = user.is_superuser? delegate :patient, :session, :programme, to: :record delegate :academic_year, to: :session diff --git a/app/views/sessions/record/show.html.erb b/app/views/sessions/record/show.html.erb index e72878d8be..22696722e1 100644 --- a/app/views/sessions/record/show.html.erb +++ b/app/views/sessions/record/show.html.erb @@ -45,7 +45,7 @@ url: session_record_path(@session), programmes: @session.programmes, year_groups: @session.year_groups, - vaccine_methods: @session.vaccine_methods.then { it.length > 1 ? it : [] }, + vaccine_methods: @vaccine_methods.length > 1 ? @vaccine_methods : [], ) %> diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index fe502d3e48..f0899e9a52 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -23,6 +23,7 @@ inflect.acronym "FHIR" inflect.acronym "GIAS" inflect.acronym "GP" + inflect.acronym "HCA" inflect.acronym "JWKS" inflect.acronym "NHS" inflect.acronym "OAuth2" diff --git a/spec/features/flu_vaccination_hca_pgd_supply_spec.rb b/spec/features/flu_vaccination_hca_pgd_supply_spec.rb new file mode 100644 index 0000000000..38755a9891 --- /dev/null +++ b/spec/features/flu_vaccination_hca_pgd_supply_spec.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +describe "Flu vaccination" do + around { |example| travel_to(Time.zone.local(2024, 10, 1)) { example.run } } + + scenario "Administered by HCA" do + given_a_session_exists + and_patients_exist + + when_i_visit_the_session_record_tab + then_i_only_see_nasal_spray_patients + + when_i_click_on_the_nasal_only_patient + then_i_am_able_to_vaccinate_them + + when_i_click_on_the_nasal_and_injection_patient + then_i_am_able_to_vaccinate_them + + when_i_click_on_the_injection_patient + then_i_am_not_able_to_vaccinate_them + end + + def given_a_session_exists + programmes = [create(:programme, :flu)] + + @team = create(:team, programmes:) + @user = create(:healthcare_assistant, team: @team) + + @session = + create( + :session, + :today, + :requires_no_registration, + team: @team, + programmes: + ) + end + + def and_patients_exist + @patient_nasal_only = + create( + :patient, + :consent_given_nasal_only_triage_not_needed, + session: @session + ) + @patient_nasal_and_injection = + create( + :patient, + :consent_given_nasal_or_injection_triage_not_needed, + session: @session + ) + @patient_injection_only = + create( + :patient, + :consent_given_injection_only_triage_not_needed, + session: @session + ) + end + + def when_i_visit_the_session_record_tab + sign_in @user, role: :healthcare_assistant + visit session_record_path(@session) + end + + def then_i_only_see_nasal_spray_patients + expect(page).to have_content(@patient_nasal_only.full_name) + expect(page).to have_content(@patient_nasal_and_injection.full_name) + expect(page).not_to have_content(@patient_injection_only.full_name) + end + + def when_i_click_on_the_nasal_only_patient + click_on @patient_nasal_only.full_name + end + + def when_i_click_on_the_nasal_and_injection_patient + click_on @patient_nasal_and_injection.full_name + end + + def when_i_click_on_the_injection_patient + # This patient won't be in the "Record" tab. + within(".app-secondary-navigation") { click_on "Children" } + click_on @patient_injection_only.full_name + end + + def then_i_am_able_to_vaccinate_them + click_on "Record vaccinations" + end + + def then_i_am_not_able_to_vaccinate_them + expect(page).not_to have_content("Pre-screening checks") + expect(page).not_to have_content("ready for their") + end +end From 83e5a33b35a7a04fef5d75316eea5b1f6a1cb4eb Mon Sep 17 00:00:00 2001 From: Thomas Leese Date: Mon, 25 Aug 2025 20:38:24 +0100 Subject: [PATCH 7/8] Add supplier user to vaccination records This allows us to track who supplied the vaccine to the person who performed the vaccination. Jira-Issue: MAV-1353 --- app/models/vaccination_record.rb | 10 +++++++++- ...232_add_supplied_by_user_to_vaccination_records.rb | 11 +++++++++++ db/schema.rb | 3 +++ spec/factories/vaccination_records.rb | 3 +++ spec/models/vaccination_record_spec.rb | 4 ++++ 5 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20250825183232_add_supplied_by_user_to_vaccination_records.rb diff --git a/app/models/vaccination_record.rb b/app/models/vaccination_record.rb index 3b815533fb..7c484b43e0 100644 --- a/app/models/vaccination_record.rb +++ b/app/models/vaccination_record.rb @@ -34,6 +34,7 @@ # performed_by_user_id :bigint # programme_id :bigint not null # session_id :bigint +# supplied_by_user_id :bigint # vaccine_id :bigint # # Indexes @@ -46,6 +47,7 @@ # index_vaccination_records_on_performed_by_user_id (performed_by_user_id) # index_vaccination_records_on_programme_id (programme_id) # index_vaccination_records_on_session_id (session_id) +# index_vaccination_records_on_supplied_by_user_id (supplied_by_user_id) # index_vaccination_records_on_uuid (uuid) UNIQUE # index_vaccination_records_on_vaccine_id (vaccine_id) # @@ -56,6 +58,7 @@ # fk_rails_... (performed_by_user_id => users.id) # fk_rails_... (programme_id => programmes.id) # fk_rails_... (session_id => sessions.id) +# fk_rails_... (supplied_by_user_id => users.id) # fk_rails_... (vaccine_id => vaccines.id) # class VaccinationRecord < ApplicationRecord @@ -87,9 +90,14 @@ class VaccinationRecord < ApplicationRecord belongs_to :batch, optional: true belongs_to :vaccine, optional: true - belongs_to :performed_by_user, class_name: "User", optional: true belongs_to :programme + belongs_to :performed_by_user, class_name: "User", optional: true + belongs_to :supplied_by, + class_name: "User", + foreign_key: :supplied_by_user_id, + optional: true + has_and_belongs_to_many :immunisation_imports belongs_to :location, optional: true diff --git a/db/migrate/20250825183232_add_supplied_by_user_to_vaccination_records.rb b/db/migrate/20250825183232_add_supplied_by_user_to_vaccination_records.rb new file mode 100644 index 0000000000..cbcc185e83 --- /dev/null +++ b/db/migrate/20250825183232_add_supplied_by_user_to_vaccination_records.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class AddSuppliedByUserToVaccinationRecords < ActiveRecord::Migration[8.0] + def change + add_reference :vaccination_records, + :supplied_by_user, + foreign_key: { + to_table: :users + } + end +end diff --git a/db/schema.rb b/db/schema.rb index d4cd8a8ec5..df6553e5af 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -950,6 +950,7 @@ t.datetime "nhs_immunisations_api_sync_pending_at" t.boolean "notify_parents" t.bigint "location_id" + t.bigint "supplied_by_user_id" t.index ["batch_id"], name: "index_vaccination_records_on_batch_id" t.index ["discarded_at"], name: "index_vaccination_records_on_discarded_at" t.index ["location_id"], name: "index_vaccination_records_on_location_id" @@ -958,6 +959,7 @@ t.index ["performed_by_user_id"], name: "index_vaccination_records_on_performed_by_user_id" t.index ["programme_id"], name: "index_vaccination_records_on_programme_id" t.index ["session_id"], name: "index_vaccination_records_on_session_id" + t.index ["supplied_by_user_id"], name: "index_vaccination_records_on_supplied_by_user_id" t.index ["uuid"], name: "index_vaccination_records_on_uuid", unique: true t.index ["vaccine_id"], name: "index_vaccination_records_on_vaccine_id" end @@ -1104,6 +1106,7 @@ add_foreign_key "vaccination_records", "programmes" add_foreign_key "vaccination_records", "sessions" add_foreign_key "vaccination_records", "users", column: "performed_by_user_id" + add_foreign_key "vaccination_records", "users", column: "supplied_by_user_id" add_foreign_key "vaccination_records", "vaccines" add_foreign_key "vaccines", "programmes" end diff --git a/spec/factories/vaccination_records.rb b/spec/factories/vaccination_records.rb index 69e37ad9dd..b5ef753a34 100644 --- a/spec/factories/vaccination_records.rb +++ b/spec/factories/vaccination_records.rb @@ -34,6 +34,7 @@ # performed_by_user_id :bigint # programme_id :bigint not null # session_id :bigint +# supplied_by_user_id :bigint # vaccine_id :bigint # # Indexes @@ -46,6 +47,7 @@ # index_vaccination_records_on_performed_by_user_id (performed_by_user_id) # index_vaccination_records_on_programme_id (programme_id) # index_vaccination_records_on_session_id (session_id) +# index_vaccination_records_on_supplied_by_user_id (supplied_by_user_id) # index_vaccination_records_on_uuid (uuid) UNIQUE # index_vaccination_records_on_vaccine_id (vaccine_id) # @@ -56,6 +58,7 @@ # fk_rails_... (performed_by_user_id => users.id) # fk_rails_... (programme_id => programmes.id) # fk_rails_... (session_id => sessions.id) +# fk_rails_... (supplied_by_user_id => users.id) # fk_rails_... (vaccine_id => vaccines.id) # FactoryBot.define do diff --git a/spec/models/vaccination_record_spec.rb b/spec/models/vaccination_record_spec.rb index 2e47137ccf..b511075d46 100644 --- a/spec/models/vaccination_record_spec.rb +++ b/spec/models/vaccination_record_spec.rb @@ -34,6 +34,7 @@ # performed_by_user_id :bigint # programme_id :bigint not null # session_id :bigint +# supplied_by_user_id :bigint # vaccine_id :bigint # # Indexes @@ -46,6 +47,7 @@ # index_vaccination_records_on_performed_by_user_id (performed_by_user_id) # index_vaccination_records_on_programme_id (programme_id) # index_vaccination_records_on_session_id (session_id) +# index_vaccination_records_on_supplied_by_user_id (supplied_by_user_id) # index_vaccination_records_on_uuid (uuid) UNIQUE # index_vaccination_records_on_vaccine_id (vaccine_id) # @@ -56,6 +58,7 @@ # fk_rails_... (performed_by_user_id => users.id) # fk_rails_... (programme_id => programmes.id) # fk_rails_... (session_id => sessions.id) +# fk_rails_... (supplied_by_user_id => users.id) # fk_rails_... (vaccine_id => vaccines.id) # describe VaccinationRecord do @@ -63,6 +66,7 @@ describe "associations" do it { should have_one(:identity_check).autosave(true).dependent(:destroy) } + it { should belong_to(:supplied_by).optional } end describe "validations" do From d9e8f72e077951f55f22ec14b303c1434e9d5cc9 Mon Sep 17 00:00:00 2001 From: Thomas Leese Date: Tue, 26 Aug 2025 15:32:12 +0100 Subject: [PATCH 8/8] Allow HCAs to administer nasal flu This adds support for healthcase assistants to administer the nasal flu vaccine, requiring them to specify which nurse supplied to them the vaccine. Jira-Issue: MAV-1353 --- .../app_patient_session_record_component.rb | 12 ++++++-- .../app_vaccinate_form_component.html.erb | 16 +++++++++- .../app_vaccinate_form_component.rb | 8 ++--- ...pp_vaccination_record_summary_component.rb | 21 +++++++++++++ .../draft_vaccination_records_controller.rb | 8 ++++- .../vaccinations_controller.rb | 6 ++-- app/forms/vaccinate_form.rb | 21 +++++++++++-- app/models/draft_vaccination_record.rb | 23 ++++++++++++-- app/models/user.rb | 2 ++ app/policies/vaccination_record_policy.rb | 3 +- .../confirm.html.erb | 1 + .../supplier.html.erb | 22 ++++++++++++++ .../patient_sessions/programmes/show.html.erb | 2 +- config/locales/en.yml | 3 ++ ...p_patient_session_record_component_spec.rb | 2 ++ .../app_vaccinate_form_component_spec.rb | 10 +++++-- spec/factories/users.rb | 8 +++-- .../flu_vaccination_hca_pgd_supply_spec.rb | 30 ++++++++++++++++++- spec/forms/vaccinate_form_spec.rb | 6 ++-- 19 files changed, 179 insertions(+), 25 deletions(-) create mode 100644 app/views/draft_vaccination_records/supplier.html.erb diff --git a/app/components/app_patient_session_record_component.rb b/app/components/app_patient_session_record_component.rb index d2521f1463..5d4cf679d9 100644 --- a/app/components/app_patient_session_record_component.rb +++ b/app/components/app_patient_session_record_component.rb @@ -8,11 +8,12 @@ class AppPatientSessionRecordComponent < ViewComponent::Base <% end %> ERB - def initialize(patient_session, programme:, vaccinate_form: nil) + def initialize(patient_session, programme:, current_user:, vaccinate_form:) super @patient_session = patient_session @programme = programme + @current_user = current_user @vaccinate_form = vaccinate_form || default_vaccinate_form end @@ -27,7 +28,7 @@ def render? private - attr_reader :patient_session, :programme, :vaccinate_form + attr_reader :patient_session, :current_user, :programme, :vaccinate_form delegate :patient, :session, to: :patient_session delegate :academic_year, to: :session @@ -39,7 +40,12 @@ def vaccination_record def default_vaccinate_form pre_screening_confirmed = patient.pre_screenings.today.exists?(programme:) - VaccinateForm.new(patient_session:, programme:, pre_screening_confirmed:) + VaccinateForm.new( + current_user:, + patient_session:, + programme:, + pre_screening_confirmed: + ) end def heading diff --git a/app/components/app_vaccinate_form_component.html.erb b/app/components/app_vaccinate_form_component.html.erb index ebbdd14b73..afd935956a 100644 --- a/app/components/app_vaccinate_form_component.html.erb +++ b/app/components/app_vaccinate_form_component.html.erb @@ -1,5 +1,5 @@ <%= form_with( - model: vaccinate_form, + model: form, url:, method: :post, class: "nhsuk-card", @@ -54,6 +54,20 @@ <% end %> <%= f.govuk_text_area :pre_screening_notes, label: { text: "Pre-screening notes (optional)" }, rows: 3 %> + + <% if form.requires_supplied_by_user_id? %> + <%= f.govuk_select :supplied_by_user_id, + label: { text: "Which nurse identified and pre-screened the child and supplied the vaccine?" }, + data: { module: "autocomplete" } do %> + <%= tag.option "", value: "" %> + <% form.supplied_by_users.each do |user| %> + <%= tag.option user.full_name, + value: user.id, + selected: user.id == form.supplied_by_user_id, + data: { hint: user.email } %> + <% end %> + <% end %> + <% end %>
    diff --git a/app/components/app_vaccinate_form_component.rb b/app/components/app_vaccinate_form_component.rb index 8426b39792..327b866db3 100644 --- a/app/components/app_vaccinate_form_component.rb +++ b/app/components/app_vaccinate_form_component.rb @@ -1,17 +1,17 @@ # frozen_string_literal: true class AppVaccinateFormComponent < ViewComponent::Base - def initialize(vaccinate_form) + def initialize(form) super - @vaccinate_form = vaccinate_form + @form = form end private - attr_reader :vaccinate_form + attr_reader :form - delegate :patient_session, :programme, to: :vaccinate_form + delegate :patient_session, :programme, to: :form delegate :patient, :session, to: :patient_session delegate :academic_year, to: :session diff --git a/app/components/app_vaccination_record_summary_component.rb b/app/components/app_vaccination_record_summary_component.rb index 46bc5f9fcf..43268356f9 100644 --- a/app/components/app_vaccination_record_summary_component.rb +++ b/app/components/app_vaccination_record_summary_component.rb @@ -201,6 +201,20 @@ def call end end + if @vaccination_record.supplied_by.present? + summary_list.with_row do |row| + row.with_key { "Supplier" } + row.with_value { supplier_value } + if (href = @change_links[:supplier]) + row.with_action( + text: "Change", + visually_hidden_text: "supplier", + href: + ) + end + end + end + if @vaccination_record.performed_by.present? summary_list.with_row do |row| row.with_key { "Vaccinator" } @@ -331,6 +345,13 @@ def time_value ) end + def supplier_value + highlight_if( + @vaccination_record.supplied_by&.full_name, + @vaccination_record.supplied_by_user_id_changed? + ) + end + def vaccinator_value value = if @vaccination_record.performed_by == @current_user diff --git a/app/controllers/draft_vaccination_records_controller.rb b/app/controllers/draft_vaccination_records_controller.rb index bc194a8510..155127f841 100644 --- a/app/controllers/draft_vaccination_records_controller.rb +++ b/app/controllers/draft_vaccination_records_controller.rb @@ -17,6 +17,7 @@ class DraftVaccinationRecordsController < ApplicationController before_action :validate_params, only: :update before_action :set_batches, if: -> { current_step == :batch } before_action :set_locations, if: -> { current_step == :location } + before_action :set_supplied_by_users, if: -> { current_step == :supplier } before_action :set_back_link_path after_action :verify_authorized @@ -165,7 +166,8 @@ def update_params ], location: %i[location_name], notes: %i[notes], - outcome: %i[outcome] + outcome: %i[outcome], + supplier: %i[supplied_by_user_id] }.fetch(current_step) params @@ -231,6 +233,10 @@ def set_locations @locations = policy_scope(Location).community_clinic end + def set_supplied_by_users + @supplied_by_users = current_team.users.show_in_suppliers + end + def set_back_link_path @back_link_path = if @draft_vaccination_record.editing? diff --git a/app/controllers/patient_sessions/vaccinations_controller.rb b/app/controllers/patient_sessions/vaccinations_controller.rb index 8753287e76..4cd84c3c01 100644 --- a/app/controllers/patient_sessions/vaccinations_controller.rb +++ b/app/controllers/patient_sessions/vaccinations_controller.rb @@ -30,9 +30,10 @@ def create if @vaccinate_form.save(draft_vaccination_record:) steps = draft_vaccination_record.wizard_steps - steps.delete(:notes) # this is on the confirmation page - steps.delete(:identity) # this can only be changed from confirmation page steps.delete(:dose) # this can only be changed from confirmation page + steps.delete(:identity) # this can only be changed from confirmation page + steps.delete(:notes) # this is on the confirmation page + steps.delete(:supplier) # this can only be changed from confirmation page steps.delete(:date_and_time) steps.delete(:outcome) if draft_vaccination_record.administered? @@ -67,6 +68,7 @@ def vaccinate_form_params identity_check_confirmed_by_patient pre_screening_confirmed pre_screening_notes + supplied_by_user_id vaccine_id vaccine_method ] diff --git a/app/forms/vaccinate_form.rb b/app/forms/vaccinate_form.rb index 3c08ef1267..2c736328ee 100644 --- a/app/forms/vaccinate_form.rb +++ b/app/forms/vaccinate_form.rb @@ -13,6 +13,8 @@ class VaccinateForm attribute :pre_screening_confirmed, :boolean attribute :pre_screening_notes, :string + attribute :supplied_by_user_id, :integer + attribute :vaccine_method, :string attribute :delivery_site, :string attribute :dose_sequence, :integer @@ -31,10 +33,16 @@ class VaccinateForm maximum: 300 } - validates :vaccine_method, inclusion: { in: :vaccine_method_options } validates :pre_screening_notes, length: { maximum: 1000 } - validates :pre_screening_confirmed, presence: true, if: :administered? + + validates :supplied_by_user_id, + inclusion: { + in: :supplied_by_user_id_values + }, + if: :requires_supplied_by_user_id? + + validates :vaccine_method, inclusion: { in: :vaccine_method_options } validates :delivery_site, inclusion: { in: :delivery_site_options @@ -59,6 +67,12 @@ def delivery_site super end + def supplied_by_users + current_user.selected_team.users.show_in_suppliers + end + + def requires_supplied_by_user_id? = !current_user.show_in_suppliers + def save(draft_vaccination_record:) return nil if invalid? @@ -93,6 +107,7 @@ def save(draft_vaccination_record:) draft_vaccination_record.patient_id = patient_session.patient_id draft_vaccination_record.performed_at = Time.current draft_vaccination_record.performed_by_user = current_user + draft_vaccination_record.supplied_by_user_id = supplied_by_user_id draft_vaccination_record.performed_ods_code = organisation.ods_code draft_vaccination_record.programme = programme draft_vaccination_record.session_id = patient_session.session_id @@ -106,6 +121,8 @@ def save(draft_vaccination_record:) def administered? = vaccine_method != "none" + def supplied_by_user_id_values = supplied_by_users.pluck(:id) + def vaccine_method_options programme.vaccine_methods + ["none"] end diff --git a/app/models/draft_vaccination_record.rb b/app/models/draft_vaccination_record.rb index 83dcf87d0d..e9a152c9f1 100644 --- a/app/models/draft_vaccination_record.rb +++ b/app/models/draft_vaccination_record.rb @@ -11,8 +11,8 @@ class DraftVaccinationRecord attribute :delivery_method, :string attribute :delivery_site, :string attribute :dose_sequence, :integer + attribute :first_active_wizard_step, :string attribute :full_dose, :boolean - attribute :protocol, :string attribute :identity_check_confirmed_by_other_name, :string attribute :identity_check_confirmed_by_other_relationship, :string attribute :identity_check_confirmed_by_patient, :boolean @@ -27,8 +27,9 @@ class DraftVaccinationRecord attribute :performed_by_user_id, :integer attribute :performed_ods_code, :string attribute :programme_id, :integer + attribute :protocol, :string attribute :session_id, :integer - attribute :first_active_wizard_step, :string + attribute :supplied_by_user_id, :integer def initialize(current_user:, **attributes) @current_user = current_user @@ -47,6 +48,7 @@ def wizard_steps :notes, :date_and_time, (:outcome if can_change_outcome?), + (:supplier if requires_supplied_by?), (:delivery if administered?), (:dose if administered? && can_be_half_dose?), (:batch if administered?), @@ -198,6 +200,16 @@ def session=(value) self.session_id = value.id end + def supplied_by + return nil if supplied_by_user_id.nil? + + User.find(supplied_by_user_id) + end + + def supplied_by=(value) + self.supplied_by_user_id = value.id + end + def vaccination_record return nil if editing_id.nil? @@ -276,7 +288,6 @@ def writable_attribute_names delivery_site dose_sequence full_dose - protocol identity_check location_id location_name @@ -289,7 +300,9 @@ def writable_attribute_names performed_by_user_id performed_ods_code programme_id + protocol session_id + supplied_by_user_id vaccine_id ] end @@ -348,6 +361,10 @@ def can_change_outcome? outcome != "already_had" || editing? || session.nil? || session.today? end + def requires_supplied_by? + performed_by_user && !performed_by_user&.show_in_suppliers + end + def delivery_site_matches_delivery_method return if delivery_method.blank? diff --git a/app/models/user.rb b/app/models/user.rb index ce86d95667..5f6b4bcaef 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -72,6 +72,8 @@ class User < ApplicationRecord scope :recently_active, -> { where(last_sign_in_at: 1.week.ago..Time.current) } + scope :show_in_suppliers, -> { where(show_in_suppliers: true) } + enum :fallback_role, { nurse: 0, diff --git a/app/policies/vaccination_record_policy.rb b/app/policies/vaccination_record_policy.rb index ebe1c66d53..2f8cfd9ddb 100644 --- a/app/policies/vaccination_record_policy.rb +++ b/app/policies/vaccination_record_policy.rb @@ -17,7 +17,8 @@ def record_already_vaccinated? end def edit? - user.is_nurse? && record.recorded_in_service? && + (record.performed_by_user_id == user.id || user.is_nurse?) && + record.recorded_in_service? && record.performed_ods_code == user.selected_organisation.ods_code end diff --git a/app/views/draft_vaccination_records/confirm.html.erb b/app/views/draft_vaccination_records/confirm.html.erb index c303247c67..d348f8eeb7 100644 --- a/app/views/draft_vaccination_records/confirm.html.erb +++ b/app/views/draft_vaccination_records/confirm.html.erb @@ -20,6 +20,7 @@ delivery_site: wizard_path("delivery"), dose_volume: @draft_vaccination_record.wizard_steps.include?(:dose) ? wizard_path("dose") : nil, identity: wizard_path("identity"), + supplier: wizard_path("supplier"), location: @draft_vaccination_record.wizard_steps.include?(:location) ? wizard_path("location") : nil, notes: wizard_path("notes"), outcome: @draft_vaccination_record.wizard_steps.include?(:outcome) ? wizard_path("outcome") : nil, diff --git a/app/views/draft_vaccination_records/supplier.html.erb b/app/views/draft_vaccination_records/supplier.html.erb new file mode 100644 index 0000000000..218d7a9a8f --- /dev/null +++ b/app/views/draft_vaccination_records/supplier.html.erb @@ -0,0 +1,22 @@ +<% content_for :before_main do %> + <%= render AppBacklinkComponent.new(@back_link_path) %> +<% end %> + +<% title = "Which nurse identified and pre-screened the child and supplied the vaccine?" %> +<% content_for :page_title, title %> + +<%= form_with model: @draft_vaccination_record, url: wizard_path, method: :put do |f| %> + <%= f.govuk_error_summary %> + + <%= f.govuk_radio_buttons_fieldset :supplied_by_user_id, + caption: { text: @patient.full_name, size: "l" }, + legend: { size: "l", tag: "h1", + text: title } do %> + + <% @supplied_by_users.each do |user| %> + <%= f.govuk_radio_button :supplied_by_user_id, user.id, label: { text: user.full_name } %> + <% end %> + <% end %> + + <%= f.govuk_submit "Continue" %> +<% end %> diff --git a/app/views/patient_sessions/programmes/show.html.erb b/app/views/patient_sessions/programmes/show.html.erb index 3a0b79ba8b..b1f5de97d0 100644 --- a/app/views/patient_sessions/programmes/show.html.erb +++ b/app/views/patient_sessions/programmes/show.html.erb @@ -10,7 +10,7 @@ <%= render AppPatientSessionTriageComponent.new(@patient_session, programme: @programme, triage_form: @triage_form) %> - <%= render AppPatientSessionRecordComponent.new(@patient_session, programme: @programme, vaccinate_form: @vaccinate_form) %> + <%= render AppPatientSessionRecordComponent.new(@patient_session, programme: @programme, current_user:, vaccinate_form: @vaccinate_form) %> <%= render AppPatientSessionOutcomeComponent.new(@patient_session, programme: @programme) %> diff --git a/config/locales/en.yml b/config/locales/en.yml index d9462e52e2..3ccf61187a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -162,6 +162,8 @@ en: blank: Confirm you’ve checked the pre-screening statements are true pre_screening_notes: too_long: Enter notes that are less than %{count} characters long + supplied_by_user_id: + inclusion: Choose which nurse identified and pre-screened the child and supplied the vaccine vaccine_method: inclusion: Choose if they are ready to vaccinate vaccination_report: @@ -739,6 +741,7 @@ en: route: route school: school session: session + supplier: supplier timeline: timeline triage: triage type: type diff --git a/spec/components/app_patient_session_record_component_spec.rb b/spec/components/app_patient_session_record_component_spec.rb index 1eb5b27e25..b63caa08fd 100644 --- a/spec/components/app_patient_session_record_component_spec.rb +++ b/spec/components/app_patient_session_record_component_spec.rb @@ -7,10 +7,12 @@ described_class.new( patient_session, programme: programmes.first, + current_user:, vaccinate_form: VaccinateForm.new ) end + let(:current_user) { create(:user) } let(:programmes) { [create(:programme, :hpv)] } let(:session) { create(:session, :today, programmes:) } let(:patient) do diff --git a/spec/components/app_vaccinate_form_component_spec.rb b/spec/components/app_vaccinate_form_component_spec.rb index 946549d72b..09280f2195 100644 --- a/spec/components/app_vaccinate_form_component_spec.rb +++ b/spec/components/app_vaccinate_form_component_spec.rb @@ -5,7 +5,11 @@ let(:programme) { create(:programme) } let(:programmes) { [programme] } - let(:session) { create(:session, :today, programmes:) } + + let(:team) { create(:team, programmes:) } + let(:current_user) { create(:user, team:) } + + let(:session) { create(:session, :today, team:, programmes:) } let(:patient) do create( :patient, @@ -18,7 +22,9 @@ create(:patient_session, :in_attendance, programmes:, patient:, session:) end - let(:vaccinate_form) { VaccinateForm.new(patient_session:, programme:) } + let(:vaccinate_form) do + VaccinateForm.new(current_user:, patient_session:, programme:) + end let(:component) { described_class.new(vaccinate_form) } diff --git a/spec/factories/users.rb b/spec/factories/users.rb index dc57218e5c..b5d2703cc4 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -34,10 +34,10 @@ factory :user, aliases: %i[ nurse - assessor created_by - recorded_by performed_by + recorded_by + supplied_by uploaded_by ] do transient do @@ -61,6 +61,7 @@ sequence(:email) { |n| "nurse-#{n}@example.com" } fallback_role { :nurse } + show_in_suppliers { true } given_name { "Test" } family_name { "User" } @@ -83,12 +84,14 @@ sequence(:email) { |n| "admin-#{n}@example.com" } role_code { CIS2Info::ADMIN_ROLE } fallback_role { :admin } + show_in_suppliers { false } end trait :superuser do sequence(:email) { |n| "superuser-#{n}@example.com" } role_workgroups { [CIS2Info::SUPERUSER_WORKGROUP] } fallback_role { :superuser } + show_in_suppliers { false } end trait :healthcare_assistant do @@ -98,6 +101,7 @@ [CIS2Info::PERSONAL_MEDICATION_ADMINISTRATION_ACTIVITY_CODE] end fallback_role { :healthcare_assistant } + show_in_suppliers { false } end trait :prescriber do diff --git a/spec/features/flu_vaccination_hca_pgd_supply_spec.rb b/spec/features/flu_vaccination_hca_pgd_supply_spec.rb index 38755a9891..91613f5407 100644 --- a/spec/features/flu_vaccination_hca_pgd_supply_spec.rb +++ b/spec/features/flu_vaccination_hca_pgd_supply_spec.rb @@ -21,9 +21,20 @@ end def given_a_session_exists - programmes = [create(:programme, :flu)] + @programme = create(:programme, :flu) + programmes = [@programme] @team = create(:team, programmes:) + + @batch = + create( + :batch, + :not_expired, + team: @team, + vaccine: @programme.vaccines.nasal.first + ) + + @nurse = create(:nurse, team: @team) @user = create(:healthcare_assistant, team: @team) @session = @@ -78,11 +89,28 @@ def when_i_click_on_the_nasal_and_injection_patient def when_i_click_on_the_injection_patient # This patient won't be in the "Record" tab. + expect(page).not_to have_content(@patient_injection_only.full_name) + within(".app-secondary-navigation") { click_on "Children" } click_on @patient_injection_only.full_name end def then_i_am_able_to_vaccinate_them + check "I have checked that the above statements are true" + select @nurse.full_name + within all("section")[1] do + choose "Yes" + end + click_on "Continue" + + choose @batch.name + click_on "Continue" + + click_on "Change supplier" + choose @nurse.full_name + 4.times { click_on "Continue" } + + click_on "Confirm" click_on "Record vaccinations" end diff --git a/spec/forms/vaccinate_form_spec.rb b/spec/forms/vaccinate_form_spec.rb index e638da39fc..012b89465e 100644 --- a/spec/forms/vaccinate_form_spec.rb +++ b/spec/forms/vaccinate_form_spec.rb @@ -1,9 +1,10 @@ # frozen_string_literal: true describe VaccinateForm do - subject(:form) { described_class.new(programme:) } + subject(:form) { described_class.new(programme:, current_user:) } let(:programme) { create(:programme) } + let(:current_user) { create(:user) } describe "validations" do it do @@ -28,7 +29,8 @@ subject(:form) do described_class.new( identity_check_confirmed_by_patient: false, - programme: + programme:, + current_user: ) end