Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ AllCops:
Layout/EmptyLineAfterMagicComment:
Enabled: true

Layout/LineLength:
AllowedPatterns: [idx_on]

Lint/PercentStringArray:
Exclude:
- spec/models/dps_export_spec.rb
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,11 @@ def status_tag
end
render AppProgrammeStatusTagsComponent.new(statuses, outcome: :triage)
else
outcome = patient_session.session_outcome

# ensure status is calculated for each programme
patient_session.programmes.each { outcome.status[it] }

render AppProgrammeStatusTagsComponent.new(
outcome.status,
outcome: context == :outcome ? :session : context
)
statuses =
patient_session.programmes.index_with do |programme|
patient_session.session_status(programme:).status
end
render AppProgrammeStatusTagsComponent.new(statuses, outcome: :session)
end
end
end
22 changes: 9 additions & 13 deletions app/components/app_programme_session_table_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,6 @@ def cohort_count(session:)
format_number(session.patient_sessions.count)
end

def number_stat(session:)
format_number(session.patient_sessions.select { yield it }.length)
end

def percentage_stat(session:)
format_percentage(
session.patient_sessions.select { yield it }.length,
session.patient_sessions.count
)
end

def no_response_scope(session:)
session.patient_sessions.has_consent_status(:no_response, programme:)
end
Expand All @@ -48,12 +37,19 @@ def triage_needed_count(session:)
)
end

def vaccinated_scope(session:)
session.patient_sessions.has_session_status(:vaccinated, programme:)
end

def vaccinated_count(session:)
number_stat(session:) { it.session_outcome.vaccinated?(programme) }
format_number(vaccinated_scope(session:).count)
end

def vaccinated_percentage(session:)
percentage_stat(session:) { it.session_outcome.vaccinated?(programme) }
format_percentage(
vaccinated_scope(session:).count,
session.patient_sessions.count
)
end

def format_number(count) = count.to_s
Expand Down
6 changes: 3 additions & 3 deletions app/components/app_session_details_summary_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def call
delegate :programmes, to: :session

def cohort_row
count = patient_sessions.length
count = patient_sessions.count
href = new_draft_class_import_path(session)

