Skip to content

Commit bce830f

Browse files
authored
Merge pull request #428 from NHSDigital/release/2024-11-27
Release/2024 11 27
2 parents 8f10751 + 722f18c commit bce830f

File tree

61 files changed

+3515
-548
lines changed

Some content is hidden

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

61 files changed

+3515
-548
lines changed

.github/workflows/pull-requests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ jobs:
201201
with:
202202
ref: ${{ env.BRANCH_NAME }}
203203
- run: |
204-
poetry add pytest-nhsd-apim
204+
poetry add pytest-nhsd-apim==3.4.3
205205
- uses: ./.github/actions/make/
206206
with:
207207
command: apigee--attach-product DEV_BUILD="true"
@@ -290,7 +290,7 @@ jobs:
290290
with:
291291
ref: ${{ env.BRANCH_NAME }}
292292
- run: |
293-
poetry add pytest-nhsd-apim
293+
poetry add pytest-nhsd-apim==3.4.3
294294
- uses: ./.github/actions/make/
295295
with:
296296
command: apigee--detach-product DEV_BUILD="true"

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 2024-11-27
4+
- [PI-605] Bulk ETL (transform layer)
5+
- [PI-582] Read MHS Device
6+
37
## 2024-11-25
48
- [PI-643] Add status to Device Reference Data
59
- Dependabot: slack-github-action, pydantic

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2024.11.25
1+
2024.11.27

changelog/2024-11-27.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- [PI-605] Bulk ETL (transform layer)
2+
- [PI-582] Read MHS Device

infrastructure/terraform/per_workspace/vars.tf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ variable "api_lambda_layers" {
4040
default = [
4141
"domain",
4242
"event",
43-
"api_utils"
43+
"api_utils",
44+
"sds"
4445
]
4546
}
4647

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "connecting-party-manager"
3-
version = "2024.11.25"
3+
version = "2024.11.27"
44
description = "Repository for the Connecting Party Manager API and related services"
55
authors = ["NHS England"]
66
license = "LICENSE.md"

src/api/createDeviceMessageHandlingSystem/src/v1/steps.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
)
1010
from domain.core.cpm_product import CpmProduct
1111
from domain.core.device import (
12-
MHS_DEVICE_NAME,
1312
Device,
1413
DeviceKeyAddedEvent,
1514
DeviceReferenceDataIdAddedEvent,
@@ -31,6 +30,7 @@
3130
)
3231
from domain.request_models import CpmProductPathParams, CreateMhsDeviceIncomingParams
3332
from domain.response.validation_errors import mark_validation_errors_as_inbound
33+
from sds.epr.constants import EprNameTemplate, SdsDeviceReferenceDataPath, SdsFieldName
3434

3535

3636
@mark_validation_errors_as_inbound
@@ -42,13 +42,17 @@ def parse_mhs_device_payload(data, cache) -> CreateMhsDeviceIncomingParams:
4242
def check_for_existing_mhs(data, cache):
4343
product_team: ProductTeam = data[read_product_team]
4444
product: CpmProduct = data[read_product]
45+
party_key: str = data[get_party_key]
4546

4647
device_repo = DeviceRepository(
4748
table_name=cache["DYNAMODB_TABLE"], dynamodb_client=cache["DYNAMODB_CLIENT"]
4849
)
4950

5051
devices = device_repo.search(product_team_id=product_team.id, product_id=product.id)
51-
if any(device.name == MHS_DEVICE_NAME for device in devices):
52+
if any(
53+
device.name == EprNameTemplate.MHS_DEVICE.format(party_key=party_key)
54+
for device in devices
55+
):
5256
raise ConfigurationError(
5357
"There is already an existing MHS Device for this Product"
5458
)
@@ -65,12 +69,11 @@ def read_device_reference_data(data, cache) -> DeviceReferenceData:
6569
)
6670

