Skip to content

Commit 38cc61d

Browse files
authored
Merge branch 'master' into dependabot/pip/backend/pip-minor-patch-af7325f94c
2 parents 57a27d9 + e3807bd commit 38cc61d

File tree

59 files changed

+583
-542
lines changed

Some content is hidden

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

59 files changed

+583
-542
lines changed

backend/src/authorisation/authoriser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def _expand_permissions(
1818
permissions: list[str],
1919
) -> dict[str, list[ApiOperationCode]]:
2020
"""Parses and expands permissions data into a dictionary mapping vaccination types to a list of permitted
21-
API operations. The raw string from Redis will be in the form VAC.PERMS e.g. COVID19.CRUDS
21+
API operations. The raw string from Redis will be in the form VAC.PERMS e.g. COVID.CRUDS
2222
"""
2323
expanded_permissions = {}
2424

backend/src/controller/fhir_controller.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
from models.utils.generic_utils import check_keys_in_sources
3333
from parameter_parser import create_query_string, process_params, process_search_params
3434
from repository.fhir_repository import ImmunizationRepository, create_table
35-
from service.fhir_service import FhirService, UpdateOutcome, get_service_url
35+
from service.fhir_service import FhirService, get_service_url
3636

3737
IMMUNIZATION_ENV = os.getenv("IMMUNIZATION_ENV")
3838

@@ -297,7 +297,7 @@ def update_immunization(self, aws_event):
297297
diagnostics=resource["diagnostics"],
298298
)
299299
return create_response(400, json.dumps(exp_error))
300-
if outcome == UpdateOutcome.UPDATE:
300+
if outcome:
301301
return create_response(
302302
200, None, {"E-Tag": updated_version}
303303
) # include e-tag here, is it not included in the response resource

backend/src/models/failures.py

Lines changed: 0 additions & 7 deletions
This file was deleted.

backend/src/service/fhir_service.py

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import logging
33
import os
44
import uuid
5-
from enum import Enum
65
from typing import Optional, Union, cast
76
from uuid import uuid4
87

