Skip to content

Commit 0eb6eb7

Browse files
committed
NPA-4689 Refactor endpoints into seperate files
1 parent 144e810 commit 0eb6eb7

File tree

13 files changed

+417
-221
lines changed

13 files changed

+417
-221
lines changed

sandbox/api/app.py

Lines changed: 21 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,18 @@
11
from logging import INFO, basicConfig, getLogger
22
from typing import Union
3-
from flask import Flask, request
4-
5-
from .constants import (
6-
INTERNAL_SERVER_ERROR_EXAMPLE,
7-
QUESTIONNAIRE_RESPONSE__SUCCESS,
8-
RELATED__LIST_RELATIONSHIP,
9-
RELATED__LIST_RELATIONSHIP_WITH_INCLUDE,
10-
RELATED__VERIFY_RELATIONSHIP_09,
11-
RELATED__VERIFY_RELATIONSHIP_09_WITH_INCLUDE,
12-
RELATED__VERIFY_RELATIONSHIP_25,
13-
RELATED__VERIFY_RELATIONSHIP_25_WITH_INCLUDE,
14-
POST_CONSENT__SUCCESS,
15-
POST_CONSENT__DUPLICATE_RELATIONSHIP_ERROR,
16-
POST_CONSENT__PERFORMER_IDENTIFIER_ERROR,
17-
PATCH_CONSENT__SUCCESS,
18-
PATCH_CONSENT__INVALID_PATCH_FORMAT,
19-
PATCH_CONSENT__INVALID_PATH,
20-
PATCH_CONSENT__INVALID_STATUS_CODE,
21-
PATCH_CONSENT__RESOURCE_NOT_FOUND,
22-
PATCH_CONSENT__INVALID_STATE_TRANSITION,
23-
)
3+
4+
from flask import Flask
5+
246
from .get_consent import get_consent_response
25-
from .utils import (
26-
check_for_empty,
27-
check_for_list,
28-
check_for_related_person_errors,
29-
check_for_validate,
30-
generate_response_from_example,
31-
remove_system,
32-
)
7+
from .get_related_person import get_related_person_response
8+
from .patch_consent import patch_consent_response
9+
from .post_consent import post_consent_response
10+
from .post_questionnaire_response import post_questionnaire_response_response
3311

3412
app = Flask(__name__)
3513
basicConfig(level=INFO, format="%(asctime)s - %(message)s")
3614
logger = getLogger(__name__)
37-
APP_BASE_PATH = "https://sandbox.api.service.nhs.uk/validated-relationships/FHIR/R4/Consent"
15+
3816
COMMON_PATH = "FHIR/R4"
3917

4018

