Skip to content

Commit ab3ae8e

Browse files
committed
Add ability to send clinic invitations in bulk
This adds a new page when viewing unknown or home-schooled patients, allowing users to send clinic invitations to any of those patients who have not yet received one. Jira-Issue: MAV-3886 Jira-Issue: MAV-3428
1 parent bb06f62 commit ab3ae8e

6 files changed

Lines changed: 250 additions & 0 deletions

File tree

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# frozen_string_literal: true
2+
3+
class Schools::InviteToClinicController < Schools::BaseController
4+
before_action :check_can_send_clinic_invitations
5+
before_action :set_back_link_path
6+
before_action :set_programme_statuses
7+
before_action :set_eligible_patients_not_vaccinated
8+
before_action :set_invitations_count_by_programme_type
9+
10+
layout "two_thirds"
11+
12+
def edit
13+
@form = SchoolInviteToClinicForm.new
14+
end
15+
16+
def update
17+
@form =
18+
SchoolInviteToClinicForm.new(
19+
programme_types:
20+
params.dig(:school_invite_to_clinic_form, :programme_types)
21+
)
22+
23+
if @form.valid?
24+
clinic_notifcations =
25+
@eligible_patients_not_vaccinated.filter_map do |patient|
26+
patient.notifier.send_clinic_invitation(
27+
Programme.find_all(@form.programme_types),
28+
team: current_team,
29+
academic_year: @academic_year,
30+
sent_by: current_user,
31+
include_already_invited_programmes: false
32+
)
33+
end
34+
35+
flash[
36+
:success
37+
] = "#{I18n.t("children", count: clinic_notifcations.count)} invited to the clinic"
38+
39+
redirect_to @back_link_path
40+
else
41+
render :edit, status: :unprocessable_entity
42+
end
43+
end
44+
45+
private
46+
47+
def check_can_send_clinic_invitations
48+
render status: :not_found unless @location.generic_clinic?
49+
end
50+
51+
def set_back_link_path
52+
@back_link_path = school_patients_path(Location::URN_UNKNOWN)
53+
end
54+
55+
def set_programme_statuses
56+
@programme_statuses =
57+
Patient::ProgrammeStatus.statuses.keys -
58+
Patient::ProgrammeStatus::NOT_ELIGIBLE_STATUSES.keys -
59+
Patient::ProgrammeStatus::HAS_REFUSAL_STATUSES.keys -
60+
Patient::ProgrammeStatus::VACCINATED_STATUSES.keys
61+
end
62+
63+
def set_eligible_patients_not_vaccinated
64+
@eligible_patients_not_vaccinated =
65+
Patient
66+
.joins(:patient_locations)
67+
.where(
68+
patient_locations: {
69+
location: @location,
70+
academic_year: @academic_year
71+
}
72+
)
73+
.where(school_id: @location.school_id)
74+
.includes_statuses
75+
.has_programme_status(
76+
@programme_statuses,
77+
programme: current_team.programmes,
78+
academic_year: @academic_year
79+
)
80+
end
81+
82+
def set_invitations_count_by_programme_type
83+
@invitations_count_by_programme_type =
84+
current_team.programmes.index_with do |programme|
85+
@eligible_patients_not_vaccinated
86+
.includes(:clinic_notifications)
87+
.has_programme_status(
88+
@programme_statuses,
89+
programme:,
90+
academic_year: @academic_year
91+
)
92+
.count do |patient|
93+
!patient.invited_to_clinic?(
94+
[programme],
95+
team: current_team,
96+
academic_year: @academic_year
97+
)
98+
end
99+
end
100+
end
101+
end
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<% content_for :before_main do %>
2+
<%= govuk_back_link(href: @back_link_path) %>
3+
<% end %>
4+
5+
<%= h1 "Invite parents to book a clinic appointment" do %>
6+
<span class="nhsuk-caption-l"><%= @location.alternative_name %></span>
7+
Invite parents to book a clinic appointment
8+
<% end %>
9+
10+
<% if @invitations_count_by_programme_type.values.all?(&:zero?) %>
11+
<p>You do not need to send any clinic invitations. The parents of any children who were not vaccinated have already received clinic invitations.</p>
12+
13+
<p><%= link_to "Return to school", school_patients_path(Location::URN_UNKNOWN) %></p>
14+
<% else %>
15+
<p><%= I18n.t("children_be", count: @eligible_patients_not_vaccinated.count) %> due a vaccination for at least 1 programme.</p>
16+
17+
<p>You can now send clinic booking invitations to their parents.</p>
18+
19+
<%= form_with model: @form, url: school_invite_to_clinic_path(Location::URN_UNKNOWN), method: :put do |f| %>
20+
<%= f.govuk_check_boxes_fieldset :programme_types, legend: nil do %>
21+
<% current_team.programmes.each do |programme| %>
22+
<% if (count = @invitations_count_by_programme_type[programme]) > 0 %>
23+
<%= f.govuk_check_box :programme_types,
24+
programme.type,
25+
label: { text: programme.name },
26+
hint: { text: "#{I18n.t("children_have", count:)} not been invited to a clinic yet" } %>
27+
<% end %>
28+
<% end %>
29+
<% end %>
30+
31+
<%= f.govuk_submit "Send clinic invitations" %>
32+
<% end %>
33+
<% end %>

