From 2308e7b27f5bbb702713a249aa6245421c16d573 Mon Sep 17 00:00:00 2001 From: Jack Wainwright <79214177+nhsd-jack-wainwright@users.noreply.github.com> Date: Thu, 16 Apr 2026 15:15:25 +0000 Subject: [PATCH] [CDAPI-150]: Added validation ensuring an empty string cannot be provided as a subject identifier or ODS code --- pathology-api/src/pathology_api/handler.py | 4 +- .../src/pathology_api/test_handler.py | 41 ++++++++++++++++++- .../tests/integration/test_endpoints.py | 36 ++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/pathology-api/src/pathology_api/handler.py b/pathology-api/src/pathology_api/handler.py index 1ed5062..83a9bac 100644 --- a/pathology-api/src/pathology_api/handler.py +++ b/pathology-api/src/pathology_api/handler.py @@ -103,7 +103,7 @@ def _fetch_requesting_organisation( organisation_identifiers = [ identifier for identifier in requesting_organisation.identifier - if isinstance(identifier, OrganizationIdentifier) + if isinstance(identifier, OrganizationIdentifier) and identifier.value ] if not organisation_identifiers: @@ -141,7 +141,7 @@ def handle_request(bundle: Bundle) -> PdmResponse: _logger.debug("Requesting organization: %s", requesting_organisation) subject = composition.subject - if subject is None: + if subject is None or not subject.identifier.value: raise ValidationError("Composition does not define a valid subject identifier") pdm_response = post_document(bundle) diff --git a/pathology-api/src/pathology_api/test_handler.py b/pathology-api/src/pathology_api/test_handler.py index 71233cf..d43ae86 100644 --- a/pathology-api/src/pathology_api/test_handler.py +++ b/pathology-api/src/pathology_api/test_handler.py @@ -263,10 +263,49 @@ def test_handle_request( bundle_id=result_bundle.id, ) + def test_handle_request_with_empty_subject( + self, build_valid_test_result: Callable[[str, str], Bundle] + ) -> None: + bundle = build_valid_test_result("", "ods_code") + + with pytest.raises( + ValidationError, + match="Composition does not define a valid subject identifier", + ): + handle_request(bundle) + + def test_handle_request_with_empty_ods_code( + self, build_valid_test_result: Callable[[str, str], Bundle] + ) -> None: + bundle = build_valid_test_result("nhs_number_1", "") + + if ( + created_practitioner_role := bundle.get_resource( + url="practitioner_role", t=PractitionerRole + ) + ) is None: + raise ValueError( + "Test setup error: PractitionerRole resource not found in bundle" + ) + + if ( + expected_organisation_reference := created_practitioner_role.organization + ) is None: + raise ValueError( + "Test setup error: PractitionerRole resource does not define an " + "organization reference" + ) + + with pytest.raises( + ValidationError, + match=rf"Organization \({expected_organisation_reference.reference}\) does " + "not define a supported identifier. Supported system 'https://fhir.nhs.uk/Id/ods-organization-code'", + ): + handle_request(bundle) + def test_handle_request_raises_error_when_create_event_fails( self, build_valid_test_result: Callable[[str, str], Bundle] ) -> None: - # Arrange bundle = build_valid_test_result("nhs_number_1", "ods_code") expected_error_message = "Failed to create bundle" diff --git a/pathology-api/tests/integration/test_endpoints.py b/pathology-api/tests/integration/test_endpoints.py index 6614179..bf51e95 100644 --- a/pathology-api/tests/integration/test_endpoints.py +++ b/pathology-api/tests/integration/test_endpoints.py @@ -380,6 +380,27 @@ def test_invalid_payload_returns_error( "Composition does not define a valid subject identifier", id="composition with no subject", ), + pytest.param( + lambda service_request_reference: { + "resourceType": "Composition", + "extension": [ + { + "url": "http://hl7.eu/fhir/StructureDefinition/composition-basedOn-order-or-requisition", + "valueReference": { + "reference": service_request_reference, + }, + } + ], + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "", + } + }, + }, + "Composition does not define a valid subject identifier", + id="composition with subject with empty identifier value", + ), pytest.param( lambda _: { "resourceType": "Composition", @@ -819,6 +840,21 @@ def test_invalid_practitioner_role_resource( "Supported system 'https://fhir.nhs.uk/Id/ods-organization-code'", id="organization with unknown identifier system", ), + pytest.param( + { + "resourceType": "Organization", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "", + } + ], + }, + "Organization (organization) does not define a " + "supported identifier. " + r"Supported system 'https://fhir.nhs.uk/Id/ods-organization-code'", + id="organization with identifier with empty value", + ), ], ) def test_invalid_organization_resource(