Skip to content

Commit 4818d96

Browse files
eesa456axelkrastek1-nhs
authored andcommitted
NRL-936 add validation to create for category and type
1 parent f0554c1 commit 4818d96

File tree

5 files changed

+64
-49
lines changed

5 files changed

+64
-49
lines changed

api/producer/createDocumentReference/create_document_reference.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from nrlf.core.constants import (
55
PERMISSION_AUDIT_DATES_FROM_PAYLOAD,
66
PERMISSION_SUPERSEDE_IGNORE_DELETE_FAIL,
7+
TYPE_CATEGORIES,
78
)
89
from nrlf.core.decorators import request_handler
910
from nrlf.core.dynamodb.repository import DocumentPointer, DocumentPointerRepository
@@ -90,6 +91,19 @@ def _check_permissions(
9091
expression="type.coding[0].code",
9192
)
9293

94+
type_category = TYPE_CATEGORIES.get(core_model.type)
95+
if type_category != core_model.category:
96+
logger.log(
97+
LogReference.PROCREATE005a,
98+
ods_code=metadata.ods_code,
99+
type=core_model.type,
100+
category=core_model.category,
101+
)
102+
return SpineErrorResponse.BAD_REQUEST(
103+
diagnostics=f"The Category code of the provided document '{core_model.category}' must match the allowed category for pointer type '{core_model.type}' with a category value of '{type_category}'",
104+
expression="category.coding[0].code",
105+
)
106+
93107

94108
def _get_document_ids_to_supersede(
95109
resource: DocumentReference,

api/producer/createDocumentReference/tests/test_create_document_reference.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,51 @@ def test_create_document_reference_invalid_pointer_type():
424424
}
425425

426426

427+
def test_create_document_reference_invalid_category_type():
428+
doc_ref = load_document_reference("Y05868-736253002-Valid")
429+
430+
assert doc_ref.category and doc_ref.category[0].coding
431+
doc_ref.category[0].coding[0].code = "1102421000000108"
432+
doc_ref.category[0].coding[0].display = "Observations"
433+
434+
event = create_test_api_gateway_event(
435+
headers=create_headers(),
436+
body=doc_ref.json(exclude_none=True),
437+
)
438+
439+
result = handler(event, create_mock_context())
440+
body = result.pop("body")
441+
442+
assert result == {
443+
"statusCode": "400",
444+
"headers": {},
445+
"isBase64Encoded": False,
446+
}
447+
448+
parsed_body = json.loads(body)
449+
450+
assert parsed_body == {
451+
"resourceType": "OperationOutcome",
452+
"issue": [
453+
{
454+
"severity": "error",
455+
"code": "invalid",
456+
"details": {
457+
"coding": [
458+
{
459+
"code": "BAD_REQUEST",
460+
"display": "Bad request",
461+
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
462+
}
463+
]
464+
},
465+
"diagnostics": "The Category code of the provided document 'http://snomed.info/sct|1102421000000108' must match the allowed category for pointer type 'http://snomed.info/sct|736253002' with a category value of 'http://snomed.info/sct|734163000'",
466+
"expression": ["category.coding[0].code"],
467+
}
468+
],
469+
}
470+
471+
427472
def test_create_document_reference_no_relatesto_target():
428473
doc_ref = load_document_reference("Y05868-736253002-Valid")
429474
doc_ref.relatesTo = [

layer/nrlf/core/log_references.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ class LogReference(Enum):
210210
PROCREATE005 = _Reference(
211211
"WARN", "Organisation is not allowed to create pointer type"
212212
) #
213+
PROCREATE005a = _Reference(
214+
"WARN",
215+
"Organisation is not allowed to create pointer type with incorrect category",
216+
) #
213217
PROCREATE006 = _Reference("DEBUG", "Performing relatesTo validation on resource")
214218
PROCREATE007a = _Reference(
215219
"WARN", "RelatesTo validation failed - no target identifier value"

layer/nrlf/core/tests/test_validators.py

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -485,42 +485,6 @@ def test_validate_category_coding_display_mismatch_observations():
485485
}
486486

487487

488-
def test_validate_category_coding_and_type_mismatch():
489-
validator = DocumentReferenceValidator()
490-
document_ref_data = load_document_reference_json("Y05868-736253002-Valid")
491-
492-
document_ref_data["category"][0] = {
493-
"coding": [
494-
{
495-
"system": "http://snomed.info/sct",
496-
"code": "1102421000000108",
497-
"display": "Observations",
498-
}
499-
]
500-
}
501-
502-
result = validator.validate(document_ref_data)
503-
504-
assert result.is_valid is False
505-
assert result.resource.id == "Y05868-99999-99999-999999"
506-
assert len(result.issues) == 1
507-
assert result.issues[0].dict(exclude_none=True) == {
508-
"severity": "error",
509-
"code": "value",
510-
"details": {
511-
"coding": [
512-
{
513-
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
514-
"code": "INVALID_RESOURCE",
515-
"display": "Invalid validation of resource",
516-
}
517-
]
518-
},
519-
"diagnostics": "category code '1102421000000108' must match the allowed category for pointer type 736253002 with a category value of '734163000'",
520-
"expression": ["category[0].coding[0].code"],
521-
}
522-
523-
524488
def test_validate_category_coding_invalid_code():
525489
validator = DocumentReferenceValidator()
526490
document_ref_data = load_document_reference_json("Y05868-736253002-Valid")

layer/nrlf/core/validators.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pydantic import ValidationError
66

77
from nrlf.core.codes import SpineErrorConcept
8-
from nrlf.core.constants import CATEGORIES, REQUIRED_CREATE_FIELDS, TYPE_CATEGORIES
8+
from nrlf.core.constants import CATEGORIES, REQUIRED_CREATE_FIELDS
99
from nrlf.core.errors import ParseError
1010
from nrlf.core.logger import LogReference, logger
1111
from nrlf.core.types import DocumentReference, OperationOutcomeIssue, RequestQueryType
@@ -392,18 +392,6 @@ def _validate_category(self, model: DocumentReference):
392392
)
393393
return
394394

395-
pointer_type = model.type.coding[0].code
396-
type_category = TYPE_CATEGORIES[f"http://snomed.info/sct|{pointer_type}"].split(
397-
"|"
398-
)[1]
399-
if type_category != coding.code:
400-
self.result.add_error(
401-
issue_code="value",
402-
error_code="INVALID_RESOURCE",
403-
diagnostics=f"category code '{coding.code}' must match the allowed category for pointer type {pointer_type} with a category value of '{type_category}'",
404-
field=f"category[0].coding[{0}].code",
405-
)
406-
407395
def _validate_content_extension(self, model: DocumentReference):
408396
"""
409397
Validate the content.extension field contains an appropriate coding.

0 commit comments

Comments
 (0)