app/views/schools/patients/index.html.erb

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

1010
<% if @location.school? %>
1111
<%= govuk_button_link_to "Import class lists", new_school_import_path(@location), secondary: true %>
12+
<% elsif @location.generic_clinic? %>
13+
<%= govuk_button_link_to "Send clinic invitations", edit_school_invite_to_clinic_path(Location::URN_UNKNOWN), secondary: true %>
1214
<% end %>
1315

1416
<div class="nhsuk-grid-row">

config/locales/countables.en.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ en:
33
zero: No children
44
one: 1 child
55
other: "%{count} children"
6+
children_be:
7+
zero: No children are
8+
one: 1 child is
9+
other: "%{count} children are"
10+
children_have:
11+
zero: No children have
12+
one: 1 child has
13+
other: "%{count} children have"
614
children_for_programme:
715
zero: No children for %{programme}
816
one: 1 child for %{programme}

config/routes.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,11 @@
268268
end
269269

270270
resources :schools, only: :index, param: :urn_and_site do
271+
resource :invite_to_clinic,
272+
only: %i[edit update],
273+
path: "invite-to-clinic",
274+
controller: "schools/invite_to_clinic"
275+
271276
resources :import, only: :new, controller: "schools/import"
272277
resources :patients, only: :index, controller: "schools/patients"
273278
resources :sessions, only: :index, controller: "schools/sessions"

spec/features/schools_spec.rb

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,23 @@
2929
then_i_see_the_secondary_sessions
3030
end
3131

32+
scenario "Sending clinic invitations to children in no known school" do
33+
given_a_team_with_no_known_school_children
34+
and_i_am_signed_in
35+
36+
when_i_visit_the_schools_page
37+
and_i_click_on_no_known_school
38+
then_i_see_the_send_invitations_button
39+
40+
when_i_click_send_clinic_invitations
41+
and_i_select_programmes_and_send
42+
then_i_see_the_invitation_confirmation
43+
and_the_parents_receive_invitations
44+
45+
when_i_click_send_clinic_invitations
46+
then_i_see_no_invitations_need_to_be_sent
47+
end
48+
3249
def given_a_team_exists_with_a_few_schools
3350
programmes = [Programme.flu, Programme.hpv]
3451

@@ -134,4 +151,88 @@ def when_i_click_on_edit_session
134151
def and_i_click_on_back
135152
click_on "Back"
136153
end
154+
155+
def given_a_team_with_no_known_school_children
156+
programmes = [Programme.hpv]
157+
@team = create(:team, :with_generic_clinic, programmes:)
158+
@generic_clinic = @team.generic_clinic
159+
160+
@patients =
161+
10.times.map do
162+
create(
163+
:patient,
164+
:consent_no_response,
165+
school: nil,
166+
parents: [build(:parent)],
167+
programmes:,
168+
location: @generic_clinic,
169+
academic_year: AcademicYear.pending
170+
)
171+
end
172+
173+
# We create these to ensure these children aren't invited.
174+
create(
175+
:patient,
176+
:consent_refused,
177+
school: nil,
178+
parents: [build(:parent)],
179+
programmes:,
180+
location: @generic_clinic,
181+
academic_year: AcademicYear.pending
182+
)
183+
create(
184+
:patient,
185+
:consent_conflicting,
186+
school: nil,
187+
parents: [build(:parent)],
188+
programmes:,
189+
location: @generic_clinic,
190+
academic_year: AcademicYear.pending
191+
)
192+
193+
@nurse = create(:nurse, team: @team)
194+
end
195+
196+
def when_i_visit_the_schools_page
197+
visit schools_path
198+
end
199+
200+
def and_i_click_on_no_known_school
201+
click_on "No known school"
202+
end
203+
204+
def then_i_see_the_send_invitations_button
205+
expect(page).to have_content("Send clinic invitations")
206+
end
207+
208+
def when_i_click_send_clinic_invitations
209+
click_on "Send clinic invitations"
210+
end
211+
212+
def and_i_select_programmes_and_send
213+
check "HPV"
214+
click_on "Send clinic invitations"
215+
end
216+
217+
def then_i_see_the_invitation_confirmation
218+
expect(page).to have_content("10 children invited to the clinic")
219+
end
220+
221+
def and_the_parents_receive_invitations
222+
perform_enqueued_jobs
223+
224+
expect(email_deliveries.count).to eq(@patients.count)
225+
226+
@patients.each do |patient|
227+
patient.parents.each do |parent|
228+
expect_email_to parent.email, :clinic_initial_invitation, :any
229+
end
230+
end
231+
end
232+
233+
def then_i_see_no_invitations_need_to_be_sent
234+
expect(page).to have_content(
235+
"You do not need to send any clinic invitations."
236+
)
237+
end
137238
end

0 commit comments

Comments
 (0)