Skip to content

Commit f683ca2

Browse files
committed
Track consent status on programme status
This adds a new column to the programme status model which will store the consent status of the patient for that programme and academic year. This is needed as a replacement for the individual consent status model which we'd like to get rid of to simplify the code. There are some parts of the service (notably the offline spreadsheet and the reporting API) that relies on being able to display a list of consent statuses and therefore replacing the `Patient::ConsentStatus` with dynamically calculated values would not be performant. Instead we will add the consent status as a column on the programme status model, allowing us to simplify the `StatusUpdater` class and likely cut down how long it takes to run by approximately half. Jira-Issue: MAV-2660
1 parent a551a3b commit f683ca2

8 files changed

Lines changed: 120 additions & 43 deletions

File tree

app/lib/status_generator/programme.rb

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def without_gelatine
7878
if vaccination_generator.status == :not_eligible ||
7979
triage_generator.status.in?(
8080
%i[required invite_to_clinic do_not_vaccinate]
81-
) || consent_generator.status.in?(%i[no_response conflicts refused])
81+
) || consent_status.in?(%i[no_response conflicts refused])
8282
return nil
8383
end
8484

@@ -89,14 +89,14 @@ def vaccine_methods
8989
if vaccination_generator.status == :not_eligible ||
9090
triage_generator.status.in?(
9191
%i[required invite_to_clinic do_not_vaccinate]
92-
) || consent_generator.status.in?(%i[no_response conflicts refused])
92+
) || consent_status.in?(%i[no_response conflicts refused])
9393
return nil
9494
end
9595

9696
if triage_generator.vaccine_method
9797
[triage_generator.vaccine_method]
9898
else
99-
consent_generator.vaccine_methods
99+
consent_vaccine_methods
100100
end
101101
end
102102

@@ -105,7 +105,7 @@ def disease_types
105105

106106
if vaccination_generator.disease_types
107107
vaccination_generator.disease_types
108-
elsif consent_generator.status.in?(%i[given refused conflicts])
108+
elsif consent_status.in?(%i[given refused conflicts])
109109
consent_generator.disease_types
110110
end
111111
end
@@ -119,6 +119,14 @@ def location_id
119119
vaccination_generator.latest_location_id
120120
end
121121

122+
def consent_status
123+
consent_generator.status
124+
end
125+
126+
def consent_vaccine_methods
127+
consent_generator.vaccine_methods
128+
end
129+
122130
private
123131

124132
attr_reader :programme_type,
@@ -182,20 +190,19 @@ def should_be_needs_triage?
182190
end
183191

184192
def should_be_has_refusal_consent_conflicts?
185-
consent_generator.status == :conflicts
193+
consent_status == :conflicts
186194
end
187195

188196
def should_be_has_refusal_consent_refused?
189-
consent_generator.status == :refused
197+
consent_status == :refused
190198
end
191199

192200
def should_be_needs_consent_follow_up_requested?
193201
false # TODO: Implement this status.
194202
end
195203

196204
def should_be_needs_consent_no_response?
197-
vaccination_generator.status == :eligible &&
198-
consent_generator.status == :no_response
205+
vaccination_generator.status == :eligible && consent_status == :no_response
199206
end
200207

201208
def should_be_needs_consent_request_failed?

