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
11 changes: 10 additions & 1 deletion layer/nrlf/core/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ class PointerTypes(Enum):
APPOINTMENT = "http://snomed.info/sct|749001000000101"
SHARED_CARE_RECORD = "http://snomed.info/sct|887181000000106"
ABOUT_ME = "http://snomed.info/sct|1515851000000101" # NOSONAR (S5332) This is a type code, not an actual URL
DISCHARGE_PLAN = (
"https://fhir.nhs.uk/England/CodeSystem/England-NRLRecordType|HDTAP"
)

@staticmethod
def list():
Expand Down Expand Up @@ -194,6 +197,7 @@ def coding_value(self):
},
PointerTypes.SHARED_CARE_RECORD.value: {"display": "Clinical summary"},
PointerTypes.ABOUT_ME.value: {"display": "About me"},
PointerTypes.DISCHARGE_PLAN.value: {"display": "Hospital Discharge to Assess Plan"},
}

TYPE_CATEGORIES = {
Expand Down Expand Up @@ -228,6 +232,7 @@ def coding_value(self):
#
# Clinical documents
PointerTypes.ABOUT_ME.value: Categories.CLINICAL_DOCUMENT.value,
PointerTypes.DISCHARGE_PLAN.value: Categories.CLINICAL_DOCUMENT.value,
}

#
Expand Down Expand Up @@ -711,7 +716,11 @@ def coding_value(self):
}


SYSTEM_SHORT_IDS = {"http://snomed.info/sct": "SCT", "https://nicip.nhs.uk": "NICIP"}
SYSTEM_SHORT_IDS = {
"http://snomed.info/sct": "SCT",
"https://nicip.nhs.uk": "NICIP",
"https://fhir.nhs.uk/England/CodeSystem/England-NRLRecordType": "NRL",
}
CONTENT_STABILITY_EXTENSION_URL = (
"https://fhir.nhs.uk/England/StructureDefinition/Extension-England-ContentStability"
)
Expand Down
2 changes: 1 addition & 1 deletion layer/nrlf/core/dynamodb/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def validate_type(cls, type: str) -> str:
Validate the type of the DocumentPointer
The type should be in the format <system>|<code>
"""
if not re.match(r"^[A-Za-z0-9:/\.]+\|[A-Za-z0-9]+$", type):
if not re.match(r"^[A-Za-z0-9:/\.\-]+\|[A-Za-z0-9]+$", type):
raise ValueError("type must be in the format <system>|<code>")

return type
Expand Down
2 changes: 1 addition & 1 deletion layer/nrlf/core/tests/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ def test_validate_type_coding_invalid_system():
}
]
},
"diagnostics": "Invalid type system: http://snoooooomed/sctfffffg Type system must be either 'http://snomed.info/sct' or 'https://nicip.nhs.uk'",
"diagnostics": "Invalid type system: http://snoooooomed/sctfffffg Type system must be either 'http://snomed.info/sct', 'https://nicip.nhs.uk' or 'https://fhir.nhs.uk/England/CodeSystem/England-NRLRecordType'",
"expression": ["type.coding[0].system"],
}

Expand Down
8 changes: 6 additions & 2 deletions layer/nrlf/core/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,11 +351,15 @@ def _validate_type(self, model: DocumentReference):
return

coding = model.type.coding[0]
if coding.system not in ["http://snomed.info/sct", "https://nicip.nhs.uk"]:
if coding.system not in [
"http://snomed.info/sct",
"https://nicip.nhs.uk",
"https://fhir.nhs.uk/England/CodeSystem/England-NRLRecordType",
Comment thread
anjalitrace2-nhs marked this conversation as resolved.
]:
self.result.add_error(
issue_code="business-rule",
error_code="UNPROCESSABLE_ENTITY",
diagnostics=f"Invalid type system: {coding.system} Type system must be either 'http://snomed.info/sct' or 'https://nicip.nhs.uk'",
diagnostics=f"Invalid type system: {coding.system} Type system must be either 'http://snomed.info/sct', 'https://nicip.nhs.uk' or 'https://fhir.nhs.uk/England/CodeSystem/England-NRLRecordType'",
field="type.coding[0].system",
)
return
Expand Down
34 changes: 34 additions & 0 deletions resources/fhir/NRLF-RecordType-CodeSystem.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"resourceType": "CodeSystem",
"id": "England-NRLRecordType",
"url": "https://fhir.nhs.uk/England/CodeSystem/England-NRLRecordType",
"version": "1.1.0",
"name": "EnglandNRLRecordType",
"title": "England NRL Record Typê",
"status": "draft",
"experimental": false,
"date": "2026-04-28",
"publisher": "NHS England",
"contact": [
{
"name": "NRL Team at NHS Digital",
"telecom": [
{
"system": "email",
"value": "nrls@nhs.net",
"use": "work"
}
]
}
],
"description": "A CodeSystem to define types of DocumentReference that can be published and retrieved via NHS England's National Record Locator v3 APIs.",
"copyright": "Copyright © 2026+ NHS England Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. HL7® FHIR® standard Copyright © 2011+ HL7 The HL7® FHIR® standard is used under the FHIR license. You may obtain a copy of the FHIR license at https://www.hl7.org/fhir/license.html.",
"content": "complete",
"concept": [
{
"code": "HDTAP",
"display": "Hospital Discharge to Assess Plan",
"definition": "A \\\"Discharge to Assess\\\" (D2A) plan. D2A is a model whereby people with new or additional health and/or social care needs on discharge receive post-discharge recovery support, and where assessments of longer-term or ongoing needs (if required) are fully completed only once a person has reached a point of recovery and stability."
}
]
}
13 changes: 11 additions & 2 deletions resources/fhir/NRLF-RecordType-ValueSet.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"resourceType": "ValueSet",
"id": "NRLF-RecordType",
"url": "https://fhir.nhs.uk/England/ValueSet/England-NRLRecordType",
"version": "1.1.4",
"version": "1.1.6",
Comment thread
anjalitrace2-nhs marked this conversation as resolved.
"name": "NRLF Record Type",
"status": "draft",
"date": "2025-08-14T00:00:00+00:00",
"date": "2026-04-27T00:00:00+00:00",
"publisher": "NHS Digital",
"contact": {
"name": "NRL Team at NHS Digital",
Expand Down Expand Up @@ -84,6 +84,15 @@
}
]
},
{
"system": "https://fhir.nhs.uk/England/CodeSystem/England-NRLRecordType",
"concept": [
{
"code": "HDTAP",
"display": "Hospital Discharge to Assess Plan"
}
]
},
{
"system": "https://nicip.nhs.uk",
"concept": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ Feature: Producer - createDocumentReference - Failure Scenarios
}
]
},
"diagnostics": "Invalid type system: http://invalidsystem.info/sct Type system must be either 'http://snomed.info/sct' or 'https://nicip.nhs.uk'",
"diagnostics": "Invalid type system: http://invalidsystem.info/sct Type system must be either 'http://snomed.info/sct', 'https://nicip.nhs.uk' or 'https://fhir.nhs.uk/England/CodeSystem/England-NRLRecordType'",
"expression": ["type.coding[0].system"]
}
"""
Expand Down
49 changes: 49 additions & 0 deletions tests/features/producer/createDocumentReference-success.feature
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,55 @@ Feature: Producer - createDocumentReference - Success Scenarios
| formatCode | urn:nhs-ic:structured |
| formatDisplay | Structured Document |

