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

Large diffs are not rendered by default.

335 changes: 235 additions & 100 deletions postman/validated_relationship_service.sandbox.postman_collection.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions sandbox/api/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
POST_CONSENT__SUCCESS = f"{POST_CONSENT__DIRECTORY}success.yaml"
POST_CONSENT__DUPLICATE_RELATIONSHIP_ERROR = f"{POST_CONSENT__DIRECTORY}errors/duplicate_relationship_error.yaml"
POST_CONSENT__PERFORMER_IDENTIFIER_ERROR = f"{POST_CONSENT__DIRECTORY}errors/invalid_performer_identifier_error.yaml"
POST_CONSENT__MISSING_FREE_TEXT_FOR_OTHER = f"{POST_CONSENT__DIRECTORY}errors/missing_free_text_for_other.yaml"

# PATCH Consent
PATCH_CONSENT__DIRECTORY = "./api/examples/PATCH_Consent/"
Expand All @@ -93,6 +94,7 @@
PATCH_CONSENT__INVALID_STATUS_REASON = f"{PATCH_CONSENT__DIRECTORY}errors/invalid_status_reason.yaml"
PATCH_CONSENT__RESOURCE_NOT_FOUND = f"{PATCH_CONSENT__DIRECTORY}errors/resource_not_found.yaml"
PATCH_CONSENT__INVALID_STATE_TRANSITION = f"{PATCH_CONSENT__DIRECTORY}errors/invalid_state_transition.yaml"
PATCH_CONSENT__MISSING_FREE_TEXT_FOR_OTHER = f"{PATCH_CONSENT__DIRECTORY}errors/missing_free_text_for_other.yaml"

# POST QuestionnaireResponse
POST_QUESTIONNAIRE_RESPONSE_DIRECTORY = "./api/examples/POST_QuestionnaireResponse/"
Expand Down
19 changes: 19 additions & 0 deletions sandbox/api/patch_consent.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
PATCH_CONSENT__RESOURCE_NOT_FOUND,
PATCH_CONSENT__SUCCESS,
PATCH_CONSENT__INVALID_STATUS_REASON,
PATCH_CONSENT__MISSING_FREE_TEXT_FOR_OTHER,
)
from .utils import generate_response_from_example

Expand Down Expand Up @@ -63,6 +64,24 @@ def patch_consent_response(id: str) -> Union[dict, tuple]:
# Invalid state transition
return generate_response_from_example(PATCH_CONSENT__INVALID_STATE_TRANSITION, 422)

# Mandatory free text for OTHER reason codes
elif id == "d4e8a6f2-1c3b-4a7e-9d2f-8b5c7e9f1a3d":
# Missing free text for OTHER reason code (should fail)
return generate_response_from_example(PATCH_CONSENT__MISSING_FREE_TEXT_FOR_OTHER, 400)

elif id == "a1b2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7":
# Valid OTHER reason code WITH free text (should succeed)
return generate_response_from_example(PATCH_CONSENT__SUCCESS, 200)

# Optional free text for non-OTHER reason codes
elif id == "b2c3d4e5-f6a7-4890-b1c2-d3e4f5a6b7c8":
# Non-OTHER reason code WITHOUT free text (should succeed)
return generate_response_from_example(PATCH_CONSENT__SUCCESS, 200)

elif id == "c3d4e5f6-a7b8-4901-c2d3-e4f5a6b7c8d9":
# Non-OTHER reason code WITH free text (should succeed)
return generate_response_from_example(PATCH_CONSENT__SUCCESS, 200)

else:
# Resource not found
return generate_response_from_example(PATCH_CONSENT__RESOURCE_NOT_FOUND, 404)
Expand Down
23 changes: 23 additions & 0 deletions sandbox/api/post_consent.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
POST_CONSENT__DUPLICATE_RELATIONSHIP_ERROR,
POST_CONSENT__PERFORMER_IDENTIFIER_ERROR,
POST_CONSENT__SUCCESS,
POST_CONSENT__MISSING_FREE_TEXT_FOR_OTHER,
)
from .utils import generate_response_from_example

