Skip to content

Commit 234e31c

Browse files
Merge pull request #6484 from NHSDigital/split-vax-reporting
Split `vaccinations_given` by school and community
2 parents fcebc6d + 62f5be2 commit 234e31c

2 files changed

Lines changed: 152 additions & 35 deletions

File tree

app/controllers/api/reporting/totals_controller.rb

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ class API::Reporting::TotalsController < API::Reporting::BaseController
2525
patient_school_name: "School Name"
2626
}.freeze
2727

28+
SCHOOL_LOCATION_TYPES = %w[gias_school generic_school].freeze
29+
COMMUNITY_LOCATION_TYPES = %w[
30+
generic_clinic
31+
community_clinic
32+
gp_practice
33+
].freeze
34+
2835
METRIC_HEADERS = {
2936
cohort: "Cohort",
3037
no_consent: "No Consent",
@@ -179,7 +186,7 @@ def apply_year_group_filter
179186
def team_vaccination_records_scope
180187
VaccinationRecord
181188
.where(discarded_at: nil, outcome: :administered)
182-
.joins(session: :team_location)
189+
.joins(session: { team_location: :location })
183190
.where(
184191
team_locations: {
185192
team_id: @team&.id || current_user.team_ids,
@@ -205,24 +212,50 @@ def team_vaccination_records_scope
205212
end
206213

207214
def team_vaccinations_given_count
208-
team_vaccination_records_scope.count
215+
pivot_location_counts(
216+
team_vaccination_records_scope.group("locations.type").count
217+
)
209218
end
210219

211220
def team_monthly_vaccinations_given
212-
counts =
213-
team_vaccination_records_scope
214-
.group(
215-
Arel.sql(
216-
"EXTRACT(YEAR FROM vaccination_records.performed_at_date)::integer"
217-
),
218-
Arel.sql(
219-
"EXTRACT(MONTH FROM vaccination_records.performed_at_date)::integer"
220-
)
221-
)
222-
.count
223-
.map do |(year, month), count|
224-
{ year:, month: Date::MONTHNAMES[month], count: }
225-
end
226-
counts.sort_by! { [it[:year], Date::MONTHNAMES.index(it[:month])] }
221+
counts_by_key =
222+
team_vaccination_records_scope.group(
223+
Arel.sql(
224+
"EXTRACT(YEAR FROM vaccination_records.performed_at_date)::integer"
225+
),
226+
Arel.sql(
227+
"EXTRACT(MONTH FROM vaccination_records.performed_at_date)::integer"
228+
),
229+
"locations.type"
230+
).count
231+
232+
grouped = Hash.new { |h, k| h[k] = { school_count: 0, community_count: 0 } }
233+
234+
counts_by_key.each do |(year, month, loc_type), count|
235+
key = [year, month]
236+
if SCHOOL_LOCATION_TYPES.include?(loc_type)
237+
grouped[key][:school_count] += count
238+
elsif COMMUNITY_LOCATION_TYPES.include?(loc_type)
239+
grouped[key][:community_count] += count
240+
end
241+
end
242+
243+
result =
244+
grouped.map do |(year, month), counts|
245+
{ year:, month: Date::MONTHNAMES[month], **counts }
246+
end
247+
result.sort_by! { [it[:year], Date::MONTHNAMES.index(it[:month])] }
248+
end
249+
250+
def pivot_location_counts(counts_by_type)
251+
school_count =
252+
counts_by_type.sum do |type, count|
253+
SCHOOL_LOCATION_TYPES.include?(type) ? count : 0
254+
end
255+
community_count =
256+
counts_by_type.sum do |type, count|
257+
COMMUNITY_LOCATION_TYPES.include?(type) ? count : 0
258+
end
259+
{ school_count:, community_count: }
227260
end
228261
end

spec/controllers/api/reporting/totals_controller_spec.rb

Lines changed: 102 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@
6565
expect(not_vaccinated).to eq(1) # patient3
6666
expect(vaccinated + not_vaccinated).to eq(cohort)
6767

68-
expect(parsed_response["vaccinations_given"]).to eq(2) # 2 administered records
68+
expect(parsed_response["vaccinations_given"]).to eq(
69+
{ "school_count" => 2, "community_count" => 0 }
70+
)
6971
expect(parsed_response["monthly_vaccinations_given"]).to be_an(Array)
7072
end
7173

@@ -510,15 +512,18 @@ def refresh_and_get_totals(programme_type: "hpv")
510512
expect(cohort).to eq(1)
511513
expect(vaccinated).to eq(1)
512514
expect(not_vaccinated).to eq(0)
513-
expect(vaccinations_given).to eq(1)
515+
expect(vaccinations_given).to eq(
516+
{ "school_count" => 1, "community_count" => 0 }
517+
)
514518

515519
monthly =
516520
monthly_vaccinations_given.find do
517521
it["year"] == Time.current.year &&
518522
it["month"] == Date::MONTHNAMES[Time.current.month]
519523
end
520524
expect(monthly).to be_present
521-
expect(monthly["count"]).to eq(1)
525+
expect(monthly["school_count"]).to eq(1)
526+
expect(monthly["community_count"]).to eq(0)
522527
end
523528

524529
it "counts vaccination in correct month when performed during BST" do
@@ -540,7 +545,8 @@ def refresh_and_get_totals(programme_type: "hpv")
540545
end
541546
expect(monthly).to be_present,
542547
"Expected vaccination to be counted in September, not August"
543-
expect(monthly["count"]).to eq(1)
548+
expect(monthly["school_count"]).to eq(1)
549+
expect(monthly["community_count"]).to eq(0)
544550
end
545551

546552
it "child archived after being vaccinated by SAIS" do
@@ -628,7 +634,9 @@ def refresh_and_get_totals(programme_type: "hpv")
628634
expect(cohort).to eq(1)
629635
expect(vaccinated).to eq(1)
630636
expect(not_vaccinated).to eq(0)
631-
expect(vaccinations_given).to eq(0)
637+
expect(vaccinations_given).to eq(
638+
{ "school_count" => 0, "community_count" => 0 }
639+
)
632640
expect(monthly_vaccinations_given).to be_empty
633641
end
634642

@@ -649,7 +657,9 @@ def refresh_and_get_totals(programme_type: "hpv")
649657
expect(cohort).to eq(1)
650658
expect(vaccinated).to eq(1)
651659
expect(not_vaccinated).to eq(0)
652-
expect(vaccinations_given).to eq(0)
660+
expect(vaccinations_given).to eq(
661+
{ "school_count" => 0, "community_count" => 0 }
662+
)
653663
expect(monthly_vaccinations_given).to be_empty
654664
end
655665

@@ -673,7 +683,9 @@ def refresh_and_get_totals(programme_type: "hpv")
673683
expect(vaccinated).to eq(0)
674684
expect(not_vaccinated).to eq(1)
675685

676-
expect(vaccinations_given).to eq(0)
686+
expect(vaccinations_given).to eq(
687+
{ "school_count" => 0, "community_count" => 0 }
688+
)
677689
expect(monthly_vaccinations_given).to be_empty
678690
end
679691

@@ -693,7 +705,9 @@ def refresh_and_get_totals(programme_type: "hpv")
693705
expect(cohort).to eq(1)
694706
expect(vaccinated).to eq(1)
695707
expect(not_vaccinated).to eq(0)
696-
expect(vaccinations_given).to eq(0)
708+
expect(vaccinations_given).to eq(
709+
{ "school_count" => 0, "community_count" => 0 }
710+
)
697711
expect(monthly_vaccinations_given).to be_empty
698712
end
699713

@@ -717,7 +731,9 @@ def refresh_and_get_totals(programme_type: "hpv")
717731
expect(cohort).to eq(1)
718732
expect(vaccinated).to eq(1)
719733
expect(not_vaccinated).to eq(0)
720-
expect(vaccinations_given).to eq(0)
734+
expect(vaccinations_given).to eq(
735+
{ "school_count" => 0, "community_count" => 0 }
736+
)
721737
expect(monthly_vaccinations_given).to be_empty
722738
end
723739

@@ -749,7 +765,9 @@ def refresh_and_get_totals(programme_type: "hpv")
749765
expect(cohort).to eq(1)
750766
expect(vaccinated).to eq(1)
751767
expect(not_vaccinated).to eq(0)
752-
expect(vaccinations_given).to eq(0)
768+
expect(vaccinations_given).to eq(
769+
{ "school_count" => 0, "community_count" => 0 }
770+
)
753771
expect(monthly_vaccinations_given).to be_empty
754772
end
755773

@@ -774,7 +792,9 @@ def refresh_and_get_totals(programme_type: "hpv")
774792
# flu is seasonal so vaccinations from a previous year don't count
775793
expect(vaccinated).to eq(0)
776794
expect(not_vaccinated).to eq(1)
777-
expect(vaccinations_given).to eq(0)
795+
expect(vaccinations_given).to eq(
796+
{ "school_count" => 0, "community_count" => 0 }
797+
)
778798
expect(monthly_vaccinations_given).to be_empty
779799
end
780800

@@ -794,7 +814,9 @@ def refresh_and_get_totals(programme_type: "hpv")
794814
expect(cohort).to eq(1)
795815
expect(vaccinated).to eq(0)
796816
expect(not_vaccinated).to eq(1)
797-
expect(vaccinations_given).to eq(0)
817+
expect(vaccinations_given).to eq(
818+
{ "school_count" => 0, "community_count" => 0 }
819+
)
798820
expect(monthly_vaccinations_given).to be_empty
799821
end
800822

@@ -815,7 +837,9 @@ def refresh_and_get_totals(programme_type: "hpv")
815837
expect(cohort).to eq(1)
816838
expect(vaccinated).to eq(0)
817839
expect(not_vaccinated).to eq(1)
818-
expect(vaccinations_given).to eq(0)
840+
expect(vaccinations_given).to eq(
841+
{ "school_count" => 0, "community_count" => 0 }
842+
)
819843
expect(monthly_vaccinations_given).to be_empty
820844
end
821845

@@ -836,7 +860,9 @@ def refresh_and_get_totals(programme_type: "hpv")
836860
expect(cohort).to eq(1)
837861
expect(vaccinated).to eq(1)
838862
expect(not_vaccinated).to eq(0)
839-
expect(vaccinations_given).to eq(0)
863+
expect(vaccinations_given).to eq(
864+
{ "school_count" => 0, "community_count" => 0 }
865+
)
840866
expect(monthly_vaccinations_given).to be_empty
841867
end
842868

@@ -869,7 +895,9 @@ def refresh_and_get_totals(programme_type: "hpv")
869895
expect(cohort).to eq(1)
870896
expect(vaccinated).to eq(1)
871897
expect(not_vaccinated).to eq(0)
872-
expect(vaccinations_given).to eq(0)
898+
expect(vaccinations_given).to eq(
899+
{ "school_count" => 0, "community_count" => 0 }
900+
)
873901
expect(monthly_vaccinations_given).to be_empty
874902
end
875903

@@ -893,7 +921,9 @@ def refresh_and_get_totals(programme_type: "hpv")
893921
expect(cohort).to eq(1)
894922
expect(vaccinated).to eq(1)
895923
expect(not_vaccinated).to eq(0)
896-
expect(vaccinations_given).to eq(0)
924+
expect(vaccinations_given).to eq(
925+
{ "school_count" => 0, "community_count" => 0 }
926+
)
897927
expect(monthly_vaccinations_given).to be_empty
898928
end
899929

@@ -928,14 +958,68 @@ def refresh_and_get_totals(programme_type: "hpv")
928958

929959
# Child moved out, but vaccination was given by this team
930960
# so it should be counted as given
931-
expect(vaccinations_given).to eq(1)
961+
expect(vaccinations_given).to eq(
962+
{ "school_count" => 1, "community_count" => 0 }
963+
)
964+
monthly =
965+
monthly_vaccinations_given.find do
966+
it["year"] == Time.current.year &&
967+
it["month"] == Date::MONTHNAMES[Time.current.month]
968+
end
969+
expect(monthly).to be_present
970+
expect(monthly["school_count"]).to eq(1)
971+
expect(monthly["community_count"]).to eq(0)
972+
end
973+
974+
it "splits vaccinations given by school and community location" do
975+
school_patient = create(:patient, session: hpv_session)
976+
create(
977+
:vaccination_record,
978+
patient: school_patient,
979+
programme: hpv_programme,
980+
session: hpv_session,
981+
outcome: "administered",
982+
performed_at: Time.current
983+
)
984+
985+
community_clinic =
986+
create(
987+
:community_clinic,
988+
team:,
989+
programmes: [hpv_programme],
990+
academic_year: AcademicYear.current
991+
)
992+
community_session =
993+
create(
994+
:session,
995+
team:,
996+
location: community_clinic,
997+
programmes: [hpv_programme]
998+
)
999+
community_patient = create(:patient, session: community_session)
1000+
create(
1001+
:vaccination_record,
1002+
patient: community_patient,
1003+
programme: hpv_programme,
1004+
session: community_session,
1005+
outcome: "administered",
1006+
performed_at: Time.current
1007+
)
1008+
1009+
refresh_and_get_totals
1010+
1011+
expect(vaccinations_given).to eq(
1012+
{ "school_count" => 1, "community_count" => 1 }
1013+
)
1014+
9321015
monthly =
9331016
monthly_vaccinations_given.find do
9341017
it["year"] == Time.current.year &&
9351018
it["month"] == Date::MONTHNAMES[Time.current.month]
9361019
end
9371020
expect(monthly).to be_present
938-
expect(monthly["count"]).to eq(1)
1021+
expect(monthly["school_count"]).to eq(1)
1022+
expect(monthly["community_count"]).to eq(1)
9391023
end
9401024

9411025
it "counts HPV cohort correctly across years 8 to 11" do

0 commit comments

Comments
 (0)