diff --git a/app/components/app_patient_session_record_component.rb b/app/components/app_patient_session_record_component.rb index 33c1f94760..6322d761d1 100644 --- a/app/components/app_patient_session_record_component.rb +++ b/app/components/app_patient_session_record_component.rb @@ -22,7 +22,7 @@ def render? ( patient_session.registration_status&.attending? || patient_session.registration_status&.completed? || - !patient_session.session.requires_registration? + !session.requires_registration? ) end @@ -35,8 +35,14 @@ def render? def default_vaccinate_form pre_screening_confirmed = patient.pre_screenings.today.exists?(programme:) + session_date = session.session_dates.today.first - VaccinateForm.new(patient_session:, programme:, pre_screening_confirmed:) + VaccinateForm.new( + patient:, + session_date:, + programme:, + pre_screening_confirmed: + ) end def heading diff --git a/app/components/app_vaccinate_form_component.rb b/app/components/app_vaccinate_form_component.rb index 8426b39792..06dc19a26c 100644 --- a/app/components/app_vaccinate_form_component.rb +++ b/app/components/app_vaccinate_form_component.rb @@ -11,8 +11,7 @@ def initialize(vaccinate_form) attr_reader :vaccinate_form - delegate :patient_session, :programme, to: :vaccinate_form - delegate :patient, :session, to: :patient_session + delegate :patient, :session, :programme, to: :vaccinate_form delegate :academic_year, to: :session def url diff --git a/app/controllers/api/testing/teams_controller.rb b/app/controllers/api/testing/teams_controller.rb index a330d973f6..a1625f7812 100644 --- a/app/controllers/api/testing/teams_controller.rb +++ b/app/controllers/api/testing/teams_controller.rb @@ -27,11 +27,7 @@ def destroy patient_ids = team.patients.pluck(:id) - patient_sessions = PatientSession.where(session: sessions) - log_destroy(PreScreening.where(patient_session: patient_sessions)) - patient_sessions.in_batches { log_destroy(it) } - - log_destroy(SessionDate.where(session: sessions)) + log_destroy(PatientSession.where(session: sessions)) log_destroy(AccessLogEntry.where(patient_id: patient_ids)) log_destroy(ArchiveReason.where(patient_id: patient_ids)) @@ -41,11 +37,14 @@ def destroy # In local dev we can end up with NotifyLogEntries without a patient log_destroy(NotifyLogEntry.where(patient_id: nil)) log_destroy(NotifyLogEntry.where(patient_id: patient_ids)) + log_destroy(PreScreening.where(patient_id: patient_ids)) log_destroy(SchoolMove.where(patient_id: patient_ids)) log_destroy(SchoolMove.where(team:)) log_destroy(SchoolMoveLogEntry.where(patient_id: patient_ids)) log_destroy(VaccinationRecord.where(patient_id: patient_ids)) + log_destroy(SessionDate.where(session: sessions)) + log_destroy(ConsentForm.where(team:)) log_destroy(Consent.where(team:)) log_destroy(Triage.where(team:)) diff --git a/app/controllers/patient_sessions/base_controller.rb b/app/controllers/patient_sessions/base_controller.rb index 8a3614bc56..f67917208b 100644 --- a/app/controllers/patient_sessions/base_controller.rb +++ b/app/controllers/patient_sessions/base_controller.rb @@ -19,6 +19,10 @@ def set_session ) end + def set_session_date + @session_date = @session.session_dates.find_by!(value: Date.current) + end + def set_academic_year @academic_year = @session.academic_year end diff --git a/app/controllers/patient_sessions/session_attendances_controller.rb b/app/controllers/patient_sessions/session_attendances_controller.rb index 18965d87cd..9f2c762d33 100644 --- a/app/controllers/patient_sessions/session_attendances_controller.rb +++ b/app/controllers/patient_sessions/session_attendances_controller.rb @@ -41,10 +41,6 @@ def update private - def set_session_date - @session_date = @session.session_dates.find_by!(value: Date.current) - end - def set_session_attendance @session_attendance = authorize @patient_session diff --git a/app/controllers/patient_sessions/vaccinations_controller.rb b/app/controllers/patient_sessions/vaccinations_controller.rb index 03c173c2ed..72a9b2268c 100644 --- a/app/controllers/patient_sessions/vaccinations_controller.rb +++ b/app/controllers/patient_sessions/vaccinations_controller.rb @@ -5,6 +5,7 @@ class PatientSessions::VaccinationsController < PatientSessions::BaseController include VaccinationMailerConcern before_action :set_todays_batch + before_action :set_session_date after_action :verify_authorized @@ -17,7 +18,8 @@ def create @vaccinate_form = VaccinateForm.new( current_user:, - patient_session: @patient_session, + patient: @patient, + session_date: @session_date, programme: @programme, todays_batch: @todays_batch, **vaccinate_form_params diff --git a/app/forms/vaccinate_form.rb b/app/forms/vaccinate_form.rb index 3c08ef1267..c354de203b 100644 --- a/app/forms/vaccinate_form.rb +++ b/app/forms/vaccinate_form.rb @@ -4,7 +4,13 @@ class VaccinateForm include ActiveModel::Model include ActiveModel::Attributes - attr_accessor :patient_session, :programme, :current_user, :todays_batch + attr_accessor :patient, + :session_date, + :programme, + :current_user, + :todays_batch + + delegate :session, to: :session_date attribute :identity_check_confirmed_by_other_name, :string attribute :identity_check_confirmed_by_other_relationship, :string @@ -90,19 +96,19 @@ def save(draft_vaccination_record:) identity_check_confirmed_by_patient draft_vaccination_record.location_id = session.location_id unless session.generic_clinic? - draft_vaccination_record.patient_id = patient_session.patient_id + draft_vaccination_record.patient_id = patient.id draft_vaccination_record.performed_at = Time.current draft_vaccination_record.performed_by_user = current_user draft_vaccination_record.performed_ods_code = organisation.ods_code draft_vaccination_record.programme = programme - draft_vaccination_record.session_id = patient_session.session_id + draft_vaccination_record.session_id = session.id draft_vaccination_record.save # rubocop:disable Rails/SaveBang end private - delegate :organisation, :session, to: :patient_session + delegate :organisation, to: :session def administered? = vaccine_method != "none" @@ -131,10 +137,11 @@ def delivery_method def pre_screening @pre_screening ||= - patient_session.pre_screenings.build( + patient.pre_screenings.build( notes: pre_screening_notes, performed_by: current_user, - programme: + programme:, + session_date: ) end end diff --git a/app/lib/patient_merger.rb b/app/lib/patient_merger.rb index 1c7ae387c9..2d054a5bb6 100644 --- a/app/lib/patient_merger.rb +++ b/app/lib/patient_merger.rb @@ -40,6 +40,10 @@ def call patient_id: patient_to_keep.id ) + patient_to_destroy.pre_screenings.update_all( + patient_id: patient_to_keep.id + ) + patient_to_destroy.school_moves.find_each do |school_move| if patient_to_keep.school_moves.exists?( home_educated: school_move.home_educated, @@ -78,18 +82,12 @@ def call end patient_to_destroy.patient_sessions.each do |patient_session| - if ( - existing_patient_session = - patient_to_keep.patient_sessions.find_by( - session_id: patient_session.session_id - ) + if patient_to_keep.patient_sessions.exists?( + session_id: patient_session.session_id ) - patient_session.pre_screenings.update_all( - patient_session_id: existing_patient_session.id - ) - else - patient_session.update!(patient: patient_to_keep) + next end + patient_session.update!(patient: patient_to_keep) end PatientSession.where(patient: patient_to_destroy).destroy_all diff --git a/app/models/patient.rb b/app/models/patient.rb index 835427976b..eac95b4e5b 100644 --- a/app/models/patient.rb +++ b/app/models/patient.rb @@ -70,6 +70,7 @@ class Patient < ApplicationRecord has_many :parent_relationships, -> { order(:created_at) } has_many :patient_sessions has_many :pds_search_results + has_many :pre_screenings has_many :school_move_log_entries has_many :school_moves has_many :session_notifications @@ -81,7 +82,6 @@ class Patient < ApplicationRecord has_many :gillick_assessments has_many :parents, through: :parent_relationships has_many :patient_specific_directions - has_many :pre_screenings, through: :patient_sessions has_many :session_attendances, through: :patient_sessions has_many :sessions, through: :patient_sessions has_many :teams, -> { distinct }, through: :sessions diff --git a/app/models/patient_session.rb b/app/models/patient_session.rb index 712b37fa50..15f6339b2f 100644 --- a/app/models/patient_session.rb +++ b/app/models/patient_session.rb @@ -44,7 +44,6 @@ class PatientSession < ApplicationRecord belongs_to :patient belongs_to :session - has_many :pre_screenings has_many :session_attendances, dependent: :destroy has_one :registration_status @@ -64,6 +63,10 @@ class PatientSession < ApplicationRecord through: :patient, source: :notes + has_many :pre_screenings, + -> { where(patient_id: it.patient_id) }, + through: :session + has_many :session_notifications, -> { where(session_id: it.session_id) }, through: :patient diff --git a/app/models/pre_screening.rb b/app/models/pre_screening.rb index e6efc5a290..7c735542c2 100644 --- a/app/models/pre_screening.rb +++ b/app/models/pre_screening.rb @@ -8,34 +8,36 @@ # notes :text default(""), not null # created_at :datetime not null # updated_at :datetime not null -# patient_session_id :bigint not null +# patient_id :bigint not null # performed_by_user_id :bigint not null # programme_id :bigint not null +# session_date_id :bigint not null # # Indexes # -# index_pre_screenings_on_patient_session_id (patient_session_id) +# index_pre_screenings_on_patient_id (patient_id) # index_pre_screenings_on_performed_by_user_id (performed_by_user_id) # index_pre_screenings_on_programme_id (programme_id) +# index_pre_screenings_on_session_date_id (session_date_id) # # Foreign Keys # -# fk_rails_... (patient_session_id => patient_sessions.id) +# fk_rails_... (patient_id => patients.id) # fk_rails_... (performed_by_user_id => users.id) # fk_rails_... (programme_id => programmes.id) +# fk_rails_... (session_date_id => session_dates.id) # class PreScreening < ApplicationRecord - audited associated_with: :patient_session + audited associated_with: :patient - belongs_to :patient_session + belongs_to :patient + belongs_to :session_date belongs_to :programme belongs_to :performed_by, class_name: "User", foreign_key: :performed_by_user_id - has_one :patient, through: :patient_session - - scope :today, -> { where(created_at: Date.current.all_day) } + scope :today, -> { joins(:session_date).merge(SessionDate.today) } encrypts :notes diff --git a/app/models/session.rb b/app/models/session.rb index 1d7031bf8e..765452bed1 100644 --- a/app/models/session.rb +++ b/app/models/session.rb @@ -51,6 +51,7 @@ class Session < ApplicationRecord has_one :organisation, through: :team has_one :subteam, through: :location + has_many :pre_screenings, through: :session_dates has_many :programmes, through: :session_programmes has_many :gillick_assessments, through: :session_dates has_many :patients, through: :patient_sessions diff --git a/app/models/session_date.rb b/app/models/session_date.rb index ef617f17d7..1e366eaaae 100644 --- a/app/models/session_date.rb +++ b/app/models/session_date.rb @@ -22,6 +22,7 @@ class SessionDate < ApplicationRecord belongs_to :session has_many :gillick_assessments, dependent: :restrict_with_error + has_many :pre_screenings, dependent: :restrict_with_error has_many :session_attendances, dependent: :restrict_with_error scope :for_session, -> { where("session_id = sessions.id") } @@ -44,7 +45,7 @@ def today_or_past? = today? || past? def today_or_future? = today? || future? def has_been_attended? - gillick_assessments.any? || session_attendances.any? + gillick_assessments.any? || pre_screenings.any? || session_attendances.any? end private diff --git a/db/migrate/20250821124416_remove_patient_session_from_pre_screenings.rb b/db/migrate/20250821124416_remove_patient_session_from_pre_screenings.rb new file mode 100644 index 0000000000..5a1813b755 --- /dev/null +++ b/db/migrate/20250821124416_remove_patient_session_from_pre_screenings.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +class RemovePatientSessionFromPreScreenings < ActiveRecord::Migration[8.0] + def up + change_table :pre_screenings, bulk: true do |t| + t.references :patient, foreign_key: true + t.references :session_date, foreign_key: true + end + + PreScreening.find_each do |pre_screening| + patient_session = PatientSession.find(pre_screening.patient_session_id) + patient_id = patient_session.patient_id + session_id = patient_session.session_id + session_date_id = + SessionDate.find_by!( + session_id:, + value: pre_screening.created_at.to_date + ) + pre_screening.update_columns(patient_id:, session_date_id:) + end + + change_table :pre_screenings, bulk: true do |t| + t.change_null :patient_id, false + t.change_null :session_date_id, false + t.remove_references :patient_session + end + end + + def down + add_reference :pre_screenings, :patient_session + + PreScreening.find_each do |pre_screening| + session_id = SessionDate.find(pre_screening.session_date_id).session_id + patient_session = + PatientSession.find_by!( + patient_id: pre_screening.patient_id, + session_id: + ) + pre_screening.update_column(:patient_session_id, patient_session.id) + end + + change_table :pre_screenings, bulk: true do |t| + t.change_null :patient_session_id, false + t.remove_references :patient, :session_date + end + end +end diff --git a/db/schema.rb b/db/schema.rb index d4cd8a8ec5..7673f8b546 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -722,15 +722,17 @@ end create_table "pre_screenings", force: :cascade do |t| - t.bigint "patient_session_id", null: false t.bigint "performed_by_user_id", null: false t.text "notes", default: "", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.bigint "programme_id", null: false - t.index ["patient_session_id"], name: "index_pre_screenings_on_patient_session_id" + t.bigint "patient_id", null: false + t.bigint "session_date_id", null: false + t.index ["patient_id"], name: "index_pre_screenings_on_patient_id" t.index ["performed_by_user_id"], name: "index_pre_screenings_on_performed_by_user_id" t.index ["programme_id"], name: "index_pre_screenings_on_programme_id" + t.index ["session_date_id"], name: "index_pre_screenings_on_session_date_id" end create_table "programmes", force: :cascade do |t| @@ -1072,8 +1074,9 @@ add_foreign_key "patients", "locations", column: "gp_practice_id" add_foreign_key "patients", "locations", column: "school_id" add_foreign_key "pds_search_results", "patients" - add_foreign_key "pre_screenings", "patient_sessions" + add_foreign_key "pre_screenings", "patients" add_foreign_key "pre_screenings", "programmes" + add_foreign_key "pre_screenings", "session_dates" add_foreign_key "pre_screenings", "users", column: "performed_by_user_id" add_foreign_key "reporting_api_one_time_tokens", "users" add_foreign_key "school_move_log_entries", "locations", column: "school_id" diff --git a/spec/components/app_activity_log_component_spec.rb b/spec/components/app_activity_log_component_spec.rb index 24d0d5bb59..85da16d3df 100644 --- a/spec/components/app_activity_log_component_spec.rb +++ b/spec/components/app_activity_log_component_spec.rb @@ -483,7 +483,8 @@ create( :pre_screening, performed_by: user, - patient_session:, + patient:, + session: patient_session.session, notes: "Some notes", created_at: Time.zone.local(2025, 6, 1, 12) ) diff --git a/spec/components/app_vaccinate_form_component_spec.rb b/spec/components/app_vaccinate_form_component_spec.rb index 946549d72b..40ef233d3a 100644 --- a/spec/components/app_vaccinate_form_component_spec.rb +++ b/spec/components/app_vaccinate_form_component_spec.rb @@ -6,6 +6,7 @@ let(:programme) { create(:programme) } let(:programmes) { [programme] } let(:session) { create(:session, :today, programmes:) } + let(:session_date) { session.session_dates.first } let(:patient) do create( :patient, @@ -18,7 +19,9 @@ create(:patient_session, :in_attendance, programmes:, patient:, session:) end - let(:vaccinate_form) { VaccinateForm.new(patient_session:, programme:) } + let(:vaccinate_form) do + VaccinateForm.new(patient:, session_date:, programme:) + end let(:component) { described_class.new(vaccinate_form) } diff --git a/spec/controllers/api/testing/teams_controller_spec.rb b/spec/controllers/api/testing/teams_controller_spec.rb index 5935538b82..67c1bdc75e 100644 --- a/spec/controllers/api/testing/teams_controller_spec.rb +++ b/spec/controllers/api/testing/teams_controller_spec.rb @@ -71,7 +71,7 @@ create(:school_move, :to_school, patient: Patient.first) create(:session_date, session: Session.first) - create(:pre_screening, patient_session: PatientSession.first) + create(:pre_screening, patient: Patient.first, session: Session.first) end it "deletes associated data" do diff --git a/spec/factories/pre_screenings.rb b/spec/factories/pre_screenings.rb index 4b7b4d3d7d..5ea885a108 100644 --- a/spec/factories/pre_screenings.rb +++ b/spec/factories/pre_screenings.rb @@ -8,27 +8,34 @@ # notes :text default(""), not null # created_at :datetime not null # updated_at :datetime not null -# patient_session_id :bigint not null +# patient_id :bigint not null # performed_by_user_id :bigint not null # programme_id :bigint not null +# session_date_id :bigint not null # # Indexes # -# index_pre_screenings_on_patient_session_id (patient_session_id) +# index_pre_screenings_on_patient_id (patient_id) # index_pre_screenings_on_performed_by_user_id (performed_by_user_id) # index_pre_screenings_on_programme_id (programme_id) +# index_pre_screenings_on_session_date_id (session_date_id) # # Foreign Keys # -# fk_rails_... (patient_session_id => patient_sessions.id) +# fk_rails_... (patient_id => patients.id) # fk_rails_... (performed_by_user_id => users.id) # fk_rails_... (programme_id => programmes.id) +# fk_rails_... (session_date_id => session_dates.id) # FactoryBot.define do factory :pre_screening do - patient_session - programme { patient_session.programmes.first } + transient { session { association(:session) } } + + patient + session_date { session.session_dates.first } + programme { session_date.session.programmes.first } performed_by + notes { "Fine to vaccinate" } end end diff --git a/spec/lib/patient_merger_spec.rb b/spec/lib/patient_merger_spec.rb index b8791ea848..22e3d41a98 100644 --- a/spec/lib/patient_merger_spec.rb +++ b/spec/lib/patient_merger_spec.rb @@ -57,7 +57,7 @@ let(:patient_session) do create(:patient_session, session:, patient: patient_to_destroy) end - let(:pre_screening) { create(:pre_screening, patient_session:) } + let(:pre_screening) { create(:pre_screening, patient: patient_to_destroy) } let(:school_move) do create(:school_move, :to_school, patient: patient_to_destroy) end diff --git a/spec/models/pre_screening_spec.rb b/spec/models/pre_screening_spec.rb index d75e2f0ffd..82c6c812e2 100644 --- a/spec/models/pre_screening_spec.rb +++ b/spec/models/pre_screening_spec.rb @@ -8,25 +8,34 @@ # notes :text default(""), not null # created_at :datetime not null # updated_at :datetime not null -# patient_session_id :bigint not null +# patient_id :bigint not null # performed_by_user_id :bigint not null # programme_id :bigint not null +# session_date_id :bigint not null # # Indexes # -# index_pre_screenings_on_patient_session_id (patient_session_id) +# index_pre_screenings_on_patient_id (patient_id) # index_pre_screenings_on_performed_by_user_id (performed_by_user_id) # index_pre_screenings_on_programme_id (programme_id) +# index_pre_screenings_on_session_date_id (session_date_id) # # Foreign Keys # -# fk_rails_... (patient_session_id => patient_sessions.id) +# fk_rails_... (patient_id => patients.id) # fk_rails_... (performed_by_user_id => users.id) # fk_rails_... (programme_id => programmes.id) +# fk_rails_... (session_date_id => session_dates.id) # describe PreScreening do subject(:pre_screening) { build(:pre_screening) } + describe "associations" do + it { should belong_to(:patient) } + it { should belong_to(:session_date) } + it { should belong_to(:programme) } + end + describe "scopes" do describe "#today" do subject { described_class.today } @@ -37,8 +46,9 @@ it { should include(pre_screening) } end - context "with an instance created yesterday" do - let(:pre_screening) { create(:pre_screening, created_at: 1.day.ago) } + context "with an instance for yesterday" do + let(:session_date) { create(:session_date, value: Date.yesterday) } + let(:pre_screening) { create(:pre_screening, session_date:) } it { should_not include(pre_screening) } end diff --git a/spec/models/session_date_spec.rb b/spec/models/session_date_spec.rb index 0149ee04a1..70bc81bab2 100644 --- a/spec/models/session_date_spec.rb +++ b/spec/models/session_date_spec.rb @@ -66,6 +66,12 @@ it { should be(true) } end + context "with a pre-screening" do + before { create(:pre_screening, session:) } + + it { should be(true) } + end + context "with a session attendance" do before do create(