11from logging import INFO , basicConfig , getLogger
22from typing import Union
3-
43from flask import Flask , request
54
65from .constants import (
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)
2934from .utils import (
3035 check_for_empty ,
4146app = Flask (__name__ )
4247basicConfig (level = INFO , format = "%(asctime)s - %(message)s" )
4348logger = getLogger (__name__ )
49+ APP_BASE_PATH = "https://sandbox.api.service.nhs.uk/validated-relationships/FHIR/R4/Consent"
4450COMMON_PATH = "FHIR/R4"
4551
4652
@@ -107,8 +113,8 @@ def get_related_persons() -> Union[dict, tuple]:
107113
108114 raise ValueError ("Invalid request" )
109115
110- except Exception as e :
111- logger .error ( e )
116+ except Exception :
117+ logger .exception ( "GET related person failed" )
112118 return generate_response_from_example (INTERNAL_SERVER_ERROR_EXAMPLE , 500 )
113119
114120
@@ -122,8 +128,8 @@ def post_questionnaire_response() -> Union[dict, tuple]:
122128
123129 try :
124130 return generate_response_from_example (QUESTIONNAIRE_RESPONSE__SUCCESS , 200 )
125- except Exception as e :
126- logger .error ( e )
131+ except Exception :
132+ logger .exception ( "POST questionnaire response failed" )
127133 return generate_response_from_example (INTERNAL_SERVER_ERROR_EXAMPLE , 500 )
128134
129135
@@ -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
184- except Exception as e :
185- logger .error (e )
190+ except Exception :
191+ logger .exception ("GET Consent failed" )
192+ 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 :
242+ # Handle any general error
243+ logger .exception ("POST Consent failed" )
186244 return generate_response_from_example (INTERNAL_SERVER_ERROR_EXAMPLE , 500 )
0 commit comments