Expand Down Expand Up @@ -38,9 +39,31 @@ def post_consent_response() -> Union[dict, tuple]:
# Duplicate relationship
elif patient_identifier == "9000000049":
response = generate_response_from_example(POST_CONSENT__DUPLICATE_RELATIONSHIP_ERROR, 409)

# Invalid performer NHS number
elif patient_identifier == "9000000000":
response = generate_response_from_example(POST_CONSENT__PERFORMER_IDENTIFIER_ERROR, 422)

elif patient_identifier == "9000000050":
# Missing free text for OTHER reason code (should fail)
response = generate_response_from_example(POST_CONSENT__MISSING_FREE_TEXT_FOR_OTHER, 400)

elif patient_identifier == "9000000051":
# Valid OTHER reason code WITH free text (should succeed)
header = {"location": f"{CONSENT_APP_BASE_PATH}/a1b2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7"}
response = generate_response_from_example(POST_CONSENT__SUCCESS, 201, headers=header)

# Optional free text for non-OTHER reason codes
elif patient_identifier == "9000000052":
# Non-OTHER reason code WITHOUT free text (should succeed)
header = {"location": f"{CONSENT_APP_BASE_PATH}/b2c3d4e5-f6a7-4890-b1c2-d3e4f5a6b7c8"}
response = generate_response_from_example(POST_CONSENT__SUCCESS, 201, headers=header)

elif patient_identifier == "9000000053":
# Non-OTHER reason code WITH free text (should succeed)
header = {"location": f"{CONSENT_APP_BASE_PATH}/c3d4e5f6-a7b8-4901-c2d3-e4f5a6b7c8d9"}
response = generate_response_from_example(POST_CONSENT__SUCCESS, 201, headers=header)

else:
# Out of scope errors
raise ValueError("Invalid Request")
Expand Down
21 changes: 21 additions & 0 deletions sandbox/api/tests/test_patch_consent.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
PATCH_CONSENT__RESOURCE_NOT_FOUND,
PATCH_CONSENT__SUCCESS,
PATCH_CONSENT__INVALID_STATUS_REASON,
PATCH_CONSENT__MISSING_FREE_TEXT_FOR_OTHER,
)

CONSENT_API_ENDPOINT = "/FHIR/R4/Consent"
Expand Down Expand Up @@ -44,6 +45,26 @@
PATCH_CONSENT__INVALID_STATE_TRANSITION,
422,
),
(
"d4e8a6f2-1c3b-4a7e-9d2f-8b5c7e9f1a3d",
PATCH_CONSENT__MISSING_FREE_TEXT_FOR_OTHER,
400,
),
(
"a1b2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7",
PATCH_CONSENT__SUCCESS,
200,
),
(
"b2c3d4e5-f6a7-4890-b1c2-d3e4f5a6b7c8",
PATCH_CONSENT__SUCCESS,
200,
),
(
"c3d4e5f6-a7b8-4901-c2d3-e4f5a6b7c8d9",
PATCH_CONSENT__SUCCESS,
200,
),
("xxxxxxxx", PATCH_CONSENT__RESOURCE_NOT_FOUND, 404),
("12345678", PATCH_CONSENT__RESOURCE_NOT_FOUND, 404),
],
Expand Down
25 changes: 25 additions & 0 deletions sandbox/api/tests/test_post_consent.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
POST_CONSENT__DUPLICATE_RELATIONSHIP_ERROR,
POST_CONSENT__PERFORMER_IDENTIFIER_ERROR,
POST_CONSENT__SUCCESS,
POST_CONSENT__MISSING_FREE_TEXT_FOR_OTHER,
)

