Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 2024-12-11
- [PI-650] Modify the Read Device endpoint for AS Devices
- [PI-666] Create an ASID for AS Device and add as a DeviceKey
- [PI-603] Update the spine_mhs questionnaire
- [PI-645] Update the spine_mhs_message_sets questionnaire

## 2024-12-05
- [PI-631] Generate Product Ids
- [PI-691] Allow devs to clear terminal after each Feature Test
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,21 +247,21 @@ Executing feature tests in integration mode will then give you confidence that t
To execute the feature tests entirely locally (executing lambdas directly, and otherwise mocking databases and responses to a high standard) you can do:

```shell
make test--feature-local
make test--feature--local
```

If you would like to pass `behave` flags, e.g. to \[stop after the first failure\]:

```shell
make test--feature-local BEHAVE_FLAGS="--stop"
make test--feature--local BEHAVE_FLAGS="--stop"
```

#### Integration

To execute the feature tests across the entire stack (including Apigee and AWS) you can do

```shell
make test--feature-integration
make test--feature--integration
```

### Generate the Feature Test Postman collection
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2024.12.05
2024.12.11
4 changes: 4 additions & 0 deletions changelog/2024-12-11.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- [PI-650] Modify the Read Device endpoint for AS Devices
- [PI-666] Create an ASID for AS Device and add as a DeviceKey
- [PI-603] Update the spine_mhs questionnaire
- [PI-645] Update the spine_mhs_message_sets questionnaire
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "connecting-party-manager"
version = "2024.12.05"
version = "2024.12.11"
description = "Repository for the Connecting Party Manager API and related services"
authors = ["NHS England"]
license = "LICENSE.md"
Expand Down
46 changes: 37 additions & 9 deletions src/api/createDeviceAccreditedSystem/src/v1/steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
read_product_team,
)
from domain.core.cpm_product import CpmProduct
from domain.core.cpm_system_id import AsidId
from domain.core.device import (
Device,
DeviceTagAddedEvent,
QuestionnaireResponseUpdatedEvent,
)
from domain.core.device_key.v1 import DeviceKeyType
from domain.core.device_reference_data import DeviceReferenceData
from domain.core.error import (
AccreditedSystemFatalError,
Expand All @@ -20,6 +22,7 @@
)
from domain.core.product_key import ProductKeyType
from domain.core.questionnaire import Questionnaire, QuestionnaireResponse
from domain.repository.cpm_system_id_repository import CpmSystemIdRepository
from domain.repository.device_reference_data_repository import (
DeviceReferenceDataRepository,
)
Expand Down Expand Up @@ -85,28 +88,41 @@ def validate_spine_as_questionnaire_response(data, cache) -> QuestionnaireRespon
)


def create_party_key_tag(data, cache) -> DeviceTagAddedEvent:
as_device: Device = data[create_as_device]
return as_device.add_tag(party_key=data[get_party_key])


def create_asid(data, cache) -> AsidId:
repository = CpmSystemIdRepository[AsidId](
table_name=cache["DYNAMODB_TABLE"],
dynamodb_client=cache["DYNAMODB_CLIENT"],
model=AsidId,
)
asid = repository.read()
new_asid = AsidId.create(current_number=asid.latest_number)
return new_asid


def create_as_device(data, cache) -> Device:
product: CpmProduct = data[read_product]
asid: AsidId = data[create_asid]
payload: CreateAsDeviceIncomingParams = data[parse_as_device_payload]
party_key: str = data[get_party_key]

# Create a new Device dictionary excluding 'questionnaire_responses'
# Ticket PI-666 adds ASID generation. This will need to be sent across in the arguments instead of an empty string.
device_payload = payload.dict(exclude={"questionnaire_responses"})
return product.create_device(
name=EprNameTemplate.AS_DEVICE.format(party_key=party_key, asid=""),
name=EprNameTemplate.AS_DEVICE.format(party_key=party_key, asid=asid.__root__),
**device_payload
)


def create_party_key_tag(data, cache) -> DeviceTagAddedEvent:
as_device: Device = data[create_as_device]
return as_device.add_tag(party_key=data[get_party_key])


def create_device_keys(data, cache) -> Device:
# We will need to add some keys in the future, ASID?
as_device: Device = data[create_as_device]
asid: AsidId = data[create_asid]
as_device.add_key(
key_type=DeviceKeyType.ACCREDITED_SYSTEM_ID, key_value=asid.__root__
)
return as_device