Scenario: Successfully create a Document Pointer (non-SNOMED type)
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
And the organisation 'ANGY1' is authorised to access pointer types:
| system | value |
| https://fhir.nhs.uk/England/CodeSystem/England-NRLRecordType | HDTAP |
When producer 'ANGY1' creates a DocumentReference with values:
| property | value |
| subject | 9278693472 |
| status | current |
| type | HDTAP |
| type_system | https://fhir.nhs.uk/England/CodeSystem/England-NRLRecordType |
| category | 423876004 |
| custodian | ANGY1 |
| author | HAR1 |
| url | https://example.org/my-doc.pdf |
| practiceSetting | 224891009 |
Then the response status code is 201
And the response is an OperationOutcome with 1 issue
And the OperationOutcome contains the issue:
"""
{
"severity": "information",
"code": "informational",
"details": {
"coding": [
{
"system": "https://fhir.nhs.uk/ValueSet/NRL-ResponseCode",
"code": "RESOURCE_CREATED",
"display": "Resource created"
}
]
},
"diagnostics": "The document has been created"
}
"""
And the response has a Location header
And the Location header starts with '/DocumentReference/ANGY1-'
And the resource in the Location header exists with values:
| property | value |
| subject | 9278693472 |
| status | current |
| type | HDTAP |
| type_system | https://fhir.nhs.uk/England/CodeSystem/England-NRLRecordType |
| category | 423876004 |
| custodian | ANGY1 |
| author | HAR1 |
| url | https://example.org/my-doc.pdf |
| practiceSetting | 224891009 |

Scenario: Successfully create a DocumentReference with two contents and different retrieval mechanisms
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
And the organisation 'TSTCUS' is authorised to access pointer types:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ Feature: Producer - upsertDocumentReference - Failure Scenarios
}
]
},
"diagnostics": "Invalid type system: http://invalidsystem.info/sct Type system must be either 'http://snomed.info/sct' or 'https://nicip.nhs.uk'",
"diagnostics": "Invalid type system: http://invalidsystem.info/sct Type system must be either 'http://snomed.info/sct', 'https://nicip.nhs.uk' or 'https://fhir.nhs.uk/England/CodeSystem/England-NRLRecordType'",
"expression": ["type.coding[0].system"]
}
"""
Expand Down
Loading