Skip to content

Commit fc29146

Browse files
authored
Merge pull request #721 from NHSDigital/feature/eema1-NRL-476-validateStatus
NRL-476 validate status as current
2 parents 10e6770 + 057a088 commit fc29146

File tree

14 files changed

+352
-15
lines changed

14 files changed

+352
-15
lines changed

api/consumer/swagger.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,7 @@ components:
788788
description: Other identifiers associated with the document, including version independent identifiers.
789789
status:
790790
type: string
791-
pattern: "[^\\s]+(\\s[^\\s]+)*"
791+
pattern: "^current$"
792792
description: The status of this document reference.
793793
docStatus:
794794
type: string

api/producer/createDocumentReference/tests/test_create_document_reference.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,54 @@ def test_create_document_reference_invalid_category_type():
472472
}
473473

474474

475+
@mock_aws
476+
@mock_repository
477+
def test_create_document_reference_cannot_set_status_to_not_current(repository):
478+
doc_ref = load_document_reference("Y05868-736253002-Valid")
479+
doc_pointer = DocumentPointer.from_document_reference(doc_ref)
480+
repository.create(doc_pointer)
481+
482+
doc_ref.status = "somethingElse"
483+
484+
event = create_test_api_gateway_event(
485+
headers=create_headers(),
486+
path_parameters={"id": "Y05868-99999-99999-999999"},
487+
body=doc_ref.model_dump_json(exclude_none=True),
488+
)
489+
490+
result = handler(event, create_mock_context())
491+
492+
body = result.pop("body")
493+
494+
assert result == {
495+
"statusCode": "400",
496+
"headers": default_response_headers(),
497+
"isBase64Encoded": False,
498+
}
499+
parsed_body = json.loads(body)
500+
501+
assert parsed_body == {
502+
"resourceType": "OperationOutcome",
503+
"issue": [
504+
{
505+
"severity": "error",
506+
"code": "invalid",
507+
"details": {
508+
"coding": [
509+
{
510+
"code": "MESSAGE_NOT_WELL_FORMED",
511+
"display": "Message not well formed",
512+
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
513+
}
514+
]
515+
},
516+
"diagnostics": "Request body could not be parsed (status: String should match pattern '^current$')",
517+
"expression": ["status"],
518+
}
519+
],
520+
}
521+
522+
475523
def test_create_document_reference_no_relatesto_target():
476524
doc_ref = load_document_reference("Y05868-736253002-Valid")
477525
doc_ref.relatesTo = [

api/producer/swagger.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1324,7 +1324,7 @@ components:
13241324
description: Other identifiers associated with the document, including version independent identifiers.
13251325
status:
13261326
type: string
1327-
pattern: "[^\\s]+(\\s[^\\s]+)*"
1327+
pattern: "^current$"
13281328
description: The status of this document reference.
13291329
docStatus:
13301330
type: string

api/producer/updateDocumentReference/tests/test_update_document_reference.py

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
handler,
1010
)
1111
from nrlf.core.dynamodb.repository import DocumentPointer, DocumentPointerRepository
12-
from nrlf.producer.fhir.r4.model import DocumentReference
12+
from nrlf.producer.fhir.r4.model import CodeableConcept, Coding, DocumentReference
1313
from nrlf.tests.data import load_document_reference
1414
from nrlf.tests.dynamodb import mock_repository
1515
from nrlf.tests.events import (
@@ -478,7 +478,22 @@ def test_update_document_reference_immutable_fields(repository):
478478
doc_pointer = DocumentPointer.from_document_reference(doc_ref)
479479
repository.create(doc_pointer)
480480

481-
doc_ref.status = "draft"
481+
doc_ref.type = CodeableConcept(
482+
id=None,
483+
coding=[
484+
Coding(
485+
id=None,
486+
system="http://snomed.info/sct",
487+
version=None,
488+
code="1213324",
489+
display="Some Code",
490+
userSelected=None,
491+
)
492+
],
493+
text=None,
494+
extension=None,
495+
)
496+
482497
event = create_test_api_gateway_event(
483498
headers=create_headers(),
484499
path_parameters={"id": "Y05868-99999-99999-999999"},
@@ -511,7 +526,55 @@ def test_update_document_reference_immutable_fields(repository):
511526
}
512527
]
513528
},
514-
"diagnostics": "The field 'status' is immutable and cannot be updated",
529+
"diagnostics": "The field 'type' is immutable and cannot be updated",
530+
"expression": ["type"],
531+
}
532+
],
533+
}
534+
535+
536+
@mock_aws
537+
@mock_repository
538+
def test_update_document_reference_cannot_change_status_to_not_current(repository):
539+
doc_ref = load_document_reference("Y05868-736253002-Valid")
540+
doc_pointer = DocumentPointer.from_document_reference(doc_ref)
541+
repository.create(doc_pointer)
542+
543+
doc_ref.status = "somethingElse"
544+
545+
event = create_test_api_gateway_event(
546+
headers=create_headers(),
547+
path_parameters={"id": "Y05868-99999-99999-999999"},
548+
body=doc_ref.model_dump_json(exclude_none=True),
549+
)
550+
551+
result = handler(event, create_mock_context())
552+
553+
body = result.pop("body")
554+
555+
assert result == {
556+
"statusCode": "400",
557+
"headers": default_response_headers(),
558+
"isBase64Encoded": False,
559+
}
560+
parsed_body = json.loads(body)
561+
562+
assert parsed_body == {
563+
"resourceType": "OperationOutcome",
564+
"issue": [
565+
{
566+
"severity": "error",
567+
"code": "invalid",
568+
"details": {
569+
"coding": [
570+
{
571+
"code": "MESSAGE_NOT_WELL_FORMED",
572+
"display": "Message not well formed",
573+
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
574+
}
575+
]
576+
},
577+
"diagnostics": "Request body could not be parsed (status: String should match pattern '^current$')",
515578
"expression": ["status"],
516579
}
517580
],
@@ -821,8 +884,6 @@ def test_update_document_reference_existing_invalid_json(
821884
doc_pointer.document = "invalid json"
822885
repository.create(doc_pointer)
823886

824-
doc_ref.status = "draft"
825-
826887
event = create_test_api_gateway_event(
827888
headers=create_headers(),
828889
path_parameters={"id": "Y05868-99999-99999-999999"},

api/producer/upsertDocumentReference/tests/test_upsert_document_reference.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,54 @@ def test_upsert_document_reference_happy_path_with_ssp(
145145
}
146146

147147

148+
@mock_aws
149+
@mock_repository
150+
def test_upsert_document_reference_cannot_set_status_to_not_current(repository):
151+
doc_ref = load_document_reference("Y05868-736253002-Valid")
152+
doc_pointer = DocumentPointer.from_document_reference(doc_ref)
153+
repository.create(doc_pointer)
154+
155+
doc_ref.status = "somethingElse"
156+
157+
event = create_test_api_gateway_event(
158+
headers=create_headers(),
159+
path_parameters={"id": "Y05868-99999-99999-999999"},
160+
body=doc_ref.model_dump_json(exclude_none=True),
161+
)
162+
163+
result = handler(event, create_mock_context())
164+
165+
body = result.pop("body")
166+
167+
assert result == {
168+
"statusCode": "400",
169+
"headers": default_response_headers(),
170+
"isBase64Encoded": False,
171+
}
172+
parsed_body = json.loads(body)
173+
174+
assert parsed_body == {
175+
"resourceType": "OperationOutcome",
176+
"issue": [
177+
{
178+
"severity": "error",
179+
"code": "invalid",
180+
"details": {
181+
"coding": [
182+
{
183+
"code": "MESSAGE_NOT_WELL_FORMED",
184+
"display": "Message not well formed",
185+
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
186+
}
187+
]
188+
},
189+
"diagnostics": "Request body could not be parsed (status: String should match pattern '^current$')",
190+
"expression": ["status"],
191+
}
192+
],
193+
}
194+
195+
148196
def test_upsert_document_reference_invalid_category_type():
149197
doc_ref = load_document_reference("Y05868-736253002-Valid")
150198

layer/nrlf/consumer/fhir/r4/model.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# generated by datamodel-codegen:
22
# filename: swagger.yaml
3-
# timestamp: 2024-10-21T12:20:36+00:00
3+
# timestamp: 2024-10-28T10:30:48+00:00
44

55
from __future__ import annotations
66

@@ -568,8 +568,7 @@ class DocumentReference(BaseModel):
568568
status: Annotated[
569569
str,
570570
Field(
571-
description="The status of this document reference.",
572-
pattern="[^\\s]+(\\s[^\\s]+)*",
571+
description="The status of this document reference.", pattern="^current$"
573572
),
574573
]
575574
docStatus: Annotated[

layer/nrlf/producer/fhir/r4/model.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# generated by datamodel-codegen:
22
# filename: swagger.yaml
3-
# timestamp: 2024-10-21T12:20:33+00:00
3+
# timestamp: 2024-10-28T10:30:43+00:00
44

55
from __future__ import annotations
66

@@ -552,8 +552,7 @@ class DocumentReference(BaseModel):
552552
status: Annotated[
553553
str,
554554
Field(
555-
description="The status of this document reference.",
556-
pattern="[^\\s]+(\\s[^\\s]+)*",
555+
description="The status of this document reference.", pattern="^current$"
557556
),
558557
]
559558
docStatus: Annotated[

layer/nrlf/producer/fhir/r4/strict_model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# generated by datamodel-codegen:
22
# filename: swagger.yaml
3-
# timestamp: 2024-10-21T12:20:35+00:00
3+
# timestamp: 2024-10-28T10:30:45+00:00
44

55
from __future__ import annotations
66

tests/features/producer/createDocumentReference-failure.feature

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,44 @@ Feature: Producer - createDocumentReference - Failure Scenarios
219219
}
220220
"""
221221

222+
Scenario: Invalid status
223+
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
224+
And the organisation 'X26' is authorised to access pointer types:
225+
| system | value |
226+
| http://snomed.info/sct | 1363501000000100 |
227+
| http://snomed.info/sct | 736253002 |
228+
When producer 'X26' creates a DocumentReference with values:
229+
| property | value |
230+
| subject | 9999999999 |
231+
| type | 736253002 |
232+
| category | 734163000 |
233+
| custodian | X26 |
234+
| author | HAR1 |
235+
| url | https://example.org/my-doc.pdf |
236+
| status | invalid |
237+
Then the response status code is 400
238+
And the response is an OperationOutcome with 1 issue
239+
And the OperationOutcome contains the issue:
240+
"""
241+
{
242+
"severity": "error",
243+
"code": "invalid",
244+
"details": {
245+
"coding": [
246+
{
247+
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
248+
"code": "MESSAGE_NOT_WELL_FORMED",
249+
"display": "Message not well formed"
250+
}
251+
]
252+
},
253+
"diagnostics": "Request body could not be parsed (status: String should match pattern '^current$')",
254+
"expression": [
255+
"status"
256+
]
257+
}
258+
"""
259+
222260
# Credentials - missing pointer type for create
223261
Scenario: Producer lacks the permission for the pointer type requested
224262
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API

tests/features/producer/updateDocumentReference-failure.feature

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,47 @@
44
# Invalid document reference - changing immutable fields
55
# Provider ID mismatch
66
# No existing document reference
7+
Feature: Producer - updateDocumentReference - Failure Scenarios
8+
9+
Scenario: Invalid status
10+
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
11+
And the organisation 'X26' is authorised to access pointer types:
12+
| system | value |
13+
| http://snomed.info/sct | 1363501000000100 |
14+
| http://snomed.info/sct | 736253002 |
15+
And a DocumentReference resource exists with values:
16+
| property | value |
17+
| id | X26-1114567890-updateDocTest |
18+
| subject | 9999999999 |
19+
| status | current |
20+
| type | 736253002 |
21+
| category | 734163000 |
22+
| contentType | application/pdf |
23+
| url | https://example.org/my-doc.pdf |
24+
| custodian | X26 |
25+
| author | X26 |
26+
When producer 'X26' updates a DocumentReference 'X26-1114567890-updateDocTest' with values:
27+
| property | value |
28+
| status | invalid |
29+
Then the response status code is 400
30+
And the response is an OperationOutcome with 1 issue
31+
And the OperationOutcome contains the issue:
32+
"""
33+
{
34+
"severity": "error",
35+
"code": "invalid",
36+
"details": {
37+
"coding": [
38+
{
39+
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
40+
"code": "MESSAGE_NOT_WELL_FORMED",
41+
"display": "Message not well formed"
42+
}
43+
]
44+
},
45+
"diagnostics": "Request body could not be parsed (status: String should match pattern '^current$')",
46+
"expression": [
47+
"status"
48+
]
49+
}
50+
"""

0 commit comments

Comments
 (0)