From 87a158f55aee1296c05598bd236a3e1aaf325eee Mon Sep 17 00:00:00 2001 From: Edd Almond Date: Fri, 21 Mar 2025 16:37:34 +0000 Subject: [PATCH 1/5] eli-173 adding simple container based approach to converting the specification to a postman collection --- Makefile | 10 +- .../eligibility-signposting-api.yaml | 260 +++++++++++++++--- specification/postman/Dockerfile | 9 + 3 files changed, 233 insertions(+), 46 deletions(-) create mode 100644 specification/postman/Dockerfile diff --git a/Makefile b/Makefile index 5c42e288..da6d9a88 100644 --- a/Makefile +++ b/Makefile @@ -48,9 +48,6 @@ dependencies: # Install dependencies needed to build and test the project @Pipel build: # Build lambda in dist poetry build-lambda -vv -publish: # Publish the project artefact @Pipeline - # TODO: Implement the artefact publishing step - deploy: # Deploy the project artefact to the target environment @Pipeline # TODO: Implement the artefact deployment step @@ -61,6 +58,13 @@ config:: # Configure development environment (main) @Configuration precommit: test-unit build test-integration lint ## Pre-commit tasks python -m this +SPEC_DIR := $(CURDIR)/specification +POSTMAN_DIR := $(SPEC_DIR)/postman + +convert-postman: + docker build -t portman-converter -f $(POSTMAN_DIR)/Dockerfile $(SPEC_DIR) + docker run --rm -v $(SPEC_DIR):/app portman-converter \ + portman -l /app/eligibility-signposting-api.yaml -o /app/postman/collection.json # ============================================================================== ${VERBOSE}.SILENT: \ diff --git a/specification/eligibility-signposting-api.yaml b/specification/eligibility-signposting-api.yaml index 4690ad75..5ea0695a 100644 --- a/specification/eligibility-signposting-api.yaml +++ b/specification/eligibility-signposting-api.yaml @@ -1,46 +1,220 @@ -# This is an OpenAPI Specification (https://swagger.io/specification/) -# for eligibility-signposting-api owned by NHS Digital (https://digital.nhs.uk/) -openapi: '3.0.0' +openapi: 3.0.1 info: - title: 'eligibility-signposting-api' - version: 'Computed and injected at build time by `scripts/set_version.py`' - description: | - ## Overview - Add a fully fledged description here with markdown syntax. - For help completing the content of your API spec, see [our guidance](https://nhsd-confluence.digital.nhs.uk/display/APM/Documenting+your+API). - You should also base your content on our exemplar API - [PDS FHIR](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-fhir). - ## Who can use this API - To be completed. - ## Related APIs - To be completed. - ## API status and roadmap - To be completed. - ## Service level - To be completed. - ## Technology - To be completed. - ## Network access - To be completed. - ## Security and authorisation - To be completed. - ## Errors - To be completed. - ### Open source - To be completed. - ## Environments and testing - To be completed. - ## Onboarding - To be completed. - + title: Eligibility Signposting API + version: 1.0.0-alpha + description: API to assess eligibility based on category, condition and NHS number. contact: - name: 'eligibility-signposting-api API Support' - url: 'https://digital.nhs.uk/developer/help-and-support' - email: api.management@nhs.net + url: https://developer.nhs.uk/apis/eligibility-signposting-api + termsOfService: https://developer.nhs.uk/apis/eligibility-signposting-api +tags: + - name: Eligibility + - name: Signposting + - name: NextActions servers: - - url: 'https://sandbox.api.service.nhs.uk/eligibility-signposting-api' - description: Sandbox environment. - - url: 'https://int.api.service.nhs.uk/eligibility-signposting-api' - description: Integration test environment. - - url: 'https://api.service.nhs.uk/eligibility-signposting-api' - description: Production environment. -paths: {} + - url: https://sandbox.api.service.nhs.uk/eligibility-signposting + description: Sandbox Server + - url: https://int.api.service.nhs.uk/eligibility-signposting + description: Integration Server + - url: https://api.service.nhs.uk/eligibility-signposting + description: Production Server +security: + - OAuth_Token: [] +paths: + /eligibility: + get: + summary: Check Eligibility + description: >- + Determines which suggestions a person is eligible for and which they are + not, including reasons and next steps. + operationId: checkEligibility + parameters: + - name: patient + in: query + required: true + schema: + type: string + example: '9876543210' + description: The NHS number of the person. + - name: category + in: query + required: false + schema: + type: string + example: VACCINATIONS + default: ALL + description: >- + The category for which the caller is checking eligibility + suggestions. If not provided, eligibility for all supported + categories will be checked. + - name: conditions + in: query + required: false + schema: + type: string + example: FLU,RSV + default: ALL + description: >- + The diseases or conditions for which the caller is checking + eligibility suggestions in a comma separated list. If not provided, eligibility for all + supported diseases will be checked. + responses: + '200': + description: Eligibility response. + content: + application/json: + schema: + type: object + properties: + responseId: + type: guid + description: GUID assigned when the decisioning evaluation is carried out. This will be useful if you ever need to request support for a particular request. This will not change if you receive a cached response. + example: 1a233ba5-e1eb-4080-a086-2962f6fc3473 + processedDateTime: + type: string + description: Timestamp of when the decisioning evaluation is carried out. This will not change if you receive a cached response. + example: '2025-02-12T16:11:22Z' + processedSuggestions: + type: array + description: List of suggestions the person is eligible for. + items: + type: object + properties: + condition: + type: string + example: FLU + status: + type: string + example: Bookable + reasons: + type: array + description: Reasons that the status returned was returned. + items: + type: object + properties: + reasonCode: + type: string + reasonText: + type: string + example: + - reasonCode: 'flu_coded_eligibility' + reasonText: Our records indicate that you might be at a higher risk of illness if you were to catch Flu. + - reasonCode: 'flu_65+_autumnwinter2023' + reasonText: Our records indicate you are over 65 + nextSteps: + type: array + description: List of next steps for the person. + items: + type: object + properties: + actionType: + type: string + description: >- + The type of step (e.g., information, link, + button). + actionCode: + type: string + description: Code representing the action to be taken + description: + type: string + description: A brief description of the step. + markdownText: + type: string + description: Additional information in markdown format. + htmlText: + type: string + description: Additional information in HTML format. + actionDate: + type: string + description: Optional date by which this action should be undertaken + example: + - actionType: "Link" + actionCode: "BOOK" + description: "Book an appointment here" + markdownText: >- + [Click here](https://www.nhs.uk/nhs-services/pharmacies/book-flu-vaccination/) to book your + appointment. + actionDate: "2025-03-31" + - actionType: "INFO" + actionCode: "NHS" + description: "Visit the NHS website for more details." + markdownText: "[Click here](https://www.nhs.uk/vaccinations/flu-vaccine/) to get more information" + htmlText: "Click here to get more information." + examples: + example1: + summary: Example 1 + value: + responseId: 1a233ba5-e1eb-4080-a086-2962f6fc3473 + processedDateTime: '2025-02-12T16:11:22Z' + processedSuggestions: + - condition: FLU + status: Bookable + reasons: + - reasonCode: 'flu_coded_eligibility' + reasonText: Our records indicate that you might be at a higher risk of illness if you were to catch Flu. + - reasonCode: 'flu_65+_autumnwinter2023' + reasonText: Our records indicate you are over 65 + nextSteps: + - actionType: "Link" + actionCode: "BOOK" + description: "Book an appointment here" + markdownText: >- + [Click here](https://www.nhs.uk/nhs-services/pharmacies/book-flu-vaccination/) to book your + appointment. + actionDate: "2025-03-31" + - actionType: "INFO" + actionCode: "NHS" + description: "Visit the NHS website for more details." + markdownText: "[Click here](https://www.nhs.uk/vaccinations/flu-vaccine/) to get more information" + htmlText: "Click here to get more information." + example2: + summary: Example 2 + value: + responseId: 2b344cb6-f2fc-5091-b197-4073f7fd4584 + processedDateTime: '2025-03-15T10:22:33Z' + processedSuggestions: + - condition: RSV + status: Not Bookable + reasons: + - reasonCode: 'rsv_coded_eligibility' + reasonText: Our records indicate that you might be at a higher risk of illness if you were to catch RSV. + - reasonCode: 'rsv_65+_autumnwinter2023' + reasonText: Our records indicate you are over 65 + nextSteps: + - actionType: "Link" + actionCode: "INFO" + description: "Visit the NHS website for more details." + markdownText: "[Click here](https://www.nhs.uk/vaccinations/rsv-vaccine/) to get more information" + htmlText: "Click here to get more information." + '400': + description: Invalid input data. + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: + - The values submitted in your request were not valid. + - The condition list was badly formatted or contained unrecognised conditions. + - The category contained an unrecognised value. + '404': + description: Person not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: >- + The given NHS number was not found in our datasets. This + could be because the number is incorrect or some other + reason we cannot process that number. + '500': + description: Internal server error. +components: + securitySchemes: + OAuth_Token: + type: http + scheme: bearer diff --git a/specification/postman/Dockerfile b/specification/postman/Dockerfile new file mode 100644 index 00000000..5f164b15 --- /dev/null +++ b/specification/postman/Dockerfile @@ -0,0 +1,9 @@ +FROM node:18-alpine + +RUN npm install -g @apideck/portman + +WORKDIR /app + +COPY ../eligibility-signposting-api.yaml . + +CMD ["portman", "-l", "eligibility-signposting-api.yaml", "-o", "collection.json"] From d62b04d4b41ce3b26de8fc83d68ee21ad056b49c Mon Sep 17 00:00:00 2001 From: Edd Almond Date: Mon, 24 Mar 2025 11:07:29 +0000 Subject: [PATCH 2/5] eli-173 updating .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 35320c42..b638bfb9 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,7 @@ test-report.xml localstack_data/ /volume/* /coverage.xml +/lines-of-code-report* +/specification/tmp +/specification/postman +/sandbox/specification/* From 825abb8d49a908d060372ea3ce052b9041b253d2 Mon Sep 17 00:00:00 2001 From: Edd Almond Date: Tue, 25 Mar 2025 15:54:45 +0000 Subject: [PATCH 3/5] eli-173 adding readme section and commenting on make command --- Makefile | 2 +- README.md | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index da6d9a88..24331415 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ precommit: test-unit build test-integration lint ## Pre-commit tasks SPEC_DIR := $(CURDIR)/specification POSTMAN_DIR := $(SPEC_DIR)/postman -convert-postman: +convert-postman: # Create Postman collection from OAS spec docker build -t portman-converter -f $(POSTMAN_DIR)/Dockerfile $(SPEC_DIR) docker run --rm -v $(SPEC_DIR):/app portman-converter \ portman -l /app/eligibility-signposting-api.yaml -o /app/postman/collection.json diff --git a/README.md b/README.md index 37a29553..da80ab43 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ The software will only be used for signposting an individual to an appropriate s - [Configuration](#configuration) - [Usage](#usage) - [Testing](#testing) + - [Conflict with yanai](#conflict-with-yanai) + - [Creating a Postman collection](#creating-a-postman-collection) - [Design](#design) - [Diagrams](#diagrams) - [Modularity](#modularity) @@ -88,6 +90,17 @@ If you have previously built [yanai](https://nhsd-confluence.digital.nhs.uk/page docker rmi localstack/localstack ``` +## Creating a Postman collection + +A Postman collection can be generated from the Open API specification in `specification/` by running the following make command: + +```shell +make convert-postman +``` + +The conversion is done using the [Portman CLI](https://github.com/apideck-libraries/portman). The resulting Postman collection +is saved to `specification/postman/`. + ## Design We'll be separating our [presentation](https://martinfowler.com/eaaDev/SeparatedPresentation.html) layer (where API logic lives, in [`views/`](src/eligibility_signposting_api/views)), [business services](https://martinfowler.com/eaaCatalog/serviceLayer.html) layer (where business logic lives, in [`services/`](src/eligibility_signposting_api/services)) and [repository](https://martinfowler.com/eaaCatalog/repository.html) layer (where database logic lives, [`repos/`](src/eligibility_signposting_api/repos)). We will be using [wireup](https://pypi.org/project/wireup/) for [dependency injection](https://pinboard.in/u:brunns/t:dependency-injection), so services get their dependencies given to them ("injection"), and wireup takes care of that. (We'll usually use the [`@service` annotation](https://maldoinc.github.io/wireup/latest/services/), but [factory functions](https://maldoinc.github.io/wireup/latest/factory_functions/) will be used where necessary, typically for creating resources from 3rd party libraries.) We'll be using [Pydantic](https://pypi.org/project/pydantic/) for both response models and database models. From 562f193ecdb697ba3336f37538f5dc248edd609d Mon Sep 17 00:00:00 2001 From: Edd Almond Date: Tue, 25 Mar 2025 17:26:55 +0000 Subject: [PATCH 4/5] eli-173 adding Portman to the list of allowed words --- scripts/config/vale/styles/config/vocabularies/words/accept.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/config/vale/styles/config/vocabularies/words/accept.txt b/scripts/config/vale/styles/config/vocabularies/words/accept.txt index cae10a15..d4e7d15e 100644 --- a/scripts/config/vale/styles/config/vocabularies/words/accept.txt +++ b/scripts/config/vale/styles/config/vocabularies/words/accept.txt @@ -22,3 +22,4 @@ colima wireup Pydantic yanai +Portman From dac347872429182e63dd5edd557304022a720077 Mon Sep 17 00:00:00 2001 From: Edd Almond Date: Tue, 25 Mar 2025 17:44:10 +0000 Subject: [PATCH 5/5] eli-173 updating makefile command so it'll pull in the spec file to the build context for other machines --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 24331415..e845e2e4 100644 --- a/Makefile +++ b/Makefile @@ -62,9 +62,12 @@ SPEC_DIR := $(CURDIR)/specification POSTMAN_DIR := $(SPEC_DIR)/postman convert-postman: # Create Postman collection from OAS spec + mkdir -p $(POSTMAN_DIR) + cp $(SPEC_DIR)/eligibility-signposting-api.yaml $(POSTMAN_DIR)/ docker build -t portman-converter -f $(POSTMAN_DIR)/Dockerfile $(SPEC_DIR) docker run --rm -v $(SPEC_DIR):/app portman-converter \ portman -l /app/eligibility-signposting-api.yaml -o /app/postman/collection.json + rm $(POSTMAN_DIR)/eligibility-signposting-api.yaml # ============================================================================== ${VERBOSE}.SILENT: \