diff --git a/sandbox/src/mocks/stu3/patientServiceSearch/requests/SpcMinimal.json b/sandbox/src/mocks/stu3/patientServiceSearch/requests/SpcMinimal.json new file mode 100644 index 000000000..42be176ce --- /dev/null +++ b/sandbox/src/mocks/stu3/patientServiceSearch/requests/SpcMinimal.json @@ -0,0 +1,77 @@ +{ + "resourceType": "Parameters", + "meta": { + "profile": [ + "https://fhir.nhs.uk/STU3/StructureDefinition/eRS-PatientServiceSearch-Parameters-1" + ] + }, + "parameter": [ + { + "name": "requestType", + "valueCoding": { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-RequestType-1", + "code": "APPOINTMENT_REQUEST" + } + }, + { + "name": "sortBy", + "valueCoding": { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-SortBy-1", + "code": "DISTANCE" + } + }, + { + "name": "patient", + "valueIdentifier": { + "system": "http://fhir.nhs.net/Id/nhs-number", + "value": "9912003888" + } + }, + { + "name": "ubrn", + "valueIdentifier": { + "system": "https://fhir.nhs.uk/Id/ers-request-id", + "value": "000000070000" + } + }, + { + "name": "searchCriteria", + "resource": { + "resourceType": "Parameters", + "meta": { + "profile": [ + "https://fhir.nhs.uk/STU3/StructureDefinition/eRS-ServiceSearchCriteria-Parameters-1" + ] + }, + "id": "ServiceSearchCriteria-1", + "parameter": [ + { + "name": "priority", + "valueCoding": { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-Priority-1", + "code": "URGENT" + } + }, + { + "name": "specialty", + "valueCoding": { + "system": "_baseUrl_/STU3/CodeSystem/SPECIALTY", + "code": "CARDIOLOGY" + } + }, + { + "name": "clinicType", + "valueCoding": { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-ClinicType-1", + "code": "LIPID_MANAGEMENT" + } + }, + { + "name": "ageAndGenderAppropriate", + "valueBoolean": true + } + ] + } + } + ] +} diff --git a/sandbox/src/mocks/stu3/patientServiceSearch/requests/SpcaWithIWT.json b/sandbox/src/mocks/stu3/patientServiceSearch/requests/SpcaWithIWT.json new file mode 100644 index 000000000..469efc4b5 --- /dev/null +++ b/sandbox/src/mocks/stu3/patientServiceSearch/requests/SpcaWithIWT.json @@ -0,0 +1,81 @@ +{ + "resourceType": "Parameters", + "meta": { + "profile": [ + "https://fhir.nhs.uk/STU3/StructureDefinition/eRS-PatientServiceSearch-Parameters-1" + ] + }, + "parameter": [ + { + "name": "requestType", + "valueCoding": { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-RequestType-1", + "code": "APPOINTMENT_REQUEST" + } + }, + { + "name": "sortBy", + "valueCoding": { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-SortBy-1", + "code": "DISTANCE" + } + }, + { + "name": "patient", + "valueIdentifier": { + "system": "http://fhir.nhs.net/Id/nhs-number", + "value": "9912003888" + } + }, + { + "name": "ubrn", + "valueIdentifier": { + "system": "https://fhir.nhs.uk/Id/ers-request-id", + "value": "000000070000" + } + }, + { + "name": "searchCriteria", + "resource": { + "resourceType": "Parameters", + "meta": { + "profile": [ + "https://fhir.nhs.uk/STU3/StructureDefinition/eRS-ServiceSearchCriteria-Parameters-1" + ] + }, + "id": "ServiceSearchCriteria-1", + "parameter": [ + { + "name": "priority", + "valueCoding": { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-Priority-1", + "code": "URGENT" + } + }, + { + "name": "specialty", + "valueCoding": { + "system": "_baseUrl_/STU3/CodeSystem/SPECIALTY", + "code": "CARDIOLOGY" + } + }, + { + "name": "clinicType", + "valueCoding": { + "system": "https://fhir.nhs.uk/STU3/CodeSystem/eRS-ClinicType-1", + "code": "LIPID_MANAGEMENT" + } + }, + { + "name": "indicativeAppointmentWaitTimeLimit", + "valueUnsignedInt": 15 + }, + { + "name": "ageAndGenderAppropriate", + "valueBoolean": true + } + ] + } + } + ] +} diff --git a/sandbox/src/routes/stu3/patientServiceSearch.js b/sandbox/src/routes/stu3/patientServiceSearch.js index a01ee51df..70f92b2e6 100644 --- a/sandbox/src/routes/stu3/patientServiceSearch.js +++ b/sandbox/src/routes/stu3/patientServiceSearch.js @@ -10,7 +10,7 @@ module.exports = [ path: '/FHIR/STU3/HealthcareService/$ers.searchHealthcareServicesForPatient', handler: (request, h) => { - const allowedBusinessFunctions = ["REFERRING_CLINICIAN", "REFERRING_CLINICIAN_ADMIN"] + const allowedBusinessFunctions = ["REFERRING_CLINICIAN", "REFERRING_CLINICIAN_ADMIN", "SERVICE_PROVIDER_CLINICIAN", "SERVICE_PROVIDER_CLINICIAN_ADMIN"] const validationResult = validationUtils.validateBusinessFunction(request, h, allowedBusinessFunctions) if (validationResult) { diff --git a/sandbox/src/routes/stu3/services/mockResponseProvider.js b/sandbox/src/routes/stu3/services/mockResponseProvider.js index 3e31b22f5..af71fc6f6 100644 --- a/sandbox/src/routes/stu3/services/mockResponseProvider.js +++ b/sandbox/src/routes/stu3/services/mockResponseProvider.js @@ -87,9 +87,32 @@ module.exports = { 'src/mocks/stu3/patientServiceSearch/requests/RcaWithIWT.json': 'stu3/patientServiceSearch/responses/FetchServiceListWithSingleService.json' }; - const isRCBusinessRole = request.headers["nhsd-ers-business-function"] === 'REFERRING_CLINICIAN' + var responseMapForSPC = { + 'src/mocks/stu3/patientServiceSearch/requests/SpcMinimal.json': 'stu3/patientServiceSearch/responses/FetchServiceListWithMultipleServices.json' + }; - return mapExampleResponse(request, isRCBusinessRole ? responseMapForRC : responseMapForRCA); + var responseMapForSPCA = { + 'src/mocks/stu3/patientServiceSearch/requests/SpcaWithIWT.json': 'stu3/patientServiceSearch/responses/FetchServiceListWithSingleService.json' + }; + + const businessFunction = request.headers["nhsd-ers-business-function"] + + var responseMap + switch (businessFunction) { + case 'REFERRING_CLINICIAN': + responseMap = responseMapForRC + break + case 'SERVICE_PROVIDER_CLINICIAN': + responseMap = responseMapForSPC + break + case 'SERVICE_PROVIDER_CLINICIAN_ADMIN': + responseMap = responseMapForSPCA + break + default: + responseMap = responseMapForRCA + } + + return mapExampleResponse(request, responseMap); }, diff --git a/specification/components/stu3/schemas/eRS-PatientServiceSearch-Parameters.yaml b/specification/components/stu3/schemas/eRS-PatientServiceSearch-Parameters.yaml index e2b69fce1..8d2e79727 100644 --- a/specification/components/stu3/schemas/eRS-PatientServiceSearch-Parameters.yaml +++ b/specification/components/stu3/schemas/eRS-PatientServiceSearch-Parameters.yaml @@ -35,6 +35,7 @@ properties: | `SearchCriteria` | `1..1` | | | `ReferringClinician` | `0..1` | | | `CommissioningRuleOrganisation` | `0..1` | Required if searching for services for an existing Referral. This field should be provided using the returned Commissioning Rule Organisation already included on the Referral to ensure the services returned are valid. Note this field is not supported when searching with the `ADVICE_AND_GUIDANCE_REQUEST` request type. | + | `Ubrn` | `0..1` | Mandatory for `SERVICE_PROVIDER_CLINICIAN` and `SERVICE_PROVIDER_CLINICIAN_ADMIN` requests. This parameter is ignored for `REFERRING_CLINICIAN` and `REFERRING_CLINICIAN_ADMIN` requests. | items: anyOf: - $ref: 'parameters/RequestType.yaml' @@ -55,3 +56,28 @@ properties: example: 'searchCriteria' resource: $ref: 'eRS-ServiceSearchCriteria-Parameters.yaml' + - title: Ubrn + description: The UBRN of the referral request (required for SERVICE_PROVIDER_CLINICIAN and SERVICE_PROVIDER_CLINICIAN_ADMIN). + type: object + required: + - name + - valueIdentifier + properties: + name: + type: string + enum: + - ubrn + valueIdentifier: + type: object + required: + - system + - value + properties: + system: + type: string + enum: + - 'https://fhir.nhs.uk/Id/ers-request-id' + example: 'https://fhir.nhs.uk/Id/ers-request-id' + value: + type: string + example: '000000070000' diff --git a/specification/components/stu3/schemas/endpoints/a010-patient-service-search.yaml b/specification/components/stu3/schemas/endpoints/a010-patient-service-search.yaml index bcc50f5cb..c7617a780 100644 --- a/specification/components/stu3/schemas/endpoints/a010-patient-service-search.yaml +++ b/specification/components/stu3/schemas/endpoints/a010-patient-service-search.yaml @@ -11,8 +11,12 @@ description: | In order to use this endpoint you must be an authenticated e-RS user and use one of the following e-RS roles: - `REFERRING_CLINICIAN` - `REFERRING_CLINICIAN_ADMIN` + - `SERVICE_PROVIDER_CLINICIAN` + - `SERVICE_PROVIDER_CLINICIAN_ADMIN` You need to have identified a `patient`, for example via [[HYPERLINK_PDS]]. + + Where a `SERVICE_PROVIDER_CLINICIAN_ADMIN` (SPCA) is acting on behalf of a `SERVICE_PROVIDER_CLINICIAN` (SPC), the on behalf of user ID must be that of an appropriate SPC. You can use endpoint [[HYPERLINK_A040]] to determine which e-RS users a `SERVICE_PROVIDER_CLINICIAN_ADMIN` is allowed to work "on-behalf-of". ## Use case As an authenticated user @@ -36,6 +40,7 @@ parameters: - $ref: '../headers/request/BearerAuthorization.yaml' - $ref: '../headers/request/OdsCode.yaml' - $ref: '../headers/request/BusinessFunction.yaml' + - $ref: '../headers/request/OnBehalfOfUserID.yaml' - $ref: '../headers/request/CorrelationID.yaml' requestBody: required: true @@ -68,6 +73,14 @@ requestBody: summary: Referring Clinician search with commissioning rule organisation value: $ref: '../../examples/patientServiceSearch/requests/RcSearchWithCommissioningRuleOrganisation.json' + spc-minimal: + summary: Service Provider Clinician minimal search + value: + $ref: '../../examples/patientServiceSearch/requests/SpcMinimal.json' + spca-with-iwt: + summary: Service Provider Clinician Admin search + value: + $ref: '../../examples/patientServiceSearch/requests/SpcaWithIWT.json' responses: '200': $ref: '../responses/patientServiceSearch/200Response.yaml' diff --git a/specification/components/stu3/schemas/responses/patientServiceSearch/ErrorOutcome.yaml b/specification/components/stu3/schemas/responses/patientServiceSearch/ErrorOutcome.yaml index c8d5b4d22..061282b90 100644 --- a/specification/components/stu3/schemas/responses/patientServiceSearch/ErrorOutcome.yaml +++ b/specification/components/stu3/schemas/responses/patientServiceSearch/ErrorOutcome.yaml @@ -12,6 +12,8 @@ description: | | PATIENT_ERROR | An error occurred while retrieving the requested patient. Do not attempt again. | | INVALID_VALUE | The input provided does not conform to the expected data types and format. | | INVALID_CODE | The input provided for a field is not one of the defined legal values. | + | INVALID_STATE | Indicates that the referenced item is not in the correct state for the request to be processed (e.g. a service of the wrong type). | + | INVALID_REQUEST_STATE | Indicates that the referral item is not in the correct state for the request to be processed. | | UNEXPECTED_FIELD | A field is provided that is not expected as part of the request. E.g. a field is mis-spelt, was defined on a previous version of the endpoint but has subsequently been removed. | | INVALID_FHIR_STRUCTURE | The FHIR data structure in the message body does not match the expected structure (e.g. an array is present for a value when no array is expected). | | REFERENCED_USER_IS_NOT_SPC | The user provided does not have the Service Provider Clinician authorisation in the e-RS. | diff --git a/tests/sandbox/stu3/test_a010_patient_service_search.py b/tests/sandbox/stu3/test_a010_patient_service_search.py index 36e79970b..0ee6b9d6c 100644 --- a/tests/sandbox/stu3/test_a010_patient_service_search.py +++ b/tests/sandbox/stu3/test_a010_patient_service_search.py @@ -14,6 +14,8 @@ class TestPatientServiceSearch(SandboxTest): allowed_business_function_data = [ "REFERRING_CLINICIAN", "REFERRING_CLINICIAN_ADMIN", + "SERVICE_PROVIDER_CLINICIAN", + "SERVICE_PROVIDER_CLINICIAN_ADMIN", ] authorised_actor_data = Actor.all( @@ -51,6 +53,16 @@ class TestPatientServiceSearch(SandboxTest): "stu3/patientServiceSearch/requests/RcSearchWithCommissioningRuleOrganisation.json", "stu3/patientServiceSearch/responses/FetchServiceListWithMultipleServices.json", ), + ( + Actor.SPC, + "stu3/patientServiceSearch/requests/SpcMinimal.json", + "stu3/patientServiceSearch/responses/FetchServiceListWithMultipleServices.json", + ), + ( + Actor.SPCA, + "stu3/patientServiceSearch/requests/SpcaWithIWT.json", + "stu3/patientServiceSearch/responses/FetchServiceListWithSingleService.json", + ), ] @pytest.fixture @@ -103,9 +115,11 @@ def test_success( ) def _request_path(self, actor: Actor) -> str: - path = ( - "stu3/patientServiceSearch/requests/RcaWithIWT.json" - if actor == Actor.RCA - else "stu3/patientServiceSearch/requests/RcMinimal.json" + request_paths = { + Actor.RCA: "stu3/patientServiceSearch/requests/RcaWithIWT.json", + Actor.SPC: "stu3/patientServiceSearch/requests/SpcMinimal.json", + Actor.SPCA: "stu3/patientServiceSearch/requests/SpcaWithIWT.json", + } + return request_paths.get( + actor, "stu3/patientServiceSearch/requests/RcMinimal.json" ) - return path