@@ -56,54 +34,7 @@ def get_related_persons() -> Union[dict, tuple]:
5634
Returns:
5735
Union[dict, tuple]: Response for GET /RelatedPerson
5836
"""
59-
60-
try:
61-
# Check Headers
62-
if errors := check_for_related_person_errors(request):
63-
return errors
64-
65-
identifier = remove_system(request.args.get("identifier"))
66-
patient_identifier = remove_system(request.args.get("patient:identifier"))
67-
include = request.args.get("_include")
68-
69-
if empty := check_for_empty(identifier, patient_identifier):
70-
return empty
71-
72-
# Successful request, select response
73-
if zero_nine := check_for_validate(
74-
"9000000009",
75-
identifier,
76-
patient_identifier,
77-
include,
78-
RELATED__VERIFY_RELATIONSHIP_09,
79-
RELATED__VERIFY_RELATIONSHIP_09_WITH_INCLUDE,
80-
):
81-
return zero_nine
82-
83-
if two_five := check_for_validate(
84-
"9000000025",
85-
identifier,
86-
patient_identifier,
87-
include,
88-
RELATED__VERIFY_RELATIONSHIP_25,
89-
RELATED__VERIFY_RELATIONSHIP_25_WITH_INCLUDE,
90-
):
91-
return two_five
92-
93-
if one_seven := check_for_list(
94-
"9000000017",
95-
identifier,
96-
include,
97-
RELATED__LIST_RELATIONSHIP,
98-
RELATED__LIST_RELATIONSHIP_WITH_INCLUDE,
99-
):
100-
return one_seven
101-
102-
raise ValueError("Invalid request")
103-
104-
except Exception:
105-
logger.exception("GET related person failed")
106-
return generate_response_from_example(INTERNAL_SERVER_ERROR_EXAMPLE, 500)
37+
return get_related_person_response()
10738

10839

10940
@app.route(f"/{COMMON_PATH}/QuestionnaireResponse", methods=["POST"])
@@ -113,12 +44,7 @@ def post_questionnaire_response() -> Union[dict, tuple]:
11344
Returns:
11445
Union[dict, tuple]: Response for POST /QuestionnaireResponse
11546
"""
116-
117-
try:
118-
return generate_response_from_example(QUESTIONNAIRE_RESPONSE__SUCCESS, 200)
119-
except Exception:
120-
logger.exception("POST questionnaire response failed")
121-
return generate_response_from_example(INTERNAL_SERVER_ERROR_EXAMPLE, 500)
47+
return post_questionnaire_response_response()
12248

12349

