Skip to content

Commit 2e21776

Browse files
authored
Generate consent status from submitted at time (#3563)
This changes how we determine the most recent consent response from the `created_at` to the `submitted_at`. In most cases these values will be the same, but it's possible for a consent to be matched with a patient manually which can occur some period of time after the consent was submitted. In particular, it's possible to manually match multiple consents in a different order to when they were submitted, which can lead to bugs where the patient is given the wrong consent status. This has been implemented by storing a `submitted_at` column on consent responses, which has been done to ensure we don't hit performance issues when filtering or ordering consents where we need to fetch the related consent form. This is a version of #3558 which will be merged in to `main` to make sure it's in the 2.2.2 release. [Jira Issue](https://nhsd-jira.digital.nhs.uk/browse/MAV-1196)
2 parents 876ae42 + 77accfc commit 2e21776

14 files changed

Lines changed: 132 additions & 35 deletions

app/components/app_activity_log_component.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def consent_events
9999
{
100100
title:
101101
"Consent #{original_response} by #{consent.name} (#{consent.who_responded})",
102-
at: consent.created_at,
102+
at: consent.submitted_at,
103103
by: consent.recorded_by,
104104
programmes: programmes_for(consent)
105105
}

app/lib/consent_grouper.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ def call
1515
.reject(&:invalidated?)
1616
.select(&:response_provided?)
1717
.group_by(&:name)
18-
.map { it.second.max_by(&:created_at) }
18+
.map { it.second.max_by(&:submitted_at) }
1919
else
2020
consents
2121
.where(programme_id:)
2222
.not_invalidated
2323
.response_provided
2424
.includes(:parent)
2525
.group_by(&:name)
26-
.map { it.second.max_by(&:created_at) }
26+
.map { it.second.max_by(&:submitted_at) }
2727
end
2828
end
2929

app/models/consent.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# reason_for_refusal :integer
1313
# response :integer not null
1414
# route :integer not null
15+
# submitted_at :datetime not null
1516
# withdrawn_at :datetime
1617
# created_at :datetime not null
1718
# updated_at :datetime not null
@@ -121,7 +122,7 @@ def can_invalidate?
121122
end
122123

123124
def responded_at
124-
invalidated_at || withdrawn_at || consent_form&.recorded_at || created_at
125+
invalidated_at || withdrawn_at || submitted_at
125126
end
126127

127128
def triage_needed?
@@ -149,6 +150,8 @@ def reasons_triage_needed
149150
end
150151

151152
def self.from_consent_form!(consent_form, patient:, current_user:)
153+
raise ConsentFormNotRecorded unless consent_form.recorded?
154+
152155
ActiveRecord::Base.transaction do
153156
parent =
154157
consent_form.find_or_create_parent_with_relationship_to!(patient:)
@@ -164,7 +167,8 @@ def self.from_consent_form!(consent_form, patient:, current_user:)
164167
response: "given",
165168
route: "website",
166169
health_answers: consent_form.health_answers,
167-
recorded_by: current_user
170+
recorded_by: current_user,
171+
submitted_at: consent_form.recorded_at
168172
)
169173
end
170174

@@ -180,7 +184,8 @@ def self.from_consent_form!(consent_form, patient:, current_user:)
180184
response: "refused",
181185
route: "website",
182186
health_answers: consent_form.health_answers,
183-
recorded_by: current_user
187+
recorded_by: current_user,
188+
submitted_at: consent_form.recorded_at
184189
)
185190
end
186191

@@ -194,4 +199,7 @@ def notes_required?
194199
withdrawn? || invalidated? ||
195200
(response_refused? && !reason_for_refusal_personal_choice?)
196201
end
202+
203+
class ConsentFormNotRecorded < StandardError
204+
end
197205
end

app/models/consent_form.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,10 @@ def wizard_steps
278278
].compact
279279
end
280280

281+
def recorded?
282+
recorded_at != nil
283+
end
284+
281285
def each_health_answer
282286
return if health_answers.empty?
283287
return to_enum(:each_health_answer) unless block_given?

app/models/draft_consent.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ def write_to!(consent, triage:)
250250
super(consent)
251251