{
Expand Down Expand Up @@ -57,7 +57,7 @@ def vaccinated_row
texts =
session.programmes.map do |programme|
count =
patient_sessions.count { it.session_outcome.vaccinated?(programme) }
patient_sessions.has_session_status(:vaccinated, programme:).count

"#{I18n.t("vaccinations_given", count:)} for #{programme.name}"
end
Expand All @@ -66,7 +66,7 @@ def vaccinated_row
session_outcome_path(
session,
search_form: {
session_status: PatientSession::SessionOutcome::VACCINATED
session_status: "vaccinated"
}
)

Expand Down
7 changes: 5 additions & 2 deletions app/controllers/patients_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ def update
if organisation_id.nil?
@patient
.patient_sessions
.preload_for_status
.includes(:gillick_assessments, :session_attendances)
.includes(
:gillick_assessments,
:session_attendances,
:vaccination_records
)
.where(session: old_organisation.sessions)
.find_each(&:destroy_if_safe!)
end
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/session_attendances_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ def update
@session_attendance.save!
end => success

StatusUpdater.call(patient: @patient)

if success
name = @patient.full_name

Expand Down
2 changes: 2 additions & 0 deletions app/controllers/session_dates_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ def update
@session.save!
end

StatusUpdaterJob.perform_later(session: @session)

if params.include?(:add_another)
@session.session_dates.build
render :show
Expand Down
23 changes: 6 additions & 17 deletions app/controllers/sessions/outcome_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

require "pagy/extras/array"

class Sessions::OutcomeController < ApplicationController
include Pagy::Backend
include SearchFormConcern
Expand All @@ -12,28 +10,19 @@ class Sessions::OutcomeController < ApplicationController
layout "full"

def show
@statuses = PatientSession::SessionOutcome::STATUSES
@statuses = PatientSession::SessionStatus.statuses.keys
@programmes = @session.programmes

scope =
@session.patient_sessions.preload_for_status.in_programmes(
@session.programmes
)

patient_sessions = @form.apply(scope)
@session.patient_sessions.preload_for_status.in_programmes(@programmes)

if patient_sessions.is_a?(Array)
@pagy, @patient_sessions = pagy_array(patient_sessions)
else
@pagy, @patient_sessions = pagy(patient_sessions)
end
patient_sessions = @form.apply(scope, programme: @programmes)
@pagy, @patient_sessions = pagy(patient_sessions)
end

private

def set_session
@session =
policy_scope(Session).includes(:programmes).find_by!(
slug: params[:session_slug]
)
@session = policy_scope(Session).find_by!(slug: params[:session_slug])
end
end
6 changes: 5 additions & 1 deletion app/controllers/sessions/register_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ def show

def create
session_attendance = authorize @patient_session.register_outcome.latest
session_attendance.update!(attending: params[:status] == "present")

ActiveRecord::Base.transaction do
session_attendance.update!(attending: params[:status] == "present")
StatusUpdater.call(patient: @patient_session.patient)
end

name = @patient_session.patient.full_name

Expand Down
2 changes: 2 additions & 0 deletions app/controllers/vaccination_records_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ def destroy

@vaccination_record.discard!

StatusUpdater.call(patient: @vaccination_record.patient)

if @vaccination_record.confirmation_sent?
send_vaccination_deletion(@vaccination_record)
end
Expand Down
2 changes: 1 addition & 1 deletion app/forms/search_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def apply(scope, programme: nil)
end

if (status = session_status&.to_sym).present?
scope = scope.select { it.session_outcome.status.values.include?(status) }
scope = scope.has_session_status(status, programme:)
end

if (status = register_status&.to_sym).present?
Expand Down
2 changes: 1 addition & 1 deletion app/forms/session_programmes_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def save
return false if invalid?

session.programme_ids = programme_ids
StatusUpdater.call(session:)
StatusUpdaterJob.perform_later(session:)

true
end
Expand Down
13 changes: 13 additions & 0 deletions app/jobs/status_updater_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

class StatusUpdaterJob < NotifyDeliveryJob
include GoodJob::ActiveJobExtensions::Concurrency

queue_as :statuses

good_job_control_concurrency_with perform_limit: 1

def perform(patient: nil, session: nil)
StatusUpdater.call(patient: patient, session: session)
end
end
6 changes: 5 additions & 1 deletion app/lib/reports/careplus_exporter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,11 @@ def rows(patient_session:)
patient = patient_session.patient

vaccination_records =
patient_session.session_outcome.all[programme].select(&:administered?)
patient
.latest_vaccination_records(programme:)
.select do
it.administered? && it.session_id == patient_session.session_id
end

if vaccination_records.any?
[existing_row(patient:, patient_session:, vaccination_records:)]
Expand Down
36 changes: 36 additions & 0 deletions app/lib/status_updater.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def initialize(patient: nil, session: nil)

def call
update_consent_statuses!
update_session_statuses!
update_triage_statuses!
update_vaccination_statuses!
end
Expand Down Expand Up @@ -47,6 +48,29 @@ def update_consent_statuses!
end
end

def update_session_statuses!
PatientSession::SessionStatus.import!(
%i[patient_session_id programme_id],
patient_session_statuses_to_import,
on_duplicate_key_ignore: true
)

PatientSession::SessionStatus
.where(patient_session_id: patient_sessions.select(:id))
.includes(:consents, :triages, :vaccination_records, :session_attendance)
.find_in_batches(batch_size: 10_000) do |batch|
batch.each(&:assign_status)

PatientSession::SessionStatus.import!(
batch.select(&:changed?),
on_duplicate_key_update: {
conflict_target: [:id],
columns: %i[status]
}
)
end
end

def update_triage_statuses!
Patient::TriageStatus.import!(
%i[patient_id programme_id],
Expand Down Expand Up @@ -106,6 +130,18 @@ def patient_statuses_to_import
end
end

def patient_session_statuses_to_import
@patient_session_statuses_to_import ||=
patient_sessions
.joins(:patient)
.pluck(:id, :"patients.birth_academic_year")
.flat_map do |patient_session_id, birth_academic_year|
programme_ids_per_birth_academic_year
.fetch(birth_academic_year, [])
.map { [patient_session_id, it] }
end
end

def programme_ids_per_birth_academic_year
@programme_ids_per_birth_academic_year ||=
Programme
Expand Down
3 changes: 2 additions & 1 deletion app/models/concerns/patient_session_status_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ def status(programme:)
"consent_refused"
elsif patient.triage_status(programme:).do_not_vaccinate?
"triaged_do_not_vaccinate"
elsif session_outcome.not_vaccinated?(programme)
elsif !session_status(programme:).none_yet? &&
!session_status(programme:).vaccinated?
"unable_to_vaccinate"
elsif patient.consent_status(programme:).given? &&
patient.triage_status(programme:).safe_to_vaccinate?
Expand Down
7 changes: 5 additions & 2 deletions app/models/patient.rb
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,11 @@ def destroy_childless_parents

def clear_sessions_for_current_academic_year!
patient_sessions
.preload_for_status
.includes(:gillick_assessments, :session_attendances)
.includes(
:gillick_assessments,
:session_attendances,
:vaccination_records
)
.where(session: sessions_for_current_academic_year)
.find_each(&:destroy_if_safe!)
end
Expand Down
Loading
Loading