Skip to content

Commit defc1de

Browse files
Merge pull request #6481 from NHSDigital/alistair/imms-api-improve-dose-parsing
Naively parse the `doseNumberString` field from the Imms API
2 parents 6aee05e + 5be6caf commit defc1de

2 files changed

Lines changed: 104 additions & 28 deletions

File tree

app/lib/fhir_mapper/vaccination_record.rb

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,15 @@ def self.from_fhir_record(fhir_record, patient:)
123123
attrs[:delivery_site] = site_from_fhir(fhir_record)
124124

125125
dose_sequence = dose_sequence_from_fhir(fhir_record)
126-
max_dose_sequence = attrs[:programme].maximum_dose_sequence
127-
if dose_sequence.present? && dose_sequence > max_dose_sequence
128-
notes << "Reported dose sequence: #{dose_sequence}"
126+
if dose_sequence
127+
if dose_sequence > attrs[:programme].maximum_dose_sequence ||
128+
dose_sequence < 1
129+
notes << "Reported dose number: #{dose_sequence}"
130+
else
131+
attrs[:dose_sequence] = dose_sequence
132+
end
129133
else
130-
attrs[:dose_sequence] = dose_sequence
134+
notes << dose_number_string_note_from_fhir(fhir_record)
131135
end
132136

133137
attrs[:vaccine] = Vaccine.from_fhir_record(fhir_record)
@@ -351,10 +355,21 @@ def fhir_protocol_applied
351355
end
352356

353357
private_class_method def self.dose_sequence_from_fhir(fhir_record)
354-
# TODO: currently we only look at `doseNumberPositiveInt` but often `doseNumberString` is populated instead
355-
# This doesn't matter much for flu, but this may need to be revisited when we start consuming programmes
356-
# where dose number matters more (eg MMR)
357-
fhir_record.protocolApplied.sole.doseNumberPositiveInt
358+
protocol = fhir_record.protocolApplied&.sole
359+
360+
if protocol&.doseNumberPositiveInt.present?
361+
return protocol&.doseNumberPositiveInt
362+
end
363+
364+
Integer(protocol&.doseNumberString, exception: false)
365+
end
366+
367+
private_class_method def self.dose_number_string_note_from_fhir(fhir_record)
368+
dose_string = fhir_record.protocolApplied&.sole&.doseNumberString
369+
370+
return if dose_string.blank?
371+
372+
"Reported dose number string: #{dose_string}"
358373
end
359374
end
360375
end

spec/lib/fhir_mapper/vaccination_record_spec.rb

Lines changed: 81 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -504,44 +504,97 @@
504504
end
505505
end
506506

507-
describe "the parsed dose_sequence value" do
507+
describe "dose sequence parsing" do
508508
subject { record.dose_sequence }
509509

510510
let(:fixture_file_name) { "fhir/flu/fhir_record_full.json" }
511+
let(:dose_number_positive_int) { nil }
512+
let(:dose_number_string) { nil }
511513

512514
before do
513-
allow(fhir_immunization.protocolApplied.sole).to receive(
514-
:doseNumberPositiveInt
515-
).and_return(dose_number)
515+
allow(fhir_immunization.protocolApplied.sole).to receive_messages(
516+
doseNumberPositiveInt: dose_number_positive_int,
517+
doseNumberString: dose_number_string
518+
)
516519
end
517520

518-
context "when doseNumberPositiveInt is nil" do
519-
let(:dose_number) { nil }
520-
521+
context "when both fields are nil" do
521522
it { should be_nil }
522523

523-
it "does not include a dose sequence note" do
524-
expect(record.notes.to_s).not_to include("Reported dose sequence")
524+
it "does not include any dose notes" do
525+
expect(record.notes.to_s).not_to include("Reported dose number")
526+
expect(record.notes.to_s).not_to include(
527+
"Reported dose number string"
528+
)
525529
end
526530
end
527531

528-
context "when doseNumberPositiveInt is less than the maximum dose sequence for flu" do
529-
let(:dose_number) { 1 }
532+
context "when doseNumberPositiveInt is within the maximum dose sequence for flu" do
533+
let(:dose_number_positive_int) { 1 }
530534

531535
it { should eq 1 }
532536