252252
consent.parent = parent
253+
consent.submitted_at ||= Time.current
253254

254255
if triage_allowed? && response_given?
255256
triage.notes = triage_notes || ""
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
class AddSubmittedAtToConsents < ActiveRecord::Migration[8.0]
4+
def up
5+
add_column :consents, :submitted_at, :datetime
6+
7+
Consent
8+
.includes(:consent_form)
9+
.find_each do |consent|
10+
submitted_at = consent.consent_form&.recorded_at || consent.created_at
11+
consent.update_column(:submitted_at, submitted_at)
12+
end
13+
14+
change_column_null :consents, :submitted_at, false
15+
end
16+
17+
def down
18+
remove_column :consents, :submitted_at
19+
end
20+
end

db/schema.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema[8.0].define(version: 2025_04_29_140846) do
13+
ActiveRecord::Schema[8.0].define(version: 2025_05_15_173205) do
1414
# These are extensions that must be enabled in order to support this database
1515
enable_extension "pg_catalog.plpgsql"
1616
enable_extension "pg_trgm"
@@ -237,6 +237,7 @@
237237
t.datetime "withdrawn_at"
238238
t.datetime "invalidated_at"
239239
t.boolean "notify_parents"
240+
t.datetime "submitted_at", null: false
240241
t.index ["organisation_id"], name: "index_consents_on_organisation_id"
241242
t.index ["parent_id"], name: "index_consents_on_parent_id"
242243
t.index ["patient_id"], name: "index_consents_on_patient_id"

spec/components/app_activity_log_component_spec.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
programme: programmes.first,
6464
patient:,
6565
parent: mum,
66-
created_at: Time.zone.parse("2024-05-30 12:00"),
66+
submitted_at: Time.zone.parse("2024-05-30 12:00"),
6767
recorded_by: user
6868
)
6969
create(
@@ -72,7 +72,7 @@
7272
programme: programmes.first,
7373
patient:,
7474
parent: dad,
75-
created_at: Time.zone.parse("2024-05-30 13:00")
75+
submitted_at: Time.zone.parse("2024-05-30 13:00")
7676
)
7777

7878
create(
@@ -251,7 +251,7 @@
251251
:self_consent,
252252
programme: programmes.first,
253253
patient:,
254-
created_at: Time.zone.parse("2024-05-30 12:00")
254+
submitted_at: Time.zone.parse("2024-05-30 12:00")
255255
)
256256
end
257257

@@ -308,7 +308,7 @@
308308
programme: programmes.first,
309309
patient:,
310310
parent: mum,
311-
created_at: Time.zone.local(2024, 5, 30, 12),
311+
submitted_at: Time.zone.local(2024, 5, 30, 12),
312312
withdrawn_at: Time.zone.local(2024, 6, 30, 12)
313313
)
314314
end
@@ -333,7 +333,7 @@
333333
programme: programmes.first,
334334
patient:,
335335
parent: mum,
336-
created_at: Time.zone.local(2024, 5, 30, 12),
336+
submitted_at: Time.zone.local(2024, 5, 30, 12),
337337
invalidated_at: Time.zone.local(2024, 6, 30, 12)
338338
)
339339
end

spec/factories/consents.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# reason_for_refusal :integer
1313
# response :integer not null
1414
# route :integer not null
15+
# submitted_at :datetime not null
1516
# withdrawn_at :datetime
1617
# created_at :datetime not null
1718
# updated_at :datetime not null
@@ -71,6 +72,8 @@
7172
end
7273
end
7374

75+
submitted_at { consent_form&.recorded_at || Time.current }
76+
7477
traits_for_enum :response
7578

7679
trait :given_verbally do

spec/jobs/consent_form_matching_job_spec.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
let(:consent_form) do
88
create(
99
:consent_form,
10+
:recorded,
1011
session:,
1112
given_name: "John",
1213
family_name: "Smith",
@@ -70,6 +71,7 @@
7071
let(:consent_form) do
7172
create(
7273
:consent_form,
74+
:recorded,
7375
session:,
7476
given_name: "john",
7577
family_name: "SMITH",

0 commit comments

Comments
 (0)