Skip to content

Commit c0aeca5

Browse files
authored
Merge pull request #6187 from NHSDigital/add-consent-to-notifier-patient
Add consent notifications to `Notifier::Patient`
2 parents 06a08e6 + 405fbcf commit c0aeca5

11 files changed

Lines changed: 864 additions & 900 deletions

app/controllers/patient_sessions/consents_controller.rb

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,10 @@ def send_request
3838
.values
3939
.find { it.include?(@programme) }
4040

41-
ConsentNotification.create_and_send!(
42-
patient: @patient,
43-
programmes:,
41+
@patient.notifier.send_consent_request(
42+
programmes,
4443
session: @session,
45-
type: :request,
46-
current_user:
44+
sent_by: current_user
4745
)
4846

4947
redirect_to session_patient_programme_path(@session, @patient, @programme),

app/jobs/concerns/send_school_consent_notification_concern.rb

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,4 @@ def get_programmes_that_need_consent(patient:, session:, programmes:)
3434
patient.programme_status(programme, academic_year:).needs_consent?
3535
end
3636
end
37-
38-
def reminder_notification_type(patient:, programmes:)
39-
sent_initial_reminder =
40-
programmes.all? do |programme|
41-
patient
42-
.consent_notifications
43-
.select { it.programmes.include?(programme) }
44-
.any?(&:initial_reminder?)
45-
end
46-
47-
sent_initial_reminder ? :subsequent_reminder : :initial_reminder
48-
end
4937
end

app/jobs/send_automatic_school_consent_reminders_job.rb

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,7 @@ def perform(session)
99
) do |patient, programmes|
1010
next unless should_send_notification?(patient:, session:, programmes:)
1111

12-
ConsentNotification.create_and_send!(
13-
patient:,
14-
session:,
15-
programmes:,
16-
type: notification_type(patient:, programmes:),
17-
current_user: nil
18-
)
12+
patient.notifier.send_consent_reminder(programmes, session:, sent_by: nil)
1913
end
2014
end
2115

