Skip to content

Commit b5ab7ec

Browse files
[PRMP-1078] resolve conflicts, address PR comments
2 parents b2c273d + ce7a52c commit b5ab7ec

File tree

49 files changed

+2225
-231
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2225
-231
lines changed

.github/workflows/base-lambdas-reusable-deploy-all.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,3 +766,17 @@ jobs:
766766
lambda_layer_names: "core_lambda_layer"
767767
secrets:
768768
AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }}
769+
770+
deploy_post_document_review_lambda:
771+
name: Deploy PostDocumentReview lambda
772+
uses: ./.github/workflows/base-lambdas-reusable-deploy.yml
773+
with:
774+
environment: ${{ inputs.environment }}
775+
python_version: ${{ inputs.python_version }}
776+
build_branch: ${{ inputs.build_branch }}
777+
sandbox: ${{ inputs.sandbox }}
778+
lambda_handler_name: post_document_review_handler
779+
lambda_aws_name: PostDocumentReview
780+
lambda_layer_names: "core_lambda_layer"
781+
secrets:
782+
AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }}

lambdas/enums/document_review_status.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,9 @@ class DocumentReviewStatus(StrEnum):
1010
REASSIGNED = "REASSIGNED"
1111
REASSIGNED_PATIENT_UNKNOWN = "REASSIGNED_PATIENT_UNKNOWN"
1212
NEVER_REVIEWED = "NEVER_REVIEWED"
13+
REVIEW_PENDING_UPLOAD = "REVIEW_PENDING_UPLOAD"
14+
VIRUS_SCAN_FAILED = "VIRUS_SCAN_FAILED"
15+
16+
17+
class DocumentReviewReason(StrEnum):
18+
REVIEW_FROM_DATA_CONTROLLER = "Needs review from data controller"