Expand Down Expand Up @@ -139,6 +155,16 @@ def write_device(data: dict[str, Device], cache) -> Device:
return repo.write(as_device)


def write_asid(data: dict[str, AsidId], cache) -> str:
repository = CpmSystemIdRepository[AsidId](
table_name=cache["DYNAMODB_TABLE"],
dynamodb_client=cache["DYNAMODB_CLIENT"],
model=AsidId,
)
asid: AsidId = data[create_asid]
return repository.create_or_update(asid)


def set_http_status(data, cache) -> tuple[HTTPStatus, dict]:
as_device: Device = data[create_as_device]
return HTTPStatus.CREATED, as_device.state_exclude_tags()
Expand Down Expand Up @@ -170,11 +196,13 @@ def get_party_key(data, cache) -> str:
read_device_reference_data,
read_spine_as_questionnaire,
validate_spine_as_questionnaire_response,
create_asid,
create_as_device,
create_party_key_tag,
create_device_keys,
add_device_reference_data_id,
add_spine_as_questionnaire_response,
write_device,
write_asid,
set_http_status,
]
119 changes: 100 additions & 19 deletions src/api/createDeviceAccreditedSystem/tests/test_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from domain.core.cpm_product import CpmProduct
from domain.core.cpm_system_id import ProductId
from domain.core.device import Device
from domain.core.device_key.v1 import DeviceKey, DeviceKeyType
from domain.core.product_key import ProductKeyType
from domain.core.root import Root
from domain.repository.cpm_product_repository import CpmProductRepository
Expand All @@ -34,6 +35,7 @@
PRODUCT_TEAM_NAME = "My Product Team"
PRODUCT_NAME = "My Product"
VERSION = 1
PARTY_KEY = "ABC1234-987654"