@@ -74,10 +68,6 @@ def earliest_date_to_send_reminder(
7468
scheduled_automatic_reminder_dates[date_index_to_send_reminder_for]
7569
end
7670

77-
def notification_type(patient:, programmes:)
78-
reminder_notification_type(patient:, programmes:)
79-
end
80-
8171
def already_sent_automatic_consent_reminders_count(patient:, programme:)
8272
patient.consent_notifications.count do
8373
it.automated_reminder? && it.programmes.include?(programme)

app/jobs/send_manual_school_consent_reminders_job.rb

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,11 @@ def perform(session, current_user:)
77
patient_programmes_eligible_for_notification(
88
session:
99
) do |patient, programmes|
10-
ConsentNotification.create_and_send!(
11-
patient:,
10+
patient.notifier.send_consent_reminder(
11+
programmes,
1212
session:,
13-
programmes:,
14-
type: notification_type(patient:, programmes:),
15-
current_user:
13+
sent_by: current_user
1614
)
1715
end
1816
end
19-
20-
def notification_type(patient:, programmes:)
21-
reminder_notification_type(patient:, programmes:)
22-
end
2317
end

app/jobs/send_school_consent_requests_job.rb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,7 @@ class SendSchoolConsentRequestsJob < ApplicationJob
55

66
def perform(session)
77
patients_and_programmes(session) do |patient, programmes|
8-
ConsentNotification.create_and_send!(
9-
patient:,
10-
session:,
11-
programmes:,
12-
type: :request,
13-
current_user: nil
14-
)
8+
patient.notifier.send_consent_request(programmes, session:, sent_by: nil)
159
end
1610
end
1711

app/lib/notifier/patient.rb

Lines changed: 145 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,32 @@ def initialize(patient)
77
@patient = patient
88
end
99

10+
##
11+
# Send a consent request email and SMS to the parents of this patient.
12+
def send_consent_request(programmes, session:, sent_by:)
13+
send_consent_notification(programmes, type: :request, session:, sent_by:)
14+
end
15+
16+
##
17+
# Send a consent reminder email and SMS to the parents of this patient.
18+
#
19+
# This determines whether to send the initial reminder or subsequent
20+
# reminder based on what has already been sent to this patient.
21+
def send_consent_reminder(programmes, session:, sent_by:)
22+
already_sent_initial_reminder =
23+
programmes.all? do |programme|
24+
patient
25+
.consent_notifications
26+
.select { it.programmes.include?(programme) }
27+
.any?(&:initial_reminder?)
28+
end
29+
30+
type =
31+
already_sent_initial_reminder ? :subsequent_reminder : :initial_reminder
32+
33+
send_consent_notification(programmes, type:, session:, sent_by:)
34+
end
35+
1036
##
1137
# Send a clinic initiation email and SMS to the parents of this patient.
1238
#
@@ -31,7 +57,7 @@ def send_clinic_invitation(
3157
return unless send_notification?(team:)
3258

3359
programme_types =
34-
programme_types_to_send_for(
60+
programme_types_to_send_clinic_invitation_for(
3561
programmes,
3662
team:,
3763
academic_year:,
@@ -43,10 +69,6 @@ def send_clinic_invitation(
4369

4470
type = clinic_invitation_type(programme_types, team:, academic_year:)
4571

46-
# We create a record in the database first to avoid sending duplicate emails/texts.
47-
# If a problem occurs while the emails/texts are sent, they will be in the job
48-
# queue and restarted at a later date.
49-
5072
ClinicNotification.create!(
5173
patient:,
5274
programme_types:,
@@ -57,7 +79,7 @@ def send_clinic_invitation(
5779
sent_by:
5880
)
5981

60-
template_name = find_template_name(type, team:)
82+
template_name = find_clinic_template_name(type, team:)
6183

6284
params = { academic_year:, patient:, programme_types:, sent_by:, team: }
6385

@@ -72,15 +94,128 @@ def send_clinic_invitation(
7294
attr_reader :patient
7395

7496
def send_notification?(team:)
75-
patient.send_notifications?(team:, send_to_archived: true) &&
76-
parents.present?
97+
patient.send_notifications?(team:) && parents.present?
7798
end
7899

79100
def parents
80101
@parents ||= patient.parents.select(&:contactable?).uniq
81102
end
82103

83-
def programme_types_to_send_for(
104+
def send_consent_notification(programmes, type:, session:, sent_by:)
105+
return unless send_notification?(team: session.team)
106+
107+
ConsentNotification.create!(
108+
programmes:,
109+
patient:,
110+
session:,
111+
type:,
112+
sent_at: Time.current,
113+
sent_by:
114+
)
115+
116+
email_template, sms_template =
117+
generate_consent_templates(programmes:, patient:, session:, type:)
118+
119+
programme_types = programmes.map(&:type)
120+
disease_types = programmes.flat_map(&:disease_types).presence
121+
122+
parents.each do |parent|
123+
EmailDeliveryJob.perform_later(
124+
email_template,
125+
disease_types:,
126+
parent:,
127+
patient:,
128+
programme_types:,
129+
session:,
130+
sent_by:
131+
)
132+
133+
SMSDeliveryJob.perform_later(
134+
sms_template,
135+
disease_types:,
136+
parent:,
137+
patient:,
138+
programme_types:,
139+
session:,
140+
sent_by:
141+
)
142+
end
143+
end
144+
145+
def generate_consent_templates(programmes:, patient:, session:, type:)
146+
is_school = session.location.school?
147+
base_template = :"consent_#{is_school ? "school" : "clinic"}_#{type}"
148+
149+
# We can only handle a single programme group or variant in the template.
150+
group = ProgrammeGrouper.call(programmes).keys.sole
151+
variant =
152+
if programmes.count == 1
153+
programmes.sole.variant_for(patient:).variant_type
154+
end
155+
156+
email_template =
157+
if is_school
158+
template =
159+
resolve_consent_template(
160+
base_template:,
161+
group:,
162+
variant:,
163+
session:,
164+
channel: :email
165+
)
166+
if template.blank?
167+
raise(
168+
"Missing email template for consent notification: #{base_template} " \
169+
"with group=#{group.inspect} variant=#{variant.inspect} " \
170+
"outbreak=#{is_outbreak.inspect}"
171+
)
172+
end
173+
template
174+
else
175+
base_template
176+
end
177+
178+
sms_template =
179+
if type == :request
180+
template =
181+
resolve_consent_template(
182+
base_template:,
183+
group:,
184+
variant:,
185+
session:,
186+
channel: :sms
187+
)
188+
template || base_template
189+
elsif is_school
190+
:consent_school_reminder
191+
end
192+
193+
[email_template, sms_template]
194+
end
195+
196+
def resolve_consent_template(
197+
base_template:,
198+
group:,
199+
variant:,
200+
session:,
201+
channel:
202+
)
203+
renderer = NotifyTemplateRenderer.for(channel)
204+
is_outbreak = session.outbreak
205+
206+
combinations = [([group, :outbreak] if is_outbreak), [group]]
207+
if variant.present? && variant != group
208+
combinations.prepend(([variant, :outbreak] if is_outbreak), [variant])
209+
end
210+
combinations.compact!
211+
212+
combinations
213+
.lazy
214+
.map { |parts| :"#{base_template}_#{parts.join("_")}" }
215+
.detect { renderer.template_exists?(it, source: :any) }
216+
end
217+
218+
def programme_types_to_send_clinic_invitation_for(
84219
programmes,
85220
team:,
86221
academic_year:,
@@ -129,7 +264,7 @@ def clinic_invitation_type(programme_types, team:, academic_year:)
129264
end
130265
end
131266

132-
def find_template_name(type, team:)
267+
def find_clinic_template_name(type, team:)
133268
template_names = [
134269
:"clinic_#{type}_#{team.organisation.ods_code.downcase}",
135270
:"clinic_#{type}"

0 commit comments

Comments
 (0)