Skip to content

Commit 23f1b17

Browse files
committed
Update empty identifier search bundle url
Also moved some common code that was only used in the api service layer to the relevant place.
1 parent 32bd591 commit 23f1b17

File tree

3 files changed

+60
-69
lines changed

3 files changed

+60
-69
lines changed

lambdas/backend/src/service/fhir_service.py

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import os
55
import urllib.parse
66
import uuid
7-
from typing import Optional, cast
7+
from typing import Any, Optional, cast
88
from uuid import uuid4
99

1010
from fhir.resources.R4B.bundle import (
@@ -36,7 +36,6 @@
3636
from common.models.utils.generic_utils import (
3737
get_contained_patient,
3838
get_occurrence_datetime,
39-
make_search_bundle,
4039
)
4140
from common.models.utils.validation_utils import (
4241
get_vaccine_type,
@@ -103,7 +102,7 @@ def get_immunization_by_identifier(
103102
resource, resource_metadata = self.immunization_repo.get_immunization_by_identifier(identifier)
104103

105104
if not resource:
106-
return make_search_bundle(resource, None, elements, identifier, base_url)
105+
return self.make_empty_identifier_search_bundle(base_url)
107106

108107
vaccination_type = get_vaccine_type(resource)
109108

@@ -113,7 +112,9 @@ def get_immunization_by_identifier(
113112
patient_full_url = f"urn:uuid:{str(uuid4())}"
114113
filtered_resource = Filter.search(resource, patient_full_url)
115114

116-
return make_search_bundle(filtered_resource, resource_metadata.resource_version, elements, identifier, base_url)
115+
return self.make_identifier_search_bundle(
116+
filtered_resource, resource_metadata.resource_version, elements, identifier, base_url
117+
)
117118

118119
def get_immunization_and_version_by_id(self, imms_id: str, supplier_system: str) -> tuple[Immunization, str]:
119120
"""
@@ -336,6 +337,58 @@ def is_valid_date_to(self, immunization: dict, date_to: Optional[datetime.date])
336337

337338
return occurrence_datetime.date() <= date_to
338339

340+
def make_identifier_search_bundle(
341+
self,
342+
resource: Optional[dict],
343+
version_id: Optional[int],
344+
elements: Optional[set[str]],
345+
identifier: Identifier,
346+
base_url: str,
347+
) -> FhirBundle:
348+
searched_url = f"{base_url}?identifier={identifier.system}|{identifier.value}" + (
349+
f"&_elements={','.join(sorted(elements))}" if elements else ""
350+
)
351+
352+
if not resource:
353+
return self.make_empty_identifier_search_bundle(searched_url)
354+
355+
meta = {"versionId": version_id}
356+
357+
# Full Immunization payload to be returned if only the identifier parameter was provided and truncated when
358+
# _elements is used
359+
if elements is not None:
360+
resource_for_bundle: dict[str, Any] = {"resourceType": "Immunization"}
361+
if "id" in elements:
362+
resource_for_bundle["id"] = resource["id"]
363+
if "meta" in elements:
364+
resource_for_bundle["meta"] = meta
365+
366+
else:
367+
resource_for_bundle = copy.deepcopy(resource)
368+
resource_for_bundle["meta"] = meta
369+
370+
entry = BundleEntry.construct(
371+
fullUrl=f"{base_url}/{resource['id']}",
372+
resource=(
373+
Immunization.construct(**resource_for_bundle)
374+
if elements
375+
else Immunization.parse_obj(resource_for_bundle)
376+
),
377+
search=BundleEntrySearch.construct(mode="match") if not elements else None,
378+
)
379+
380+
return FhirBundle(
381+
type="searchset",
382+
link=[BundleLink(relation="self", url=searched_url)],
383+
entry=[entry],
384+
total=1,
385+
)
386+
387+
@staticmethod
388+
def make_empty_identifier_search_bundle(base_url: str) -> FhirBundle:
389+
no_results_url = f"{base_url}?identifier=None"
390+
return FhirBundle(entry=[], link=[BundleLink(relation="self", url=no_results_url)], type="searchset", total=0)
391+
339392
@staticmethod
340393
def process_patient_for_bundle(patient: dict):
341394
"""

lambdas/backend/tests/service/test_fhir_service.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,7 @@ def test_get_immunization_by_identifier_returns_empty_search_when_not_found(self
280280
result.link[0],
281281
BundleLink.construct(
282282
relation="self",
283-
url="https://internal-dev.api.service.nhs.uk/immunisation-fhir-api/FHIR/R4/Immunization?identifier=some-"
284-
"system|some-value",
283+
url="https://internal-dev.api.service.nhs.uk/immunisation-fhir-api/FHIR/R4/Immunization?identifier=None",
285284
),
286285
)
287286
self.assertEqual(result.entry, [])

lambdas/shared/src/common/models/utils/generic_utils.py

Lines changed: 2 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,10 @@
11
"""Generic utilities"""
22

33
import base64
4-
import copy
54
import datetime
65
import urllib.parse
7-
from typing import Any, Literal, Optional
8-
9-
from fhir.resources.R4B.bundle import (
10-
Bundle as FhirBundle,
11-
)
12-
from fhir.resources.R4B.bundle import (
13-
BundleEntry,
14-
BundleEntrySearch,
15-
BundleLink,
16-
)
17-
from fhir.resources.R4B.identifier import Identifier
18-
from fhir.resources.R4B.immunization import Immunization
6+
from typing import Literal, Optional
7+
198
from stdnum.verhoeff import validate
209

2110
from common.models.constants import Constants
@@ -155,56 +144,6 @@ def create_diagnostics_error(value):
155144
return exp_error
156145

157146

158-
def make_empty_search_bundle(searched_url: str) -> FhirBundle:
159-
return FhirBundle(entry=[], link=[BundleLink(relation="self", url=searched_url)], type="searchset", total=0)
160-
161-
162-
# A lot of stuff in here is not very generic. Consider moving to relevant lambdas
163-
def make_search_bundle(
164-
resource: Optional[dict],
165-
version_id: Optional[int],
166-
elements: Optional[set[str]],
167-
identifier: Identifier,
168-
base_url: str,
169-
) -> FhirBundle:
170-
searched_url = f"{base_url}?identifier={identifier.system}|{identifier.value}" + (
171-
f"&_elements={','.join(sorted(elements))}" if elements else ""
172-
)
173-
174-
if not resource:
175-
return make_empty_search_bundle(searched_url)
176-
177-
meta = {"versionId": version_id}
178-
179-
# Full Immunization payload to be returned if only the identifier parameter was provided and truncated when
180-
# _elements is used
181-
if elements is not None:
182-
resource_for_bundle: dict[str, Any] = {"resourceType": "Immunization"}
183-
if "id" in elements:
184-
resource_for_bundle["id"] = resource["id"]
185-
if "meta" in elements:
186-
resource_for_bundle["meta"] = meta
187-
188-
else:
189-
resource_for_bundle = copy.deepcopy(resource)
190-
resource_for_bundle["meta"] = meta
191-
192-
entry = BundleEntry.construct(
193-
fullUrl=f"{base_url}/{resource['id']}",
194-
resource=(
195-
Immunization.construct(**resource_for_bundle) if elements else Immunization.parse_obj(resource_for_bundle)
196-
),
197-
search=BundleEntrySearch.construct(mode="match") if not elements else None,
198-
)
199-
200-
return FhirBundle(
201-
type="searchset",
202-
link=[BundleLink(relation="self", url=searched_url)],
203-
entry=[entry],
204-
total=1,
205-
)
206-
207-
208147
def check_keys_in_sources(event, not_required_keys):
209148
# Decode and parse the body, assuming it is JSON and base64-encoded
210149
def decode_and_parse_body(encoded_body):

0 commit comments

Comments
 (0)