533537
it "does not include a dose sequence note" do
534-
expect(record.notes.to_s).not_to include("Reported dose sequence")
538+
expect(record.notes.to_s).not_to include("Reported dose number")
535539
end
536540
end
537541

538542
context "when doseNumberPositiveInt exceeds the maximum dose sequence for flu" do
539-
let(:dose_number) { 3 }
543+
let(:dose_number_positive_int) { 3 }
540544

541545
it { should be_nil }
542546

543547
it "records the out-of-range dose sequence in notes" do
544-
expect(record.notes.to_s).to include("Reported dose sequence: 3")
548+
expect(record.notes.to_s).to include("Reported dose number: 3")
549+
end
550+
end
551+
552+
context "when doseNumberPositiveInt is present and doseNumberString is also present" do
553+
let(:dose_number_positive_int) { 2 }
554+
let(:dose_number_string) { "first" }
555+
556+
it { should eq 2 }
557+
558+
it "does not include a dose number string note" do
559+
expect(record.notes.to_s).not_to include(
560+
"Reported dose number string"
561+
)
562+
end
563+
end
564+
565+
context "when doseNumberString is an integer string" do
566+
let(:dose_number_string) { "1" }
567+
568+
it { should eq 1 }
569+
570+
it "does not include a dose number string note" do
571+
expect(record.notes.to_s).not_to include(
572+
"Reported dose number string"
573+
)
574+
end
575+
end
576+
577+
context "when doseNumberString is a non-integer string" do
578+
let(:dose_number_string) { "first" }
579+
580+
it { should be_nil }
581+
582+
it "appends the value to notes" do
583+
expect(record.notes.to_s).to include(
584+
"Reported dose number string: first"
585+
)
586+
end
587+
end
588+
589+
context "when doseNumberString is blank" do
590+
let(:dose_number_string) { "" }
591+
592+
it { should be_nil }
593+
594+
it "does not include a dose number string note" do
595+
expect(record.notes.to_s).not_to include(
596+
"Reported dose number string"
597+
)
545598
end
546599
end
547600
end
@@ -849,7 +902,11 @@
849902
its(:performed_ods_code) { should eq "B12345" }
850903
its(:nhs_immunisations_api_primary_source) { should be false }
851904

852-
its(:notes) { should be_nil }
905+
its(:notes) do
906+
should include(
907+
"Reported dose number string: Dose sequence not recorded"
908+
)
909+
end
853910
end
854911

855912
context "with a record that is nasal flu, and is missing dose quantity (from real GP)" do
@@ -1047,7 +1104,11 @@
10471104
its(:outcome) { should eq "administered" }
10481105
its(:performed_ods_code) { should eq "B12345" }
10491106

1050-
its(:notes) { should be_nil }
1107+
its(:notes) do
1108+
should include(
1109+
"Reported dose number string: Dose sequence not recorded"
1110+
)
1111+
end
10511112
end
10521113
end
10531114

@@ -1137,7 +1198,7 @@
11371198
its(:performed_ods_code) { should eq "R1L" }
11381199
its(:nhs_immunisations_api_primary_source) { should be true }
11391200

1140-
its(:notes) { should be_nil }
1201+
its(:notes) { should include("Reported dose number string: Unknown") }
11411202
end
11421203
end
11431204

@@ -1182,7 +1243,7 @@
11821243
its(:performed_ods_code) { should eq "R1L" }
11831244
its(:nhs_immunisations_api_primary_source) { should be true }
11841245

1185-
its(:notes) { should be_nil }
1246+
its(:notes) { should include("Reported dose number string: Unknown") }
11861247
end
11871248
end
11881249

@@ -1231,7 +1292,7 @@
12311292
its(:performed_ods_code) { should eq "R1L" }
12321293
its(:nhs_immunisations_api_primary_source) { should be true }
12331294

1234-
its(:notes) { should be_nil }
1295+
its(:notes) { should include("Reported dose number string: Unknown") }
12351296
end
12361297
end
12371298

@@ -1280,7 +1341,7 @@
12801341
its(:performed_ods_code) { should eq "R1L" }
12811342
its(:nhs_immunisations_api_primary_source) { should be true }
12821343

1283-
its(:notes) { should be_nil }
1344+
its(:notes) { should include("Reported dose number string: Unknown") }
12841345
end
12851346
end
12861347
end

0 commit comments

Comments
 (0)