Skip to content

Commit 1437f94

Browse files
Fix reporting to only count dose 5 for Td/IPV
The reporting dashboard was counting childhood Td/IPV doses (1-4) as vaccinated, but in StatusGenerator::Vaccination we only consider dose 5 as completing vaccination.
1 parent 6483bba commit 1437f94

4 files changed

Lines changed: 51 additions & 8 deletions

File tree

db/migrate/20251203143325_update_reporting_api_patient_programme_statuses_to_version_8.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ class UpdateReportingAPIPatientProgrammeStatusesToVersion8 < ActiveRecord::Migra
44
8.1
55
]
66
def change
7-
replace_view :reporting_api_patient_programme_statuses,
8-
version: 8,
9-
revert_to_version: 7
7+
update_view :reporting_api_patient_programme_statuses,
8+
version: 8,
9+
revert_to_version: 7,
10+
materialized: true
1011
end
1112
end

db/schema.rb

Lines changed: 5 additions & 5 deletions
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.1].define(version: 2025_12_01_152312) do
13+
ActiveRecord::Schema[8.1].define(version: 2025_12_03_143325) 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"
@@ -1122,7 +1122,7 @@
11221122
FROM ((vaccination_records vr
11231123
JOIN sessions vr_s ON ((vr_s.id = vr.session_id)))
11241124
JOIN team_locations vr_tl ON ((vr_tl.id = vr_s.team_location_id)))
1125-
WHERE (vr.discarded_at IS NULL)
1125+
WHERE ((vr.discarded_at IS NULL) AND ((vr.programme_type <> 'td_ipv'::programme_type) OR (vr.dose_sequence = 5) OR (vr.dose_sequence IS NULL)))
11261126
GROUP BY vr.patient_id, vr.programme_type, vr_tl.team_id, vr_tl.academic_year
11271127
), all_vaccinations_by_year AS (
11281128
SELECT vr.patient_id,
@@ -1134,7 +1134,7 @@
11341134
FROM ((vaccination_records vr
11351135
JOIN sessions vr_s ON ((vr_s.id = vr.session_id)))
11361136
JOIN team_locations vr_tl ON ((vr_tl.id = vr_s.team_location_id)))
1137-
WHERE (vr.discarded_at IS NULL)
1137+
WHERE ((vr.discarded_at IS NULL) AND ((vr.programme_type <> 'td_ipv'::programme_type) OR (vr.dose_sequence = 5) OR (vr.dose_sequence IS NULL)))
11381138
UNION ALL
11391139
SELECT vr.patient_id,
11401140
vr.programme_type,
@@ -1146,7 +1146,7 @@
11461146
vr.outcome,
11471147
vr.source
11481148
FROM vaccination_records vr
1149-
WHERE ((vr.discarded_at IS NULL) AND (vr.source = ANY (ARRAY[1, 2])) AND (vr.session_id IS NULL))
1149+
WHERE ((vr.discarded_at IS NULL) AND (vr.source = ANY (ARRAY[1, 2])) AND (vr.session_id IS NULL) AND ((vr.programme_type <> 'td_ipv'::programme_type) OR (vr.dose_sequence = 5)))
11501150
), base_data AS (
11511151
SELECT concat(p.id, '-', (patient_team_prog.s_programme_type)::text, '-', t.id, '-', tl.academic_year) AS id,
11521152
p.id AS patient_id,
@@ -1243,7 +1243,7 @@
12431243
FROM ((vaccination_records vr
12441244
LEFT JOIN sessions vr_s ON ((vr_s.id = vr.session_id)))
12451245
LEFT JOIN team_locations vr_tl ON ((vr_tl.id = vr_s.team_location_id)))
1246-
WHERE ((vr.discarded_at IS NULL) AND (vr.outcome = 4))) vr_elsewhere_declared ON (((vr_elsewhere_declared.patient_id = p.id) AND (vr_elsewhere_declared.programme_type = patient_team_prog.s_programme_type) AND (vr_elsewhere_declared.academic_year = (tl.academic_year)::numeric))))
1246+
WHERE ((vr.discarded_at IS NULL) AND (vr.outcome = 4) AND ((vr.programme_type <> 'td_ipv'::programme_type) OR (vr.dose_sequence = 5) OR ((vr.dose_sequence IS NULL) AND (vr.session_id IS NOT NULL))))) vr_elsewhere_declared ON (((vr_elsewhere_declared.patient_id = p.id) AND (vr_elsewhere_declared.programme_type = patient_team_prog.s_programme_type) AND (vr_elsewhere_declared.academic_year = (tl.academic_year)::numeric))))
12471247
LEFT JOIN ( SELECT DISTINCT c.patient_id,
12481248
c.programme_type,
12491249
c.academic_year

db/views/reporting_api_patient_programme_statuses_v08.sql

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ WITH vaccination_summary AS (
1313
INNER JOIN sessions vr_s ON vr_s.id = vr.session_id
1414
INNER JOIN team_locations vr_tl ON vr_tl.id = vr_s.team_location_id
1515
WHERE vr.discarded_at IS NULL
16+
-- For Td/IPV, only count dose 5 or unknown dose (recorded in service)
17+
AND (
18+
vr.programme_type != 'td_ipv'
19+
OR vr.dose_sequence = 5
20+
OR vr.dose_sequence IS NULL
21+
)
1622
GROUP BY vr.patient_id, vr.programme_type, vr_tl.team_id, vr_tl.academic_year
1723
),
1824
all_vaccinations_by_year AS (
@@ -27,6 +33,12 @@ all_vaccinations_by_year AS (
2733
INNER JOIN sessions vr_s ON vr_s.id = vr.session_id
2834
INNER JOIN team_locations vr_tl ON vr_tl.id = vr_s.team_location_id
2935
WHERE vr.discarded_at IS NULL
36+
-- For Td/IPV, only count dose 5 or unknown dose (recorded in service)
37+
AND (
38+
vr.programme_type != 'td_ipv'
39+
OR vr.dose_sequence = 5
40+
OR vr.dose_sequence IS NULL
41+
)
3042

3143
UNION ALL
3244

@@ -45,6 +57,11 @@ all_vaccinations_by_year AS (
4557
WHERE vr.discarded_at IS NULL
4658
AND vr.source IN (1, 2)
4759
AND vr.session_id IS NULL
60+
-- For Td/IPV without session, only dose 5 counts (not recorded in service)
61+
AND (
62+
vr.programme_type != 'td_ipv'
63+
OR vr.dose_sequence = 5
64+
)
4865
),
4966
base_data AS (
5067
SELECT
@@ -194,6 +211,12 @@ LEFT JOIN (
194211
LEFT JOIN team_locations vr_tl ON vr_tl.id = vr_s.team_location_id
195212
WHERE vr.discarded_at IS NULL
196213
AND vr.outcome = 4 -- already_had (declared elsewhere)
214+
-- For Td/IPV, only count if dose 5 or unknown dose with session
215+
AND (
216+
vr.programme_type != 'td_ipv'
217+
OR vr.dose_sequence = 5
218+
OR (vr.dose_sequence IS NULL AND vr.session_id IS NOT NULL)
219+
)
197220
) vr_elsewhere_declared ON vr_elsewhere_declared.patient_id = p.id
198221
AND vr_elsewhere_declared.programme_type = s_programme_type
199222
AND vr_elsewhere_declared.academic_year = tl.academic_year

spec/controllers/api/reporting/totals_controller_spec.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,25 @@ def refresh_and_get_totals(programme_type: "hpv")
799799
expect(cohort).to eq(3)
800800
end
801801

802+
it "only counts Td/IPV dose 5 as vaccinated previously" do
803+
patient = create(:patient, session: td_ipv_session, year_group: 9)
804+
create(
805+
:vaccination_record,
806+
patient:,
807+
programme: td_ipv_programme,
808+
session: nil,
809+
source: "nhs_immunisations_api",
810+
nhs_immunisations_api_identifier_system: "test",
811+
nhs_immunisations_api_identifier_value: "123",
812+
dose_sequence: 4,
813+
performed_at: 1.year.ago
814+
)
815+
816+
refresh_and_get_totals(programme_type: "td_ipv")
817+
818+
expect(vaccinated_previously).to eq(0)
819+
end
820+
802821
it "counts year 12 students when session location has year 12 enabled" do
803822
send_location =
804823
create(

0 commit comments

Comments
 (0)