Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
27e4c86
NRL-1053 add category parameter to search requests
eesa456 Nov 10, 2024
000c691
NRL-1053 fix import
eesa456 Nov 10, 2024
ddfdf7d
NRL-1053 fix log and tests
eesa456 Nov 10, 2024
4b5bc39
NRL-1053 add category to components yaml for query params
eesa456 Nov 12, 2024
9a20a21
Merge branch 'develop' of github.com:NHSDigital/NRLF into feature/eem…
eesa456 Nov 12, 2024
e1e280d
NRL-1053 add import back
eesa456 Nov 12, 2024
062c31e
NRL-1053 add to api spec yaml
eesa456 Nov 12, 2024
a3175e4
Merge branch 'develop' of github.com:NHSDigital/NRLF into feature/eem…
eesa456 Nov 12, 2024
656bfad
NRL-1053 add category param
eesa456 Nov 12, 2024
7fbc81b
NRL-1053 add unit tests
eesa456 Nov 12, 2024
58b8086
NRL-1053 fix type and category filter expression issue
eesa456 Nov 13, 2024
3d043c3
NRL-1053 update performance tests
eesa456 Nov 13, 2024
e61078a
Merge branch 'develop' of github.com:NHSDigital/NRLF into feature/eem…
eesa456 Nov 13, 2024
969ff8f
NRL-1053 add feature tests
eesa456 Nov 13, 2024
d29c6ca
NRL-1053 fix tests by adding system in
eesa456 Nov 13, 2024
311e522
NRL-1053 fix category filter if no type filter
eesa456 Nov 13, 2024
7d37727
NRL-1053 fix failure test
eesa456 Nov 13, 2024
051fb83
NRL-1053 fix category expression value
eesa456 Nov 13, 2024
5fbd070
NRL-1053 fix test steps
eesa456 Nov 13, 2024
0dced15
NRL-1053 fix message for test
eesa456 Nov 13, 2024
912137f
NRL-1053 fix repository and perf tests
eesa456 Nov 13, 2024
f606179
NRL-1053 fix performance tests
eesa456 Nov 13, 2024
68dcb45
NRL-1053 PR comments
eesa456 Nov 14, 2024
f813b47
NRL-1053 do not allow invalid/extra params for consumer search
eesa456 Nov 18, 2024
8e1c186
NRL-1053 update models
eesa456 Nov 19, 2024
9adad71
Merge branch 'develop' into feature/eema1-NRL-1053-searchByCategory
eesa456 Nov 19, 2024
236afbb
NRL-1053 tests
eesa456 Nov 19, 2024
b61f1f2
Merge branch 'feature/eema1-NRL-1053-searchByCategory' of github.com:…
eesa456 Nov 19, 2024
02b5ca2
NRL-1053 remove npt
eesa456 Nov 19, 2024
50b3dca
NRL-1053 revert models
eesa456 Nov 19, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from nrlf.core.logger import LogReference, logger
from nrlf.core.model import ConnectionMetadata, ConsumerRequestParams
from nrlf.core.response import Response, SpineErrorResponse
from nrlf.core.validators import validate_type_system
from nrlf.core.validators import validate_category, validate_type_system


@request_handler(params=ConsumerRequestParams)
Expand Down Expand Up @@ -58,6 +58,16 @@ def handler(
expression="type",
)

if not validate_category(params.category):
logger.log(
LogReference.CONSEARCH002b,
category=params.category,
) # TODO - Should update error message once permissioning by category is implemented
return SpineErrorResponse.INVALID_CODE_SYSTEM(
diagnostics="Invalid query parameter (The provided category is not valid)",
expression="category",
)