@@ -70,11 +69,6 @@ def get_service_url(
7069
return f"https://{subdomain}api.service.nhs.uk/{service_base_path}"
7170

7271

73-
class UpdateOutcome(Enum):
74-
UPDATE = 0
75-
CREATE = 1
76-
77-
7872
class FhirService:
7973
def __init__(
8074
self,
@@ -168,13 +162,13 @@ def update_immunization(
168162
existing_resource_version: int,
169163
existing_resource_vacc_type: str,
170164
supplier_system: str,
171-
) -> tuple[Optional[UpdateOutcome], Immunization | dict, Optional[int]]:
165+
) -> tuple[bool, Immunization | dict, Optional[int]]:
172166
# VED-747 - TODO - this and the below 2 methods are duplicated. We should streamline the update journey
173167
immunization["id"] = imms_id
174168

175169
patient = self._validate_patient(immunization)
176170
if "diagnostics" in patient:
177-
return None, patient, None
171+
return False, patient, None
178172

179173
vaccination_type = get_vaccine_type(immunization)
180174

@@ -191,7 +185,7 @@ def update_immunization(
191185
imms_id, immunization, patient, existing_resource_version, supplier_system
192186
)
193187

194-
return UpdateOutcome.UPDATE, Immunization.parse_obj(imms), updated_version
188+
return True, Immunization.parse_obj(imms), updated_version
195189

196190
def reinstate_immunization(
197191
self,
@@ -200,11 +194,11 @@ def reinstate_immunization(
200194
existing_resource_version: int,
201195
existing_resource_vacc_type: str,
202196
supplier_system: str,
203-
) -> tuple[Optional[UpdateOutcome], Immunization | dict, Optional[int]]:
197+
) -> tuple[bool, Immunization | dict, Optional[int]]:
204198
immunization["id"] = imms_id
205199
patient = self._validate_patient(immunization)
206200
if "diagnostics" in patient:
207-
return None, patient, None
201+
return False, patient, None
208202

209203
vaccination_type = get_vaccine_type(immunization)
210204

@@ -219,7 +213,7 @@ def reinstate_immunization(
219213
imms_id, immunization, patient, existing_resource_version, supplier_system
220214
)
221215

222-
return UpdateOutcome.UPDATE, Immunization.parse_obj(imms), updated_version
216+
return True, Immunization.parse_obj(imms), updated_version
223217

224218
def update_reinstated_immunization(
225219
self,
@@ -228,11 +222,11 @@ def update_reinstated_immunization(
228222
existing_resource_version: int,
229223
existing_resource_vacc_type: str,
230224
supplier_system: str,
231-
) -> tuple[Optional[UpdateOutcome], Immunization | dict, Optional[int]]:
225+
) -> tuple[bool, Immunization | dict, Optional[int]]:
232226
immunization["id"] = imms_id
233227
patient = self._validate_patient(immunization)
234228
if "diagnostics" in patient:
235-
return None, patient, None
229+
return False, patient, None
236230

237231
vaccination_type = get_vaccine_type(immunization)
238232

@@ -251,7 +245,7 @@ def update_reinstated_immunization(
251245
supplier_system,
252246
)
253247

254-
return UpdateOutcome.UPDATE, Immunization.parse_obj(imms), updated_version
248+
return True, Immunization.parse_obj(imms), updated_version
255249

256250
def delete_immunization(self, imms_id: str, supplier_system: str) -> None:
257251
"""

backend/tests/authorisation/test_authoriser.py

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,63 +22,59 @@ def tearDown(self):
2222

2323
def test_authorise_returns_true_if_supplier_has_permissions(self):
2424
"""Authoriser().authorise should return true if the supplier has the required permissions"""
25-
self.mock_cache_client.hget.return_value = '["COVID19.RS"]'
25+
self.mock_cache_client.hget.return_value = '["COVID.RS"]'
2626

27-
result = self.test_authoriser.authorise(self.MOCK_SUPPLIER_NAME, ApiOperationCode.READ, {"COVID19"})
27+
result = self.test_authoriser.authorise(self.MOCK_SUPPLIER_NAME, ApiOperationCode.READ, {"COVID"})
2828

2929
self.assertTrue(result)
3030
self.mock_cache_client.hget.assert_called_once_with("supplier_permissions", self.MOCK_SUPPLIER_NAME)
3131
self.mock_logger.info.assert_called_once_with(
32-
"operation: r, supplier_permissions: {'covid19': ['r', 's']}, vaccine_types: {'COVID19'}"
32+
"operation: r, supplier_permissions: {'covid': ['r', 's']}, vaccine_types: {'COVID'}"
3333
)
3434

3535
def test_authorise_returns_false_if_supplier_does_not_have_any_permissions(self):
3636
"""Authoriser().authorise should return false if the supplier does not have any permissions in the cache"""
3737
self.mock_cache_client.hget.return_value = ""
3838

39-
result = self.test_authoriser.authorise(self.MOCK_SUPPLIER_NAME, ApiOperationCode.CREATE, {"COVID19"})
39+
result = self.test_authoriser.authorise(self.MOCK_SUPPLIER_NAME, ApiOperationCode.CREATE, {"COVID"})
4040

4141
self.assertFalse(result)
4242
self.mock_cache_client.hget.assert_called_once_with("supplier_permissions", self.MOCK_SUPPLIER_NAME)
43-
self.mock_logger.info.assert_called_once_with(
44-
"operation: c, supplier_permissions: {}, vaccine_types: {'COVID19'}"
45-
)
43+
self.mock_logger.info.assert_called_once_with("operation: c, supplier_permissions: {}, vaccine_types: {'COVID'}")
4644

4745
def test_authorise_returns_false_if_supplier_does_not_have_permission_for_operation(
4846
self,
4947
):
5048
"""Authoriser().authorise should return false if the supplier does not have permission for the operation"""
51-
self.mock_cache_client.hget.return_value = '["COVID19.RS"]'
49+
self.mock_cache_client.hget.return_value = '["COVID.RS"]'
5250

53-
result = self.test_authoriser.authorise(self.MOCK_SUPPLIER_NAME, ApiOperationCode.CREATE, {"COVID19"})
51+
result = self.test_authoriser.authorise(self.MOCK_SUPPLIER_NAME, ApiOperationCode.CREATE, {"COVID"})
5452

5553
self.assertFalse(result)
5654
self.mock_cache_client.hget.assert_called_once_with("supplier_permissions", self.MOCK_SUPPLIER_NAME)
5755
self.mock_logger.info.assert_called_once_with(
58-
"operation: c, supplier_permissions: {'covid19': ['r', 's']}, vaccine_types: {'COVID19'}"
56+
"operation: c, supplier_permissions: {'covid': ['r', 's']}, vaccine_types: {'COVID'}"
5957
)
6058

6159
def test_authorise_returns_false_if_no_permission_for_vaccination_type(self):
6260
"""Authoriser().authorise should return false if the supplier does not have permission for the vaccination
6361
type"""
64-
self.mock_cache_client.hget.return_value = '["COVID19.RS"]'
62+
self.mock_cache_client.hget.return_value = '["COVID.RS"]'
6563

6664
result = self.test_authoriser.authorise(self.MOCK_SUPPLIER_NAME, ApiOperationCode.READ, {"FLU"})
6765

6866
self.assertFalse(result)
6967
self.mock_cache_client.hget.assert_called_once_with("supplier_permissions", self.MOCK_SUPPLIER_NAME)
7068
self.mock_logger.info.assert_called_once_with(
71-
"operation: r, supplier_permissions: {'covid19': ['r', 's']}, vaccine_types: {'FLU'}"
69+
"operation: r, supplier_permissions: {'covid': ['r', 's']}, vaccine_types: {'FLU'}"
7270
)
7371

7472
def test_authorise_returns_false_multiple_vaccs_scenario(self):
7573
"""Authoriser().authorise should return false if the supplier is missing a permission for any of the vaccs in
7674
the list provided"""
77-
self.mock_cache_client.hget.return_value = '["COVID19.RS", "FLU.CRUDS"]'
75+
self.mock_cache_client.hget.return_value = '["COVID.RS", "FLU.CRUDS"]'
7876

79-
result = self.test_authoriser.authorise(
80-
self.MOCK_SUPPLIER_NAME, ApiOperationCode.READ, {"FLU", "COVID19", "RSV"}
81-
)
77+
result = self.test_authoriser.authorise(self.MOCK_SUPPLIER_NAME, ApiOperationCode.READ, {"FLU", "COVID", "RSV"})
8278

8379
self.assertFalse(result)
8480
self.mock_cache_client.hget.assert_called_once_with("supplier_permissions", self.MOCK_SUPPLIER_NAME)
@@ -87,8 +83,8 @@ def test_filter_permitted_vacc_types_returns_all_if_supplier_has_perms_for_all(
8783
self,
8884
):
8985
"""The same set of vaccination types will be returned if the supplier has the required permissions"""
90-
self.mock_cache_client.hget.return_value = '["COVID19.RS", "FLU.CRUDS", "RSV.CRUDS"]'
91-
requested_vacc_types = {"FLU", "COVID19", "RSV"}
86+
self.mock_cache_client.hget.return_value = '["COVID.RS", "FLU.CRUDS", "RSV.CRUDS"]'
87+
requested_vacc_types = {"FLU", "COVID", "RSV"}
9288

9389
result = self.test_authoriser.filter_permitted_vacc_types(
9490
self.MOCK_SUPPLIER_NAME, ApiOperationCode.SEARCH, requested_vacc_types
@@ -103,11 +99,11 @@ def test_filter_permitted_vacc_types_removes_any_vacc_types_that_the_supplier_ca
10399
):
104100
"""Filter permitted vacc types method will filter out any vaccination types that the user cannot interact
105101
with"""
106-
self.mock_cache_client.hget.return_value = '["COVID19.RS", "FLU.CRUDS", "RSV.R"]'
102+
self.mock_cache_client.hget.return_value = '["COVID.RS", "FLU.CRUDS", "RSV.R"]'
107103

108104
result = self.test_authoriser.filter_permitted_vacc_types(
109-
self.MOCK_SUPPLIER_NAME, ApiOperationCode.SEARCH, {"FLU", "COVID19", "RSV"}
105+
self.MOCK_SUPPLIER_NAME, ApiOperationCode.SEARCH, {"FLU", "COVID", "RSV"}
110106
)
111107

112-
self.assertSetEqual(result, {"FLU", "COVID19"})
108+
self.assertSetEqual(result, {"FLU", "COVID"})
113109
self.mock_cache_client.hget.assert_called_once_with("supplier_permissions", self.MOCK_SUPPLIER_NAME)

backend/tests/batch/test_batch_filename_to_events_mapper.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,18 @@
2525

2626
MOCK_SUPPLIER_TWO_COVID_EVENT_ONE = {
2727
"row_id": "row-1",
28-
"file_key": "supplier_two_covid19_file_key",
28+
"file_key": "supplier_two_covid_file_key",
2929
"created_at_formatted_string": "2025-01-24T14:00:00Z",
3030
"supplier": "supplier_two",
31-
"vax_type": "COVID-19",
31+
"vax_type": "COVID",
3232
"local_id": "local-1",
3333
"operation_requested": "CREATE",
3434
}
3535

3636

3737
class TestBatchFilenameToEventsMapper(unittest.TestCase):
3838
expected_key_supplier_one = "supplier_one_rsv_file_key_2025-01-24T12:00:00Z"
39-
expected_key_supplier_two = "supplier_two_covid19_file_key_2025-01-24T14:00:00Z"
39+
expected_key_supplier_two = "supplier_two_covid_file_key_2025-01-24T14:00:00Z"
4040

4141
def setUp(self) -> None:
4242
self.batch_filename_to_events_mapper = BatchFilenameToEventsMapper()

backend/tests/controller/test_fhir_batch_controller.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
)
1212
from repository.fhir_batch_repository import ImmunizationBatchRepository
1313
from service.fhir_batch_service import ImmunizationBatchService
14-
from testing_utils.immunization_utils import create_covid_19_immunization
14+
from testing_utils.immunization_utils import create_covid_immunization
1515

1616

1717
class TestCreateImmunizationBatchController(unittest.TestCase):
@@ -25,7 +25,7 @@ def test_send_request_to_dynamo_create_success(self):
2525
"""it should create Immunization and return imms id location"""
2626

2727
imms_id = str(uuid.uuid4())
28-
imms = create_covid_19_immunization(imms_id)
28+
imms = create_covid_immunization(imms_id)
2929
message_body = {
3030
"supplier": "test_supplier",
3131
"fhir_json": imms.json(),
@@ -50,7 +50,7 @@ def test_send_request_to_dynamo_create_badrequest(self):
5050
"""it should return error since it got failed in initial validation"""
5151

5252
imms_id = str(uuid.uuid4())
53-
imms = create_covid_19_immunization(imms_id)
53+
imms = create_covid_immunization(imms_id)
5454
create_result = CustomValidationError(
5555
message="Validation errors: contained[?(@.resourceType=='Patient')].identifier[0].value does not exists"
5656
)
@@ -79,7 +79,7 @@ def test_send_request_to_dynamo_create_duplicate(self):
7979
"""it should not create the Immunization since its a duplicate record"""
8080

8181
imms_id = str(uuid.uuid4())
82-
imms = create_covid_19_immunization(imms_id)
82+
imms = create_covid_immunization(imms_id)
8383
create_result = IdentifierDuplicationError(identifier="test#123")
8484
message_body = {
8585
"supplier": "test_supplier",
@@ -105,7 +105,7 @@ def test_send_request_to_dynamo_create_unhandled_error(self):
105105
"""it should not create the Immunization since the error occoured in db"""
106106

107107
imms_id = str(uuid.uuid4())
108-
imms = create_covid_19_immunization(imms_id)
108+
imms = create_covid_immunization(imms_id)
109109
update_result = UnhandledResponseError(response="Non-200 response from dynamodb", message="connection timeout")
110110
message_body = {
111111
"supplier": "test_supplier",
@@ -141,7 +141,7 @@ def test_send_request_to_dynamo_update_success(self):
141141
"""it should update Immunization and return imms id"""
142142

143143
imms_id = str(uuid.uuid4())
144-
imms = create_covid_19_immunization(imms_id)
144+
imms = create_covid_immunization(imms_id)
145145
message_body = {
146146
"supplier": "test_supplier",
147147
"fhir_json": imms.json(),
@@ -166,7 +166,7 @@ def test_send_request_to_dynamo_update_badrequest(self):
166166
"""it should return error since it got failed in initial validation"""
167167

168168
imms_id = str(uuid.uuid4())
169-
imms = create_covid_19_immunization(imms_id)
169+
imms = create_covid_immunization(imms_id)
170170
update_result = CustomValidationError(
171171
message="Validation errors: contained[?(@.resourceType=='Patient')].identifier[0].value does not exists"
172172
)
@@ -194,7 +194,7 @@ def test_send_request_to_dynamo_update_resource_not_found(self):
194194
"""it should not update the Immunization since no resource found for the record"""
195195

196196
imms_id = str(uuid.uuid4())
197-
imms = create_covid_19_immunization(imms_id)
197+
imms = create_covid_immunization(imms_id)
198198
update_result = ResourceNotFoundError("Immunization", "test#123")
199199
message_body = {
200200
"supplier": "test_supplier",
@@ -220,7 +220,7 @@ def test_send_request_to_dynamo_update_unhandled_error(self):
220220
"""it should not update the Immunization since the error occoured in db"""
221221

222222
imms_id = str(uuid.uuid4())
223-
imms = create_covid_19_immunization(imms_id)
223+
imms = create_covid_immunization(imms_id)
224224
update_result = UnhandledResponseError(response="Non-200 response from dynamodb", message="connection timeout")
225225
message_body = {
226226
"supplier": "test_supplier",
@@ -256,7 +256,7 @@ def test_send_request_to_dynamo_delete_success(self):
256256
"""it should delete Immunization and return imms id"""
257257

258258
imms_id = str(uuid.uuid4())
259-
imms = create_covid_19_immunization(imms_id)
259+
imms = create_covid_immunization(imms_id)
260260
message_body = {
261261
"supplier": "test_supplier",
262262
"fhir_json": imms.json(),
@@ -281,7 +281,7 @@ def test_send_request_to_dynamo_delete_badrequest(self):
281281
"""it should return error since it got failed in initial validation"""
282282

283283
imms_id = str(uuid.uuid4())
284-
imms = create_covid_19_immunization(imms_id)
284+
imms = create_covid_immunization(imms_id)
285285
update_result = CustomValidationError(
286286
message="Validation errors: contained[?(@.resourceType=='Patient')].identifier[0].value does not exists"
287287
)
@@ -309,7 +309,7 @@ def test_send_request_to_dynamo_delete_resource_not_found(self):
309309
"""it should not delete the Immunization since no resource found for the record"""
310310

311311
imms_id = str(uuid.uuid4())
312-
imms = create_covid_19_immunization(imms_id)
312+
imms = create_covid_immunization(imms_id)
313313
update_result = ResourceNotFoundError("Immunization", "test#123")
314314
message_body = {
315315
"supplier": "test_supplier",
@@ -335,7 +335,7 @@ def test_send_request_to_dynamo_delete_unhandled_error(self):
335335
"""it should not delete the Immunization since the error occoured in db"""
336336

337337
imms_id = str(uuid.uuid4())
338-
imms = create_covid_19_immunization(imms_id)
338+
imms = create_covid_immunization(imms_id)
339339
update_result = UnhandledResponseError(response="Non-200 response from dynamodb", message="connection timeout")
340340
message_body = {
341341
"supplier": "test_supplier",

0 commit comments

Comments
 (0)