Skip to content

Commit 57ac92a

Browse files
NPA-4511: Added sandbox data for post consent
1 parent 71dc3b7 commit 57ac92a

21 files changed

+485
-367
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ lint:
2222
find . -name '*.py' -not -path '**/.venv/*' | xargs poetry run flake8
2323

2424
format:
25-
find . -name '*.py' -not -path '**/.venv/*' -not -path './sandbox/api/constants.py' | xargs poetry run black --check
25+
find . -name '*.py' -not -path '**/.venv/*' | xargs poetry run black --check --line-length 120
2626

2727
#Removes build/ + dist/ directories
2828
clean:

sandbox/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ load-examples: # Load the examples from the specification (for local development
1414
cp -r ../specification/examples/responses/ ./api/examples
1515

1616
format: # Formats the code using black
17-
poetry run black . --exclude ./api/constants.py
17+
poetry run black . --line-length 120
1818

1919
start: load-examples # Starts the Flask app (Don't use this in production)
2020
poetry run flask --app api.app:app run -p 9000

sandbox/api/app.py

Lines changed: 83 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from logging import INFO, basicConfig, getLogger
22
from typing import Union
3-
43
from flask import Flask, request
54

65
from .constants import (
@@ -13,18 +12,24 @@
1312
RELATED__VERIFY_RELATIONSHIP_25,
1413
RELATED__VERIFY_RELATIONSHIP_09_WITH_INCLUDE,
1514
RELATED__VERIFY_RELATIONSHIP_25_WITH_INCLUDE,
16-
CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP,
17-
CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP_INCLUDE_BOTH,
18-
CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP,
19-
CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP_INCLUDE_BOTH,
20-
CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_BOTH,
21-
CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_PERFORMER,
22-
CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_PATIENT,
23-
CONSENT__MULTIPLE_RELATIONSHIPS,
24-
CONSENT__NO_RELATIONSHIPS,
25-
CONSENT__FILTERED_RELATIONSHIPS_STATUS_ACTIVE,
26-
CONSENT__FILTERED_RELATIONSHIPS_STATUS_INACTIVE,
27-
CONSENT__FILTERED_RELATIONSHIPS_STATUS_PROPOSED_ACTIVE,
15+
GET_CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP,
16+
GET_CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP_INCLUDE_BOTH,
17+
GET_CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP,
18+
GET_CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP_INCLUDE_BOTH,
19+
GET_CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_BOTH,
20+
GET_CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_PERFORMER,
21+
GET_CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_PATIENT,
22+
GET_CONSENT__MULTIPLE_RELATIONSHIPS,
23+
GET_CONSENT__NO_RELATIONSHIPS,
24+
GET_CONSENT__FILTERED_RELATIONSHIPS_STATUS_ACTIVE,
25+
GET_CONSENT__FILTERED_RELATIONSHIPS_STATUS_INACTIVE,
26+
GET_CONSENT__FILTERED_RELATIONSHIPS_STATUS_PROPOSED_ACTIVE,
27+
POST_CONSENT__SUCCESS,
28+
POST_CONSENT__DUPLICATE_RELATIONSHIP_ERROR,
29+
POST_CONSENT__INVALID_ACCESS_LEVEL_ERROR,
30+
POST_CONSENT__INVALID_EVIDENCE_ERROR,
31+
POST_CONSENT__INVALID_PATIENT_AGE_ERROR,
32+
POST_CONSENT__PERFORMER_IDENTIFIER_ERROR,
2833
)
2934
from .utils import (
3035
check_for_empty,
@@ -41,6 +46,7 @@
4146
app = Flask(__name__)
4247
basicConfig(level=INFO, format="%(asctime)s - %(message)s")
4348
logger = getLogger(__name__)
49+
APP_BASE_PATH = "https://sandbox.api.service.nhs.uk/validated-relationships/FHIR/R4/Consent"
4450
COMMON_PATH = "FHIR/R4"
4551

4652

@@ -147,40 +153,92 @@ def get_consent() -> Union[dict, tuple]:
147153
if performer_identifier == "9000000010":
148154
return check_for_consent_include_params(
149155
_include,
150-
CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP,
151-
CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP_INCLUDE_BOTH,
156+
GET_CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP,
157+
GET_CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP_INCLUDE_BOTH,
152158
)
153159
# Single mother child relationship
154160
elif performer_identifier == "9000000019":
155161
return check_for_consent_include_params(
156162
_include,
157-
CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP,
158-
CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP_INCLUDE_BOTH,
163+
GET_CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP,
164+
GET_CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP_INCLUDE_BOTH,
159165
)
160166
# Filtering
161167
elif performer_identifier == "9000000017":
162168
return check_for_consent_filtering(
163169
status,
164170
_include,
165-
CONSENT__FILTERED_RELATIONSHIPS_STATUS_ACTIVE,
166-
CONSENT__FILTERED_RELATIONSHIPS_STATUS_INACTIVE,
167-
CONSENT__FILTERED_RELATIONSHIPS_STATUS_PROPOSED_ACTIVE,
171+
GET_CONSENT__FILTERED_RELATIONSHIPS_STATUS_ACTIVE,
172+
GET_CONSENT__FILTERED_RELATIONSHIPS_STATUS_INACTIVE,
173+
GET_CONSENT__FILTERED_RELATIONSHIPS_STATUS_PROPOSED_ACTIVE,
168174
)
169175
elif performer_identifier == "9000000022":
170176
return check_for_consent_include_params(
171177
_include,
172-
CONSENT__MULTIPLE_RELATIONSHIPS,
173-
CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_BOTH,
174-
CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_PATIENT,
175-
CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_PERFORMER,
178+
GET_CONSENT__MULTIPLE_RELATIONSHIPS,
179+
GET_CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_BOTH,
180+
GET_CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_PATIENT,
181+
GET_CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_PERFORMER,
176182
)
177183
# No relationships
178184
elif performer_identifier == "9000000025":
179-
return generate_response_from_example(CONSENT__NO_RELATIONSHIPS, 200)
185+
return generate_response_from_example(GET_CONSENT__NO_RELATIONSHIPS, 200)
180186
else:
181187
logger.error("Performer identifier does not match examples")
182188
return generate_response_from_example(INVALIDATED_RESOURCE, 404)
183189

184190
except Exception as e:
185191
logger.error(e)
186192
return generate_response_from_example(INTERNAL_SERVER_ERROR_EXAMPLE, 500)
193+
194+
195+
@app.route(f"/{COMMON_PATH}/Consent", methods=["POST"])
196+
def post_consent() -> Union[dict, tuple]:
197+
"""Sandbox API for POST /Consent
198+
199+
Returns:
200+
Union[dict, tuple]: Response for POST /Consent
201+
"""
202+
try:
203+
logger.debug("Received request to POST consent")
204+
# Validate body - beyond the scope of sandbox - assume body is valid for scenario
205+
json = request.get_json()
206+
patient_identifier = json["performer"][0]["identifier"]["value"]
207+
response = None
208+
209+
# Successful parent-child proxy creation
210+
# Successful adult-adult proxy creation
211+
if patient_identifier == "9000000009" or patient_identifier == "9000000017":
212+
header = {"location": f"{APP_BASE_PATH}/{patient_identifier}"}
213+
response = generate_response_from_example(POST_CONSENT__SUCCESS, 201, headers=header)
214+
215+
# Invalid access level
216+
elif patient_identifier == "9000000025":
217+
response = generate_response_from_example(POST_CONSENT__INVALID_ACCESS_LEVEL_ERROR, 400)
218+
219+
# Missing required evidence
220+
elif patient_identifier == "9000000033":
221+
response = generate_response_from_example(POST_CONSENT__INVALID_EVIDENCE_ERROR, 422)
222+
223+
# Patient age validation failure
224+
elif patient_identifier == "9000000041":
225+
response = generate_response_from_example(POST_CONSENT__INVALID_PATIENT_AGE_ERROR, 422)
226+
227+
# Duplicate relationship
228+
elif patient_identifier == "9000000049":
229+
response = generate_response_from_example(POST_CONSENT__DUPLICATE_RELATIONSHIP_ERROR, 409)
230+
231+
# Invalid performer NHS number
232+
elif patient_identifier == "9000000000":
233+
response = generate_response_from_example(POST_CONSENT__PERFORMER_IDENTIFIER_ERROR, 400)
234+
235+
else:
236+
# Out of scope errors
237+
raise ValueError("Invalid Request")
238+
239+
return response
240+
241+
except Exception as e:
242+
# Handle any general error
243+
logger.error(e)
244+
return generate_response_from_example(INTERNAL_SERVER_ERROR_EXAMPLE, 500)

sandbox/api/constants.py

Lines changed: 44 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -10,77 +10,69 @@
1010

1111
# Common examples
1212
INTERNAL_SERVER_ERROR_EXAMPLE = "./api/examples/errors/internal-server-error.yaml"
13-
BAD_REQUEST_INCLUDE_PARAM_INVALID = (
14-
"./api/examples/errors/invalid-include-parameter.yaml"
15-
)
13+
BAD_REQUEST_INCLUDE_PARAM_INVALID = "./api/examples/errors/invalid-include-parameter.yaml"
1614
INVALIDATED_RESOURCE = "./api/examples/errors/invalidated-resource.yaml"
1715
MISSING_IDENTIFIER = "./api/examples/errors/missing-identifier.yaml"
1816
INVALID_IDENTIFIER = "./api/examples/errors/invalid-identifier.yaml"
1917

20-
# Consent examples
21-
CONSENT__DIRECTORY = "./api/examples/GET_Consent/"
22-
CONSENT__FILTERED_RELATIONSHIPS_STATUS_ACTIVE = (
23-
f"{CONSENT__DIRECTORY}filtered-relationships-status-active-include-details.yaml"
24-
)
25-
CONSENT__FILTERED_RELATIONSHIPS_STATUS_INACTIVE = (
26-
f"{CONSENT__DIRECTORY}filtered-relationships-status-inactive.yaml"
27-
)
28-
CONSENT__FILTERED_RELATIONSHIPS_STATUS_PROPOSED_ACTIVE = (
29-
f"{CONSENT__DIRECTORY}filtered-relationships-status-proposed-active.yaml"
18+
# GET Consent examples
19+
GET_CONSENT__DIRECTORY = "./api/examples/GET_Consent/"
20+
GET_CONSENT__FILTERED_RELATIONSHIPS_STATUS_ACTIVE = (
21+
f"{GET_CONSENT__DIRECTORY}filtered-relationships-status-active-include-details.yaml"
3022
)
31-
CONSENT__MULTIPLE_RELATIONSHIPS = f"{CONSENT__DIRECTORY}multiple-relationships.yaml"
32-
CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_BOTH = (
33-
f"{CONSENT__DIRECTORY}multiple-relationships-include-performer-patient.yaml"
23+
GET_CONSENT__FILTERED_RELATIONSHIPS_STATUS_INACTIVE = (
24+
f"{GET_CONSENT__DIRECTORY}filtered-relationships-status-inactive.yaml"
3425
)
35-
CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_PATIENT = (
36-
f"{CONSENT__DIRECTORY}multiple-relationships-include-patient.yaml"
26+
GET_CONSENT__FILTERED_RELATIONSHIPS_STATUS_PROPOSED_ACTIVE = (
27+
f"{GET_CONSENT__DIRECTORY}filtered-relationships-status-proposed-active.yaml"
3728
)
38-
CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_PERFORMER = (
39-
f"{CONSENT__DIRECTORY}multiple-relationships-include-performer.yaml"
29+
GET_CONSENT__MULTIPLE_RELATIONSHIPS = f"{GET_CONSENT__DIRECTORY}multiple-relationships.yaml"
30+
GET_CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_BOTH = (
31+
f"{GET_CONSENT__DIRECTORY}multiple-relationships-include-performer-patient.yaml"
4032
)
41-
CONSENT__NO_RELATIONSHIPS = f"{CONSENT__DIRECTORY}no-relationships.yaml"
42-
CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP = (
43-
f"{CONSENT__DIRECTORY}single-consenting-adult-relationship.yaml"
33+
GET_CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_PATIENT = (
34+
f"{GET_CONSENT__DIRECTORY}multiple-relationships-include-patient.yaml"
4435
)
45-
CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP_INCLUDE_BOTH = (
46-
f"{CONSENT__DIRECTORY}single-consenting-adult-relationship-include-performer-patient.yaml"
36+
GET_CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_PERFORMER = (
37+
f"{GET_CONSENT__DIRECTORY}multiple-relationships-include-performer.yaml"
4738
)
48-
CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP = (
49-
f"{CONSENT__DIRECTORY}single-mother-child-relationship.yaml"
39+
GET_CONSENT__NO_RELATIONSHIPS = f"{GET_CONSENT__DIRECTORY}no-relationships.yaml"
40+
GET_CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP = f"{GET_CONSENT__DIRECTORY}single-consenting-adult-relationship.yaml"
41+
GET_CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP_INCLUDE_BOTH = (
42+
f"{GET_CONSENT__DIRECTORY}single-consenting-adult-relationship-include-performer-patient.yaml"
5043
)
51-
CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP_INCLUDE_BOTH = (
52-
f"{CONSENT__DIRECTORY}single-mother-child-relationship-include-performer-patient.yaml"
44+
GET_CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP = f"{GET_CONSENT__DIRECTORY}single-mother-child-relationship.yaml"
45+
GET_CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP_INCLUDE_BOTH = (
46+
f"{GET_CONSENT__DIRECTORY}single-mother-child-relationship-include-performer-patient.yaml"
5347
)
54-
CONSENT__STATUS_PARAM_INVALID = (
55-
f"{CONSENT__DIRECTORY}errors/invalid-status-parameter.yaml"
48+
GET_CONSENT__STATUS_PARAM_INVALID = f"{GET_CONSENT__DIRECTORY}errors/invalid-status-parameter.yaml"
49+
50+
# POST Consent
51+
POST_CONSENT__DIRECTORY = "./api/examples/POST_Consent/"
52+
# POST_CONSENT__BAD_REQUEST
53+
POST_CONSENT__SUCCESS = f"{POST_CONSENT__DIRECTORY}success.yaml"
54+
POST_CONSENT__DUPLICATE_RELATIONSHIP_ERROR = (
55+
f"{POST_CONSENT__DIRECTORY}errors/PostConsentDuplicateRelationshipError.yaml"
56+
)
57+
POST_CONSENT__INVALID_ACCESS_LEVEL_ERROR = f"{POST_CONSENT__DIRECTORY}errors/PostConsentInvalidAccessLevelError.yaml"
58+
POST_CONSENT__INVALID_EVIDENCE_ERROR = f"{POST_CONSENT__DIRECTORY}errors/PostConsentInvalidEvidenceError.yaml"
59+
POST_CONSENT__INVALID_PATIENT_AGE_ERROR = f"{POST_CONSENT__DIRECTORY}errors/PostConsentInvalidPatientAgeError.yaml"
60+
POST_CONSENT__PERFORMER_IDENTIFIER_ERROR = (
61+
f"{POST_CONSENT__DIRECTORY}errors/PostConsentInvalidPerformerIdentifierError.yaml"
5662
)
5763

5864
QR_DIRECTORY = "./api/examples/POST_QuestionnaireResponse/"
5965
QUESTIONNAIRE_RESPONSE__SUCCESS = f"{QR_DIRECTORY}success.yaml"
6066

6167
RELATED_DIRECTORY = "./api/examples/GET_RelatedPerson/"
62-
RELATED__ERROR_IDENTIFIER_MISSING = (
63-
f"{RELATED_DIRECTORY}errors/invalid-identifier-missing.yaml"
64-
)
65-
RELATED__ERROR_IDENTIFIER_SYSTEM = (
66-
f"{RELATED_DIRECTORY}errors/invalid-identifier-system.yaml"
67-
)
68+
RELATED__ERROR_IDENTIFIER_MISSING = f"{RELATED_DIRECTORY}errors/invalid-identifier-missing.yaml"
69+
RELATED__ERROR_IDENTIFIER_SYSTEM = f"{RELATED_DIRECTORY}errors/invalid-identifier-system.yaml"
6870
RELATED__ERROR_IDENTIFIER = f"{RELATED_DIRECTORY}errors/invalid-identifier.yaml"
6971
RELATED__EMPTY_RESPONSE = f"{RELATED_DIRECTORY}empty_response.yaml"
7072
RELATED__LIST_RELATIONSHIP = f"{RELATED_DIRECTORY}list_relationship_9000000017.yaml"
71-
RELATED__LIST_RELATIONSHIP_WITH_INCLUDE = (
72-
f"{RELATED_DIRECTORY}list_relationship_9000000017_include.yaml"
73-
)
74-
RELATED__VERIFY_RELATIONSHIP_09 = (
75-
f"{RELATED_DIRECTORY}verify_relationship_9000000009.yaml"
76-
)
77-
RELATED__VERIFY_RELATIONSHIP_09_WITH_INCLUDE = (
78-
f"{RELATED_DIRECTORY}verify_relationship_9000000009_include.yaml"
79-
)
80-
RELATED__VERIFY_RELATIONSHIP_25 = (
81-
f"{RELATED_DIRECTORY}verify_relationship_9000000025.yaml"
82-
)
83-
RELATED__VERIFY_RELATIONSHIP_25_WITH_INCLUDE = (
84-
f"{RELATED_DIRECTORY}verify_relationship_9000000025_include.yaml"
85-
)
73+
RELATED__LIST_RELATIONSHIP_WITH_INCLUDE = f"{RELATED_DIRECTORY}list_relationship_9000000017_include.yaml"
74+
RELATED__VERIFY_RELATIONSHIP_09 = f"{RELATED_DIRECTORY}verify_relationship_9000000009.yaml"
75+
RELATED__VERIFY_RELATIONSHIP_09_WITH_INCLUDE = f"{RELATED_DIRECTORY}verify_relationship_9000000009_include.yaml"
76+
RELATED__VERIFY_RELATIONSHIP_25 = f"{RELATED_DIRECTORY}verify_relationship_9000000025.yaml"
77+
RELATED__VERIFY_RELATIONSHIP_25_WITH_INCLUDE = f"{RELATED_DIRECTORY}verify_relationship_9000000025_include.yaml"
8678
RELATED__EMPTY_RESPONSE = f"{RELATED_DIRECTORY}empty_response_9000000033.yaml"

0 commit comments

Comments
 (0)