CONSENT_API_ENDPOINT = "/FHIR/R4/Consent"
Expand All @@ -30,6 +31,30 @@
),
("9000000000", POST_CONSENT__PERFORMER_IDENTIFIER_ERROR, 422, None),
("9000000049", POST_CONSENT__DUPLICATE_RELATIONSHIP_ERROR, 409, None),
(
"9000000050",
POST_CONSENT__MISSING_FREE_TEXT_FOR_OTHER,
400,
None,
),
(
"9000000051",
POST_CONSENT__SUCCESS,
201,
"a1b2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7",
),
(
"9000000052",
POST_CONSENT__SUCCESS,
201,
"b2c3d4e5-f6a7-4890-b1c2-d3e4f5a6b7c8",
),
(
"9000000053",
POST_CONSENT__SUCCESS,
201,
"c3d4e5f6-a7b8-4901-c2d3-e4f5a6b7c8d9",
),
],
)
@patch("sandbox.api.post_consent.generate_response_from_example")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ ConsentMultipleRelationshipsStatusInactiveBundle:
- url: https://fhir.hl7.org.uk/StructureDefinition/Extension-statusReason
valueCodeableConcept:
coding:
- system: https://terminology.hl7.org/CodeSystem/consent-reason
code: ROLE_DEACTIVATED_END_DATE_REACHED
display: End-date reached
- system: http://terminology.hl7.org/CodeSystem/consent-reason
code: OTHER
display: Other
text: Patient would not respond to phone calls
search:
mode: match
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
PatchConsentMissingFreeTextForOtherError:
summary: Bad request when free text is missing for OTHER reason code
description: 400 error response when free text is not provided for OTHER reason codes
value:
issue:
- code: invalid
diagnostics: "Free text is required when reason code is OTHER."
details:
coding:
- code: "MISSING_FREE_TEXT_FOR_OTHER"
display: "Free text must be provided for OTHER reason codes."
system: "https://fhir.nhs.uk/R4/CodeSystem/ValidatedRelationships-ErrorOrWarningCode"
version: '1'
severity: error
resourceType: "OperationOutcome"
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
PostConsentMissingFreeTextForOtherError:
summary: Bad request when free text is missing for OTHER reason code
description: 400 error response when free text is not provided for OTHER reason codes
value:
issue:
- code: invalid
diagnostics: "Free text is required when reason code is OTHER."
details:
coding:
- code: "MISSING_FREE_TEXT_FOR_OTHER"
display: "Free text must be provided for OTHER reason codes."
system: "https://fhir.nhs.uk/R4/CodeSystem/ValidatedRelationships-ErrorOrWarningCode"
version: '1'
severity: error
resourceType: "OperationOutcome"
13 changes: 13 additions & 0 deletions specification/validated-relationships-service-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,10 @@ paths:
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| Successful parent-child proxy creation | Valid request with a legal basis of parental responsibility, with performer identifier value of `9000000009`| HTTP Status 201 and OperationOutcome response |
| Successful adult-adult proxy creation | Valid request with legal basis of consent, with performer identifier value of `9000000017` | HTTP Status 201 and OperationOutcome response |
| Valid OTHER reason code with free text | Request with reason code 'OTHER' and free text provided, performer identifier `9000000051` | HTTP Status 201 and OperationOutcome response |
| Non-OTHER reason code without free text | Request with a reason code other than 'OTHER', no free text, performer identifier `9000000052` | HTTP Status 201 and OperationOutcome response |
| Non-OTHER reason code with free text | Request with a reason code other than 'OTHER', with free text, performer identifier `9000000053` | HTTP Status 201 and OperationOutcome response |
| Missing free text for OTHER reason code | Request with reason code 'OTHER' but missing free text, performer identifier `9000000050` | HTTP Status 400 and MISSING_FREE_TEXT_FOR_OTHER error response |
| Invalid performer NHS number | Request with invalid NHS number format, with performer identifier value of `9000000000` | HTTP Status 422 and INVALID_IDENTIFIER_VALUE error response |
| Duplicate relationship | Request for relationship that already exists, with performer identifier value of `9000000049` | HTTP Status 409 and DUPLICATE_RELATIONSHIP error response |

