Skip to content

Commit 7e3c846

Browse files
Merge pull request #544 from NHSDigital/release/2024-03-14
Release/2024-03-14
2 parents 177e284 + 72e67d3 commit 7e3c846

File tree

28 files changed

+1725
-12
lines changed

28 files changed

+1725
-12
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 2024-03-14
4+
5+
- NRL-511 - Capability statements
6+
- NRL-496 - Update Format code system URL
7+
- NRL-521 - Port (duplicate) POST functionality to PUT Interaction
8+
39
## 2024-02-08
410

511
- SPINECLI-1795 Add open source links to documentation

api/producer/record-locator/producer.yaml

Lines changed: 102 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ paths:
328328
* `type` MUST match one of the Document Types agreed during [onboarding](#api-description__onboarding). e.g.
329329
```
330330
"type": {
331-
"coding\": [
331+
"coding": [
332332
{
333333
"system": "http://snomed.info/sct",
334334
"code": "1363501000000100",
@@ -340,7 +340,7 @@ paths:
340340
* `category` SHOULD indicate the broader class of the Document Type as agreed during [onboarding](#api-description__onboarding). e.g.
341341
```
342342
"type": {
343-
"coding\": [
343+
"coding": [
344344
{
345345
"system": "http://snomed.info/sct",
346346
"code": "1102421000000108",
@@ -354,7 +354,7 @@ paths:
354354
```
355355
"format": [
356356
{
357-
"system": "https://fhir.nhs.uk/STU3/CodeSystem/NRL-FormatCode-1",
357+
"system": "https://fhir.nhs.uk/England/CodeSystem/England-NRLFormatCode",
358358
"code": "urn:nhs-ic:unstructured"
359359
"display": "Unstructured document"
360360
}
@@ -628,6 +628,104 @@ paths:
628628
requests with the `next-page-token` found in the `meta` portion of the response.
629629
630630
This operation is also available as a http POST, which is the preferred method (see below).
631+
put:
632+
summary: Create document pointers with a specific id
633+
operationId: upsertDocumentReference
634+
parameters:
635+
- $ref: "#/components/parameters/odsCode"
636+
- $ref: "#/components/parameters/odsCodeExtension"
637+
- $ref: "#/components/parameters/requestId"
638+
- $ref: "#/components/parameters/correlationId"
639+
responses:
640+
"201":
641+
$ref: "#/components/responses/Success"
642+
description: Create / Supersede successful response
643+
content:
644+
application/fhir+json;version=1:
645+
example:
646+
resourceType: OperationOutcome
647+
id: 76db24dc-324a-468a-bf02-c06e82279488
648+
meta:
649+
profile:
650+
- https://fhir.nhs.uk/StructureDefinition/NHSDigital-OperationOutcome
651+
issue:
652+
- severity: information
653+
code: informational
654+
details:
655+
coding:
656+
- system: https://fhir.nhs.uk/CodeSystem/NRLF-SuccessCode
657+
code: RESOURCE_CREATED
658+
display: Resource created
659+
diagnostics: Resource created
660+
"4XX":
661+
description: |
662+
An error occurred as follows:
663+
664+
| HTTP status | Error code | Description |
665+
| ----------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
666+
| 400 | BAD_REQUEST | Bad Request |
667+
| 400 | VALIDATION_ERROR | A parameter or value has resulted in a validation error |
668+
| 400 | INVALID_RESOURCE_ID | Invalid resource ID |
669+
| 401 | ACCESS_DENIED | Access Denied |
670+
| 403 | ACCESS_DENIED | Forbidden |
671+
| 403 | ACCESS_DENIED_LEVEL | Access has been denied because you need higher level permissions |
672+
| 404 | RESOURCE_NOT_FOUND | Resource not found |
673+
| 409 | INVALID_VALUE | Invalid value |
674+
675+
The Error Code comes from https://fhir.nhs.uk/STU3/CodeSystem/Spine-ErrorOrWarningCode-1
676+
content:
677+
application/fhir+json;version=1:
678+
schema:
679+
$ref: "#/components/schemas/OperationOutcome"
680+
example:
681+
resourceType: OperationOutcome
682+
issue:
683+
- severity: error
684+
code: value
685+
details:
686+
coding:
687+
- system: "https://fhir.nhs.uk/STU3/CodeSystem/Spine-ErrorOrWarningCode-1"
688+
version: "1"
689+
code: VALIDATION_ERROR
690+
display: A parameter or value has resulted in a validation error
691+
diagnostics: "The requested document pointer cannot be read because it belongs to another organisation"
692+
requestBody:
693+
$ref: "#/components/requestBodies/DocumentReference"
694+
description: |
695+
Create a new pointer with a unique identifier that you specify. This is the "upsert" or "update as create" functionality in the FHIR R4 REST standard.
696+
697+
In addition to the criteria for DocumentReference validity detailed in the POST interaction, you must ensure:
698+
699+
* `id` is a composite of the ODS Code and an identifier that is locally unique to your system. NRL does not
700+
generate globally unique ids, instead relies on producers to provide a locally unique id prefixed with their
701+
ODS code, making it globally unique. e.g.
702+
```
703+
XYZ-1234567890
704+
```
705+
706+
To supersede existing pointers you must further specify:
707+
708+
* at least one existing pointer in the `relatesTo` with a `code` of `replaces`.
709+
```
710+
[
711+
{
712+
"code": "replaces",
713+
"target": {
714+
"type": "DocumentReference",
715+
"identifier": {
716+
"value": "XYZ-1234567890"
717+
}
718+
}
719+
}
720+
]
721+
```
722+
723+
* the following fields MUST match the pointers being superseded:
724+
* `subject`
725+
* `type`
726+
727+
This will cause a new pointer to be created and superseded pointers to be deleted. Multiple documents can
728+
be superseded.
631729
/DocumentReference/_search:
632730
post:
633731
summary: Retrieve document pointers (POST)
@@ -1220,7 +1318,7 @@ components:
12201318
title: Mental health crisis plan report
12211319
creation: "2022-12-21T10:45:41+11:00"
12221320
format:
1223-
system: https://fhir.nhs.uk/STU3/CodeSystem/NRL-FormatCode-1
1321+
system: https://fhir.nhs.uk/England/CodeSystem/England-NRLFormatCode
12241322
code: "urn:nhs-ic:unstructured"
12251323
display: Unstructured document
12261324
context:

api/producer/swagger.yaml

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ paths:
309309
* `type` MUST match one of the Document Types agreed during [onboarding](#api-description__onboarding). e.g.
310310
```
311311
"type": {
312-
"coding\": [
312+
"coding": [
313313
{
314314
"system": "http://snomed.info/sct",
315315
"code": "1363501000000100",
@@ -321,7 +321,7 @@ paths:
321321
* `category` SHOULD indicate the broader class of the Document Type as agreed during [onboarding](#api-description__onboarding). e.g.
322322
```
323323
"type": {
324-
"coding\": [
324+
"coding": [
325325
{
326326
"system": "http://snomed.info/sct",
327327
"code": "1102421000000108",
@@ -335,7 +335,7 @@ paths:
335335
```
336336
"format": [
337337
{
338-
"system": "https://fhir.nhs.uk/STU3/CodeSystem/NRL-FormatCode-1",
338+
"system": "https://fhir.nhs.uk/England/CodeSystem/England-NRLFormatCode",
339339
"code": "urn:nhs-ic:unstructured"
340340
"display": "Unstructured document"
341341
}
@@ -589,6 +589,84 @@ paths:
589589
requests with the `next-page-token` found in the `meta` portion of the response.
590590
591591
This operation is also available as a http POST, which is the preferred method (see below).
592+
put:
593+
tags:
594+
summary: Create document pointers with a specific id
595+
operationId: upsertDocumentReference
596+
parameters:
597+
- $ref: "#/components/parameters/odsCode"
598+
- $ref: "#/components/parameters/odsCodeExtension"
599+
- $ref: "#/components/parameters/requestId"
600+
- $ref: "#/components/parameters/correlationId"
601+
responses:
602+
"201":
603+
$ref: "#/components/responses/Success"
604+
description: Create / Supersede successful response
605+
content:
606+
application/fhir+json:
607+
example:
608+
resourceType: OperationOutcome
609+
id: 76db24dc-324a-468a-bf02-c06e82279488
610+
meta:
611+
profile:
612+
- https://fhir.nhs.uk/StructureDefinition/NHSDigital-OperationOutcome
613+
issue:
614+
- severity: information
615+
code: informational
616+
details:
617+
coding:
618+
- system: https://fhir.nhs.uk/CodeSystem/NRLF-SuccessCode
619+
code: RESOURCE_CREATED
620+
display: Resource created
621+
diagnostics: Resource created
622+
requestBody:
623+
$ref: "#/components/requestBodies/DocumentReference"
624+
security:
625+
- ${authoriser_name}: []
626+
x-amazon-apigateway-integration:
627+
type: aws_proxy
628+
httpMethod: POST
629+
uri: ${method_upsertDocumentReference}
630+
responses:
631+
default:
632+
statusCode: "201"
633+
passthroughBehavior: when_no_match
634+
contentHandling: CONVERT_TO_TEXT
635+
description: |
636+
Create a new pointer with a unique identifier that you specify. This is the "upsert" or "update as create" functionality in the FHIR R4 REST standard.
637+
638+
In addition to the criteria for DocumentReference validity detailed in the POST interaction, you must ensure:
639+
640+
* `id` is a composite of the ODS Code and an identifier that is locally unique to your system. NRL does not
641+
generate globally unique ids, instead relies on producers to provide a locally unique id prefixed with their
642+
ODS code, making it globally unique. e.g.
643+
```
644+
XYZ-1234567890
645+
```
646+
647+
To supersede existing pointers you must further specify:
648+
649+
* at least one existing pointer in the `relatesTo` with a `code` of `replaces`.
650+
```
651+
[
652+
{
653+
"code": "replaces",
654+
"target": {
655+
"type": "DocumentReference",
656+
"identifier": {
657+
"value": "XYZ-1234567890"
658+
}
659+
}
660+
}
661+
]
662+
```
663+
664+
* the following fields MUST match the pointers being superseded:
665+
* `subject`
666+
* `type`
667+
668+
This will cause a new pointer to be created and superseded pointers to be deleted. Multiple documents can
669+
be superseded.
592670
/DocumentReference/_search:
593671
post:
594672
tags:
@@ -1130,7 +1208,7 @@ components:
11301208
title: Mental health crisis plan report
11311209
creation: "2022-12-21T10:45:41+11:00"
11321210
format:
1133-
system: https://fhir.nhs.uk/STU3/CodeSystem/NRL-FormatCode-1
1211+
system: https://fhir.nhs.uk/England/CodeSystem/England-NRLFormatCode
11341212
code: "urn:nhs-ic:unstructured"
11351213
display: Unstructured document
11361214
context:
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import os
2+
from http import HTTPStatus
3+
4+
from lambda_pipeline.types import LambdaContext
5+
from lambda_utils.pipeline import execute_steps, render_response
6+
7+
from api.producer.upsertDocumentReference.src.config import (
8+
Config,
9+
build_persistent_dependencies,
10+
)
11+
12+
config = Config(
13+
**{env_var: os.environ.get(env_var) for env_var in Config.__fields__.keys()}
14+
)
15+
dependencies = build_persistent_dependencies(config)
16+
17+
18+
def handler(event: dict, context: LambdaContext = None) -> dict[str, str]:
19+
if context is None:
20+
context = LambdaContext()
21+
22+
status_code, result = execute_steps(
23+
index_path=__file__,
24+
event=event,
25+
http_status_ok=HTTPStatus.CREATED,
26+
context=context,
27+
config=config,
28+
**dependencies
29+
)
30+
return render_response(status_code, result)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from build_scripts.lambda_build import build
2+
3+
if __name__ == "__main__":
4+
build(__file__)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
3+
function _build() {
4+
python make.py
5+
}
6+
7+
function _clean() {
8+
echo "Cleaning $(dirname "$(pwd)")"
9+
rm -rf ../dist
10+
}
11+
12+
command=$1
13+
14+
case $command in
15+
"build") _build ;;
16+
"clean") _clean ;;
17+
*) echo "Unhandled command ${command}" ;;
18+
esac

api/producer/upsertDocumentReference/src/__init__.py

Whitespace-only changes.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import boto3
2+
from pydantic import BaseModel
3+
4+
from api.producer.upsertDocumentReference.src.constants import PersistentDependencies
5+
from nrlf.core.json_schema import DataContractCache
6+
from nrlf.core.model import Contract, DocumentPointer
7+
from nrlf.core.repository import Repository
8+
9+
10+
class Config(BaseModel):
11+
"""
12+
The Config class defines all the Environment Variables that are needed for
13+
the business logic to execute successfully.
14+
All Environment Variables are validated using pydantic, and will result in
15+
a 500 Internal Server Error if validation fails.
16+
17+
To add a new Environment Variable simply a new pydantic compatible
18+
definition below, and pydantic should allow for even complex validation
19+
logic to be supported.
20+
"""
21+
22+
AWS_REGION: str
23+
DOCUMENT_POINTER_TABLE_NAME: str
24+
PREFIX: str
25+
ENVIRONMENT: str
26+
SPLUNK_INDEX: str
27+
SOURCE: str
28+
29+
30+
def build_persistent_dependencies(config: Config) -> dict[str, any]:
31+
"""
32+
AWS Lambdas may be re-used, rather than spinning up a new instance each
33+
time. Doing this we can take advantage of state that persists between
34+
executions. Any dependencies returned by this function will persist
35+
between executions and can therefore lead to performance gains.
36+
This function will be called ONCE in the lambdas lifecycle, which may or
37+
may not be each execution, depending on how busy the API is.
38+
These dependencies will be passed through to your `handle` function below.
39+
"""
40+
dynamo_client = boto3.client("dynamodb")
41+
return {
42+
PersistentDependencies.DOCUMENT_POINTER_REPOSITORY: Repository(
43+
DocumentPointer, dynamo_client, environment_prefix=config.PREFIX
44+
),
45+
"contract_repository": Repository(
46+
Contract, dynamo_client, environment_prefix=config.PREFIX
47+
),
48+
DataContractCache.__name__: DataContractCache(),
49+
"environment": config.ENVIRONMENT,
50+
"splunk_index": config.SPLUNK_INDEX,
51+
"source": config.SOURCE,
52+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class PersistentDependencies:
2+
DOCUMENT_POINTER_REPOSITORY = "document_pointer_repository"

api/producer/upsertDocumentReference/src/v1/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)