6771
party_key: str = data[get_party_key]
68-
# use {QuestionnaireInstance.SPINE_MHS_MESSAGE_SETS}
69-
mhs_message_set_drd_name = f"{party_key} - MHS Message Set"
70-
7172
try:
7273
(device_reference_data,) = filter(
73-
lambda drd: drd.name == mhs_message_set_drd_name, device_reference_datas
74+
lambda drd: drd.name
75+
== EprNameTemplate.MESSAGE_SETS.format(party_key=party_key),
76+
device_reference_datas,
7477
)
7578
except ValueError:
7679
raise ConfigurationError(
@@ -98,11 +101,14 @@ def validate_spine_mhs_questionnaire_response(data, cache) -> QuestionnaireRespo
98101

99102
def create_mhs_device(data, cache) -> Device:
100103
product: CpmProduct = data[read_product]
104+
party_key: str = data[get_party_key]
101105
payload: CreateMhsDeviceIncomingParams = data[parse_mhs_device_payload]
102106

103107
# Create a new Device dictionary excluding 'questionnaire_responses'
104108
device_payload = payload.dict(exclude={"questionnaire_responses"})
105-
return product.create_device(**device_payload)
109+
return product.create_device(
110+
name=EprNameTemplate.MHS_DEVICE.format(party_key=party_key), **device_payload
111+
)
106112

107113

108114
def create_party_key_tag(data, cache) -> DeviceTagAddedEvent:
@@ -114,20 +120,18 @@ def create_cpa_id_keys(data, cache) -> DeviceKeyAddedEvent:
114120
mhs_device: Device = data[create_mhs_device]
115121
party_key = data[get_party_key]
116122
drd: DeviceReferenceData = data[read_device_reference_data]
117-
interaction_ids = []
118123

119-
# Extract Interaction IDs from questionnaire responses
120124
questionnaire_responses = drd.questionnaire_responses.get(
121125
f"{QuestionnaireInstance.SPINE_MHS_MESSAGE_SETS}/1", []
122126
)
123-
for response in questionnaire_responses:
124-
interaction_ids.append(response.data.get("Interaction ID"))
125127

126-
# Use cpa_id in furture
128+
interaction_ids = [
129+
response.data.get(SdsFieldName.INTERACTION_ID)
130+
for response in questionnaire_responses
131+
]
132+
127133
for id in interaction_ids:
128-
mhs_device.add_key(
129-
key_type=DeviceKeyType.INTERACTION_ID, key_value=f"{party_key}:{id}"
130-
)
134+
mhs_device.add_key(key_type=DeviceKeyType.CPA_ID, key_value=f"{party_key}:{id}")
131135

132136
return mhs_device
133137

@@ -136,7 +140,8 @@ def add_device_reference_data_id(data, cache) -> DeviceReferenceDataIdAddedEvent
136140
mhs_device: Device = data[create_mhs_device]
137141
drd: DeviceReferenceData = data[read_device_reference_data]
138142
return mhs_device.add_device_reference_data_id(
139-
device_reference_data_id=str(drd.id), path_to_data=["*"]
143+
device_reference_data_id=str(drd.id),
144+
path_to_data=[SdsDeviceReferenceDataPath.ALL],
140145
)
141146

142147

src/api/createDeviceMessageHandlingSystem/tests/test_index.py

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@
2323
QuestionnaireRepository,
2424
)
2525
from event.json import json_loads
26+
from sds.epr.constants import MHS_DEVICE_SUFFIX, EprNameTemplate
2627

2728
from test_helpers.dynamodb import mock_table
2829
from test_helpers.uuid import consistent_uuid
2930

3031
TABLE_NAME = "hiya"
31-
DEVICE_NAME = "Product-MHS"
32+
DEVICE_NAME = "ABC1234-987654 - Message Handling System"
3233
ODS_CODE = "AAA"
3334
PRODUCT_ID = ProductId.create()
3435
PRODUCT_TEAM_NAME = "My Product Team"
@@ -52,6 +53,7 @@
5253
"MHS Is Authenticated": "PERSISTENT",
5354
"Product Key": "product-key-001",
5455
"Requestor URP": "requestor-789",
56+
"MHS Manufacturer Organisation": "AAA",
5557
}
5658

5759

@@ -81,7 +83,7 @@ def mock_epr_product_with_message_set_drd() -> (
8183
)
8284
product_repo.write(entity=product)
8385

84-
# set up questionnaire response
86+
# set up questionnaire responses
8587
mhs_message_set_questionnaire = QuestionnaireRepository().read(
8688
QuestionnaireInstance.SPINE_MHS_MESSAGE_SETS
8789
)
@@ -92,7 +94,6 @@ def mock_epr_product_with_message_set_drd() -> (
9294
"MHS IN": "baz",
9395
}
9496
)
95-
9697
questionnaire_response_2 = mhs_message_set_questionnaire.validate(
9798
data={
9899
"Interaction ID": "urn:foo2",
@@ -103,7 +104,7 @@ def mock_epr_product_with_message_set_drd() -> (
103104

104105
# Set up DeviceReferenceData in DB
105106
device_reference_data = product.create_device_reference_data(
106-
name="ABC1234-987654 - MHS Message Set"
107+
name=EprNameTemplate.MESSAGE_SETS.format(party_key="ABC1234-987654")
107108
)
108109
device_reference_data.add_questionnaire_response(questionnaire_response)
109110
device_reference_data.add_questionnaire_response(questionnaire_response_2)
@@ -205,7 +206,7 @@ def test_index() -> None:
205206
device = Device(**_device)
206207
assert device.product_team_id == product.product_team_id
207208
assert device.product_id == product.id
208-
assert device.name == DEVICE_NAME
209+
assert device.name.endswith(MHS_DEVICE_SUFFIX)
209210
assert device.ods_code == ODS_CODE
210211
assert device.created_on.date() == datetime.today().date()
211212
assert device.updated_on.date() == datetime.today().date()
@@ -302,7 +303,7 @@ def test_incoming_errors(body, path_parameters, error_code, status_code):
302303
}
303304
},
304305
"MISSING_VALUE",
305-
"Failed to validate data against 'spine_mhs/1': 'Unique Identifier' is a required property",
306+
"Failed to validate data against 'spine_mhs/1': 'MHS Manufacturer Organisation' is a required property",
306307
400,
307308
),
308309
],
@@ -375,4 +376,42 @@ def test_no_existing_message_set_drd():
375376
assert expected_message_code in response["body"]
376377