app/lib/status_updater.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ def update_programme_statuses!
7070
on_duplicate_key_update: {
7171
conflict_target: [:id],
7272
columns: %i[
73+
consent_status
74+
consent_vaccine_methods
7375
date
7476
disease_types
7577
dose_sequence

app/models/patient/programme_status.rb

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@
44
#
55
# Table name: patient_programme_statuses
66
#
7-
# id :bigint not null, primary key
8-
# academic_year :integer not null
9-
# date :date
10-
# disease_types :enum is an Array
11-
# dose_sequence :integer
12-
# programme_type :enum not null
13-
# status :integer default("not_eligible"), not null
14-
# vaccine_methods :integer is an Array
15-
# without_gelatine :boolean
16-
# location_id :bigint
17-
# patient_id :bigint not null
7+
# id :bigint not null, primary key
8+
# academic_year :integer not null
9+
# consent_status :integer default("no_response")
10+
# consent_vaccine_methods :integer default([]), is an Array
11+
# date :date
12+
# disease_types :enum is an Array
13+
# dose_sequence :integer
14+
# programme_type :enum not null
15+
# status :integer default("not_eligible"), not null
16+
# vaccine_methods :integer is an Array
17+
# without_gelatine :boolean
18+
# location_id :bigint
19+
# patient_id :bigint not null
1820
#
1921
# Indexes
2022
#
@@ -117,6 +119,16 @@ class Patient::ProgrammeStatus < ApplicationRecord
117119
default: :not_eligible,
118120
validate: true
119121

122+
enum :consent_status,
123+
{ no_response: 0, given: 1, refused: 2, conflicts: 3, not_required: 4 },
124+
default: :no_response,
125+
prefix: :consent,
126+
validate: true
127+
128+
array_enum consent_vaccine_methods: vaccine_methods
129+
130+
validates :consent_vaccine_methods, subset: consent_vaccine_methods.keys
131+
120132
scope :needs_consent, -> { where(status: NEEDS_CONSENT_STATUSES.keys) }
121133

122134
scope :has_refusal, -> { where(status: HAS_REFUSAL_STATUSES.keys) }
@@ -136,6 +148,8 @@ def vaccinated? = status.in?(VACCINATED_STATUSES.keys)
136148
def group = GROUPS.find { status.starts_with?(it) }
137149

138150
def assign
151+
self.consent_status = generator.consent_status
152+
self.consent_vaccine_methods = generator.consent_vaccine_methods
139153
self.date = generator.date
140154
self.disease_types = generator.disease_types
141155
self.dose_sequence = generator.dose_sequence
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# frozen_string_literal: true
2+
3+
class AddConsentStatusToPatientProgrammeStatuses < ActiveRecord::Migration[8.1]
4+
def change
5+
change_table :patient_programme_statuses, bulk: true do |t|
6+
t.integer :consent_status, default: 0
7+
t.integer :consent_vaccine_methods, array: true, default: []
8+
end
9+
end
10+
end

db/schema.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,8 @@
618618

619619
create_table "patient_programme_statuses", force: :cascade do |t|
620620
t.integer "academic_year", null: false
621+
t.integer "consent_status", default: 0
622+
t.integer "consent_vaccine_methods", default: [], array: true
621623
t.date "date"
622624
t.enum "disease_types", array: true, enum_type: "disease_type"
623625
t.integer "dose_sequence"

spec/factories/patient_programme_statuses.rb

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@
44
#
55
# Table name: patient_programme_statuses
66
#
7-
# id :bigint not null, primary key
8-
# academic_year :integer not null
9-
# date :date
10-
# disease_types :enum is an Array
11-
# dose_sequence :integer
12-
# programme_type :enum not null
13-
# status :integer default("not_eligible"), not null
14-
# vaccine_methods :integer is an Array
15-
# without_gelatine :boolean
16-
# location_id :bigint
17-
# patient_id :bigint not null
7+
# id :bigint not null, primary key
8+
# academic_year :integer not null
9+
# consent_status :integer default("no_response")
10+
# consent_vaccine_methods :integer default([]), is an Array
11+
# date :date
12+
# disease_types :enum is an Array
13+
# dose_sequence :integer
14+
# programme_type :enum not null
15+
# status :integer default("not_eligible"), not null
16+
# vaccine_methods :integer is an Array
17+
# without_gelatine :boolean
18+
# location_id :bigint
19+
# patient_id :bigint not null
1820
#
1921
# Indexes
2022
#

spec/lib/status_generator/programme_spec.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
create(:vaccination_record, :already_had, patient:, programme:, location:)
3131
end
3232

33+
its(:consent_status) { should be(:not_required) }
34+
its(:consent_vaccine_methods) { should be_empty }
3335
its(:date) { should eq(vaccination_record.performed_at.to_date) }
3436
its(:disease_types) { should eq(%w[human_papillomavirus]) }
3537
its(:dose_sequence) { should be_nil }
@@ -46,6 +48,8 @@
4648
create(:vaccination_record, patient:, programme:, location:)
4749
end
4850

51+
its(:consent_status) { should be(:not_required) }
52+
its(:consent_vaccine_methods) { should be_empty }
4953
its(:date) { should eq(vaccination_record.performed_at.to_date) }
5054
its(:disease_types) { should eq(%w[human_papillomavirus]) }
5155
its(:dose_sequence) { should be_nil }
@@ -62,6 +66,8 @@
6266
create(:vaccination_record, patient:, programme:, location:)
6367
end
6468

69+
its(:consent_status) { should be(:no_response) }
70+
its(:consent_vaccine_methods) { should be_empty }
6571
its(:date) { should eq(vaccination_record.performed_at.to_date) }
6672
its(:disease_types) { should be_nil }
6773
its(:dose_sequence) { should eq(2) }
@@ -73,6 +79,8 @@
7379
context "with consent for the next dose" do
7480
before { create(:consent, :given, patient:, programme:) }
7581

82+
its(:consent_status) { should be(:given) }
83+
its(:consent_vaccine_methods) { should contain_exactly("injection") }
7684
its(:status) { should be(:due) }
7785
its(:date) { should eq(vaccination_record.performed_at.to_date) }
7886
its(:disease_types) { should be_empty }
@@ -88,6 +96,8 @@
8896
create(:vaccination_record, :unwell, patient:, programme:, location:)
8997
end
9098

99+
its(:consent_status) { should be(:given) }
100+
its(:consent_vaccine_methods) { should contain_exactly("injection") }
91101
its(:date) { should eq(vaccination_record.performed_at.to_date) }
92102
its(:disease_types) { should eq(programme.disease_types) }
93103
its(:location_id) { should be_nil }
@@ -120,6 +130,8 @@
120130
create(:vaccination_record, :refused, patient:, programme:, location:)
121131
end
122132

133+
its(:consent_status) { should be(:given) }
134+
its(:consent_vaccine_methods) { should contain_exactly("injection") }
123135
its(:date) { should eq(vaccination_record.performed_at.to_date) }
124136
its(:disease_types) { should eq(programme.disease_types) }
125137
its(:location_id) { should be_nil }
@@ -151,6 +163,8 @@
151163
)
152164
end
153165

166+
its(:consent_status) { should be(:given) }
167+
its(:consent_vaccine_methods) { should contain_exactly("injection") }
154168
its(:date) { should eq(vaccination_record.performed_at.to_date) }
155169
its(:disease_types) { should eq(programme.disease_types) }
156170
its(:location_id) { should be_nil }
@@ -176,6 +190,8 @@
176190
create(:attendance_record, :absent, patient:, session:)
177191
end
178192

193+
its(:consent_status) { should be(:given) }
194+
its(:consent_vaccine_methods) { should contain_exactly("injection") }
179195
its(:date) { should eq(attendance_record.date) }
180196
its(:disease_types) { should eq(programme.disease_types) }
181197
its(:location_id) { should be_nil }
@@ -207,6 +223,8 @@
207223
)
208224
end
209225

