Skip to content

Commit b1cba0a

Browse files
Merge branch 'develop' into feature/axkr1-NRL-518-validate-context
Conflicts: - layer/nrlf/core/tests/test_validators.py - layer/nrlf/core/validators.py - tests/features/utils/data.py
2 parents 64e6312 + cb1375b commit b1cba0a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+4158
-274
lines changed

api/consumer/searchDocumentReference/search_document_reference.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from nrlf.core.logger import LogReference, logger
1010
from nrlf.core.model import ConnectionMetadata, ConsumerRequestParams
1111
from nrlf.core.response import Response, SpineErrorResponse
12-
from nrlf.core.validators import validate_category, validate_type_system
12+
from nrlf.core.validators import validate_category, validate_type
1313

1414

1515
@request_handler(params=ConsumerRequestParams)
@@ -46,8 +46,7 @@ def handler(
4646
base_url = f"https://{config.ENVIRONMENT}.api.service.nhs.uk/"
4747
self_link = f"{base_url}record-locator/consumer/FHIR/R4/DocumentReference?subject:identifier=https://fhir.nhs.uk/Id/nhs-number|{params.nhs_number}"
4848

49-
# TODO - Add checks for the type code as well as system
50-
if not validate_type_system(params.type, metadata.pointer_types):
49+
if not validate_type(params.type, metadata.pointer_types):
5150
logger.log(
5251
LogReference.CONSEARCH002,
5352
type=params.type,

api/consumer/searchPostDocumentReference/search_post_document_reference.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from nrlf.core.logger import LogReference, logger
1010
from nrlf.core.model import ConnectionMetadata, ConsumerRequestParams
1111
from nrlf.core.response import Response, SpineErrorResponse
12-
from nrlf.core.validators import validate_category, validate_type_system
12+
from nrlf.core.validators import validate_category, validate_type
1313

1414

1515
@request_handler(body=ConsumerRequestParams)
@@ -50,7 +50,7 @@ def handler(
5050
base_url = f"https://{config.ENVIRONMENT}.api.service.nhs.uk/"
5151
self_link = f"{base_url}record-locator/consumer/FHIR/R4/DocumentReference?subject:identifier=https://fhir.nhs.uk/Id/nhs-number|{body.nhs_number}"
5252

53-
if not validate_type_system(body.type, metadata.pointer_types):
53+
if not validate_type(body.type, metadata.pointer_types):
5454
logger.log(
5555
LogReference.CONPOSTSEARCH002,
5656
type=body.type,

api/producer/searchDocumentReference/search_document_reference.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from nrlf.core.logger import LogReference, logger
77
from nrlf.core.model import ConnectionMetadata, ProducerRequestParams
88
from nrlf.core.response import Response, SpineErrorResponse
9-
from nrlf.core.validators import validate_category, validate_type_system
9+
from nrlf.core.validators import validate_category, validate_type
1010
from nrlf.producer.fhir.r4.model import Bundle, DocumentReference
1111

1212

@@ -48,7 +48,7 @@ def handler(
4848
expression="subject:identifier",
4949
)
5050

51-
if not validate_type_system(params.type, metadata.pointer_types):
51+
if not validate_type(params.type, metadata.pointer_types):
5252
logger.log(
5353
LogReference.PROSEARCH002,
5454
type=params.type,

api/producer/searchPostDocumentReference/search_post_document_reference.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from nrlf.core.logger import LogReference, logger
77
from nrlf.core.model import ConnectionMetadata, ProducerRequestParams
88
from nrlf.core.response import Response, SpineErrorResponse
9-
from nrlf.core.validators import validate_category, validate_type_system
9+
from nrlf.core.validators import validate_category, validate_type
1010
from nrlf.producer.fhir.r4.model import Bundle, DocumentReference
1111

1212

@@ -42,7 +42,7 @@ def handler(
4242
expression="subject:identifier",
4343
)
4444

45-
if not validate_type_system(body.type, metadata.pointer_types):
45+
if not validate_type(body.type, metadata.pointer_types):
4646
logger.log(
4747
LogReference.PROPOSTSEARCH002,
4848
type=body.type,

layer/nrlf/core/constants.py

Lines changed: 472 additions & 0 deletions
Large diffs are not rendered by default.

layer/nrlf/core/tests/test_validators.py

Lines changed: 218 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from nrlf.core.validators import (
1414
DocumentReferenceValidator,
1515
ValidationResult,
16-
validate_type_system,
16+
validate_type,
1717
)
1818
from nrlf.producer.fhir.r4.model import (
1919
DocumentReference,
@@ -23,28 +23,37 @@
2323
from nrlf.tests.data import load_document_reference_json
2424

2525

26-
def test_validate_type_system_valid():
26+
def test_validate_type_valid():
2727
type_ = RequestQueryType(root=PointerTypes.MENTAL_HEALTH_PLAN.value)
2828
pointer_types = [
2929
PointerTypes.MENTAL_HEALTH_PLAN.value,
3030
PointerTypes.EOL_CARE_PLAN.value,
3131
]
32-
assert validate_type_system(type_, pointer_types) is True
32+
assert validate_type(type_, pointer_types) is True
3333

3434

35-
def test_validate_type_system_invalid():
35+
def test_validate_type_invalid_system():
3636
type_ = RequestQueryType(root="http://snomed.info/invalid|736373009")
3737
pointer_types = [
3838
PointerTypes.EOL_CARE_PLAN.value,
3939
PointerTypes.EOL_CARE_PLAN.value,
4040
]
41-
assert validate_type_system(type_, pointer_types) is False
41+
assert validate_type(type_, pointer_types) is False
4242

4343

44-
def test_validate_type_system_empty():
44+
def test_validate_type_invalid_code():
45+
type_ = RequestQueryType(root=PointerTypes.MRA_UPPER_LIMB_ARTERY.value)
46+
pointer_types = [
47+
PointerTypes.MENTAL_HEALTH_PLAN.value,
48+
PointerTypes.EOL_CARE_PLAN.value,
49+
]
50+
assert validate_type(type_, pointer_types) is False
51+
52+
53+
def test_validate_type_empty():
4554
type_ = None
4655
pointer_types: list[str] = []
47-
assert validate_type_system(type_, pointer_types) is True
56+
assert validate_type(type_, pointer_types) is True
4857

4958

5059
def test_validation_result_reset():
@@ -1430,3 +1439,205 @@ def test_validate_nrl_format_code_display_mismatch(
14301439
"diagnostics": f"Invalid display for format code '{format_code}'. Expected '{expected_display}'",
14311440
"expression": ["content[0].format.display"],
14321441
}
1442+
1443+
1444+
def test_validate_practiceSetting_no_coding():
1445+
validator = DocumentReferenceValidator()
1446+
document_ref_data = load_document_reference_json("Y05868-736253002-Valid")
1447+
1448+
document_ref_data["context"]["practiceSetting"] = {
1449+
"text": "Description of the clinic"
1450+
}
1451+
1452+
result = validator.validate(document_ref_data)
1453+
1454+
assert result.is_valid is False
1455+
assert len(result.issues) == 1
1456+
assert result.issues[0].model_dump(exclude_none=True) == {
1457+
"severity": "error",
1458+
"code": "value",
1459+
"details": {
1460+
"coding": [
1461+
{
1462+
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
1463+
"code": "INVALID_RESOURCE",
1464+
"display": "Invalid validation of resource",
1465+
}
1466+
]
1467+
},
1468+
"diagnostics": "Invalid practice setting: must contain a Coding",
1469+
"expression": ["context.practiceSetting.coding"],
1470+
}
1471+
1472+
1473+
def test_validate_practiceSetting_coding_invalid_system():
1474+
validator = DocumentReferenceValidator()
1475+
document_ref_data = load_document_reference_json("Y05868-736253002-Valid")
1476+
1477+
document_ref_data["context"]["practiceSetting"] = {
1478+
"coding": [
1479+
{
1480+
"system": "http://snoooooomed/sctfffffg",
1481+
"code": "788002001",
1482+
"display": "Adult mental health service",
1483+
}
1484+
]
1485+
}
1486+
1487+
result = validator.validate(document_ref_data)
1488+
1489+
assert result.is_valid is False
1490+
assert len(result.issues) == 1
1491+
assert result.issues[0].model_dump(exclude_none=True) == {
1492+
"severity": "error",
1493+
"code": "value",
1494+
"details": {
1495+
"coding": [
1496+
{
1497+
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
1498+
"code": "INVALID_RESOURCE",
1499+
"display": "Invalid validation of resource",
1500+
}
1501+
]
1502+
},
1503+
"diagnostics": "Invalid practice setting system: http://snoooooomed/sctfffffg Practice Setting system must be 'http://snomed.info/sct'",
1504+
"expression": ["context.practiceSetting.coding[0].system"],
1505+
}
1506+
1507+
1508+
def test_validate_practiceSetting_coding_invalid_code():
1509+
validator = DocumentReferenceValidator()
1510+
document_ref_data = load_document_reference_json("Y05868-736253002-Valid")
1511+
1512+
document_ref_data["context"]["practiceSetting"] = {
1513+
"coding": [
1514+
{
1515+
"system": "http://snomed.info/sct",
1516+
"code": "123",
1517+
"display": "Adult mental health service",
1518+
}
1519+
]
1520+
}
1521+
1522+
result = validator.validate(document_ref_data)
1523+
1524+
assert result.is_valid is False
1525+
assert len(result.issues) == 1
1526+
assert result.issues[0].model_dump(exclude_none=True) == {
1527+
"severity": "error",
1528+
"code": "value",
1529+
"details": {
1530+
"coding": [
1531+
{
1532+
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
1533+
"code": "INVALID_RESOURCE",
1534+
"display": "Invalid validation of resource",
1535+
}
1536+
]
1537+
},
1538+
"diagnostics": "Invalid practice setting code: 123 Practice Setting coding must be a member of value set https://fhir.nhs.uk/England/ValueSet/England-PracticeSetting",
1539+
"expression": ["context.practiceSetting.coding[0].code"],
1540+
}
1541+
1542+
1543+
def test_validate_practiceSetting_coding_missing_code():
1544+
validator = DocumentReferenceValidator()
1545+
document_ref_data = load_document_reference_json("Y05868-736253002-Valid")
1546+
1547+
document_ref_data["context"]["practiceSetting"] = {
1548+
"coding": [
1549+
{
1550+
"system": "http://snomed.info/sct",
1551+
"display": "Adult mental health service",
1552+
}
1553+
]
1554+
}
1555+
1556+
result = validator.validate(document_ref_data)
1557+
1558+
assert result.is_valid is False
1559+
assert len(result.issues) == 1
1560+
assert result.issues[0].model_dump(exclude_none=True) == {
1561+
"severity": "error",
1562+
"code": "value",
1563+
"details": {
1564+
"coding": [
1565+
{
1566+
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
1567+
"code": "INVALID_RESOURCE",
1568+
"display": "Invalid validation of resource",
1569+
}
1570+
]
1571+
},
1572+
"diagnostics": "Invalid practice setting code: None Practice Setting coding must be a member of value set https://fhir.nhs.uk/England/ValueSet/England-PracticeSetting",
1573+
"expression": ["context.practiceSetting.coding[0].code"],
1574+
}
1575+
1576+
1577+
def test_validate_practiceSetting_coding_missing_display():
1578+
validator = DocumentReferenceValidator()
1579+
document_ref_data = load_document_reference_json("Y05868-736253002-Valid")
1580+
1581+
document_ref_data["context"]["practiceSetting"] = {
1582+
"coding": [
1583+
{
1584+
"system": "http://snomed.info/sct",
1585+
"code": "788002001",
1586+
}
1587+
]
1588+
}
1589+
1590+
result = validator.validate(document_ref_data)
1591+
1592+
assert result.is_valid is False
1593+
assert len(result.issues) == 1
1594+
assert result.issues[0].model_dump(exclude_none=True) == {
1595+
"severity": "error",
1596+
"code": "value",
1597+
"details": {
1598+
"coding": [
1599+
{
1600+
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
1601+
"code": "INVALID_RESOURCE",
1602+
"display": "Invalid validation of resource",
1603+
}
1604+
]
1605+
},
1606+
"diagnostics": "Invalid practice setting coding: display None does not match the expected display for 788002001 Practice Setting coding is bound to value set https://fhir.nhs.uk/England/ValueSet/England-PracticeSetting",
1607+
"expression": ["context.practiceSetting.coding[0]"],
1608+
}
1609+
1610+
1611+
def test_validate_practiceSetting_coding_mismatch_code_and_display():
1612+
validator = DocumentReferenceValidator()
1613+
document_ref_data = load_document_reference_json("Y05868-736253002-Valid")
1614+
1615+
document_ref_data["context"]["practiceSetting"] = {
1616+
"coding": [
1617+
{
1618+
"system": "http://snomed.info/sct",
1619+
"code": "788002001",
1620+
"display": "Nephrology service",
1621+
}
1622+
]
1623+
}
1624+
1625+
result = validator.validate(document_ref_data)
1626+
1627+
assert result.is_valid is False
1628+
assert len(result.issues) == 1
1629+
assert result.issues[0].model_dump(exclude_none=True) == {
1630+
"severity": "error",
1631+
"code": "value",
1632+
"details": {
1633+
"coding": [
1634+
{
1635+
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
1636+
"code": "INVALID_RESOURCE",
1637+
"display": "Invalid validation of resource",
1638+
}
1639+
]
1640+
},
1641+
"diagnostics": "Invalid practice setting coding: display Nephrology service does not match the expected display for 788002001 Practice Setting coding is bound to value set https://fhir.nhs.uk/England/ValueSet/England-PracticeSetting",
1642+
"expression": ["context.practiceSetting.coding[0]"],
1643+
}

0 commit comments

Comments
 (0)