12450
@app.route(f"/{COMMON_PATH}/Consent", methods=["GET"])
@@ -138,77 +64,17 @@ def post_consent() -> Union[dict, tuple]:
13864
Returns:
13965
Union[dict, tuple]: Response for POST /Consent
14066
"""
141-
try:
142-
logger.debug("Received request to POST consent")
143-
# Validate body - beyond the scope of sandbox - assume body is valid for scenario
144-
json = request.get_json()
145-
patient_identifier = json["performer"][0]["identifier"]["value"]
146-
response = None
147-
148-
# Successful parent-child proxy creation
149-
# Successful adult-adult proxy creation
150-
if patient_identifier == "9000000009" or patient_identifier == "9000000017":
151-
header = {"location": f"{APP_BASE_PATH}/{patient_identifier}"}
152-
response = generate_response_from_example(POST_CONSENT__SUCCESS, 201, headers=header)
153-
154-
# Duplicate relationship
155-
elif patient_identifier == "9000000049":
156-
response = generate_response_from_example(POST_CONSENT__DUPLICATE_RELATIONSHIP_ERROR, 409)
157-
# Invalid performer NHS number
158-
elif patient_identifier == "9000000000":
159-
response = generate_response_from_example(POST_CONSENT__PERFORMER_IDENTIFIER_ERROR, 422)
160-
else:
161-
# Out of scope errors
162-
raise ValueError("Invalid Request")
163-
164-
return response
165-
166-
except Exception:
167-
# Handle any general error
168-
logger.exception("POST Consent failed")
169-
return generate_response_from_example(INTERNAL_SERVER_ERROR_EXAMPLE, 500)
67+
return post_consent_response()
17068

17169

17270
@app.route(f"/{COMMON_PATH}/Consent/<identifier>", methods=["PATCH"])
173-
def patch_consent(identifier) -> Union[dict, tuple]:
174-
try:
175-
logger.debug("Received request to PATCH consent")
176-
# Validate body - validation is beyond the scope of the sandbox.
177-
# Assume all requests are valid
178-
179-
if identifier == "c6f48e4d":
180-
# Successful status update
181-
return generate_response_from_example(PATCH_CONSENT__SUCCESS, 200)
182-
183-
elif identifier == "0c56a594":
184-
# Successful end date for a role
185-
return generate_response_from_example(PATCH_CONSENT__SUCCESS, 200)
186-
187-
elif identifier == "b02ea26c":
188-
# Multiple valid changes
189-
return generate_response_from_example(PATCH_CONSENT__SUCCESS, 200)
190-
191-
elif identifier == "3a2679eb":
192-
# Invalid patch format
193-
return generate_response_from_example(PATCH_CONSENT__INVALID_PATCH_FORMAT, 400)
194-
195-
elif identifier == "94df7c8f":
196-
# Invalid path
197-
return generate_response_from_example(PATCH_CONSENT__INVALID_PATH, 400)
198-
199-
elif identifier == "2a7b736d":
200-
# Invalid status code
201-
return generate_response_from_example(PATCH_CONSENT__INVALID_STATUS_CODE, 422)
202-
203-
elif identifier == "6fb4361b":
204-
# Invalid state transition
205-
return generate_response_from_example(PATCH_CONSENT__INVALID_STATE_TRANSITION, 422)
206-
207-
else:
208-
# Resource not found
209-
return generate_response_from_example(PATCH_CONSENT__RESOURCE_NOT_FOUND, 404)
210-
211-
except Exception:
212-
# Handle any general error
213-
logger.exception("PATCH Consent failed")
214-
return generate_response_from_example(INTERNAL_SERVER_ERROR_EXAMPLE, 500)
71+
def patch_consent(identifier: str) -> Union[dict, tuple]:
72+
"""Sandbox API for PATCH /Consent
73+
74+
Args:
75+
identifier (str): Consent identifier to be patched
76+
77+
Returns:
78+
Union[dict, tuple]: Response for PATCH /Consent
79+
"""
80+
return patch_consent_response(identifier)

sandbox/api/constants.py

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010

1111
# Common examples
1212
INTERNAL_SERVER_ERROR_EXAMPLE = "./api/examples/errors/internal-server-error.yaml"
13-
BAD_REQUEST_INCLUDE_PARAM_INVALID = "./api/examples/errors/invalid-include-parameter.yaml"
13+
BAD_REQUEST_INCLUDE_PARAM_INVALID = (
14+
"./api/examples/errors/invalid-include-parameter.yaml"
15+
)
1416
INVALIDATED_RESOURCE = "./api/examples/errors/invalidated-resource.yaml"
1517
MISSING_IDENTIFIER = "./api/examples/errors/missing-identifier.yaml"
1618
INVALID_IDENTIFIER = "./api/examples/errors/invalid-identifier.yaml"
@@ -26,7 +28,9 @@
2628
GET_CONSENT__FILTERED_RELATIONSHIPS_STATUS_PROPOSED_ACTIVE = (
2729
f"{GET_CONSENT__DIRECTORY}filtered-relationships-status-proposed-active.yaml"
2830
)
29-
GET_CONSENT__MULTIPLE_RELATIONSHIPS = f"{GET_CONSENT__DIRECTORY}multiple-relationships.yaml"
31+
GET_CONSENT__MULTIPLE_RELATIONSHIPS = (
32+
f"{GET_CONSENT__DIRECTORY}multiple-relationships.yaml"
33+
)
3034
GET_CONSENT__MULTIPLE_RELATIONSHIPS_INCLUDE_BOTH = (
3135
f"{GET_CONSENT__DIRECTORY}multiple-relationships-include-performer-patient.yaml"
3236
)
@@ -37,43 +41,71 @@
3741
f"{GET_CONSENT__DIRECTORY}multiple-relationships-include-performer.yaml"
3842
)
3943
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"
44+
GET_CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP = (
45+
f"{GET_CONSENT__DIRECTORY}single-consenting-adult-relationship.yaml"
4346
)
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"
47+
GET_CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP_INCLUDE_BOTH = f"{GET_CONSENT__DIRECTORY}single-consenting-adult-relationship-include-performer-patient.yaml"
48+
GET_CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP = (
49+
f"{GET_CONSENT__DIRECTORY}single-mother-child-relationship.yaml"
50+
)
51+
GET_CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP_INCLUDE_BOTH = f"{GET_CONSENT__DIRECTORY}single-mother-child-relationship-include-performer-patient.yaml"
52+
GET_CONSENT__STATUS_PARAM_INVALID = (
53+
f"{GET_CONSENT__DIRECTORY}errors/invalid-status-parameter.yaml"
4754
)
48-
GET_CONSENT__STATUS_PARAM_INVALID = f"{GET_CONSENT__DIRECTORY}errors/invalid-status-parameter.yaml"
4955

5056
# POST Consent
5157
POST_CONSENT__DIRECTORY = "./api/examples/POST_Consent/"
5258
POST_CONSENT__SUCCESS = f"{POST_CONSENT__DIRECTORY}success.yaml"
53-
POST_CONSENT__DUPLICATE_RELATIONSHIP_ERROR = f"{POST_CONSENT__DIRECTORY}errors/duplicate_relationship_error.yaml"
54-
POST_CONSENT__PERFORMER_IDENTIFIER_ERROR = f"{POST_CONSENT__DIRECTORY}errors/invalid_performer_identifier_error.yaml"
59+
POST_CONSENT__DUPLICATE_RELATIONSHIP_ERROR = (
60+
f"{POST_CONSENT__DIRECTORY}errors/duplicate_relationship_error.yaml"
61+
)
62+
POST_CONSENT__PERFORMER_IDENTIFIER_ERROR = (
63+
f"{POST_CONSENT__DIRECTORY}errors/invalid_performer_identifier_error.yaml"
64+
)
5565

5666
# PATCH Consent
5767
PATCH_CONSENT__DIRECTORY = "./api/examples/PATCH_Consent/"
5868
PATCH_CONSENT__SUCCESS = f"{PATCH_CONSENT__DIRECTORY}success.yaml"
59-
PATCH_CONSENT__INVALID_PATCH_FORMAT = f"{PATCH_CONSENT__DIRECTORY}errors/invalid_patch_format.yaml"
69+
PATCH_CONSENT__INVALID_PATCH_FORMAT = (
70+
f"{PATCH_CONSENT__DIRECTORY}errors/invalid_patch_format.yaml"
71+
)
6072
PATCH_CONSENT__INVALID_PATH = f"{PATCH_CONSENT__DIRECTORY}errors/invalid_path.yaml"
61-
PATCH_CONSENT__INVALID_STATUS_CODE = f"{PATCH_CONSENT__DIRECTORY}errors/invalid_status_code.yaml"
62-
PATCH_CONSENT__RESOURCE_NOT_FOUND = f"{PATCH_CONSENT__DIRECTORY}errors/resource_not_found.yaml"
63-
PATCH_CONSENT__INVALID_STATE_TRANSITION = f"{PATCH_CONSENT__DIRECTORY}errors/invalid_state_transition.yaml"
73+
PATCH_CONSENT__INVALID_STATUS_CODE = (
74+
f"{PATCH_CONSENT__DIRECTORY}errors/invalid_status_code.yaml"
75+
)
76+
PATCH_CONSENT__RESOURCE_NOT_FOUND = (
77+
f"{PATCH_CONSENT__DIRECTORY}errors/resource_not_found.yaml"
78+
)
79+
PATCH_CONSENT__INVALID_STATE_TRANSITION = (
80+
f"{PATCH_CONSENT__DIRECTORY}errors/invalid_state_transition.yaml"
81+
)
6482

6583
QR_DIRECTORY = "./api/examples/POST_QuestionnaireResponse/"
6684
QUESTIONNAIRE_RESPONSE__SUCCESS = f"{QR_DIRECTORY}success.yaml"
6785

6886
RELATED_DIRECTORY = "./api/examples/GET_RelatedPerson/"
69-
RELATED__ERROR_IDENTIFIER_MISSING = f"{RELATED_DIRECTORY}errors/invalid-identifier-missing.yaml"
70-
RELATED__ERROR_IDENTIFIER_SYSTEM = f"{RELATED_DIRECTORY}errors/invalid-identifier-system.yaml"
87+
RELATED__ERROR_IDENTIFIER_MISSING = (
88+
f"{RELATED_DIRECTORY}errors/invalid-identifier-missing.yaml"
89+
)
90+
RELATED__ERROR_IDENTIFIER_SYSTEM = (
91+
f"{RELATED_DIRECTORY}errors/invalid-identifier-system.yaml"
92+
)
7193
RELATED__ERROR_IDENTIFIER = f"{RELATED_DIRECTORY}errors/invalid-identifier.yaml"
7294
RELATED__EMPTY_RESPONSE = f"{RELATED_DIRECTORY}empty_response.yaml"
7395
RELATED__LIST_RELATIONSHIP = f"{RELATED_DIRECTORY}list_relationship_9000000017.yaml"
74-
RELATED__LIST_RELATIONSHIP_WITH_INCLUDE = f"{RELATED_DIRECTORY}list_relationship_9000000017_include.yaml"
75-
RELATED__VERIFY_RELATIONSHIP_09 = f"{RELATED_DIRECTORY}verify_relationship_9000000009.yaml"
76-
RELATED__VERIFY_RELATIONSHIP_09_WITH_INCLUDE = f"{RELATED_DIRECTORY}verify_relationship_9000000009_include.yaml"
77-
RELATED__VERIFY_RELATIONSHIP_25 = f"{RELATED_DIRECTORY}verify_relationship_9000000025.yaml"
78-
RELATED__VERIFY_RELATIONSHIP_25_WITH_INCLUDE = f"{RELATED_DIRECTORY}verify_relationship_9000000025_include.yaml"
96+
RELATED__LIST_RELATIONSHIP_WITH_INCLUDE = (
97+
f"{RELATED_DIRECTORY}list_relationship_9000000017_include.yaml"
98+
)
99+
RELATED__VERIFY_RELATIONSHIP_09 = (
100+
f"{RELATED_DIRECTORY}verify_relationship_9000000009.yaml"
101+
)
102+
RELATED__VERIFY_RELATIONSHIP_09_WITH_INCLUDE = (
103+
f"{RELATED_DIRECTORY}verify_relationship_9000000009_include.yaml"
104+
)
105+
RELATED__VERIFY_RELATIONSHIP_25 = (
106+
f"{RELATED_DIRECTORY}verify_relationship_9000000025.yaml"
107+
)
108+
RELATED__VERIFY_RELATIONSHIP_25_WITH_INCLUDE = (
109+
f"{RELATED_DIRECTORY}verify_relationship_9000000025_include.yaml"
110+
)
79111
RELATED__EMPTY_RESPONSE = f"{RELATED_DIRECTORY}empty_response_9000000033.yaml"

sandbox/api/get_consent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
from flask import request
55

66
from .constants import (
7-
INTERNAL_SERVER_ERROR_EXAMPLE,
8-
INVALIDATED_RESOURCE,
97
GET_CONSENT__FILTERED_RELATIONSHIPS_STATUS_ACTIVE,
108
GET_CONSENT__FILTERED_RELATIONSHIPS_STATUS_INACTIVE,
119
GET_CONSENT__FILTERED_RELATIONSHIPS_STATUS_PROPOSED_ACTIVE,
@@ -18,6 +16,8 @@
1816
GET_CONSENT__SINGLE_CONSENTING_ADULT_RELATIONSHIP_INCLUDE_BOTH,
1917
GET_CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP,
2018
GET_CONSENT__SINGLE_MOTHER_CHILD_RELATIONSHIP_INCLUDE_BOTH,
19+
INTERNAL_SERVER_ERROR_EXAMPLE,
20+
INVALIDATED_RESOURCE,
2121
)
2222
from .utils import (
2323
check_for_consent_errors,

0 commit comments

Comments
 (0)