226+
its(:consent_status) { should be(:given) }
227+
its(:consent_vaccine_methods) { should contain_exactly("injection") }
210228
its(:date) { should eq(Date.tomorrow) }
211229
its(:disease_types) { should eq(programme.disease_types) }
212230
its(:dose_sequence) { should be_nil }
@@ -224,6 +242,8 @@
224242
create(:triage, :invite_to_clinic, patient:, programme:)
225243
end
226244

245+
its(:consent_status) { should be(:given) }
246+
its(:consent_vaccine_methods) { should contain_exactly("injection") }
227247
its(:date) { should be_nil }
228248
its(:disease_types) { should eq(programme.disease_types) }
229249
its(:dose_sequence) { should be_nil }
@@ -241,6 +261,8 @@
241261
create(:triage, :do_not_vaccinate, patient:, programme:)
242262
end
243263

264+
its(:consent_status) { should be(:given) }
265+
its(:consent_vaccine_methods) { should contain_exactly("injection") }
244266
its(:date) { should be_nil }
245267
its(:disease_types) { should eq(programme.disease_types) }
246268
its(:dose_sequence) { should be_nil }
@@ -255,6 +277,8 @@
255277

256278
before { create(:consent, :given, :needing_triage, patient:, programme:) }
257279

280+
its(:consent_status) { should be(:given) }
281+
its(:consent_vaccine_methods) { should contain_exactly("injection") }
258282
its(:date) { should be_nil }
259283
its(:disease_types) { should eq(programme.disease_types) }
260284
its(:dose_sequence) { should be_nil }
@@ -269,6 +293,8 @@
269293

