Skip to content

Commit

Permalink
Merge pull request #422 from NHSDigital/release/2024-11-22
Browse files Browse the repository at this point in the history
Release/2024-11-22
  • Loading branch information
megan-bower4 authored Nov 25, 2024
2 parents efd21a2 + 45a3de2 commit e947cde
Show file tree
Hide file tree
Showing 196 changed files with 2,433 additions and 8,154 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy-nonprod-workspace.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
options:
- dev
- qa
- int
# - int
- ref
sandbox:
description: Do you want to deploy the sandbox version?
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 2024-11-22
- [PI-528] Collapse versioning to v1
- [PI-581] MHS Device with Device Reference Data

## 2024-11-19
- [PI-601] Workspace destroy, use main branch as fallback

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2024.11.19
2024.11.22
2 changes: 2 additions & 0 deletions changelog/2024-11-22.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- [PI-528] Collapse versioning to v1
- [PI-581] MHS Device with Device Reference Data
3 changes: 2 additions & 1 deletion infrastructure/terraform/per_workspace/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ module "lambdas" {
source = "./modules/api_worker/api_lambda"
python_version = var.python_version
name = each.key
lambda_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--${replace(replace(replace(each.key, "_", "-"), "DeviceReferenceData", "DeviceRefData"), "MessageHandlingSystem", "MHS")}"
lambda_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--${replace(replace(replace(replace(each.key, "_", "-"), "DeviceReferenceData", "DeviceRefData"), "MessageHandlingSystem", "MHS"), "MessageSet", "MsgSet")}"

//Compact will remove all nulls from the list and create a new one - this is because TF throws an error if there is a null item in the list.
layers = concat(
compact([for instance in module.layers : contains(var.api_lambda_layers, instance.name) ? instance.layer_arn : null]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ locals {
}
methods = [
for lambda_alias in setsubtract(var.lambdas, ["authoriser"]) :
{ "method_${lambda_alias}" = "${local.apigateway_lambda_arn_prefix}:${var.assume_account}:function:${var.project}--${replace(terraform.workspace, "_", "-")}--${replace(replace(replace(lambda_alias, "_", "-"), "DeviceReferenceData", "DeviceRefData"), "MessageHandlingSystem", "MHS")}/invocations" }
{ "method_${lambda_alias}" = "${local.apigateway_lambda_arn_prefix}:${var.assume_account}:function:${var.project}--${replace(terraform.workspace, "_", "-")}--${replace(replace(replace(replace(lambda_alias, "_", "-"), "DeviceReferenceData", "DeviceRefData"), "MessageHandlingSystem", "MHS"), "MessageSet", "MsgSet")}/invocations" }
]
swagger_file = templatefile("${path.root}/../../swagger/dist/aws/swagger.yaml", merge({
lambda_invoke_arn = var.authoriser_metadata.lambda_invoke_arn,
Expand Down
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.11.19"
version = "2024.11.22"
description = "Repository for the Connecting Party Manager API and related services"
authors = ["NHS England"]
license = "LICENSE.md"
Expand Down
4 changes: 2 additions & 2 deletions src/api/createCpmProduct/tests/test_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from unittest import mock

import pytest
from domain.core.root.v3 import Root
from domain.repository.product_team_repository.v2 import ProductTeamRepository
from domain.core.root import Root
from domain.repository.product_team_repository import ProductTeamRepository
from event.json import json_loads

from test_helpers.dynamodb import mock_table
Expand Down
6 changes: 3 additions & 3 deletions src/api/createCpmProductForEpr/src/v1/steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
read_product_team,
)
from domain.core.cpm_product import CpmProduct
from domain.core.cpm_system_id.v1 import PartyKeyId
from domain.core.product_key.v1 import ProductKeyType
from domain.core.product_team.v3 import ProductTeam
from domain.core.cpm_system_id import PartyKeyId
from domain.core.product_key import ProductKeyType
from domain.core.product_team import ProductTeam
from domain.repository.cpm_system_id_repository import CpmSystemIdRepository


Expand Down
8 changes: 4 additions & 4 deletions src/api/createCpmProductForEpr/tests/test_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
from unittest import mock

import pytest
from domain.core.cpm_system_id.v1 import PartyKeyId, ProductId
from domain.core.cpm_system_id import PartyKeyId, ProductId
from domain.core.enum import Status
from domain.core.root.v3 import Root
from domain.repository.cpm_product_repository.v3 import CpmProductRepository
from domain.repository.product_team_repository.v2 import ProductTeamRepository
from domain.core.root import Root
from domain.repository.cpm_product_repository import CpmProductRepository
from domain.repository.product_team_repository import ProductTeamRepository
from event.json import json_loads

from test_helpers.dynamodb import mock_table
Expand Down
10 changes: 5 additions & 5 deletions src/api/createDevice/src/v1/steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
read_product,
read_product_team,
)
from domain.core.cpm_product.v1 import CpmProduct
from domain.core.device.v3 import Device
from domain.repository.device_repository.v3 import DeviceRepository
from domain.request_models.v1 import CreateDeviceIncomingParams
from domain.core.cpm_product import CpmProduct
from domain.core.device import Device
from domain.repository.device_repository import DeviceRepository
from domain.request_models import CreateDeviceIncomingParams
from domain.response.validation_errors import mark_validation_errors_as_inbound


@mark_validation_errors_as_inbound
def parse_device_payload(data, cache) -> Device:
def parse_device_payload(data, cache) -> CreateDeviceIncomingParams:
payload: dict = data[parse_event_body]
return CreateDeviceIncomingParams(**payload)

Expand Down
14 changes: 7 additions & 7 deletions src/api/createDevice/tests/test_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
from unittest import mock

import pytest
from domain.core.cpm_product.v1 import CpmProduct
from domain.core.cpm_system_id.v1 import ProductId
from domain.core.device.v3 import Device
from domain.core.root.v3 import Root
from domain.repository.cpm_product_repository.v3 import CpmProductRepository
from domain.repository.device_repository.v3 import DeviceRepository
from domain.repository.product_team_repository.v2 import ProductTeamRepository
from domain.core.cpm_product import CpmProduct
from domain.core.cpm_system_id import ProductId
from domain.core.device import Device
from domain.core.root import Root
from domain.repository.cpm_product_repository import CpmProductRepository
from domain.repository.device_repository import DeviceRepository
from domain.repository.product_team_repository import ProductTeamRepository
from event.json import json_loads

from test_helpers.dynamodb import mock_table
Expand Down
144 changes: 110 additions & 34 deletions src/api/createDeviceMessageHandlingSystem/src/v1/steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,92 @@
read_product,
read_product_team,
)
from domain.core.cpm_product.v1 import CpmProduct
from domain.core.device.v3 import Device
from domain.core.error import InvalidSpineMhsResponse
from domain.core.questionnaire.v3 import Questionnaire, QuestionnaireResponse
from domain.repository.device_repository.v3 import DeviceRepository
from domain.repository.questionnaire_repository.v2 import QuestionnaireRepository
from domain.repository.questionnaire_repository.v2.questionnaires import (
from domain.core.cpm_product import CpmProduct
from domain.core.device import (
MHS_DEVICE_NAME,
Device,
DeviceKeyAddedEvent,
DeviceReferenceDataIdAddedEvent,
DeviceTagAddedEvent,
QuestionnaireResponseUpdatedEvent,
)
from domain.core.device_key import DeviceKeyType
from domain.core.device_reference_data import DeviceReferenceData
from domain.core.error import ConfigurationError
from domain.core.product_team import ProductTeam
from domain.core.questionnaire import Questionnaire, QuestionnaireResponse
from domain.repository.device_reference_data_repository import (
DeviceReferenceDataRepository,
)
from domain.repository.device_repository import DeviceRepository
from domain.repository.questionnaire_repository import (
QuestionnaireInstance,
QuestionnaireRepository,
)
from domain.request_models.v1 import CreateMhsDeviceIncomingParams
from domain.request_models import CpmProductPathParams, CreateMhsDeviceIncomingParams
from domain.response.validation_errors import mark_validation_errors_as_inbound


@mark_validation_errors_as_inbound
def parse_mhs_device_payload(data, cache) -> Device:
def parse_mhs_device_payload(data, cache) -> CreateMhsDeviceIncomingParams:
payload: dict = data[parse_event_body]
return CreateMhsDeviceIncomingParams(**payload)


def check_for_existing_mhs(data, cache):
product_team: ProductTeam = data[read_product_team]
product: CpmProduct = data[read_product]

device_repo = DeviceRepository(
table_name=cache["DYNAMODB_TABLE"], dynamodb_client=cache["DYNAMODB_CLIENT"]
)

devices = device_repo.search(product_team_id=product_team.id, product_id=product.id)
if any(device.name == MHS_DEVICE_NAME for device in devices):
raise ConfigurationError(
"There is already an existing MHS Device for this Product"
)


def read_device_reference_data(data, cache) -> DeviceReferenceData:
path_params: CpmProductPathParams = data[parse_path_params]
drd_repo = DeviceReferenceDataRepository(
table_name=cache["DYNAMODB_TABLE"], dynamodb_client=cache["DYNAMODB_CLIENT"]
)
device_reference_datas = drd_repo.search(
product_id=path_params.product_id,
product_team_id=path_params.product_team_id,
)

party_key: str = data[get_party_key]
# use {QuestionnaireInstance.SPINE_MHS_MESSAGE_SETS}
mhs_message_set_drd_name = f"{party_key} - MHS Message Set"

try:
(device_reference_data,) = filter(
lambda drd: drd.name == mhs_message_set_drd_name, device_reference_datas
)
except ValueError:
raise ConfigurationError(
"You must configure exactly one MessageSet Device Reference Data before creating an MHS Device"
)
return device_reference_data


def read_spine_mhs_questionnaire(data, cache) -> Questionnaire:
return QuestionnaireRepository().read(QuestionnaireInstance.SPINE_MHS)


def validate_spine_mhs_questionnaire_response(data, cache) -> QuestionnaireResponse:
spine_mhs_questionnaire: Questionnaire = data[read_spine_mhs_questionnaire]
payload: CreateMhsDeviceIncomingParams = data[parse_mhs_device_payload]
questionnaire_responses = payload.questionnaire_responses

# Ensure there's a questionnaire named 'spine_mhs' in the responses
if QuestionnaireInstance.SPINE_MHS not in questionnaire_responses:
raise InvalidSpineMhsResponse(
"Require a 'spine_mhs' questionnaire response to create a MHS Device"
)

raw_spine_mhs_questionnaire_response = payload.questionnaire_responses[
spine_mhs_questionnaire_response = payload.questionnaire_responses[
QuestionnaireInstance.SPINE_MHS
]
# Ensure there's only one response to 'spine_mhs'
if len(raw_spine_mhs_questionnaire_response) != 1:
raise InvalidSpineMhsResponse(
"Expected only one response for the 'spine_mhs' questionnaire"
)

return spine_mhs_questionnaire.validate(
data=raw_spine_mhs_questionnaire_response[0]
data=spine_mhs_questionnaire_response.__root__[0]
)


Expand All @@ -64,32 +105,63 @@ def create_mhs_device(data, cache) -> Device:
return product.create_device(**device_payload)


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


def create_cpa_id_keys(data, cache) -> DeviceKeyAddedEvent:
mhs_device: Device = data[create_mhs_device]
mhs_device.add_tag(party_key=data[get_party_key])
party_key = data[get_party_key]
drd: DeviceReferenceData = data[read_device_reference_data]
interaction_ids = []

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

# Use cpa_id in furture
for id in interaction_ids:
mhs_device.add_key(
key_type=DeviceKeyType.INTERACTION_ID, key_value=f"{party_key}:{id}"
)

return mhs_device


def add_spine_mhs_questionnaire_response(data, cache) -> list[QuestionnaireResponse]:
def add_device_reference_data_id(data, cache) -> DeviceReferenceDataIdAddedEvent:
mhs_device: Device = data[create_mhs_device]
drd: DeviceReferenceData = data[read_device_reference_data]
return mhs_device.add_device_reference_data_id(
device_reference_data_id=str(drd.id), path_to_data=["*"]
)


def add_spine_mhs_questionnaire_response(
data, cache
) -> QuestionnaireResponseUpdatedEvent:
spine_mhs_questionnaire_response: QuestionnaireResponse = data[
validate_spine_mhs_questionnaire_response
]
mhs_device: Device = data[create_party_key_tag]
mhs_device.add_questionnaire_response(spine_mhs_questionnaire_response)
return mhs_device
mhs_device: Device = data[create_mhs_device]

return mhs_device.add_questionnaire_response(spine_mhs_questionnaire_response)


def write_device(data: dict[str, CpmProduct], cache) -> CpmProduct:
mhs_device: Device = data[add_spine_mhs_questionnaire_response]
def write_device(data: dict[str, Device], cache) -> Device:
mhs_device: Device = data[create_mhs_device]
repo = DeviceRepository(
table_name=cache["DYNAMODB_TABLE"], dynamodb_client=cache["DYNAMODB_CLIENT"]
)
return repo.write(mhs_device)


def set_http_status(data, cache) -> tuple[HTTPStatus, str]:
device: Device = data[create_mhs_device]
return HTTPStatus.CREATED, device.state_exclude_tags()
def set_http_status(data, cache) -> tuple[HTTPStatus, dict]:
mhs_device: Device = data[create_mhs_device]
return HTTPStatus.CREATED, mhs_device.state_exclude_tags()


steps = [
Expand All @@ -99,10 +171,14 @@ def set_http_status(data, cache) -> tuple[HTTPStatus, str]:
read_product_team,
read_product,
get_party_key,
check_for_existing_mhs,
read_device_reference_data,
read_spine_mhs_questionnaire,
validate_spine_mhs_questionnaire_response,
create_mhs_device,
create_party_key_tag,
create_cpa_id_keys,
add_device_reference_data_id,
add_spine_mhs_questionnaire_response,
write_device,
set_http_status,
Expand Down
Loading

0 comments on commit e947cde

Please sign in to comment.