377378

378-
# add test for already existing mhs device?
379+
def test_mhs_already_exists() -> None:
380+
with mock_epr_product_with_message_set_drd() as (index, product):
381+
# Execute the lambda
382+
response = index.handler(
383+
event={
384+
"headers": {"version": VERSION},
385+
"body": json.dumps(
386+
{"questionnaire_responses": {"spine_mhs": [QUESTIONNAIRE_DATA]}}
387+
),
388+
"pathParameters": {
389+
"product_team_id": str(product.product_team_id),
390+
"product_id": str(product.id),
391+
},
392+
}
393+
)
394+
395+
assert response["statusCode"] == 201
396+
397+
# Execute the lambda again
398+
response = index.handler(
399+
event={
400+
"headers": {"version": VERSION},
401+
"body": json.dumps(
402+
{"questionnaire_responses": {"spine_mhs": [QUESTIONNAIRE_DATA]}}
403+
),
404+
"pathParameters": {
405+
"product_team_id": str(product.product_team_id),
406+
"product_id": str(product.id),
407+
},
408+
}
409+
)
410+
411+
assert response["statusCode"] == 400
412+
expected_error_code = "VALIDATION_ERROR"
413+
expected_message_code = (
414+
"There is already an existing MHS Device for this Product"
415+
)
416+
assert expected_error_code in response["body"]
417+
assert expected_message_code in response["body"]

src/api/createDeviceReferenceDataASActions/src/v1/steps.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121
)
2222
from domain.request_models import CreateDeviceReferenceAdditionalInteractionsDataParams
2323
from domain.response.validation_errors import mark_validation_errors_as_inbound
24-
25-
DEVICE_NAME_MARKER = "AS Additional Interactions"
24+
from sds.epr.constants import ADDITIONAL_INTERACTIONS_SUFFIX, EprNameTemplate
2625

2726

2827
@mark_validation_errors_as_inbound
@@ -60,7 +59,7 @@ def require_no_existing_additional_interactions_device_reference_data(
6059
product_team_id=product.product_team_id, product_id=product.id
6160
)
6261
if any(
63-
device_reference_data.name.endswith(DEVICE_NAME_MARKER)
62+
device_reference_data.name.endswith(ADDITIONAL_INTERACTIONS_SUFFIX)
6463
for device_reference_data in results
6564
):
6665
raise AlreadyExistsError(
@@ -91,7 +90,7 @@ def create_additional_interactions_device_reference_data(
9190
product: CpmProduct = data[read_product]
9291
party_key: str = data[get_party_key]
9392
return product.create_device_reference_data(
94-
name=f"{party_key} - {DEVICE_NAME_MARKER}"
93+
name=EprNameTemplate.ADDITIONAL_INTERACTIONS.format(party_key=party_key)
9594
)
9695

9796

src/api/createDeviceReferenceDataMessageSet/src/v1/steps.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
)
2121
from domain.request_models import CreateDeviceReferenceMessageSetsDataParams
2222
from domain.response.validation_errors import mark_validation_errors_as_inbound
23-
24-
DEVICE_NAME_MARKER = "MHS Message Set"
23+
from sds.epr.constants import MESSAGE_SETS_SUFFIX, EprNameTemplate
2524

2625

2726
@mark_validation_errors_as_inbound
@@ -43,11 +42,11 @@ def require_no_existing_message_sets_device_reference_data(
4342
product_team_id=product.product_team_id, product_id=product.id
4443
)
4544
if any(
46-
device_reference_data.name.endswith(DEVICE_NAME_MARKER)
45+
device_reference_data.name.endswith(MESSAGE_SETS_SUFFIX)
4746
for device_reference_data in results
4847
):
4948
raise AlreadyExistsError(
50-
"This product already has a 'Message Set' DeviceReferenceData. "
49+
"This product already has a 'Message Sets' DeviceReferenceData. "
5150
"Please update, or delete and recreate if you wish to make changes."
5251
)
5352

@@ -71,7 +70,7 @@ def create_message_set_device_reference_data(data, cache) -> DeviceReferenceData
7170
product: CpmProduct = data[read_product]
7271
party_key: str = data[get_party_key]
7372
return product.create_device_reference_data(
74-
name=f"{party_key} - {DEVICE_NAME_MARKER}"
73+
name=EprNameTemplate.MESSAGE_SETS.format(party_key=party_key)
7574
)
7675

7776

0 commit comments

Comments
 (0)