Expand Down Expand Up @@ -792,6 +796,8 @@ paths:
$ref: "./examples/responses/POST_Consent/errors/invalid_request.yaml#/PostConsentInvalidRequestError"
postConsentInvalidFHIRRequest:
$ref: "./examples/responses/POST_Consent/errors/invalid_request.yaml#/PostConsentInvalidFHIRRequestError"
postConsentMissingFreeTextForOther:
$ref: "./examples/responses/POST_Consent/errors/missing_free_text_for_other.yaml#/PostConsentMissingFreeTextForOtherError"

"5XX":
description: |
Expand Down Expand Up @@ -966,12 +972,17 @@ paths:
| Successful status update | Valid patch changing status to 'active', request with id '74eed847-ca25-4e76-8cf2-f2c2d7842a7a' | HTTP Status 200 and OperationOutcome |
| Successful access level update | Valid patch modifying the role end date, request with id '6b71ac92-baa3-4b76-b0f5-a601257e2722' | HTTP Status 200 and OperationOutcome |
| Multiple valid changes | Valid patch with multiple operations, request with id '43003db8-ffcd-4bd6-ab2f-b49b9656f9e5' | HTTP Status 200 and OperationOutcome |
| Valid OTHER reason code with free text | Patch with reason code 'OTHER' and free text, id='a1b2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7'| HTTP Status 200 and OperationOutcome |
| Non-OTHER reason code without free text | Patch with a reason code other than 'OTHER', no free text, id='b2c3d4e5-f6a7-4890-b1c2-d3e4f5a6b7c8' | HTTP Status 200 and OperationOutcome |
| Non-OTHER reason code with free text | Patch with a reason code other than 'OTHER', with free text, id='c3d4e5f6-a7b8-4901-c2d3-e4f5a6b7c8d9' | HTTP Status 200 and OperationOutcome |
| Invalid patch format | Malformed JSON patch document, request with id '849ea584-2318-471b-a24c-cee1b5ad0137' | HTTP Status 400 and INVALID_PATCH_FORMAT error response |
| Invalid path | Patch targeting non-existent element, request with id '01abb0c5-b1ac-499d-9655-9cd0b8d3588f' | HTTP Status 400 and INVALID_PATCH_PATH error response |
| Invalid status code | Patch with invalid status value, request with id '78c35330-fa2f-4934-a5dd-fff847f38de5' | HTTP Status 422 and INVALID_STATUS_CODE error response |
| Invalid status reason | Patch with invalid status reason value, request with id '51fb4df5-815a-45cd-8427-04d6558336b7' | HTTP Status 422 and INVALID_STATUS_REASON error response |
| Resource not found | Patch for non-existent Consent, request with an id not listed here | HTTP Status 404 and RESOURCE_NOT_FOUND error response |
| Invalid state transition | Patch attempting invalid status change, request with id '7b7f47b8-96e5-43eb-b733-283bf1449f2c' | HTTP Status 422 and INVALID_STATE_TRANSITION error response |
| Missing free text for OTHER reason code | Patch with reason code 'OTHER' but missing free text, id='d4e8a6f2-1c3b-4a7e-9d2f-8b5c7e9f1a3d' | HTTP Status 400 and MISSING_FREE_TEXT_FOR_OTHER error response |

parameters:
- $ref: "#/components/parameters/ConsentID"
requestBody:
Expand Down Expand Up @@ -1062,6 +1073,8 @@ paths:
$ref: "./examples/responses/PATCH_Consent/errors/invalid_status_reason.yaml#/PatchConsentInvalidStatusReasonError"
patchConsentInvalidStateTransitionError:
$ref: "./examples/responses/PATCH_Consent/errors/invalid_state_transition.yaml#/PatchConsentInvalidStateTransitionError"
patchConsentMissingFreeTextForOther:
$ref: "./examples/responses/PATCH_Consent/errors/missing_free_text_for_other.yaml#/PatchConsentMissingFreeTextForOtherError"
"5XX":
description: |
Errors will be returned for the first error encountered in the request. An error occurred as follows:
Expand Down