lambdas/enums/lambda_error.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -661,17 +661,17 @@ def create_error_body(self, params: Optional[dict] = None, **kwargs) -> str:
661661
Errors for DocumentReview exceptions
662662
"""
663663
DocumentReviewDB = {
664-
"err_code": "SDR_5001",
664+
"err_code": "UDR_5001",
665665
"message": RETRIEVE_DOCUMENTS,
666666
}
667667

668668
DocumentReviewValidation = {
669-
"err_code": "SDR_5002",
669+
"err_code": "UDR_5002",
670670
"message": "Review document model error",
671671
}
672672

673673
DocumentReviewMissingODS = {
674-
"err_code": "SDR_4011",
674+
"err_code": "UDR_4001",
675675
"message": "Missing ODS code in request context",
676676
}
677677

@@ -680,13 +680,17 @@ def create_error_body(self, params: Optional[dict] = None, **kwargs) -> str:
680680
"message": "Invalid query string passed",
681681
}
682682

683-
DocumentReviewStatusMissingId = {
684-
"err_code": "SDR_4003",
685-
"message": "Missing path parameters"
683+
DocumentReviewUploadInvalidRequest = {
684+
"err_code": "UDR_4003",
685+
"message": "Invalid request",
686686
}
687687

688-
DocumentReviewForbidden = {
689-
"err_code": "SDR_4031",
690-
"message": "User is not permitted to review document"
688+
DocumentReviewUploadForbidden = {
689+
"err_code": "UDR_4031",
690+
"message": "Forbidden"
691691
}
692692

693+
DocumentReviewPresignedFailure = {
694+
"err_code": "UDR_5003",
695+
"message": "Presign creation process failure",
696+
}

lambdas/handlers/document_reference_virus_scan_handler.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from enums.logging_app_interaction import LoggingAppInteraction
2+
from services.staged_document_review_processing_service import (
3+
StagedDocumentReviewProcessingService,
4+
)
25
from services.upload_document_reference_service import UploadDocumentReferenceService
36
from utils.audit_logging_setup import LoggingService
47
from utils.decorators.ensure_env_var import ensure_environment_variables
5-
from utils.decorators.handle_lambda_exceptions import handle_lambda_exceptions
68
from utils.decorators.set_audit_arg import set_request_context_for_logging
79
from utils.lambda_response import ApiGatewayResponse
810
from utils.request_context import request_context
@@ -19,19 +21,26 @@
1921
"LLOYD_GEORGE_BUCKET_NAME",
2022
"PDM_BUCKET_NAME",
2123
"VIRUS_SCAN_STUB",
24+
"DOCUMENT_REVIEW_DYNAMODB_NAME",
25+
"PENDING_REVIEW_BUCKET_NAME"
2226
]
2327
)
24-
@handle_lambda_exceptions
2528
def lambda_handler(event, context):
2629
request_context.app_interaction = LoggingAppInteraction.VIRUS_SCAN.value
2730
upload_document_reference_service = UploadDocumentReferenceService()
31+
review_upload_document_reference_service = StagedDocumentReviewProcessingService()
2832

2933
for s3_object in event.get("Records"):
3034
object_key = s3_object["s3"]["object"]["key"]
3135
object_size = s3_object["s3"]["object"]["size"]
32-
upload_document_reference_service.handle_upload_document_reference_request(
33-
object_key, object_size
34-
)
36+
if object_key.startswith("review/"):
37+
logger.info("Using review document service")
38+
service = review_upload_document_reference_service
39+
else:
40+
logger.info("Using upload document service")
41+
service = upload_document_reference_service
42+
43+
service.handle_upload_document_reference_request(object_key, object_size)
3544

3645
return ApiGatewayResponse(
3746
200, "Virus Scan was successful", "POST"
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import json
2+
3+
from enums.feature_flags import FeatureFlags
4+
from enums.lambda_error import LambdaError
5+
from models.document_review import DocumentReviewUploadEvent
6+
from pydantic import ValidationError
7+
from services.feature_flags_service import FeatureFlagService
8+
from services.post_document_review_service import PostDocumentReviewService
9+
from utils.audit_logging_setup import LoggingService
10+
from utils.decorators.ensure_env_var import ensure_environment_variables
11+
from utils.decorators.handle_lambda_exceptions import handle_lambda_exceptions
12+
from utils.decorators.set_audit_arg import set_request_context_for_logging
13+
from utils.exceptions import InvalidNhsNumberException
14+
from utils.lambda_exceptions import DocumentReviewLambdaException
15+
from utils.lambda_response import ApiGatewayResponse
16+
17+
logger = LoggingService("__name__")
18+
19+
20+
@set_request_context_for_logging
21+
@ensure_environment_variables(
22+
names=[
23+
"STAGING_STORE_BUCKET_NAME",
24+
"PRESIGNED_ASSUME_ROLE",
25+
"EDGE_REFERENCE_TABLE",
26+
"CLOUDFRONT_URL",
27+
]
28+
)
29+
@handle_lambda_exceptions
30+
def lambda_handler(event, context):
31+
feature_flag_service = FeatureFlagService()
32+
feature_flag_service.validate_feature_flag(
33+
FeatureFlags.UPLOAD_DOCUMENT_ITERATION_3_ENABLED
34+
)
35+
36+
try:
37+
validated_event_body = validate_event_body(event["body"])
38+
except KeyError as e:
39+
logger.error(e)
40+
raise DocumentReviewLambdaException(
41+
400, LambdaError.DocumentReviewUploadInvalidRequest
42+
)
43+
44+
post_document_review_service = PostDocumentReviewService()
45+
logger.info(f"Processing event: {event}.")
46+
response = post_document_review_service.process_event(event=validated_event_body)
47+
48+
return ApiGatewayResponse(
49+
status_code=200, body=json.dumps(response), methods="POST"
50+
).create_api_gateway_response()
51+
52+
53+
def validate_event_body(body):
54+
try:
55+
event_body = DocumentReviewUploadEvent.model_validate_json(body)
56+
57+
return event_body
58+
except (ValidationError, InvalidNhsNumberException) as e:
59+
logger.error(e)
60+
raise DocumentReviewLambdaException(
61+
400, LambdaError.DocumentReviewUploadInvalidRequest
62+
)

lambdas/handlers/review_document_status_check_handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from utils.decorators.handle_lambda_exceptions import handle_lambda_exceptions
1212
from utils.decorators.set_audit_arg import set_request_context_for_logging
1313
from utils.exceptions import OdsErrorException
14-
from utils.lambda_exceptions import DocumentReviewException
14+
from utils.lambda_exceptions import DocumentReviewLambdaException
1515
from utils.lambda_handler_utils import validate_review_path_parameters
1616
from utils.lambda_response import ApiGatewayResponse
1717
from utils.ods_utils import extract_ods_code_from_request_context
@@ -68,4 +68,4 @@ def lambda_handler(event, context):
6868

6969
except OdsErrorException:
7070
logger.error("Missing ODS code in request context.")
71-
raise DocumentReviewException(401, LambdaError.DocumentReviewMissingODS)
71+
raise DocumentReviewLambdaException(401, LambdaError.DocumentReviewMissingODS)

lambdas/handlers/search_document_review_handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from utils.decorators.override_error_check import override_error_check
1414
from utils.decorators.set_audit_arg import set_request_context_for_logging
1515
from utils.exceptions import OdsErrorException
16-
from utils.lambda_exceptions import DocumentReviewException
16+
from utils.lambda_exceptions import DocumentReviewLambdaException
1717
from utils.lambda_response import ApiGatewayResponse
1818
from utils.ods_utils import extract_ods_code_from_request_context
1919

@@ -54,7 +54,7 @@ def lambda_handler(event, context):
5454
FeatureFlags.UPLOAD_DOCUMENT_ITERATION_3_ENABLED
5555
]:
5656
logger.info("Feature flag not enabled, event will not be processed")
57-
raise DocumentReviewException(403, LambdaError.FeatureFlagDisabled)
57+
raise DocumentReviewLambdaException(403, LambdaError.FeatureFlagDisabled)
5858

5959
ods_code = extract_ods_code_from_request_context()
6060

lambdas/models/document_review.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import uuid
2+
from datetime import datetime, timezone
23

34
from enums.document_review_status import DocumentReviewStatus
45
from enums.metadata_field_names import DocumentReferenceMetadataFields
56
from enums.snomed_codes import SnomedCodes
6-
from pydantic import BaseModel, ConfigDict, Field, model_validator
7+
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
78
from pydantic.alias_generators import to_camel, to_pascal
89
from utils.exceptions import InvalidNhsNumberException
910
from utils.utilities import validate_nhs_number
@@ -17,7 +18,7 @@ class DocumentReviewFileDetails(BaseModel):
1718
)
1819

1920
file_name: str
20-
file_location: str
21+
file_location: str | None = None
2122
presigned_url: str | None = None
2223

2324

@@ -37,10 +38,12 @@ class DocumentUploadReviewReference(BaseModel):
3738
review_status: DocumentReviewStatus = Field(
3839
default=DocumentReviewStatus.PENDING_REVIEW
3940
)
40-
review_reason: str
41+
review_reason: str | None = None
4142
review_date: int | None = Field(default=None)
4243
reviewer: str | None = Field(default=None)
43-
upload_date: int
44+
upload_date: int = Field(
45+
default_factory=lambda: int(datetime.now(timezone.utc).timestamp()),
46+
)
4447
files: list[DocumentReviewFileDetails] = Field(min_length=1)
4548
nhs_number: str
4649
version: int = Field(default=1)
@@ -126,3 +129,29 @@ def validate_reassign_nhs_number(self):
126129
except InvalidNhsNumberException:
127130
raise ValueError("Invalid NHS number")
128131
return self
132+
133+
134+
class DocumentReviewUploadEvent(BaseModel):
135+
model_config = ConfigDict(
136+
validate_by_alias=True,
137+
populate_by_name=True,
138+
validate_by_name=True,
139+
alias_generator=to_camel,
140+
use_enum_values=True,
141+
extra="forbid",
142+
)
143+
144+
nhs_number: str
145+
snomed_code: SnomedCodes
146+
documents: list = Field(min_length=1, max_length=1)
147+
148+
@field_validator("snomed_code", mode="before")
149+
@classmethod
150+
def check_snomed_code(cls, value) -> SnomedCodes | None:
151+
return SnomedCodes.find_by_code(value)
152+
153+
@field_validator("nhs_number", mode="before")
154+
@classmethod
155+
def verify_nhs_number(cls, value) -> str | None:
156+
if validate_nhs_number(value):
157+
return value

lambdas/repositories/bulk_upload/bulk_upload_s3_repository.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from services.base.s3_service import S3Service
88
from utils.audit_logging_setup import LoggingService
99
from utils.exceptions import (
10-
CorruptedFileException,
1110
DocumentInfectedException,
1211
S3FileNotFoundException,
1312
TagNotFoundException,

lambdas/requirements/layers/requirements_core_lambda_layer.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PyJWT==2.8.0
22
PyYAML==6.0.1
3-
boto3==1.40.71
4-
botocore==1.40.71
3+
boto3==1.42.1
4+
botocore==1.42.1
55
charset-normalizer==3.2.0
66
cryptography==44.0.1
77
idna==3.7

0 commit comments

Comments
 (0)