custodian_id = (
params.custodian_identifier.root.split("|", maxsplit=1)[1]
if params.custodian_identifier
Expand All @@ -70,6 +80,9 @@ def handler(
if params.type:
self_link += f"&type={params.type.root}"

if params.category:
self_link += f"&category={params.category.root}"

bundle = {
"resourceType": "Bundle",
"type": "searchset",
Expand All @@ -89,6 +102,7 @@ def handler(
nhs_number=params.nhs_number,
custodian=custodian_id,
pointer_types=pointer_types,
categories=[params.category.root] if params.category else [],
):
try:
document_reference = DocumentReference.model_validate_json(result.document)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,47 @@ def test_search_document_reference_happy_path_with_type(
}


@mock_aws
@mock_repository
def test_search_document_reference_happy_path_with_category(
repository: DocumentPointerRepository,
):
doc_ref = load_document_reference("Y05868-736253002-Valid")
doc_pointer = DocumentPointer.from_document_reference(doc_ref)
repository.create(doc_pointer)

event = create_test_api_gateway_event(
headers=create_headers(),
query_string_parameters={
"subject:identifier": "https://fhir.nhs.uk/Id/nhs-number|6700028191",
"category": "http://snomed.info/sct|734163000",
},
)

result = handler(event, create_mock_context())
body = result.pop("body")

assert result == {
"statusCode": "200",
"headers": default_response_headers(),
"isBase64Encoded": False,
}

parsed_body = json.loads(body)
assert parsed_body == {
"resourceType": "Bundle",
"type": "searchset",
"link": [
{
"relation": "self",
"url": "https://pytest.api.service.nhs.uk/record-locator/consumer/FHIR/R4/DocumentReference?subject:identifier=https://fhir.nhs.uk/Id/nhs-number|6700028191&category=http://snomed.info/sct|734163000",
}
],
"total": 1,
"entry": [{"resource": doc_ref.model_dump(exclude_none=True)}],
}


@mock_aws
@mock_repository
def test_search_document_reference_happy_path_with_nicip_type(
Expand Down Expand Up @@ -342,6 +383,51 @@ def test_search_document_reference_invalid_type(repository: DocumentPointerRepos
}


@mock_aws
@mock_repository
def test_search_document_reference_invalid_category(
repository: DocumentPointerRepository,
):
event = create_test_api_gateway_event(
headers=create_headers(),
query_string_parameters={
"subject:identifier": "https://fhir.nhs.uk/Id/nhs-number|6700028191",
"category": "https://fhir.nhs.uk/CodeSystem/Document-Type|invalid",
},
)

result = handler(event, create_mock_context())
body = result.pop("body")

assert result == {
"statusCode": "400",
"headers": default_response_headers(),
"isBase64Encoded": False,
}

parsed_body = json.loads(body)
assert parsed_body == {
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "code-invalid",
"details": {
"coding": [
{
"code": "INVALID_CODE_SYSTEM",
"display": "Invalid code system",
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
}
]
},
"diagnostics": "Invalid query parameter (The provided category is not valid)",
"expression": ["category"],
}
],
}


@mock_aws
@mock_repository
def test_search_document_reference_invalid_json(repository: DocumentPointerRepository):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from nrlf.core.logger import LogReference, logger
from nrlf.core.model import ConnectionMetadata, ConsumerRequestParams
from nrlf.core.response import Response, SpineErrorResponse
from nrlf.core.validators import validate_type_system
from nrlf.core.validators import validate_category, validate_type_system


@request_handler(body=ConsumerRequestParams)
Expand Down Expand Up @@ -61,6 +61,16 @@ def handler(
expression="type",
)

if not validate_category(body.category):
logger.log(
LogReference.CONPOSTSEARCH002b,
type=body.category,
) # TODO - Should update error message once permissioning by category is implemented
return SpineErrorResponse.INVALID_CODE_SYSTEM(
diagnostics="The provided category is not valid",
expression="category",
)

custodian_id = (
body.custodian_identifier.root.split("|", maxsplit=1)[1]
if body.custodian_identifier
Expand All @@ -73,6 +83,9 @@ def handler(
if body.type:
self_link += f"&type={body.type.root}"

if body.category:
self_link += f"&category={body.category.root}"

bundle = {
"resourceType": "Bundle",
"type": "searchset",
Expand All @@ -89,7 +102,10 @@ def handler(
)

for result in repository.search(
nhs_number=body.nhs_number, custodian=custodian_id, pointer_types=pointer_types
nhs_number=body.nhs_number,
custodian=custodian_id,
pointer_types=pointer_types,
categories=[body.category.root] if body.category else [],
):
try:
document_reference = DocumentReference.model_validate_json(result.document)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,49 @@ def test_search_post_document_reference_happy_path_with_type(
}


@mock_aws
@mock_repository
def test_search_post_document_reference_happy_path_with_category(
repository: DocumentPointerRepository,
):
doc_ref = load_document_reference("Y05868-736253002-Valid")
doc_pointer = DocumentPointer.from_document_reference(doc_ref)
repository.create(doc_pointer)

event = create_test_api_gateway_event(
headers=create_headers(),
body=json.dumps(
{
"subject:identifier": "https://fhir.nhs.uk/Id/nhs-number|6700028191",
"category": "http://snomed.info/sct|734163000",
},
),
)

result = handler(event, create_mock_context())
body = result.pop("body")

assert result == {
"statusCode": "200",
"headers": default_response_headers(),
"isBase64Encoded": False,
}

parsed_body = json.loads(body)
assert parsed_body == {
"resourceType": "Bundle",
"type": "searchset",
"link": [
{
"relation": "self",
"url": "https://pytest.api.service.nhs.uk/record-locator/consumer/FHIR/R4/DocumentReference?subject:identifier=https://fhir.nhs.uk/Id/nhs-number|6700028191&category=http://snomed.info/sct|734163000",
}
],
"total": 1,
"entry": [{"resource": doc_ref.model_dump(exclude_none=True)}],
}


@mock_aws
@mock_repository
def test_search_document_reference_no_results(repository: DocumentPointerRepository):
Expand Down Expand Up @@ -310,6 +353,53 @@ def test_search_post_document_reference_invalid_type(
}


@mock_aws
@mock_repository
def test_search_document_reference_invalid_category(
repository: DocumentPointerRepository,
):
event = create_test_api_gateway_event(
headers=create_headers(),
body=json.dumps(
{
"subject:identifier": "https://fhir.nhs.uk/Id/nhs-number|6700028191",
"category": "https://fhir.nhs.uk/CodeSystem/Document-Type|invalid",
}
),
)

result = handler(event, create_mock_context())
body = result.pop("body")

assert result == {
"statusCode": "400",
"headers": default_response_headers(),
"isBase64Encoded": False,
}

parsed_body = json.loads(body)
assert parsed_body == {
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "code-invalid",
"details": {
"coding": [
{
"code": "INVALID_CODE_SYSTEM",
"display": "Invalid code system",
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
}
]
},
"diagnostics": "The provided category is not valid",
"expression": ["category"],
}
],
}


@mock_aws
@mock_repository
def test_search_post_document_reference_invalid_json(
Expand Down
33 changes: 33 additions & 0 deletions api/consumer/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ paths:
- $ref: "#/components/parameters/subject"
- $ref: "#/components/parameters/custodian"
- $ref: "#/components/parameters/type"
- $ref: "#/components/parameters/category"
- $ref: "#/components/parameters/nextPageToken"
- $ref: "#/components/parameters/odsCode"
- $ref: "#/components/parameters/odsCodeExtension"
Expand Down Expand Up @@ -1399,6 +1400,8 @@ components:
$ref: "#/components/schemas/RequestQueryCustodian"
type:
$ref: "#/components/schemas/RequestQueryType"
category:
$ref: "#/components/schemas/RequestQueryCategory"
next-page-token:
$ref: "#/components/schemas/NextPageToken"
required:
Expand All @@ -1421,6 +1424,9 @@ components:
RequestQueryType:
type: string
example: "http://snomed.info/sct|736253002"
RequestQueryCategory:
type: string
example: "http://snomed.info/sct|103693007"
NextPageToken:
type: string
RequestHeaderOdsCode:
Expand Down Expand Up @@ -1531,6 +1537,33 @@ components:
invalid:
summary: Unknown
value: http://snomed.info/sct|410970009
category:
name: category
in: query
schema:
$ref: "#/components/schemas/RequestQueryCategory"
examples:
none:
summary: None
value: ""
SNOMED_CODES_CARE_PLAN:
summary: Care plan
value: http://snomed.info/sct|734163000
SNOMED_CODES_OBSERVATIONS:
summary: Observations
value: http://snomed.info/sct|1102421000000108
SNOMED_CODES_CLINICAL_NOTE:
summary: Clinical note
value: http://snomed.info/sct|823651000000106
SNOMED_CODES_DIAGNOSTIC_STUDIES_REPORT:
summary: Diagnostic studies report
value: http://snomed.info/sct|721981007
SNOMED_CODES_DIAGNOSTIC_PROCEDURE:
summary: Diagnostic procedure
value: http://snomed.info/sct|103693007
invalid:
summary: Unknown
value: http://snomed.info/sct|410970009
nextPageToken:
name: next-page-token
description: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from nrlf.core.logger import LogReference, logger
from nrlf.core.model import ConnectionMetadata, ProducerRequestParams
from nrlf.core.response import Response, SpineErrorResponse
from nrlf.core.validators import validate_type_system
from nrlf.core.validators import validate_category, validate_type_system
from nrlf.producer.fhir.r4.model import Bundle, DocumentReference


Expand Down Expand Up @@ -59,6 +59,16 @@ def handler(
expression="type",
)

if not validate_category(params.category):
logger.log(
LogReference.PROSEARCH002b,
type=params.category,
) # TODO - Should update error message once permissioning by category is implemented
return SpineErrorResponse.INVALID_CODE_SYSTEM(
diagnostics="Invalid query parameter (The provided category is not valid)",
expression="category",
)

pointer_types = [params.type.root] if params.type else metadata.pointer_types
bundle = {"resourceType": "Bundle", "type": "searchset", "total": 0, "entry": []}

Expand All @@ -68,13 +78,15 @@ def handler(
custodian_suffix=metadata.ods_code_extension,
nhs_number=params.nhs_number,
pointer_types=pointer_types,
categories=[params.category.root] if params.category else [],
)

for result in repository.search(
custodian=metadata.ods_code,
custodian_suffix=metadata.ods_code_extension,
nhs_number=params.nhs_number,
pointer_types=pointer_types,
categories=[params.category.root] if params.category else [],
):
try:
document_reference = DocumentReference.model_validate_json(result.document)
Expand Down
Loading