From 18f558ffc18d0791dca56901dee48896a7b8d163 Mon Sep 17 00:00:00 2001 From: eesa456 Date: Mon, 3 Jun 2024 12:31:07 +0100 Subject: [PATCH 1/4] NRL-708 initial exception handling --- .../create_document_reference.py | 20 +++++++++++++++---- layer/nrlf/core/dynamodb/model.py | 10 +++++++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/api/producer/createDocumentReference/create_document_reference.py b/api/producer/createDocumentReference/create_document_reference.py index d7d03474e..5aae9ee7f 100644 --- a/api/producer/createDocumentReference/create_document_reference.py +++ b/api/producer/createDocumentReference/create_document_reference.py @@ -1,5 +1,7 @@ from uuid import uuid4 +from core.errors import OperationOutcomeError + from nrlf.core.constants import PERMISSION_AUDIT_DATES_FROM_PAYLOAD from nrlf.core.decorators import request_handler from nrlf.core.dynamodb.repository import DocumentPointer, DocumentPointerRepository @@ -74,10 +76,20 @@ def handler( document_reference=result.resource, nrl_permissions=metadata.nrl_permissions, ) - - core_model = DocumentPointer.from_document_reference( - document_reference, created_on=creation_time - ) + try: + core_model = DocumentPointer.from_document_reference( + document_reference, created_on=creation_time + ) + except OperationOutcomeError as exc: + return SpineErrorResponse.BAD_REQUEST( + diagnostics=exc.diagnostics, + expression="DocumentReference.type.coding", + ) + except Exception as exc: + return SpineErrorResponse.BAD_REQUEST( + diagnostics=f"Parsing of Document Pointer has raised exception with message: '{str(exc)}'.", + expression="DocumentReference", + ) custodian_parts = tuple( filter(None, (core_model.custodian, core_model.custodian_suffix)) diff --git a/layer/nrlf/core/dynamodb/model.py b/layer/nrlf/core/dynamodb/model.py index 9ebb9b731..2afcc7a80 100644 --- a/layer/nrlf/core/dynamodb/model.py +++ b/layer/nrlf/core/dynamodb/model.py @@ -3,6 +3,8 @@ from enum import Enum from typing import Any, Dict, Optional +from core.codes import SpineErrorConcept +from core.errors import OperationOutcomeError from nhs_number import is_valid as is_valid_nhs_number from pydantic import BaseModel, Field, PrivateAttr, root_validator, validator @@ -77,7 +79,13 @@ def from_document_reference( custodian = getattr(custodian_identifier, "value") if len(coding) > 1: - raise ValueError("DocumentReference.type.coding must have exactly one item") + raise OperationOutcomeError( + status_code="400", + severity="error", + code="invalid", + details=SpineErrorConcept.from_code("INVALID_RESOURCE"), + diagnostics="DocumentReference.type.coding must have exactly one item", + ) from None pointer_type = f"{coding[0].system}|{coding[0].code}" From 6a7f3cd91124576dff057a736ee3deddf0d7608a Mon Sep 17 00:00:00 2001 From: eesa456 Date: Wed, 19 Mar 2025 00:09:14 +0000 Subject: [PATCH 2/4] NRL-708 fix asid exception issue --- .../create_document_reference.py | 19 +----- .../tests/test_create_document_reference.py | 65 +++++++++++++++++++ layer/nrlf/core/validators.py | 2 +- 3 files changed, 69 insertions(+), 17 deletions(-) diff --git a/api/producer/createDocumentReference/create_document_reference.py b/api/producer/createDocumentReference/create_document_reference.py index f12b39ff7..0dd415c0d 100644 --- a/api/producer/createDocumentReference/create_document_reference.py +++ b/api/producer/createDocumentReference/create_document_reference.py @@ -1,7 +1,5 @@ from uuid import uuid4 -from core.errors import OperationOutcomeError - from nrlf.core.codes import SpineErrorConcept from nrlf.core.constants import ( PERMISSION_AUDIT_DATES_FROM_PAYLOAD, @@ -54,20 +52,9 @@ def _create_core_model(resource: DocumentReference, metadata: ConnectionMetadata document_reference=resource, nrl_permissions=metadata.nrl_permissions, ) - try: - core_model = DocumentPointer.from_document_reference( - document_reference, created_on=creation_time - ) - except OperationOutcomeError as exc: - return SpineErrorResponse.BAD_REQUEST( - diagnostics=exc.diagnostics, - expression="DocumentReference.type.coding", - ) - except Exception as exc: - return SpineErrorResponse.BAD_REQUEST( - diagnostics=f"Parsing of Document Pointer has raised exception with message: '{str(exc)}'.", - expression="DocumentReference", - ) + return DocumentPointer.from_document_reference( + document_reference, created_on=creation_time + ) def _check_permissions( diff --git a/api/producer/createDocumentReference/tests/test_create_document_reference.py b/api/producer/createDocumentReference/tests/test_create_document_reference.py index f6a6238db..146c91693 100644 --- a/api/producer/createDocumentReference/tests/test_create_document_reference.py +++ b/api/producer/createDocumentReference/tests/test_create_document_reference.py @@ -154,6 +154,71 @@ def test_create_document_reference_happy_path_with_ssp( } +@mock_aws +@mock_repository +@freeze_time("2024-03-21T12:34:56.789") +@freeze_uuid("00000000-0000-0000-0000-000000000001") +def test_create_document_reference_without_related_value_exception( + repository: DocumentPointerRepository, +): + doc_ref = load_document_reference("Y05868-736253002-Valid-with-ssp-content") + doc_ref.context = { + "practiceSetting": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "788002001", + "display": "Adult mental health service", + } + ] + }, + "sourcePatientInfo": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "6700028191", + } + }, + "related": [{"identifier": {"system": "https://fhir.nhs.uk/Id/nhsSpineASID"}}], + } + + event = create_test_api_gateway_event( + headers=create_headers(), + body=doc_ref.model_dump_json(exclude_none=True), + ) + + result = handler(event, create_mock_context()) + body = result.pop("body") + + assert result == { + "statusCode": "400", + "headers": default_response_headers(), + "isBase64Encoded": False, + } + + parsed_body = json.loads(body) + + assert parsed_body == { + "resourceType": "OperationOutcome", + "issue": [ + { + "severity": "error", + "code": "value", + "details": { + "coding": [ + { + "code": "INVALID_IDENTIFIER_VALUE", + "display": "Invalid identifier value", + "system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1", + } + ] + }, + "diagnostics": "Invalid ASID value ''. A single ASID consisting of 12 digits can be provided in the context.related field.", + "expression": ["context.related[0].identifier.value"], + } + ], + } + + def test_create_document_reference_no_body(): event = create_test_api_gateway_event( headers=create_headers(), diff --git a/layer/nrlf/core/validators.py b/layer/nrlf/core/validators.py index 94c086afa..588845797 100644 --- a/layer/nrlf/core/validators.py +++ b/layer/nrlf/core/validators.py @@ -272,7 +272,7 @@ def _validate_asid(self, asid_references: list): return idx, asid_reference = asid_references[0] - asid_value = getattr(asid_reference.identifier, "value", "") + asid_value = getattr(asid_reference.identifier, "value") or "" if not match(r"^\d{12}$", asid_value): self.result.add_error( issue_code="value", From 303804a47c8d3b673edc732de905595eff12067d Mon Sep 17 00:00:00 2001 From: eesa456 Date: Wed, 19 Mar 2025 00:16:27 +0000 Subject: [PATCH 3/4] NRL-708 add space --- .../createDocumentReference/create_document_reference.py | 1 + 1 file changed, 1 insertion(+) diff --git a/api/producer/createDocumentReference/create_document_reference.py b/api/producer/createDocumentReference/create_document_reference.py index 0dd415c0d..020f84d80 100644 --- a/api/producer/createDocumentReference/create_document_reference.py +++ b/api/producer/createDocumentReference/create_document_reference.py @@ -52,6 +52,7 @@ def _create_core_model(resource: DocumentReference, metadata: ConnectionMetadata document_reference=resource, nrl_permissions=metadata.nrl_permissions, ) + return DocumentPointer.from_document_reference( document_reference, created_on=creation_time ) From 291a23d24519b12303fbbe4117e67815fad774c7 Mon Sep 17 00:00:00 2001 From: eesa456 Date: Wed, 19 Mar 2025 00:20:31 +0000 Subject: [PATCH 4/4] NRL-708 use constant for sonarcloud --- .../tests/test_create_document_reference.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/producer/createDocumentReference/tests/test_create_document_reference.py b/api/producer/createDocumentReference/tests/test_create_document_reference.py index 146c91693..a9c85d796 100644 --- a/api/producer/createDocumentReference/tests/test_create_document_reference.py +++ b/api/producer/createDocumentReference/tests/test_create_document_reference.py @@ -10,6 +10,7 @@ _set_create_time_fields, handler, ) +from nrlf.core.constants import SNOMED_SYSTEM_URL from nrlf.core.dynamodb.repository import DocumentPointer, DocumentPointerRepository from nrlf.producer.fhir.r4.model import ( DocumentReferenceRelatesTo, @@ -166,7 +167,7 @@ def test_create_document_reference_without_related_value_exception( "practiceSetting": { "coding": [ { - "system": "http://snomed.info/sct", + "system": SNOMED_SYSTEM_URL, "code": "788002001", "display": "Adult mental health service", }