Skip to content

Commit 5be6caf

Browse files
Parse the doseNumberString field from the Imms API
The logic for extracting `dose_sequence` is now as follows: 1. Use `doseNumberPositiveInt` 2. Naively cast `doseNumberString` to an `int` 3. Save the value to the `notes` field, so we can analyse them easily in the future, to decide how to best parse them Jira-Issue: MAV-5716
1 parent 3ce9cd2 commit 5be6caf

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
@@ -107,11 +107,15 @@ def self.from_fhir_record(fhir_record, patient:)
107107
attrs[:delivery_site] = site_from_fhir(fhir_record)
108108

109109
dose_sequence = dose_sequence_from_fhir(fhir_record)
110-
max_dose_sequence = attrs[:programme].maximum_dose_sequence
111-
if dose_sequence.present? && dose_sequence > max_dose_sequence
112-
notes << "Reported dose sequence: #{dose_sequence}"
110+
if dose_sequence
111+
if dose_sequence > attrs[:programme].maximum_dose_sequence ||
112+
dose_sequence < 1
113+
notes << "Reported dose number: #{dose_sequence}"
114+
else
115+
attrs[:dose_sequence] = dose_sequence
116+
end
113117
else
114-
attrs[:dose_sequence] = dose_sequence
118+
notes << dose_number_string_note_from_fhir(fhir_record)
115119
end
116120

117121
attrs[:vaccine] = Vaccine.from_fhir_record(fhir_record)
@@ -331,10 +335,21 @@ def fhir_protocol_applied
331335
end
332336

333337
private_class_method def self.dose_sequence_from_fhir(fhir_record)
334-
# TODO: currently we only look at `doseNumberPositiveInt` but often `doseNumberString` is populated instead
335-
# This doesn't matter much for flu, but this may need to be revisited when we start consuming programmes
336-
# where dose number matters more (eg MMR)
337-
fhir_record.protocolApplied.sole.doseNumberPositiveInt
338+
protocol = fhir_record.protocolApplied&.sole
339+
340+
if protocol&.doseNumberPositiveInt.present?
341+
return protocol&.doseNumberPositiveInt
342+
end
343+
344+
Integer(protocol&.doseNumberString, exception: false)
345+
end
346+
347+
private_class_method def self.dose_number_string_note_from_fhir(fhir_record)
348+
dose_string = fhir_record.protocolApplied&.sole&.doseNumberString
349+
350+
return if dose_string.blank?
351+
352+
"Reported dose number string: #{dose_string}"
338353
end
339354
end
340355
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
@@ -783,7 +836,11 @@
783836
its(:performed_ods_code) { should eq "B12345" }
784837
its(:nhs_immunisations_api_primary_source) { should be false }
785838

786-
its(:notes) { should be_nil }
839+
its(:notes) do
840+
should include(
841+
"Reported dose number string: Dose sequence not recorded"
842+
)
843+
end
787844
end
788845

789846
context "with a record that is nasal flu, and is missing dose quantity (from real GP)" do
@@ -980,7 +1037,11 @@
9801037
its(:outcome) { should eq "administered" }
9811038
its(:performed_ods_code) { should eq "B12345" }
9821039

983-
its(:notes) { should be_nil }
1040+
its(:notes) do
1041+
should include(
1042+
"Reported dose number string: Dose sequence not recorded"
1043+
)
1044+
end
9841045
end
9851046
end
9861047

@@ -1070,7 +1131,7 @@
10701131
its(:performed_ods_code) { should eq "R1L" }
10711132
its(:nhs_immunisations_api_primary_source) { should be true }
10721133

1073-
its(:notes) { should be_nil }
1134+
its(:notes) { should include("Reported dose number string: Unknown") }
10741135
end
10751136
end
10761137

@@ -1115,7 +1176,7 @@
11151176
its(:performed_ods_code) { should eq "R1L" }
11161177
its(:nhs_immunisations_api_primary_source) { should be true }
11171178

1118-
its(:notes) { should be_nil }
1179+
its(:notes) { should include("Reported dose number string: Unknown") }
11191180
end
11201181
end
11211182

@@ -1164,7 +1225,7 @@
11641225
its(:performed_ods_code) { should eq "R1L" }
11651226
its(:nhs_immunisations_api_primary_source) { should be true }
11661227

1167-
its(:notes) { should be_nil }
1228+
its(:notes) { should include("Reported dose number string: Unknown") }
11681229
end
11691230
end
11701231

@@ -1213,7 +1274,7 @@
12131274
its(:performed_ods_code) { should eq "R1L" }
12141275
its(:nhs_immunisations_api_primary_source) { should be true }
12151276

1216-
its(:notes) { should be_nil }
1277+
its(:notes) { should include("Reported dose number string: Unknown") }
12171278
end
12181279
end
12191280
end

0 commit comments

Comments
 (0)