44
55import pydantic
66from botocore .exceptions import ClientError
7+ from enums .document_review_reason import DocumentReviewReason
78from enums .patient_ods_inactive_status import PatientOdsInactiveStatus
89from enums .snomed_codes import SnomedCodes
910from enums .upload_status import UploadStatus
1011from enums .virus_scan_result import VirusScanResult
1112from models .document_reference import DocumentReference
1213from models .sqs .pdf_stitching_sqs_message import PdfStitchingSqsMessage
13- from models .staging_metadata import BulkUploadQueueMetadata , StagingSqsMetadata
14+ from models .staging_metadata import (
15+ NHS_NUMBER_PLACEHOLDER ,
16+ BulkUploadQueueMetadata ,
17+ StagingSqsMetadata ,
18+ )
1419from repositories .bulk_upload .bulk_upload_dynamo_repository import (
1520 BulkUploadDynamoRepository ,
1621)
5257
5358
5459class BulkUploadService :
55- def __init__ (self , strict_mode , bypass_pds = False ):
60+ def __init__ (self , strict_mode , bypass_pds = False , send_to_review_enabled = False ):
5661 self .dynamo_repository = BulkUploadDynamoRepository ()
5762 self .sqs_repository = BulkUploadSqsRepository ()
5863 self .bulk_upload_s3_repository = BulkUploadS3Repository ()
@@ -62,6 +67,7 @@ def __init__(self, strict_mode, bypass_pds=False):
6267 self .file_path_cache = {}
6368 self .pdf_stitching_queue_url = os .environ ["PDF_STITCHING_SQS_URL" ]
6469 self .bypass_pds = bypass_pds
70+ self .send_to_review_enabled = send_to_review_enabled
6571
6672 def process_message_queue (self , records : list ):
6773 for index , message in enumerate (records , start = 1 ):
@@ -74,9 +80,7 @@ def process_message_queue(self, records: list):
7480 logger .info (
7581 "Cannot validate patient due to PDS responded with Too Many Requests"
7682 )
77- logger .info (
78- "Cannot process for now due to PDS rate limit reached."
79- )
83+ logger .info ("Cannot process for now due to PDS rate limit reached." )
8084 logger .info (
8185 "All remaining messages in this batch will be returned to sqs queue to retry later."
8286 )
@@ -132,6 +136,9 @@ def handle_sqs_message(self, message: dict):
132136 for file_metadata in staging_metadata .files :
133137 file_names .append (os .path .basename (file_metadata .stored_file_name ))
134138 file_metadata .scan_date = validate_scan_date (file_metadata .scan_date )
139+ file_metadata .file_path = self .strip_leading_slash (
140+ file_metadata .file_path
141+ )
135142 request_context .patient_nhs_no = staging_metadata .nhs_number
136143 validate_nhs_number (staging_metadata .nhs_number )
137144 pds_patient_details = getting_patient_info_from_pds (
@@ -194,9 +201,19 @@ def handle_sqs_message(self, message: dict):
194201 logger .info ("Will stop processing Lloyd George record for this patient." )
195202
196203 reason = str (error )
204+ uploader_ods = (
205+ staging_metadata .files [0 ].gp_practice_code
206+ if staging_metadata .files
207+ else ""
208+ )
209+
197210 self .dynamo_repository .write_report_upload_to_dynamo (
198211 staging_metadata , UploadStatus .FAILED , reason , patient_ods_code
199212 )
213+ if isinstance (error , (InvalidNhsNumberException , PatientNotFoundException )):
214+ logger .info ("Invalid NHS number detected. Will set as placeholder" )
215+ staging_metadata .nhs_number = NHS_NUMBER_PLACEHOLDER
216+ self .send_to_review_queue_if_enabled (staging_metadata , uploader_ods )
200217 return
201218
202219 logger .info (
@@ -336,8 +353,7 @@ def resolve_source_file_path(self, staging_metadata: StagingSqsMetadata):
336353 if not contains_accent_char (sample_file_path ):
337354 logger .info ("No accented character detected in file path." )
338355 self .file_path_cache = {
339- file .file_path : self .strip_leading_slash (file .file_path )
340- for file in staging_metadata .files
356+ file .file_path : file .file_path for file in staging_metadata .files
341357 }
342358 return
343359
@@ -347,11 +363,8 @@ def resolve_source_file_path(self, staging_metadata: StagingSqsMetadata):
347363 resolved_file_paths = {}
348364 for file in staging_metadata .files :
349365 file_path_in_metadata = file .file_path
350- file_path_without_leading_slash = self .strip_leading_slash (
351- file_path_in_metadata
352- )
353- file_path_in_nfc_form = convert_to_nfc_form (file_path_without_leading_slash )
354- file_path_in_nfd_form = convert_to_nfd_form (file_path_without_leading_slash )
366+ file_path_in_nfc_form = convert_to_nfc_form (file_path_in_metadata )
367+ file_path_in_nfd_form = convert_to_nfd_form (file_path_in_metadata )
355368
356369 if self .bulk_upload_s3_repository .file_exists_on_staging_bucket (
357370 file_path_in_nfc_form
@@ -440,3 +453,29 @@ def strip_leading_slash(filepath: str) -> str:
440453 @staticmethod
441454 def concatenate_acceptance_reason (previous_reasons : str | None , new_reason : str ):
442455 return previous_reasons + ", " + new_reason if previous_reasons else new_reason
456+
457+ def send_to_review_queue_if_enabled (
458+ self ,
459+ staging_metadata : StagingSqsMetadata ,
460+ uploader_ods : str ,
461+ ):
462+ if not self .send_to_review_enabled :
463+ return
464+
465+ review_reason = DocumentReviewReason .UNSUCCESSFUL_UPLOAD
466+
467+ try :
468+ self .sqs_repository .send_message_to_review_queue (
469+ staging_metadata = staging_metadata ,
470+ failure_reason = review_reason ,
471+ uploader_ods = uploader_ods ,
472+ )
473+ logger .info (
474+ f"Sent failed record to review queue with reason: { review_reason } "
475+ )
476+ except Exception as e :
477+ logger .error (
478+ f"Failed to send message to review queue: { e } " ,
479+ {"Result" : "Review queue send failed" },
480+ )
481+ raise e
0 commit comments