QUESTIONNAIRE_DATA = {
"ODS Code": "FH15R",
Expand Down Expand Up @@ -68,7 +70,7 @@ def mock_epr_product_with_one_message_set_drd() -> (
product = product_team.create_cpm_product(
name=PRODUCT_NAME, product_id=PRODUCT_ID
)
product.add_key(key_type=ProductKeyType.PARTY_KEY, key_value="ABC1234-987654")
product.add_key(key_type=ProductKeyType.PARTY_KEY, key_value=PARTY_KEY)
product_repo = CpmProductRepository(
table_name=TABLE_NAME, dynamodb_client=client
)
Expand All @@ -78,10 +80,22 @@ def mock_epr_product_with_one_message_set_drd() -> (
QuestionnaireInstance.SPINE_MHS_MESSAGE_SETS
)
questionnaire_response_1 = mhs_message_set_questionnaire.validate(
data={"Interaction ID": "urn:foo1", "MHS SN": "bar", "MHS IN": "baz"}
data={
"Interaction ID": "bar:baz",
"MHS SN": "bar",
"MHS IN": "baz",
"MHS CPA ID": f"{PARTY_KEY}:bar:baz",
"Unique Identifier": f"{PARTY_KEY}:bar:baz",
}
)
questionnaire_response_2 = mhs_message_set_questionnaire.validate(
data={"Interaction ID": "urn:foo2", "MHS SN": "bar2", "MHS IN": "baz2"}
data={
"Interaction ID": "bar2:baz2",
"MHS SN": "bar2",
"MHS IN": "baz2",
"MHS CPA ID": f"{PARTY_KEY}:bar2:baz2",
"Unique Identifier": f"{PARTY_KEY}:bar2:baz2",
}
)

# Set up DeviceReferenceData in DB
Expand Down Expand Up @@ -123,7 +137,7 @@ def mock_epr_product_with_message_sets_drd() -> (
product = product_team.create_cpm_product(
name=PRODUCT_NAME, product_id=PRODUCT_ID
)
product.add_key(key_type=ProductKeyType.PARTY_KEY, key_value="ABC1234-987654")
product.add_key(key_type=ProductKeyType.PARTY_KEY, key_value=PARTY_KEY)
product_repo = CpmProductRepository(
table_name=TABLE_NAME, dynamodb_client=client
)
Expand All @@ -134,10 +148,22 @@ def mock_epr_product_with_message_sets_drd() -> (
)

questionnaire_response_1 = mhs_message_set_questionnaire.validate(
data={"Interaction ID": "urn:foo1", "MHS SN": "bar", "MHS IN": "baz"}
data={
"Interaction ID": "bar:baz",
"MHS SN": "bar",
"MHS IN": "baz",
"MHS CPA ID": f"{PARTY_KEY}:bar:baz",
"Unique Identifier": f"{PARTY_KEY}:bar:baz",
}
)
questionnaire_response_2 = mhs_message_set_questionnaire.validate(
data={"Interaction ID": "urn:foo2", "MHS SN": "bar2", "MHS IN": "baz2"}
data={
"Interaction ID": "bar2:baz2",
"MHS SN": "bar2",
"MHS IN": "baz2",
"MHS CPA ID": f"{PARTY_KEY}:bar2:baz2",
"Unique Identifier": f"{PARTY_KEY}:bar2:baz2",
}
)
# Set up DeviceReferenceData in DB
device_reference_data_mhs = product.create_device_reference_data(
Expand Down Expand Up @@ -196,7 +222,7 @@ def mock_epr_product_with_more_than_two_message_sets_drd() -> (
product = product_team.create_cpm_product(
name=PRODUCT_NAME, product_id=PRODUCT_ID
)
product.add_key(key_type=ProductKeyType.PARTY_KEY, key_value="ABC1234-987654")
product.add_key(key_type=ProductKeyType.PARTY_KEY, key_value=PARTY_KEY)
product_repo = CpmProductRepository(
table_name=TABLE_NAME, dynamodb_client=client
)
Expand All @@ -206,10 +232,22 @@ def mock_epr_product_with_more_than_two_message_sets_drd() -> (
QuestionnaireInstance.SPINE_MHS_MESSAGE_SETS
)
questionnaire_response_1 = mhs_message_set_questionnaire_1.validate(
data={"Interaction ID": "urn:foo1", "MHS SN": "bar", "MHS IN": "baz"}
data={
"Interaction ID": "bar:baz",
"MHS SN": "bar",
"MHS IN": "baz",
"MHS CPA ID": f"{PARTY_KEY}:bar:baz",
"Unique Identifier": f"{PARTY_KEY}:bar:baz",
}
)
questionnaire_response_2 = mhs_message_set_questionnaire_1.validate(
data={"Interaction ID": "urn:foo2", "MHS SN": "bar2", "MHS IN": "baz2"}
data={
"Interaction ID": "bar2:baz2",
"MHS SN": "bar2",
"MHS IN": "baz2",
"MHS CPA ID": f"{PARTY_KEY}:bar2:baz2",
"Unique Identifier": f"{PARTY_KEY}:bar2:baz2",
}
)

# Set up DeviceReferenceData in DB
Expand All @@ -223,10 +261,22 @@ def mock_epr_product_with_more_than_two_message_sets_drd() -> (
QuestionnaireInstance.SPINE_MHS_MESSAGE_SETS
)
questionnaire_response_3 = mhs_message_set_questionnaire_2.validate(
data={"Interaction ID": "urn:foo3", "MHS SN": "bar3", "MHS IN": "baz3"}
data={
"Interaction ID": "bar3:baz3",
"MHS SN": "bar3",
"MHS IN": "baz3",
"MHS CPA ID": f"{PARTY_KEY}:bar3:baz3",
"Unique Identifier": f"{PARTY_KEY}:bar3:baz3",
}
)
questionnaire_response_4 = mhs_message_set_questionnaire_2.validate(
data={"Interaction ID": "urn:foo4", "MHS SN": "bar4", "MHS IN": "baz4"}
data={
"Interaction ID": "bar4:baz4",
"MHS SN": "bar4",
"MHS IN": "baz4",
"MHS CPA ID": f"{PARTY_KEY}:bar4:baz4",
"Unique Identifier": f"{PARTY_KEY}:bar4:baz4",
}
)

# Set up DeviceReferenceData in DB
Expand Down Expand Up @@ -286,7 +336,7 @@ def mock_epr_product_with_two_message_sets_the_same_drd() -> (
product = product_team.create_cpm_product(
name=PRODUCT_NAME, product_id=PRODUCT_ID
)
product.add_key(key_type=ProductKeyType.PARTY_KEY, key_value="ABC1234-987654")
product.add_key(key_type=ProductKeyType.PARTY_KEY, key_value=PARTY_KEY)
product_repo = CpmProductRepository(
table_name=TABLE_NAME, dynamodb_client=client
)
Expand All @@ -296,10 +346,22 @@ def mock_epr_product_with_two_message_sets_the_same_drd() -> (
QuestionnaireInstance.SPINE_MHS_MESSAGE_SETS
)
questionnaire_response_1 = mhs_message_set_questionnaire_1.validate(
data={"Interaction ID": "urn:foo1", "MHS SN": "bar", "MHS IN": "baz"}
data={
"Interaction ID": "bar:baz",
"MHS SN": "bar",
"MHS IN": "baz",
"MHS CPA ID": f"{PARTY_KEY}:bar:baz",
"Unique Identifier": f"{PARTY_KEY}:bar:baz",
}
)
questionnaire_response_2 = mhs_message_set_questionnaire_1.validate(
data={"Interaction ID": "urn:foo2", "MHS SN": "bar2", "MHS IN": "baz2"}
data={
"Interaction ID": "bar2:baz2",
"MHS SN": "ba2r",
"MHS IN": "baz2",
"MHS CPA ID": f"{PARTY_KEY}:bar2:baz2",
"Unique Identifier": f"{PARTY_KEY}:bar2:baz2",
}
)

# Set up DeviceReferenceData in DB
Expand All @@ -313,10 +375,22 @@ def mock_epr_product_with_two_message_sets_the_same_drd() -> (
QuestionnaireInstance.SPINE_MHS_MESSAGE_SETS
)
questionnaire_response_3 = mhs_message_set_questionnaire_2.validate(
data={"Interaction ID": "urn:foo3", "MHS SN": "bar3", "MHS IN": "baz3"}
data={
"Interaction ID": "bar3:baz3",
"MHS SN": "bar3",
"MHS IN": "baz3",
"MHS CPA ID": f"{PARTY_KEY}:bar3:baz3",
"Unique Identifier": f"{PARTY_KEY}:bar3:baz3",
}
)
questionnaire_response_4 = mhs_message_set_questionnaire_2.validate(
data={"Interaction ID": "urn:foo4", "MHS SN": "bar4", "MHS IN": "baz4"}
data={
"Interaction ID": "bar4:baz4",
"MHS SN": "bar4",
"MHS IN": "baz4",
"MHS CPA ID": f"{PARTY_KEY}:bar4:baz4",
"Unique Identifier": f"{PARTY_KEY}:bar4:baz4",
}
)

# Set up DeviceReferenceData in DB
Expand Down Expand Up @@ -389,7 +463,7 @@ def mock_epr_product_without_message_set_drd() -> (
product = product_team.create_cpm_product(
name=PRODUCT_NAME, product_id=PRODUCT_ID
)
product.add_key(key_type=ProductKeyType.PARTY_KEY, key_value="ABC1234-987654")
product.add_key(key_type=ProductKeyType.PARTY_KEY, key_value=PARTY_KEY)
product_repo = CpmProductRepository(
table_name=TABLE_NAME, dynamodb_client=client
)
Expand Down Expand Up @@ -425,7 +499,7 @@ def test_index() -> None:
device = Device(**_device)
assert device.product_team_id == product.product_team_id
assert device.product_id == product.id
assert device.name == "ABC1234-987654/ - Accredited System"
assert device.name == "ABC1234-987654/200000100000 - Accredited System"
assert device.ods_code == ODS_CODE
assert device.created_on.date() == datetime.today().date()
assert device.updated_on.date() == datetime.today().date()
Expand All @@ -448,9 +522,16 @@ def test_index() -> None:
)

# Check party_key is added to tags in the created device
expected_party_key = (str(ProductKeyType.PARTY_KEY), "abc1234-987654")
expected_party_key = (str(ProductKeyType.PARTY_KEY), PARTY_KEY.lower())
assert any(expected_party_key in tag.__root__ for tag in created_device.tags)

# Check an ASID is generated and added to the keys.
assert isinstance(created_device.keys[0], DeviceKey)
assert created_device.keys[0].__dict__ == {
"key_type": DeviceKeyType.ACCREDITED_SYSTEM_ID,
"key_value": "200000100000",
}


@pytest.mark.parametrize(
["body", "path_parameters", "error_code", "status_code"],
Expand Down
Loading
Loading