|
675 | 675 |
|
676 | 676 | perform |
677 | 677 |
|
678 | | - ppis = |
| 678 | + ppvs = |
679 | 679 | PatientProgrammeVaccinationsSearch.find_by( |
680 | 680 | patient:, |
681 | 681 | programme_type: programme.type |
682 | 682 | ) |
683 | | - expect(ppis.last_searched_at).to eq Time.current |
| 683 | + expect(ppvs.last_searched_at).to eq Time.current |
684 | 684 | end |
685 | 685 | end |
686 | 686 | end |
687 | 687 |
|
688 | 688 | shared_examples "does not record the search" do |
689 | 689 | describe "the PatientProgrammeVaccinationsSearch record" do |
690 | 690 | it "is not created or updated" do |
| 691 | + freeze_time |
| 692 | + |
691 | 693 | perform |
692 | 694 |
|
693 | | - expect( |
| 695 | + ppvs = |
694 | 696 | PatientProgrammeVaccinationsSearch.find_by( |
695 | 697 | patient:, |
696 | 698 | programme_type: programme.type |
697 | 699 | ) |
698 | | - ).to be_nil |
| 700 | + expect(ppvs.last_searched_at).not_to eq Time.current |
699 | 701 | end |
700 | 702 | end |
701 | 703 | end |
|
713 | 715 | let(:body) { file_fixture("fhir/search_responses/2_results.json").read } |
714 | 716 | let(:headers) { { "content-type" => "application/fhir+json" } } |
715 | 717 |
|
716 | | - let(:existing_bundle) do |
717 | | - FHIR.from_contents( |
718 | | - file_fixture("fhir/search_responses/0_results.json").read |
719 | | - ) |
720 | | - end |
721 | | - let!(:existing_records) do |
722 | | - fhir_records = |
723 | | - described_class.new.send( |
724 | | - :extract_fhir_vaccination_records, |
725 | | - existing_bundle |
| 718 | + # Simulates a previous job run |
| 719 | + let(:existing_records) do |
| 720 | + first_run_stub = |
| 721 | + stub_request( |
| 722 | + :get, |
| 723 | + "https://sandbox.api.service.nhs.uk/immunisation-fhir-api/FHIR/R4/Immunization" |
| 724 | + ).with(query: expected_query).to_return( |
| 725 | + status: 200, |
| 726 | + body: existing_bundle_body, |
| 727 | + headers: { |
| 728 | + "content-type" => "application/fhir+json" |
| 729 | + } |
726 | 730 | ) |
727 | | - mapped_records = |
728 | | - fhir_records.map do |fhir_record| |
729 | | - mapped = |
730 | | - FHIRMapper::VaccinationRecord.from_fhir_record( |
731 | | - fhir_record, |
732 | | - patient: |
733 | | - ) |
734 | | - mapped.save! |
735 | 731 |
|
736 | | - mapped |
737 | | - end |
| 732 | + described_class.new.perform(patient_id) |
| 733 | + |
| 734 | + WebMock::StubRegistry.instance.remove_request_stub(first_run_stub) |
738 | 735 |
|
739 | | - mapped_records |
| 736 | + patient |
| 737 | + .vaccination_records |
| 738 | + .with_discarded |
| 739 | + .sourced_from_nhs_immunisations_api |
| 740 | + .reload |
| 741 | + .to_a |
| 742 | + end |
| 743 | + |
| 744 | + let(:existing_bundle_body) do |
| 745 | + file_fixture("fhir/search_responses/0_results.json").read |
740 | 746 | end |
741 | 747 |
|
742 | 748 | before do |
|
766 | 772 | end |
767 | 773 |
|
768 | 774 | context "with 1 existing record and 1 new incoming record" do |
769 | | - let(:existing_bundle) do |
770 | | - FHIR.from_contents( |
771 | | - file_fixture("fhir/search_responses/1_result.json").read |
772 | | - ) |
| 775 | + let(:existing_bundle_body) do |
| 776 | + file_fixture("fhir/search_responses/1_result.json").read |
773 | 777 | end |
774 | 778 |
|
| 779 | + before { existing_records } |
| 780 | + |
775 | 781 | it "updates existing records and creates new records not present" do |
776 | 782 | expect { perform }.to change { patient.vaccination_records.count }.by(1) |
777 | 783 | expect(patient.vaccination_records.map(&:id)).to include( |
|
787 | 793 | end |
788 | 794 |
|
789 | 795 | context "with 2 existing records and only 1 incoming (edited) record" do |
790 | | - let(:existing_bundle) do |
791 | | - FHIR.from_contents( |
792 | | - file_fixture("fhir/search_responses/2_results.json").read |
793 | | - ) |
| 796 | + let(:existing_bundle_body) do |
| 797 | + file_fixture("fhir/search_responses/2_results.json").read |
794 | 798 | end |
795 | 799 | let(:body) { file_fixture("fhir/search_responses/1_result.json").read } |
796 | 800 |
|
| 801 | + before { existing_records } |
| 802 | + |
797 | 803 | it "deletes the record that is no longer present, and edits the existing record" do |
798 | 804 | expect { perform }.to change { patient.vaccination_records.count }.by( |
799 | 805 | -1 |
|
812 | 818 | end |
813 | 819 |
|
814 | 820 | context "when re-running after a previous search (patient already has API records in the DB)" do |
| 821 | + before { existing_records } |
| 822 | + |
815 | 823 | context "with the same 2 records returned again" do |
816 | | - let(:existing_bundle) do |
817 | | - FHIR.from_contents( |
818 | | - file_fixture("fhir/search_responses/2_results.json").read |
819 | | - ) |
| 824 | + let(:existing_bundle_body) do |
| 825 | + file_fixture("fhir/search_responses/2_results.json").read |
820 | 826 | end |
821 | 827 |
|
822 | 828 | it "does not create any new records on the second run" do |
|
840 | 846 | # 1_result_old_date.json and 1_result.json |
841 | 847 | # have the same nhs_immunisations_api_id but different occurrenceDateTimes |
842 | 848 | # (2025-08-22 vs 2025-08-23), simulating a record being corrected in the API. |
843 | | - let(:existing_bundle) do |
844 | | - FHIR.from_contents( |
845 | | - file_fixture("fhir/search_responses/1_result_old_date.json").read |
846 | | - ) |
| 849 | + let(:existing_bundle_body) do |
| 850 | + file_fixture("fhir/search_responses/1_result_old_date.json").read |
847 | 851 | end |
848 | 852 | let(:body) { file_fixture("fhir/search_responses/1_result.json").read } |
849 | 853 |
|
|
872 | 876 |
|
873 | 877 | # Seed just the non-Mavis API record that the fixture will return, |
874 | 878 | # as it would have been after the first search run. |
875 | | - let(:existing_bundle) do |
876 | | - FHIR.from_contents( |
877 | | - file_fixture("fhir/search_responses/0_results.json").read |
878 | | - ) |
879 | | - end |
880 | 879 | let!(:existing_api_record) do |
881 | 880 | create( |
882 | 881 | :vaccination_record, |
|
931 | 930 | # The first run created a kept (primary) record and a discarded |
932 | 931 | # (non-primary) record. On re-run with the same response, both should |
933 | 932 | # be updated in-place with no new records created. |
934 | | - let(:existing_bundle) do |
935 | | - FHIR.from_contents( |
936 | | - file_fixture("fhir/search_responses/duplicate.json").read |
937 | | - ) |
| 933 | + let(:existing_bundle_body) do |
| 934 | + file_fixture("fhir/search_responses/duplicate.json").read |
938 | 935 | end |
939 | 936 | let(:body) { file_fixture("fhir/search_responses/duplicate.json").read } |
940 | 937 |
|
|
1198 | 1195 | end |
1199 | 1196 |
|
1200 | 1197 | context "when pre-cutoff records were already imported" do |
1201 | | - let(:existing_bundle) do |
1202 | | - FHIR.from_contents( |
1203 | | - file_fixture("fhir/search_responses/2_results.json").read |
| 1198 | + let(:existing_bundle_body) do |
| 1199 | + file_fixture("fhir/search_responses/2_results.json").read |
| 1200 | + end |
| 1201 | + |
| 1202 | + before do |
| 1203 | + # The first run happened before the cutoff flag was introduced |
| 1204 | + Flipper.disable( |
| 1205 | + :imms_api_ignore_records_prior_to_2025_academic_year |
| 1206 | + ) |
| 1207 | + existing_records |
| 1208 | + Flipper.enable( |
| 1209 | + :imms_api_ignore_records_prior_to_2025_academic_year, |
| 1210 | + Programme.flu |
1204 | 1211 | ) |
1205 | 1212 | end |
1206 | 1213 |
|
|
1255 | 1262 | end |
1256 | 1263 |
|
1257 | 1264 | context "with no NHS number" do |
1258 | | - let(:nhs_number) { nil } |
| 1265 | + let(:existing_bundle_body) do |
| 1266 | + file_fixture("fhir/search_responses/2_results.json").read |
| 1267 | + end |
1259 | 1268 |
|
1260 | | - let(:existing_bundle) do |
1261 | | - FHIR.from_contents( |
1262 | | - file_fixture("fhir/search_responses/2_results.json").read |
1263 | | - ) |
| 1269 | + before do |
| 1270 | + existing_records |
| 1271 | + patient.update!(nhs_number: nil) |
1264 | 1272 | end |
1265 | 1273 |
|
1266 | 1274 | it "deletes all the API records and does not create any new ones" do |
|
0 commit comments