From 1caa1ad611ed8b5e3f1e585d705893f1491c6a75 Mon Sep 17 00:00:00 2001 From: steph-torres-nhs Date: Fri, 17 Jan 2025 14:30:44 +0000 Subject: [PATCH] [PRMP-1257] Add log messages to adhere to audit requirements (#479) Add log messages to adhere to audit requirements --------- Co-authored-by: robg-nhs --- .../handlers/manage_nrl_pointer_handler.py | 10 ++++++ lambdas/models/nrl_fhir_document_reference.py | 18 ++++++++-- lambdas/models/nrl_sqs_message.py | 16 +++++---- lambdas/services/bulk_upload_service.py | 1 + lambdas/services/nrl_api_service.py | 33 ++++++++++++++++++- .../unit/services/test_nrl_api_service.py | 1 + 6 files changed, 70 insertions(+), 9 deletions(-) diff --git a/lambdas/handlers/manage_nrl_pointer_handler.py b/lambdas/handlers/manage_nrl_pointer_handler.py index cc0c24e27..4b8525113 100644 --- a/lambdas/handlers/manage_nrl_pointer_handler.py +++ b/lambdas/handlers/manage_nrl_pointer_handler.py @@ -1,4 +1,5 @@ import json +from datetime import datetime from enums.nrl_sqs_upload import NrlActionTypes from models.nrl_fhir_document_reference import FhirDocumentReference @@ -58,7 +59,16 @@ def lambda_handler(event, context): .json() ) + logger.info( + f"Create pointer request: Body: {json.loads(document)}, " + f"RequestURL: {nrl_api_service.endpoint}, " + "HTTP Verb: POST, " + f"NHS Number: {nrl_message.nhs_number}, " + f"ODS Code: {nrl_api_service.end_user_ods_code}, " + f"Datetime: {int(datetime.now().timestamp())} " + ) nrl_api_service.create_new_pointer(json.loads(document)) + case NrlActionTypes.DELETE: nrl_api_service.delete_pointer( nrl_message.nhs_number, nrl_message.snomed_code_doc_type diff --git a/lambdas/models/nrl_fhir_document_reference.py b/lambdas/models/nrl_fhir_document_reference.py index 196d03ecf..291744ac5 100644 --- a/lambdas/models/nrl_fhir_document_reference.py +++ b/lambdas/models/nrl_fhir_document_reference.py @@ -66,13 +66,27 @@ def build_fhir_dict(self): "content": [ { "attachment": self.attachment.model_dump( - by_alias=True, exclude_none=True, exclude_defaults=True + by_alias=True, exclude_none=True ), "format": { "system": "https://fhir.nhs.uk/England/CodeSystem/England-NRLFormatCode", "code": "urn:nhs-ic:unstructured", "display": "Unstructured document", }, + "extension": [ + { + "url": "https://fhir.nhs.uk/England/StructureDefinition/Extension-England-ContentStability", + "valueCodeableConcept": { + "coding": [ + { + "system": "https://fhir.nhs.uk/England/CodeSystem/England-NRLContentStability", + "code": "static", + "display": "Static", + } + ] + }, + } + ], } ], "context": { @@ -84,7 +98,7 @@ def build_fhir_dict(self): "display": self.snomed_code_practice_setting.display_name, } ] - } + }, }, } return DocumentReference(**structure_json) diff --git a/lambdas/models/nrl_sqs_message.py b/lambdas/models/nrl_sqs_message.py index aa3b9dbdd..e6cbbd315 100644 --- a/lambdas/models/nrl_sqs_message.py +++ b/lambdas/models/nrl_sqs_message.py @@ -6,13 +6,17 @@ class NrlAttachment(BaseModel): + model_config = ConfigDict( + alias_generator=AliasGenerator(serialization_alias=to_camel), + use_enum_values=True, + ) content_type: str = "application/pdf" language: str = "en-UK" - url: str = "" - size: int = 0 - hash: str = "" - title: str = "" - creation: str = "" + url: Optional[str] = None + size: Optional[int] = None + hash: Optional[str] = None + title: Optional[str] = None + creation: Optional[str] = None class NrlSqsMessage(BaseModel): @@ -27,6 +31,6 @@ class NrlSqsMessage(BaseModel): snomed_code_practice_setting: SnomedCode = ( SnomedCodes.GENERAL_MEDICAL_PRACTICE.value ) - description: str = "" + description: Optional[str] = None attachment: Optional[NrlAttachment] = None action: str diff --git a/lambdas/services/bulk_upload_service.py b/lambdas/services/bulk_upload_service.py index 72cd35499..b4f30a29d 100644 --- a/lambdas/services/bulk_upload_service.py +++ b/lambdas/services/bulk_upload_service.py @@ -281,6 +281,7 @@ def handle_sqs_message(self, message: dict): ) doc_details = NrlAttachment( url=document_api_endpoint, + content_type="application/pdf", ) nrl_sqs_message = NrlSqsMessage( nhs_number=staging_metadata.nhs_number, diff --git a/lambdas/services/nrl_api_service.py b/lambdas/services/nrl_api_service.py index 52f3ed5bb..3fe8b3599 100644 --- a/lambdas/services/nrl_api_service.py +++ b/lambdas/services/nrl_api_service.py @@ -1,5 +1,6 @@ import os import uuid +from datetime import datetime import requests from enums.snomed_codes import SnomedCode @@ -10,6 +11,7 @@ from utils.exceptions import NrlApiException logger = LoggingService(__name__) +NRL_USER_ID = "National-Document-Repository" class NrlApiService: @@ -45,6 +47,11 @@ def create_new_pointer(self, body, retry_on_expired: bool = True): response = self.session.post( url=self.endpoint, headers=self.headers, json=body ) + logger.info( + f"Create pointer response: Status code: {response.status_code}, " + f"Body: {response.json()}, " + f"Headers: {response.headers}" + ) response.raise_for_status() logger.info("Successfully created new pointer") except (ConnectionError, Timeout, HTTPError) as e: @@ -70,6 +77,18 @@ def get_pointer( response = self.session.get( url=self.endpoint, params=params, headers=self.headers ) + logger.info( + f"Get pointer request: URL: {response.url}, " + "HTTP Verb: GET, " + f"ODS Code: {self.end_user_ods_code}, " + f"Datetime: {int(datetime.now().timestamp())}, " + f"UserID: {self.end_user_ods_code} - {NRL_USER_ID}" + ) + logger.info( + f"Get pointer response: Status code: {response.status_code}, " + f"Body: {response.json()}, " + f"Headers: {response.headers}" + ) response.raise_for_status() return response.json() except HTTPError as e: @@ -90,7 +109,19 @@ def delete_pointer(self, nhs_number, record_type: SnomedCode = None): url_endpoint = self.endpoint + f"/{pointer_id}" try: response = self.session.delete(url=url_endpoint, headers=self.headers) - logger.info(response.json()) + logger.info( + f"Delete pointer request: URL: {url_endpoint}, " + f"HTTP Verb: DELETE, " + f"ODS Code: {self.end_user_ods_code}, " + f"NHS Number: {nhs_number}, " + f"Datetime: {int(datetime.now().timestamp())}, " + f"UserID: {self.end_user_ods_code} - {NRL_USER_ID}." + ) + logger.info( + f"Delete pointer response: Body: {response.json()}, " + f"Status Code: {response.status_code}, " + f"Headers: {response.headers}" + ) response.raise_for_status() except HTTPError as e: logger.error(e.response.json()) diff --git a/lambdas/tests/unit/services/test_nrl_api_service.py b/lambdas/tests/unit/services/test_nrl_api_service.py index 0c0241bd4..4cf18d465 100644 --- a/lambdas/tests/unit/services/test_nrl_api_service.py +++ b/lambdas/tests/unit/services/test_nrl_api_service.py @@ -31,6 +31,7 @@ def test_create_new_pointer(nrl_service): def test_create_new_pointer_raise_error(nrl_service): mock_body = {"test": "tests"} response = Response() + response._content = b"{}" response.status_code = 400 nrl_service.session.post.return_value = response pytest.raises(NrlApiException, nrl_service.create_new_pointer, mock_body)