270294
before { create(:consent, :refused, patient:, programme:) }
271295

296+
its(:consent_status) { should be(:refused) }
297+
its(:consent_vaccine_methods) { should be_empty }
272298
its(:date) { should be_nil }
273299
its(:disease_types) { should be_empty }
274300
its(:dose_sequence) { should eq(1) }
@@ -286,6 +312,8 @@
286312
create(:consent, :given, patient:, programme:, parent: create(:parent))
287313
end
288314

315+
its(:consent_status) { should be(:conflicts) }
316+
its(:consent_vaccine_methods) { should be_empty }
289317
its(:date) { should be_nil }
290318
its(:disease_types) { should be_empty }
291319
its(:dose_sequence) { should be(1) }
@@ -298,6 +326,8 @@
298326
context "when consent is needed" do
299327
let(:programme) { Programme.menacwy }
300328

329+
its(:consent_status) { should be(:no_response) }
330+
its(:consent_vaccine_methods) { should be_empty }
301331
its(:date) { should be_nil }
302332
its(:disease_types) { should be_nil }
303333
its(:dose_sequence) { should be_nil }
@@ -316,6 +346,8 @@
316346
context "when not eligible" do
317347
let(:patient) { create(:patient, year_group: 20) }
318348

349+
its(:consent_status) { should be(:no_response) }
350+
its(:consent_vaccine_methods) { should be_empty }
319351
its(:date) { should be_nil }
320352
its(:disease_types) { should be_nil }
321353
its(:dose_sequence) { should be_nil }

spec/models/patient/programme_status_spec.rb

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@
44
#
55
# Table name: patient_programme_statuses
66
#
7-
# id :bigint not null, primary key
8-
# academic_year :integer not null
9-
# date :date
10-
# disease_types :enum is an Array
11-
# dose_sequence :integer
12-
# programme_type :enum not null
13-
# status :integer default("not_eligible"), not null
14-
# vaccine_methods :integer is an Array
15-
# without_gelatine :boolean
16-
# location_id :bigint
17-
# patient_id :bigint not null
7+
# id :bigint not null, primary key
8+
# academic_year :integer not null
9+
# consent_status :integer default("no_response")
10+
# consent_vaccine_methods :integer default([]), is an Array
11+
# date :date
12+
# disease_types :enum is an Array
13+
# dose_sequence :integer
14+
# programme_type :enum not null
15+
# status :integer default("not_eligible"), not null
16+
# vaccine_methods :integer is an Array
17+
# without_gelatine :boolean
18+
# location_id :bigint
19+
# patient_id :bigint not null
1820
#
1921
# Indexes
2022
#
@@ -45,11 +47,13 @@
4547
programme_generator
4648
)
4749
allow(programme_generator).to receive_messages(
50+
consent_status: :given,
51+
consent_vaccine_methods: %w[injection],
4852
date: Date.new(2020, 1, 1),
4953
disease_types: %w[influenza],
5054
dose_sequence: 1,
5155
location_id: 1,
52-
status: "vaccinated",
56+
status: :vaccinated_fully,
5357
vaccine_methods: %w[injection],
5458
without_gelatine: true
5559
)
@@ -58,11 +62,15 @@
5862
it "calls the status generator" do
5963
assign
6064

65+
expect(patient_programme_status.consent_status).to eq("given")
66+
expect(patient_programme_status.consent_vaccine_methods).to eq(
67+
%w[injection]
68+
)
6169
expect(patient_programme_status.date).to eq(Date.new(2020, 1, 1))
6270
expect(patient_programme_status.disease_types).to eq(%w[influenza])
6371
expect(patient_programme_status.dose_sequence).to eq(1)
6472
expect(patient_programme_status.location_id).to eq(1)
65-
expect(patient_programme_status.status).to eq("vaccinated")
73+
expect(patient_programme_status.status).to eq("vaccinated_fully")
6674
expect(patient_programme_status.vaccine_methods).to eq(%w[injection])
6775
expect(patient_programme_status.without_gelatine).to be(true)
6876
end

0 commit comments

Comments
 (0)