From 6a7d428e7f616eeabf7b4ed69279c29b75818d99 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Wed, 16 Oct 2024 15:33:29 +0100 Subject: [PATCH 01/38] [feature/PI-548-sonarcloud_ignore_duplicated_index] sonarcloud ignore duplicated index --- .sonarcloud.properties | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .sonarcloud.properties diff --git a/.sonarcloud.properties b/.sonarcloud.properties new file mode 100644 index 00000000..fa4f3b44 --- /dev/null +++ b/.sonarcloud.properties @@ -0,0 +1,3 @@ +sonar.sources=. +sonar.tests=. +sonar.cpd.exclusions=src/api/**/index.py From 83cf0a204b28f22ee471aef3cce6c6d2fd800c90 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Wed, 16 Oct 2024 14:41:55 +0100 Subject: [PATCH 02/38] [feature/PI-276-proxygen_spec] add api spec --- .github/workflows/_deploy.yml | 18 +- docs/public_swagger/swagger.yaml | 3012 --------------------- docs/public_swagger/tests/test_swagger.py | 30 - scripts/infrastructure/apigee.mk | 2 - scripts/infrastructure/apigee/proxygen.sh | 46 + scripts/infrastructure/swagger.mk | 18 + 6 files changed, 81 insertions(+), 3045 deletions(-) delete mode 100644 docs/public_swagger/swagger.yaml delete mode 100644 docs/public_swagger/tests/test_swagger.py diff --git a/.github/workflows/_deploy.yml b/.github/workflows/_deploy.yml index e0545eb7..978e5db7 100644 --- a/.github/workflows/_deploy.yml +++ b/.github/workflows/_deploy.yml @@ -145,6 +145,22 @@ jobs: infrastructure/swagger/dist/apigee/swagger.yaml if: ${{ always() }} + swagger--publish: + needs: [get-branch-from-workflow-file, apigee--deploy] + runs-on: [self-hosted, ci] + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ needs.get-branch-from-workflow-file.outputs.branch_name }} + # change below to (env.ACCOUNT == 'int') || (env.ACCOUNT == 'prod') when ready for prod + - if: (${{ env.SCOPE == 'per_workspace'}}) && (${{ env.ACCOUNT == 'int' }}) + uses: ./.github/actions/make/ + with: + command: swagger--publish + requires-aws: true + restore-from-cache: "true" + cache-suffix: ${{ env.CACHE_NAME }} + test--smoke: needs: [get-branch-from-workflow-file, apigee--deploy] runs-on: [self-hosted, ci] @@ -162,7 +178,7 @@ jobs: set-success: name: Set Success - needs: [test--smoke] + needs: [test--smoke, apigee--deploy] runs-on: [self-hosted, ci] steps: - name: Set success env var diff --git a/docs/public_swagger/swagger.yaml b/docs/public_swagger/swagger.yaml deleted file mode 100644 index d17a6cd8..00000000 --- a/docs/public_swagger/swagger.yaml +++ /dev/null @@ -1,3012 +0,0 @@ -servers: - - url: https://sandbox.api.service.nhs.uk/connecting-party-manager/FHIR/R4 - description: Sandbox environment. - - url: https://int.api.service.nhs.uk/connecting-party-manager/FHIR/R4 - description: Integration test environment. - - url: https://api.service.nhs.uk/connecting-party-manager/FHIR/R4 - description: Production environment. -info: - version: 1.0.0 - contact: - name: NHS Digital API Management - url: "https://digital.nhs.uk/developer/help-and-support" - email: api.management@nhs.net - title: Connecting Party Manager - FHIR API - description: | - ## Overview - - API to configure internal systems to allow a Connecting Party to connect. A source of information about Connecting Parties (systems that connect to NHSE) that helps provide system identity attributes that ensure NHSE services know what systems they are connecting to and the legal entities they are sharing data with. This service is driven by APIs that enable self-service for activities such as certificate management and environment access. It also is a store of end-to-end onboarding/integration data and a catalogue of endpoints. - - ## Who can use this API - - This API can only be used where there is a legal basis to do so. Make sure you have a valid use case before you go too far with your development. You must demonstrate you have a valid use case as part of digital onboarding. Connecting Parties must have an appointed Clinical Safety Officer and undertake a Clinical Safety Assessment. - - ## API status and roadmap - - This API is in [development](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#statuses). - - To see our roadmap, or to suggest, comment or vote on features for this API, see our interactive [product backlog](https://nhs-digital-api-management.featureupvote.com/). - - If you have any other queries, [contact us](https://digital.nhs.uk/developer/help-and-support). - - ## Service level - - This API is a platinum service, meaning it is operational and supported 24 hours a day, 365 days a year. - - For more details, see [service levels](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#service-levels). - - ## Technology - - This API is [RESTful](https://digital.nhs.uk/developer/guides-and-documentation/our-api-technologies#basic-rest). - - It conforms to the [FHIR](https://digital.nhs.uk/developer/guides-and-documentation/our-api-technologies#fhir) global standard for health care data exchange, specifically to [FHIR R4 (v4.0.1)](https://hl7.org/fhir/r4/), except that it does not support the [capabilities](http://hl7.org/fhir/R4/http.html#capabilities) interaction. - - It includes some country-specific FHIR extensions, which conform to [FHIR UK Core](https://digital.nhs.uk/services/fhir-uk-core), specifically [fhir.r4.ukcore.stu1 0.5.1](https://simplifier.net/packages/fhir.r4.ukcore.stu1/0.5.1). - - You do not need to know much about FHIR to use this API - FHIR APIs are just RESTful APIs that follow specific rules. - - In particular: - - * resource names are capitalised and singular, and use US spellings, for example `Organization` not `organisations` - * array names are singular, for example `entry` not `entries` for address lines - * data items that are country-specific and thus not included in the FHIR global base resources are usually wrapped in an `extension` object - - There are [libraries and SDKs available](https://digital.nhs.uk/developer/guides-and-documentation/api-technologies-at-nhs-digital#fhir-libraries-and-sdks) to help with FHIR API integration. - - ## Network access - - This API is available on the internet and, indirectly, on the [Health and Social Care Network (HSCN)](https://digital.nhs.uk/services/health-and-social-care-network). - - For more details see [Network access for APIs](https://digital.nhs.uk/developer/guides-and-documentation/network-access-for-apis). - - ## Security and authorisation - - This API uses the following access modes: - - * [Application-restricted RESTful API - signed JWT authentication](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/application-restricted-restful-apis-signed-jwt-authentication) - - ## Errors - - We use standard HTTP status codes to show whether an API request succeeded or not. They are usually in the range: - - * 200 to 299 if it succeeded, including code 202 if it was accepted by an API that needs to wait for further action - * 400 to 499 if it failed because of a client error by your application - * 500 to 599 if it failed because of an error on our server - - Errors specific to each API are shown in the Endpoints section, under Response. See our [reference guide](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#http-status-codes) for more on errors. - - ## Open source - - You might find the following open source resources useful: - - | Resource | Description | Links | - |--------------------------------|--------------------------------------------|--------------------------------------------------------------------------| - | Connecting Party Manager | Source code for the core API and sandbox | [GitHub repo](https://github.com/NHSDigital/connecting-party-manager) | - | Connecting Party Manager - CI | Source code for the Github Actions runners | [GitHub repo](https://github.com/NHSDigital/connecting-party-manager-CI) | - - We currently don't have any open source client libraries or sample code for this API. If you think this would be useful, you can [upvote the suggestion on our Interactive Product Backlog](https://nhs-digital-api-management.featureupvote.com/suggestions/107439/client-libraries-and-reference-implementations). - - ## Environments and testing - - | Environment | Base URL | - | ----------------- | --------------------------------------------------------------------------- | - | Sandbox | `https://sandbox.api.service.nhs.uk/connecting-party-manager/FHIR/R4/` | - | Integration | `https://int.api.service.nhs.uk/connecting-party-manager/consumer/FHIR/R4/` | - | Production | `https://api.service.nhs.uk/connecting-party-manager/consumer/FHIR/R4/` | - - ### Sandbox and Integration environments - - Our [sandbox environment](https://digital.nhs.uk/developer/guides-and-documentation/testing#sandbox-testing): - - * is for early developer testing, - * is open access, so does not allow you to test authorisation, - * includes ready-to-use test data - for details [contact us](https://digital.nhs.uk/developer/help-and-support), - * underpins our `Try this API` feature; see the documentation for each endpoint for more details. - - Our [integration test environment](https://digital.nhs.uk/developer/guides-and-documentation/testing#integration-testing): - - * is for formal integration testing, - * includes authorisation, - * includes ready-to-use test data - for details [contact us](https://digital.nhs.uk/developer/help-and-support). - - For more details see [integration testing with our RESTful APIs](https://digital.nhs.uk/developer/guides-and-documentation/testing#integration-testing-with-our-restful-apis). - - ## Onboarding - - You need to get your software approved by us before it can go live with this API. We call this onboarding. The onboarding process can sometimes be quite long, so it’s worth planning well ahead. - - As part of this process, you need to demonstrate that you can manage risks and that your software conforms technically with the requirements for this API. - - Information on this page might impact the design of your software. For details, see [Onboarding support information](https://digital.nhs.uk/developer/api-catalogue/national-record-locator-consumer-fhir/onboarding-support-information). - - To understand how our online digital onboarding process works, see [digital onboarding](https://digital.nhs.uk/developer/guides-and-documentation/digital-onboarding#using-the-digital-onboarding-portal). - -
-
-
-
- - - -
-
-
-

To get started, sign in or create a developer account, then select 'product onboarding'.

-
-
-
- - ## Change log - - For details of how this API has changed over time, see the [change log](https://github.com/NHSDigital/connecting-party-manager/blob/main/CHANGELOG.md). - license: - name: MIT - url: https://github.com/NHSDigital/connecting-party-manager/blob/main/LICENCE.md -openapi: 3.0.3 -paths: - /Device: - post: - summary: Create a Device resource - operationId: createDevice - responses: - "201": - description: Create operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - requestBody: - $ref: "#/components/requestBodies/Device" - parameters: - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - get: - summary: Search for Device resources - operationId: searchDevice - parameters: - - name: device_type - in: query - required: true - description: "Type of device (product or endpoint)" - schema: - type: string - enum: - - product - - endpoint - - $ref: "#/components/parameters/profileParam" - - $ref: "#/components/parameters/lastUpdatedParam" - - $ref: "#/components/parameters/tagParam" - - $ref: "#/components/parameters/securityParam" - - $ref: "#/components/parameters/sourceParam" - - $ref: "#/components/parameters/idParam" - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Search Device operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Bundle" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /Device/{id}: - get: - summary: Read a Device resource - operationId: readDevice - parameters: - - name: id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Read Device operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Device" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /Organization/{id}: - get: - summary: Read an Organization resource - operationId: readOrganization - parameters: - - name: id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Read Organization operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Organization" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /ProductTeam: - post: - operationId: createproductteam - summary: createProductTeam endpoint for APIGEE integration - requestBody: - $ref: "#/components/requestBodies/Organization" - responses: - "201": - description: Create operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - parameters: - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - /ProductTeam/{product_team_id}: - get: - operationId: readproductteam - summary: readProductTeam endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - $ref: "#/components/parameters/profileParam" - - $ref: "#/components/parameters/lastUpdatedParam" - - $ref: "#/components/parameters/tagParam" - - $ref: "#/components/parameters/securityParam" - - $ref: "#/components/parameters/sourceParam" - - $ref: "#/components/parameters/idParam" - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Read Product Team operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Organization" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /ProductTeam/{product_team_id}/Product: - get: - operationId: searchCpmProduct - summary: searchCpmProduct endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - $ref: "#/components/parameters/profileParam" - - $ref: "#/components/parameters/lastUpdatedParam" - - $ref: "#/components/parameters/tagParam" - - $ref: "#/components/parameters/securityParam" - - $ref: "#/components/parameters/sourceParam" - - $ref: "#/components/parameters/idParam" - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Search CpmProducts operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Bundle" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - post: - operationId: createproductendpoint - summary: createProduct endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - product_name: - type: string - description: Name of the product - responses: - "201": - description: Create operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /ProductTeam/{product_team_id}/Product/{product_id}: - get: - operationId: readproductendpoint - summary: readProduct endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - name: product_id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Read Product operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Bundle" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - delete: - operationId: deleteproductendpoint - summary: deleteProduct endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - name: product_id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "204": - description: Delete Product operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Bundle" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /ProductTeam/{product_team_id}/Product/Epr: - post: - operationId: createproductforeprendpoint - summary: createCpmProductForEpr endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - product_name: - type: string - description: Name of the product - responses: - "201": - description: Create operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /searchSdsDevice: - get: - operationId: searchsdsdevice - summary: searchSdsDevice endpoint for APIGEE integration - parameters: - - name: nhs_as_client - in: query - required: false - description: "Accredited System Client" - schema: - type: string - - name: nhs_as_svc_ia - in: query - required: false - description: "Accredited System Client Interaction" - schema: - type: string - - name: nhs_mhs_manufacturer_org - in: query - required: false - description: "Manufacturer Organisation" - schema: - type: string - - name: nhs_mhs_party_key - in: query - required: false - description: "Party Key" - schema: - type: string - - $ref: "#/components/parameters/profileParam" - - $ref: "#/components/parameters/lastUpdatedParam" - - $ref: "#/components/parameters/tagParam" - - $ref: "#/components/parameters/securityParam" - - $ref: "#/components/parameters/sourceParam" - - $ref: "#/components/parameters/idParam" - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Search Device operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Bundle" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /searchSdsEndpoint: - get: - operationId: searchsdsendpoint - summary: searchSdsEndpoint endpoint for APIGEE integration - parameters: - - name: nhs_id_code - in: query - required: false - description: "NHS ID Code" - schema: - type: string - - name: nhs_mhs_svc_ia - in: query - required: false - description: "Endpoint Interaction" - schema: - type: string - - name: nhs_mhs_party_key - in: query - required: false - description: "Party Key" - schema: - type: string - - $ref: "#/components/parameters/profileParam" - - $ref: "#/components/parameters/lastUpdatedParam" - - $ref: "#/components/parameters/tagParam" - - $ref: "#/components/parameters/securityParam" - - $ref: "#/components/parameters/sourceParam" - - $ref: "#/components/parameters/idParam" - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Search Device operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Bundle" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" -components: - parameters: - profileParam: - name: _profile - description: Profiles this resource claims to conform to - in: query - required: false - schema: - type: string - lastUpdatedParam: - name: _lastUpdated - description: When the resource version last changed - in: query - required: false - schema: - type: string - tagParam: - name: _tag - description: Tags applied to this resource - in: query - required: false - schema: - type: string - securityParam: - name: _security - description: Security Labels applied to this resource - in: query - required: false - schema: - type: string - sourceParam: - name: _source - description: Identifies where the resource comes from - in: query - required: false - schema: - type: string - idParam: - name: _id - description: Logical id of this artifact - in: query - required: false - schema: - type: string - requestBodies: - Device: - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Device" - required: true - Organization: - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Organization" - required: true - schemas: - Resource: - type: object - properties: - resourceType: - type: string - enum: - - Account - - ActivityDefinition - - AdverseEvent - - AllergyIntolerance - - Appointment - - AppointmentResponse - - AuditEvent - - Basic - - Binary - - BiologicallyDerivedProduct - - BodyStructure - - Bundle - - CapabilityStatement - - CarePlan - - CareTeam - - CatalogEntry - - ChargeItem - - ChargeItemDefinition - - Claim - - ClaimResponse - - ClinicalImpression - - CodeSystem - - Communication - - CommunicationRequest - - CompartmentDefinition - - Composition - - ConceptMap - - Condition - - Consent - - Contract - - Coverage - - CoverageEligibilityRequest - - CoverageEligibilityResponse - - DetectedIssue - - Device - - DeviceDefinition - - DeviceMetric - - DeviceRequest - - DeviceUseStatement - - DiagnosticReport - - DocumentManifest - - DocumentReference - - DomainResource - - EffectEvidenceSynthesis - - Encounter - - Endpoint - - EnrollmentRequest - - EnrollmentResponse - - EpisodeOfCare - - EventDefinition - - Evidence - - EvidenceVariable - - ExampleScenario - - ExplanationOfBenefit - - FamilyMemberHistory - - Flag - - Goal - - GraphDefinition - - Group - - GuidanceResponse - - HealthcareService - - ImagingStudy - - Immunization - - ImmunizationEvaluation - - ImmunizationRecommendation - - ImplementationGuide - - InsurancePlan - - Invoice - - Library - - Linkage - - List - - Location - - Measure - - MeasureReport - - Media - - Medication - - MedicationAdministration - - MedicationDispense - - MedicationKnowledge - - MedicationRequest - - MedicationStatement - - MedicinalProduct - - MedicinalProductAuthorization - - MedicinalProductContraindication - - MedicinalProductIndication - - MedicinalProductIngredient - - MedicinalProductInteraction - - MedicinalProductManufactured - - MedicinalProductPackaged - - MedicinalProductPharmaceutical - - MedicinalProductUndesirableEffect - - MessageDefinition - - MessageHeader - - MolecularSequence - - NamingSystem - - NutritionOrder - - Observation - - ObservationDefinition - - OperationDefinition - - OperationOutcome - - Organization - - OrganizationAffiliation - - Parameters - - Patient - - PaymentNotice - - PaymentReconciliation - - Person - - PlanDefinition - - Practitioner - - PractitionerRole - - Procedure - - Provenance - - Questionnaire - - QuestionnaireResponse - - RelatedPerson - - RequestGroup - - ResearchDefinition - - ResearchElementDefinition - - ResearchStudy - - ResearchSubject - - Resource - - RiskAssessment - - RiskEvidenceSynthesis - - Schedule - - SearchParameter - - ServiceRequest - - Slot - - Specimen - - SpecimenDefinition - - StructureDefinition - - StructureMap - - Subscription - - Substance - - SubstanceNucleicAcid - - SubstancePolymer - - SubstanceProtein - - SubstanceReferenceInformation - - SubstanceSourceMaterial - - SubstanceSpecification - - SupplyDelivery - - SupplyRequest - - Task - - TerminologyCapabilities - - TestReport - - TestScript - - ValueSet - - VerificationResult - - VisionPrescription - id: - type: string - pattern: "[A-Za-z0-9\\-\\.]{1,64}" - description: The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes. - meta: - $ref: "#/components/schemas/Meta" - description: The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource. - implicitRules: - type: string - pattern: \S* - description: A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc. - language: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: The base language in which the resource is written. - required: - - resourceType - DomainResource: - allOf: - - $ref: "#/components/schemas/Resource" - - type: object - properties: - text: - $ref: "#/components/schemas/Narrative" - description: A human–readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it "clinically safe" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety. - contained: - type: array - items: - $ref: "#/components/schemas/Resource" - description: These resources do not have an independent existence apart from the resource that contains them – they cannot be identified independently, and nor can they have their own independent transaction scope. - extension: - type: array - items: - $ref: "#/components/schemas/Extension" - description: May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. - modifierExtension: - type: array - items: - $ref: "#/components/schemas/Extension" - description: |- - May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. - - Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself). - Device: - allOf: - - $ref: "#/components/schemas/DomainResource" - - type: object - properties: - identifier: - type: array - items: - $ref: "#/components/schemas/Identifier" - description: Unique instance identifiers assigned to a device by manufacturers other organizations or owners. - definition: - $ref: "#/components/schemas/Reference" - description: The reference to the definition for the device. - udiCarrier: - type: array - items: - $ref: "#/components/schemas/DeviceUdiCarrier" - description: Unique device identifier (UDI) assigned to device label or package. Note that the Device may include multiple udiCarriers as it either may include just the udiCarrier for the jurisdiction it is sold, or for multiple jurisdictions it could have been sold. - status: - type: string - enum: - - active - - inactive - - entered-in-error - - unknown - description: Status of the Device availability. - statusReason: - type: array - items: - $ref: "#/components/schemas/CodeableConcept" - description: Reason for the dtatus of the Device availability. - distinctIdentifier: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The distinct identification string as required by regulation for a human cell, tissue, or cellular and tissue–based product. - manufacturer: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A name of the manufacturer. - manufactureDate: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: The date and time when the device was manufactured. - expirationDate: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: The date and time beyond which this device is no longer valid or should not be used (if applicable). - lotNumber: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Lot number assigned by the manufacturer. - serialNumber: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The serial number assigned by the organization when the device was manufactured. - deviceName: - type: array - items: - $ref: "#/components/schemas/DeviceDeviceName" - description: This represents the manufacturer's name of the device as provided by the device, from a UDI label, or by a person describing the Device. This typically would be used when a person provides the name(s) or when the device represents one of the names available from DeviceDefinition. - modelNumber: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The model number for the device. - partNumber: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The part number of the device. - type: - $ref: "#/components/schemas/CodeableConcept" - description: |- - The type of deviceName. - UDILabelName | UserFriendlyName | PatientReportedName | ManufactureDeviceName | ModelName. - specialization: - type: array - items: - $ref: "#/components/schemas/DeviceSpecialization" - description: The capabilities supported on a device, the standards to which the device conforms for a particular purpose, and used for the communication. - version: - type: array - items: - $ref: "#/components/schemas/DeviceVersion" - description: The version of the standard that is used to operate and communicate. - property: - type: array - items: - $ref: "#/components/schemas/DeviceProperty" - description: The actual configuration settings of a device as it actually operates, e.g., regulation status, time properties. - patient: - $ref: "#/components/schemas/Reference" - description: Patient information, If the device is affixed to a person. - owner: - $ref: "#/components/schemas/Reference" - description: An organization that is responsible for the provision and ongoing maintenance of the device. - contact: - type: array - items: - $ref: "#/components/schemas/ContactPoint" - description: Contact details for an organization or a particular human that is responsible for the device. - location: - $ref: "#/components/schemas/Reference" - description: The place where the device can be found. - url: - type: string - pattern: \S* - description: A network address on which the device may be contacted directly. - note: - type: array - items: - $ref: "#/components/schemas/Annotation" - description: Descriptive information, usage information or implantation information that is not captured in an existing element. - safety: - type: array - items: - $ref: "#/components/schemas/CodeableConcept" - description: Provides additional safety characteristics about a medical device. For example devices containing latex. - parent: - $ref: "#/components/schemas/Reference" - description: The parent device. - example: - resourceType: Device - meta: - versionId: leAx-ab3l3 - lastUpdated: "2020-11-04T11:22:43.963014-05:00" - source: yOjqeCo0bv - profile: - - Z7pJUfqU6t - security: - - system: 5wvbYyTKjt - version: wfYhQqDqvR - code: fsuby16DBu - display: XUC_83exZs - userSelected: true - tag: - - system: rW_khzpssy - version: z9LyFhRYvf - code: qPlH1wpJTv - display: wLhj3rWEFb - userSelected: true - - code: ibm/complete-mock - implicitRules: EY3J2qd657 - language: en-US - text: - status: additional - div:
- identifier: - - use: temp - type: - coding: - - system: 2NnKDj0XAP - version: kowcO4_ibR - code: o_qjfWR1E4 - display: wYXJaKt_KP - userSelected: true - text: jJdgrpRSLO - system: kYVnOGpPz1 - value: 3VT6Q1la6l - period: - start: "2020-11-04T11:22:43.966349-05:00" - end: "2020-11-04T11:22:43.96665-05:00" - definition: - reference: DeviceDefinition/0iz1m36ZqT - type: DeviceDefinition - identifier: - use: old - type: - coding: - - system: OTscJIufV8 - version: I8wNZsOCgm - code: KpiL5ZvBe5 - display: VKdG88p1aR - userSelected: true - text: KuSxhlgLYM - system: FcXewtum1O - value: ft0VUZ5axC - period: - start: "2020-11-04T11:22:43.968256-05:00" - end: "2020-11-04T11:22:43.968431-05:00" - display: c7rPPL3q1K - udiCarrier: - - deviceIdentifier: 5_yGXOVzlZ - issuer: ctRAL2MENY - jurisdiction: 2XSxq5Q5y9 - carrierAIDC: aTZfAVA= - carrierHRF: GwKJEb2UCd - entryType: card - status: active - statusReason: - - coding: - - system: MAb0Kyat4R - version: PUnRaXzCOB - code: p6bo2NaOkq - display: 2wb3XMKYkC - userSelected: true - text: qnlahiKNH4 - distinctIdentifier: EtpCekS5ug - manufacturer: c0cXF0rkid - manufactureDate: "2020-11-04T11:22:43.971972-05:00" - expirationDate: "2020-11-04T11:22:43.972144-05:00" - lotNumber: GlPVAmvgfX - serialNumber: UW8XQT_T8f - deviceName: - - name: 8EqKlRy_yO - type: patient-reported-name - modelNumber: QbStiBsInX - partNumber: 0FLeLYIh9j - type: - coding: - - system: pVH61hMZ_7 - version: Ym58JrWbnW - code: OgYEL_SpMs - display: wpDPKyN213 - userSelected: true - text: 7QfkFIJgpQ - specialization: - - systemType: - coding: - - system: VfhTWTWEfq - version: RC50TO6Cqd - code: I7kYlWxkV9 - display: EvRlmuXclO - userSelected: true - text: 2kVAmKpHVs - version: hV9MlnjJOL - version: - - type: - coding: - - system: PlURX9yHqf - version: Z43HjFOG4n - code: Eb6jJbeQIi - display: aQqE9qlvUD - userSelected: true - text: N4pyV2sdOJ - component: - use: usual - type: - coding: - - system: 74u6CAqeKT - version: E7p3ozfUut - code: ii15Kf5ScQ - display: oUYOGoD92f - userSelected: true - text: OYzBklTNKx - system: WGx_ohb6b9 - value: vkE_QfvSaK - period: - start: "2020-11-04T11:22:43.976086-05:00" - end: "2020-11-04T11:22:43.976259-05:00" - value: fWWMVmjtNX - property: - - type: - coding: - - system: ATwcqz7UcD - version: ykvNaWcVZV - code: _DBffQxSd4 - display: 2ApwgE3YfV - userSelected: true - text: f8uQAjqrhp - valueQuantity: - - value: 0.5877067255449361 - comparator: <= - unit: 7wLeVdJkhT - system: 72b4FQk2t1 - code: 6aVpwGwaaW - valueCode: - - coding: - - system: nXMhN7nH07 - version: CyD__CA_WP - code: qpdZVSHj36 - display: rRQLOwfvD8 - userSelected: true - text: ZYFB2Ufe5R - patient: - reference: Patient/TqL2pL98gA - type: Patient - identifier: - use: secondary - type: - coding: - - system: P2PK0tK6V9 - version: OrESnC4jsJ - code: QqMZU6DqG5 - display: XlGeotrgMG - userSelected: true - text: xEXDseHkip - system: NTHRO2OZDt - value: eoRXk6X9Pr - period: - start: "2020-11-04T11:22:43.979104-05:00" - end: "2020-11-04T11:22:43.979266-05:00" - display: yGWttxdCia - owner: - reference: Organization/JIX1Dk6PAC - type: Organization - identifier: - use: usual - type: - coding: - - system: uaqEtS8sNB - version: 1W8XBAjFAT - code: iHVSugMYKD - display: CCk69MgMGW - userSelected: true - text: aEfa7a5wh3 - system: stVF7jEeSP - value: jlifbu4zbx - period: - start: "2020-11-04T11:22:43.980235-05:00" - end: "2020-11-04T11:22:43.980404-05:00" - display: Nu_u2FD_dT - contact: - - system: other - value: JFzCk8sShT - use: old - rank: 1.917455768e+09 - period: - start: "2020-11-04T11:22:43.980769-05:00" - end: "2020-11-04T11:22:43.980915-05:00" - location: - reference: Location/xpkwiiYA4U - type: Location - identifier: - use: official - type: - coding: - - system: pCFDnsZMjg - version: weiCRuKs87 - code: gCmknogj7c - display: JlQr_Y5Diy - userSelected: true - text: oUQVwdjR7n - system: igZLLInYvJ - value: RXuSd3x7Kn - period: - start: "2020-11-04T11:22:43.983113-05:00" - end: "2020-11-04T11:22:43.983285-05:00" - display: bcgajGFE6f - url: arZRapDYp_ - note: - - authorReference: - reference: Practitioner/2ci2Lv99EG - type: Practitioner - identifier: - use: secondary - type: - coding: - - system: x8D7d6u4wp - version: uEjUR7XG2Q - code: VgUQBAyio4 - display: qMDU9hbJCE - userSelected: true - text: bsHPggO95l - system: 12Y6tNgx1B - value: Fxafvym0mI - period: - start: "2020-11-04T11:22:43.984583-05:00" - end: "2020-11-04T11:22:43.984747-05:00" - display: icpyr8sCM5 - time: "2020-11-04T11:22:43.984961-05:00" - text: JyDVmzuT2F - safety: - - coding: - - system: n24W87b8CN - version: McPNdd8p8E - code: 7UXjXlUQ1n - display: vDlZ4y5Rcu - userSelected: true - text: PgGlM0rU_z - parent: - reference: Device/13x_MypWi2 - type: Device - identifier: - use: secondary - type: - coding: - - system: xFI4BESbB0 - version: ok5uyHpmCL - code: ltvv_3oObD - display: NE8QkVBRIW - userSelected: true - text: uOS0kmo3ZP - system: aHn4gLNrsa - value: mjdYRXyVLu - period: - start: "2020-11-04T11:22:43.986647-05:00" - end: "2020-11-04T11:22:43.986859-05:00" - display: d49bgelgmI - Bundle: - allOf: - - $ref: "#/components/schemas/Resource" - - type: object - properties: - identifier: - $ref: "#/components/schemas/Identifier" - description: A persistent identifier for the bundle that won't change as a bundle is copied from server to server. - type: - type: string - enum: - - document - - message - - transaction - - transaction-response - - batch - - batch-response - - history - - searchset - - collection - description: Indicates the purpose of this bundle – how it is intended to be used. - timestamp: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)) - description: The date/time that the bundle was assembled – i.e. when the resources were placed in the bundle. - total: - type: integer - format: int32 - description: If a set of search matches, this is the total number of entries of type 'match' across all pages in the search. It does not include search.mode = 'include' or 'outcome' entries and it does not provide a count of the number of entries in the Bundle. - link: - type: array - items: - $ref: "#/components/schemas/BundleLink" - description: A series of links that provide context to this bundle. - entry: - type: array - items: - $ref: "#/components/schemas/BundleEntry" - description: An entry in a bundle resource – will either contain a resource or information about a resource (transactions and history only). - signature: - $ref: "#/components/schemas/Signature" - description: Digital Signature – base64 encoded. XML–DSig or a JWT. - required: - - type - example: - resourceType: Bundle - meta: - versionId: F7bitzw1Hj - lastUpdated: "2020-11-04T11:22:43.502316-05:00" - source: JRkgOa8bwm - profile: - - i4gpGowr6Y - security: - - system: lTnQF4OV3w - version: hTth0i4Ivs - code: P6iXDX6DcV - display: rMonvtKiO8 - userSelected: true - tag: - - system: 4HA_3UN6ab - version: FvMU1dv9n6 - code: AjrpSN9l0q - display: V3cjH6t7zX - userSelected: true - - code: ibm/complete-mock - implicitRules: IUOLjdM2gr - language: en-US - identifier: - use: temp - type: - coding: - - system: GG7NhXNGqZ - version: hTXMVyhLkS - code: fimixp8PMa - display: aYmxIkjI7w - userSelected: true - text: znbNwNNzOo - system: zxGBnkW0WU - value: lpcL4XUHKZ - period: - start: "2020-11-04T11:22:43.507146-05:00" - end: "2020-11-04T11:22:43.507335-05:00" - type: document - timestamp: "2020-11-04T11:22:43.507779-05:00" - total: 8.04618139e+08 - link: - - relation: 0h9oqVMQIt - url: N6t6uzHuIy - entry: - - link: - - relation: IWG3UO5Awa - url: MJBFG1zxnb - fullUrl: PKkErHU9RX - search: - mode: match - score: 0.7827620245063741 - request: - method: DELETE - url: EX5t3mSMJh - ifNoneMatch: TXPgvN30LK - ifModifiedSince: "2020-11-04T11:22:43.514903-05:00" - ifMatch: ESkJi0jaVC - ifNoneExist: fuSskChKIq - response: - status: avVXy1xkRq - location: v0Ub50vvWL - etag: BmCLcXDNuX - lastModified: "2020-11-04T11:22:43.516375-05:00" - signature: - type: - - system: YievdsQnmM - version: 3um1GW4GVD - code: sNUnxWccmG - display: pqCTozifNV - userSelected: true - when: "2020-11-04T11:22:43.518017-05:00" - who: - reference: Practitioner/7tLbieRmnA - type: Practitioner - identifier: - use: secondary - type: - coding: - - system: 9BzciHf_0T - version: em1dSVwNdC - code: LD7gU1VdIa - display: l_je45PsqP - userSelected: true - text: Kd2TxyCZR7 - system: pACafNTDh7 - value: _hcXO_NlZg - period: - start: "2020-11-04T11:22:43.519783-05:00" - end: "2020-11-04T11:22:43.520066-05:00" - display: l79nsD4sN6 - onBehalfOf: - reference: Practitioner/LiWB2VJ2UG - type: Practitioner - identifier: - use: official - type: - coding: - - system: 64W3kvPnCz - version: 1LnrLVgWre - code: oHtu3WoiKi - display: gMKD8fdCjt - userSelected: true - text: bu5V13p166 - system: Graf7De_yt - value: UWJRgHe9wr - period: - start: "2020-11-04T11:22:43.544663-05:00" - end: "2020-11-04T11:22:43.545138-05:00" - display: kQ5612idGd - targetFormat: AQCVaUpSER - sigFormat: FxtGIjypV6 - data: dUUnF3I= - OperationOutcome: - allOf: - - $ref: "#/components/schemas/DomainResource" - - type: object - properties: - issue: - type: array - items: - $ref: "#/components/schemas/OperationOutcomeIssue" - description: An error, warning, or information message that results from a system action. - minItems: 1 - required: - - issue - example: - resourceType: OperationOutcome - meta: - versionId: q63JAUPuUM - lastUpdated: "2020-11-04T11:22:40.494613-05:00" - source: lwnaIGbKJn - profile: - - XGQPxL1j9k - security: - - system: sPgaKWp0jQ - version: wZHLBfjatw - code: DMQqy4R3E8 - display: mmxOeLn3hG - userSelected: true - tag: - - system: MtLYCBYPWS - version: 8Ak7HZQrke - code: 0DRWc7UuJB - display: 6NXvm6cEoG - userSelected: true - - code: ibm/complete-mock - implicitRules: siFyYo720q - language: en-US - text: - status: generated - div:
- issue: - - severity: fatal - code: required - details: - coding: - - system: YAwo1XN_fv - version: 9ycWn1vQBR - code: Y4ci7ASL_1 - display: lq_CJ5bq6Z - userSelected: true - text: aWHd4ZkhaW - diagnostics: yew1JE2w0X - location: - - ZDqBVS3Xgx - expression: - - yYfbNaNi8V - BundleEntry: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - link: - type: array - items: - $ref: "#/components/schemas/BundleLink" - description: A series of links that provide context to this entry. - fullUrl: - type: string - pattern: \S* - description: "The Absolute URL for the resource. The fullUrl SHALL NOT disagree with the id in the resource – i.e. if the fullUrl is not a urn:uuid, the URL shall be version–independent URL consistent with the Resource.id. The fullUrl is a version independent reference to the resource. The fullUrl element SHALL have a value except that: \n* fullUrl can be empty on a POST (although it does not need to when specifying a temporary id for reference in the bundle)\n* Results from operations might involve resources that are not identified." - resource: - $ref: "#/components/schemas/Resource" - description: The Resource for the entry. The purpose/meaning of the resource is determined by the Bundle.type. - search: - $ref: "#/components/schemas/BundleEntrySearch" - description: Information about the search process that lead to the creation of this entry. - request: - $ref: "#/components/schemas/BundleEntryRequest" - description: Additional information about how this entry should be processed as part of a transaction or batch. For history, it shows how the entry was processed to create the version contained in the entry. - response: - $ref: "#/components/schemas/BundleEntryResponse" - description: Indicates the results of processing the corresponding 'request' entry in the batch or transaction being responded to or what the results of an operation where when returning history. - BundleEntryResponse: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - status: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The status code returned by processing this entry. The status SHALL start with a 3 digit HTTP code (e.g. 404) and may contain the standard HTTP description associated with the status code. - location: - type: string - pattern: \S* - description: The location header created by processing this operation, populated if the operation returns a location. - etag: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The Etag for the resource, if the operation for the entry produced a versioned resource (see [Resource Metadata and Versioning](http.html#versioning) and [Managing Resource Contention](http.html#concurrency)). - lastModified: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)) - description: The date/time that the resource was modified on the server. - outcome: - $ref: "#/components/schemas/Resource" - description: An OperationOutcome containing hints and warnings produced as part of processing this entry in a batch or transaction. - required: - - status - BundleEntryRequest: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - method: - type: string - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - PATCH - description: In a transaction or batch, this is the HTTP action to be executed for this entry. In a history bundle, this indicates the HTTP action that occurred. - url: - type: string - pattern: \S* - description: The URL for this entry, relative to the root (the address to which the request is posted). - ifNoneMatch: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: If the ETag values match, return a 304 Not Modified status. See the API documentation for ["Conditional Read"](http.html#cread). - ifModifiedSince: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)) - description: Only perform the operation if the last updated date matches. See the API documentation for ["Conditional Read"](http.html#cread). - ifMatch: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Only perform the operation if the Etag value matches. For more information, see the API section ["Managing Resource Contention"](http.html#concurrency). - ifNoneExist: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Instruct the server not to perform the create if a specified resource already exists. For further information, see the API documentation for ["Conditional Create"](http.html#ccreate). This is just the query portion of the URL – what follows the "?" (not including the "?"). - required: - - method - - url - BundleEntrySearch: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - mode: - type: string - enum: - - match - - include - - outcome - description: Why this entry is in the result set – whether it's included as a match or because of an _include requirement, or to convey information or warning information about the search process. - score: - type: number - description: When searching, the server's search ranking score for the entry. - BundleLink: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - relation: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A name which details the functional use for this link – see [http://www.iana.org/assignments/link–relations/link–relations.xhtml#link–relations–1](http://www.iana.org/assignments/link–relations/link–relations.xhtml#link–relations–1). - url: - type: string - pattern: \S* - description: The reference details for the link. - required: - - relation - - url - DeviceProperty: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - type: - $ref: "#/components/schemas/CodeableConcept" - description: Code that specifies the property DeviceDefinitionPropetyCode (Extensible). - valueQuantity: - type: array - items: - $ref: "#/components/schemas/Quantity" - description: Property value as a quantity. - valueCode: - type: array - items: - $ref: "#/components/schemas/CodeableConcept" - description: Property value as a code, e.g., NTP4 (synced to NTP). - required: - - type - DeviceVersion: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - type: - $ref: "#/components/schemas/CodeableConcept" - description: The type of the device version. - component: - $ref: "#/components/schemas/Identifier" - description: A single component of the device version. - value: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The version text. - required: - - value - DeviceSpecialization: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - systemType: - $ref: "#/components/schemas/CodeableConcept" - description: The standard that is used to operate and communicate. - version: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The version of the standard that is used to operate and communicate. - required: - - systemType - DeviceDeviceName: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - name: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The name of the device. - type: - type: string - enum: - - udi-label-name - - user-friendly-name - - patient-reported-name - - manufacturer-name - - model-name - - other - description: |- - The type of deviceName. - UDILabelName | UserFriendlyName | PatientReportedName | ManufactureDeviceName | ModelName. - required: - - name - - type - DeviceUdiCarrier: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - deviceIdentifier: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The device identifier (DI) is a mandatory, fixed portion of a UDI that identifies the labeler and the specific version or model of a device. - issuer: - type: string - pattern: \S* - description: "Organization that is charged with issuing UDIs for devices. For example, the US FDA issuers include :\n1) GS1: \nhttp://hl7.org/fhir/NamingSystem/gs1–di, \n2) HIBCC:\nhttp://hl7.org/fhir/NamingSystem/hibcc–dI, \n3) ICCBBA for blood containers:\nhttp://hl7.org/fhir/NamingSystem/iccbba–blood–di, \n4) ICCBA for other devices:\nhttp://hl7.org/fhir/NamingSystem/iccbba–other–di." - jurisdiction: - type: string - pattern: \S* - description: The identity of the authoritative source for UDI generation within a jurisdiction. All UDIs are globally unique within a single namespace with the appropriate repository uri as the system. For example, UDIs of devices managed in the U.S. by the FDA, the value is http://hl7.org/fhir/NamingSystem/fda–udi. - carrierAIDC: - type: string - pattern: (\s*([0-9a-zA-Z\+/=]){4}\s*)+ - description: The full UDI carrier of the Automatic Identification and Data Capture (AIDC) technology representation of the barcode string as printed on the packaging of the device – e.g., a barcode or RFID. Because of limitations on character sets in XML and the need to round–trip JSON data through XML, AIDC Formats *SHALL* be base64 encoded. - carrierHRF: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The full UDI carrier as the human readable form (HRF) representation of the barcode string as printed on the packaging of the device. - entryType: - type: string - enum: - - barcode - - rfid - - manual - - card - - self-reported - - unknown - description: A coded entry to indicate how the data was entered. - OperationOutcomeIssue: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - severity: - type: string - enum: - - fatal - - error - - warning - - information - description: Indicates whether the issue indicates a variation from successful processing. - code: - type: string - enum: - - invalid - - structure - - required - - value - - invariant - - security - - login - - unknown - - expired - - forbidden - - suppressed - - processing - - not-supported - - duplicate - - multiple-matches - - not-found - - deleted - - too-long - - code-invalid - - extension - - too-costly - - business-rule - - conflict - - transient - - lock-error - - no-store - - exception - - timeout - - incomplete - - throttled - - informational - description: Describes the type of the issue. The system that creates an OperationOutcome SHALL choose the most applicable code from the IssueType value set, and may additional provide its own code for the error in the details element. - details: - $ref: "#/components/schemas/CodeableConcept" - description: Additional details about the error. This may be a text description of the error or a system code that identifies the error. - diagnostics: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Additional diagnostic information about the issue. - location: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: "This element is deprecated because it is XML specific. It is replaced by issue.expression, which is format independent, and simpler to parse. \n\nFor resource issues, this will be a simple XPath limited to element names, repetition indicators and the default child accessor that identifies one of the elements in the resource that caused this issue to be raised. For HTTP errors, will be \"http.\" + the parameter name." - expression: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A [simple subset of FHIRPath](fhirpath.html#simple) limited to element names, repetition indicators and the default child accessor that identifies one of the elements in the resource that caused this issue to be raised. - required: - - severity - - code - Element: - type: object - properties: - id: - type: string - pattern: "[A-Za-z0-9\\-\\.]{1,64}" - description: Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces. - extension: - type: array - items: - $ref: "#/components/schemas/Extension" - description: May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. - example: - - url: http://example.com - valueString: text value - BackboneElement: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - modifierExtension: - type: array - items: - $ref: "#/components/schemas/Extension" - description: |- - May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. - - Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself). - Address: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - use: - type: string - enum: - - home - - work - - temp - - old - - billing - description: The purpose of this address. - type: - type: string - enum: - - postal - - physical - - both - description: Distinguishes between physical addresses (those you can visit) and mailing addresses (e.g. PO Boxes and care–of addresses). Most addresses are both. - text: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Specifies the entire address as it should be displayed e.g. on a postal label. This may be provided instead of or as well as the specific parts. - line: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: This component contains the house number, apartment number, street name, street direction, P.O. Box number, delivery hints, and similar address information. - city: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The name of the city, town, suburb, village or other community or delivery center. - district: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The name of the administrative area (county). - state: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Sub–unit of a country with limited sovereignty in a federally organized country. A code may be used if codes are in common use (e.g. US 2 letter state codes). - postalCode: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A postal code designating a region defined by the postal service. - country: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Country – a nation as commonly understood or generally accepted. - period: - $ref: "#/components/schemas/Period" - description: Time period when address was/is in use. - Age: - allOf: - - $ref: "#/components/schemas/Quantity" - - type: object - properties: {} - Annotation: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - authorReference: - $ref: "#/components/schemas/Reference" - description: The individual responsible for making the annotation. - authorString: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The individual responsible for making the annotation. - time: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: Indicates when this particular annotation was made. - text: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The text of the annotation in markdown format. - required: - - text - Attachment: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - contentType: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: Identifies the type of the data in the attachment and allows a method to be chosen to interpret or render the data. Includes mime type parameters such as charset where appropriate. - language: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: The human language of the content. The value can be any valid value according to BCP 47. - data: - type: string - pattern: (\s*([0-9a-zA-Z\+/=]){4}\s*)+ - description: The actual data of the attachment – a sequence of bytes, base64 encoded. - url: - type: string - pattern: \S* - description: A location where the data can be accessed. - size: - type: integer - format: int32 - description: The number of bytes of data that make up this attachment (before base64 encoding, if that is done). - hash: - type: string - pattern: (\s*([0-9a-zA-Z\+/=]){4}\s*)+ - description: The calculated hash of the data using SHA–1. Represented using base64. - title: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A label or set of text to display in place of the data. - creation: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: The date that the attachment was first created. - CodeableConcept: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - coding: - type: array - items: - $ref: "#/components/schemas/Coding" - description: A reference to a code defined by a terminology system. - text: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A human language representation of the concept as seen/selected/uttered by the user who entered the data and/or which represents the intended meaning of the user. - Coding: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - system: - type: string - pattern: \S* - description: The identification of the code system that defines the meaning of the symbol in the code. - version: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The version of the code system which was used when choosing this code. Note that a well–maintained code system does not need the version reported, because the meaning of codes is consistent across versions. However this cannot consistently be assured, and when the meaning is not guaranteed to be consistent, the version SHOULD be exchanged. - code: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: A symbol in syntax defined by the system. The symbol may be a predefined code or an expression in a syntax defined by the coding system (e.g. post–coordination). - display: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A representation of the meaning of the code in the system, following the rules of the system. - userSelected: - type: boolean - description: Indicates that this coding was chosen by a user directly – e.g. off a pick list of available items (codes or displays). - ContactPoint: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - system: - type: string - enum: - - phone - - fax - - email - - pager - - url - - sms - - other - description: Telecommunications form for contact point – what communications system is required to make use of the contact. - value: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The actual contact point details, in a form that is meaningful to the designated communication system (i.e. phone number or email address). - use: - type: string - enum: - - home - - work - - temp - - old - - mobile - description: Identifies the purpose for the contact point. - rank: - type: integer - format: int32 - description: Specifies a preferred order in which to use a set of contacts. ContactPoints with lower rank values are more preferred than those with higher rank values. - period: - $ref: "#/components/schemas/Period" - description: Time period when the contact point was/is in use. - Count: - allOf: - - $ref: "#/components/schemas/Quantity" - - type: object - properties: {} - Distance: - allOf: - - $ref: "#/components/schemas/Quantity" - - type: object - properties: {} - Duration: - allOf: - - $ref: "#/components/schemas/Quantity" - - type: object - properties: {} - HumanName: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - use: - type: string - enum: - - usual - - official - - temp - - nickname - - anonymous - - old - - maiden - description: Identifies the purpose for this name. - text: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Specifies the entire name as it should be displayed e.g. on an application UI. This may be provided instead of or as well as the specific parts. - family: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The part of a name that links to the genealogy. In some cultures (e.g. Eritrea) the family name of a son is the first name of his father. - given: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Given name. - prefix: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Part of the name that is acquired as a title due to academic, legal, employment or nobility status, etc. and that appears at the start of the name. - suffix: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Part of the name that is acquired as a title due to academic, legal, employment or nobility status, etc. and that appears at the end of the name. - period: - $ref: "#/components/schemas/Period" - description: Indicates the period of time when this name was valid for the named person. - Identifier: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - use: - type: string - enum: - - usual - - official - - temp - - secondary - - old - description: The purpose of this identifier. - type: - $ref: "#/components/schemas/CodeableConcept" - description: A coded type for the identifier that can be used to determine which identifier to use for a specific purpose. - system: - type: string - pattern: \S* - description: Establishes the namespace for the value – that is, a URL that describes a set values that are unique. - value: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The portion of the identifier typically relevant to the user and which is unique within the context of the system. - period: - $ref: "#/components/schemas/Period" - description: Time period during which identifier is/was valid for use. - assigner: - $ref: "#/components/schemas/Reference" - description: Organization that issued/manages the identifier. - example: - reference: Organization/123 - type: Organization - display: The Assigning Organization - Money: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - value: - type: number - description: Numerical value (with implicit precision). - currency: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: ISO 4217 Currency Code. - MoneyQuantity: - allOf: - - $ref: "#/components/schemas/Quantity" - - type: object - properties: {} - Period: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - start: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: The start of the period. The boundary is inclusive. - end: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: The end of the period. If the end of the period is missing, it means no end was known or planned at the time the instance was created. The start may be in the past, and the end date in the future, which means that period is expected/planned to end at that time. - Quantity: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - value: - type: number - description: The value of the measured amount. The value includes an implicit precision in the presentation of the value. - comparator: - type: string - enum: - - < - - <= - - ">=" - - ">" - description: How the value should be understood and represented – whether the actual value is greater or less than the stated value due to measurement issues; e.g. if the comparator is "<" , then the real value is < stated value. - unit: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A human–readable form of the unit. - system: - type: string - pattern: \S* - description: The identification of the system that provides the coded form of the unit. - code: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: A computer processable form of the unit in some unit representation system. - Range: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - low: - $ref: "#/components/schemas/SimpleQuantity" - description: The low limit. The boundary is inclusive. - high: - $ref: "#/components/schemas/SimpleQuantity" - description: The high limit. The boundary is inclusive. - Ratio: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - numerator: - $ref: "#/components/schemas/Quantity" - description: The value of the numerator. - denominator: - $ref: "#/components/schemas/Quantity" - description: The value of the denominator. - Reference: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - reference: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A reference to a location at which the other resource is found. The reference may be a relative reference, in which case it is relative to the service base URL, or an absolute URL that resolves to the location where the resource is found. The reference may be version specific or not. If the reference is not to a FHIR RESTful server, then it should be assumed to be version specific. Internal fragment references (start with '#') refer to contained resources. - type: - type: string - pattern: \S* - description: |- - The expected type of the target of the reference. If both Reference.type and Reference.reference are populated and Reference.reference is a FHIR URL, both SHALL be consistent. - - The type is the Canonical URL of Resource Definition that is the type this reference refers to. References are URLs that are relative to http://hl7.org/fhir/StructureDefinition/ e.g. "Patient" is a reference to http://hl7.org/fhir/StructureDefinition/Patient. Absolute URLs are only allowed for logical models (and can only be used in references in logical models, not resources). - identifier: - $ref: "#/components/schemas/Identifier" - description: An identifier for the target resource. This is used when there is no way to reference the other resource directly, either because the entity it represents is not available through a FHIR server, or because there is no way for the author of the resource to convert a known identifier to an actual location. There is no requirement that a Reference.identifier point to something that is actually exposed as a FHIR instance, but it SHALL point to a business concept that would be expected to be exposed as a FHIR instance, and that instance would need to be of a FHIR resource type allowed by the reference. - display: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Plain text narrative that identifies the resource in addition to the resource reference. - SampledData: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - origin: - $ref: "#/components/schemas/SimpleQuantity" - description: The base quantity that a measured value of zero represents. In addition, this provides the units of the entire measurement series. - period: - type: number - description: The length of time between sampling times, measured in milliseconds. - factor: - type: number - description: A correction factor that is applied to the sampled data points before they are added to the origin. - lowerLimit: - type: number - description: The lower limit of detection of the measured points. This is needed if any of the data points have the value "L" (lower than detection limit). - upperLimit: - type: number - description: The upper limit of detection of the measured points. This is needed if any of the data points have the value "U" (higher than detection limit). - dimensions: - type: integer - format: int32 - description: The number of sample points at each time point. If this value is greater than one, then the dimensions will be interlaced – all the sample points for a point in time will be recorded at once. - data: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A series of data points which are decimal values separated by a single space (character u20). The special values "E" (error), "L" (below detection limit) and "U" (above detection limit) can also be used in place of a decimal value. - required: - - origin - - period - - dimensions - SimpleQuantity: - allOf: - - $ref: "#/components/schemas/Quantity" - - type: object - properties: {} - Signature: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - type: - type: array - items: - $ref: "#/components/schemas/Coding" - description: An indication of the reason that the entity signed this document. This may be explicitly included as part of the signature information and can be used when determining accountability for various actions concerning the document. - minItems: 1 - when: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)) - description: When the digital signature was signed. - who: - $ref: "#/components/schemas/Reference" - description: A reference to an application–usable description of the identity that signed (e.g. the signature used their private key). - onBehalfOf: - $ref: "#/components/schemas/Reference" - description: A reference to an application–usable description of the identity that is represented by the signature. - targetFormat: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: A mime type that indicates the technical format of the target resources signed by the signature. - sigFormat: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: A mime type that indicates the technical format of the signature. Important mime types are application/signature+xml for X ML DigSig, application/jose for JWS, and image/* for a graphical image of a signature, etc. - data: - type: string - pattern: (\s*([0-9a-zA-Z\+/=]){4}\s*)+ - description: The base64 encoding of the Signature content. When signature is not recorded electronically this element would be empty. - required: - - type - - when - - who - Timing: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - event: - type: array - items: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: Identifies specific times when the event occurs. - repeat: - $ref: "#/components/schemas/TimingRepeat" - description: A set of rules that describe when the event is scheduled. - code: - $ref: "#/components/schemas/CodeableConcept" - description: A code for the timing schedule (or just text in code.text). Some codes such as BID are ubiquitous, but many institutions define their own additional codes. If a code is provided, the code is understood to be a complete statement of whatever is specified in the structured timing data, and either the code or the data may be used to interpret the Timing, with the exception that .repeat.bounds still applies over the code (and is not contained in the code). - TimingRepeat: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - boundsDuration: - $ref: "#/components/schemas/Duration" - description: Either a duration for the length of the timing schedule, a range of possible length, or outer bounds for start and/or end limits of the timing schedule. - boundsRange: - $ref: "#/components/schemas/Range" - description: Either a duration for the length of the timing schedule, a range of possible length, or outer bounds for start and/or end limits of the timing schedule. - boundsPeriod: - $ref: "#/components/schemas/Period" - description: Either a duration for the length of the timing schedule, a range of possible length, or outer bounds for start and/or end limits of the timing schedule. - count: - type: integer - format: int32 - description: A total count of the desired number of repetitions across the duration of the entire timing specification. If countMax is present, this element indicates the lower bound of the allowed range of count values. - countMax: - type: integer - format: int32 - description: If present, indicates that the count is a range – so to perform the action between [count] and [countMax] times. - duration: - type: number - description: How long this thing happens for when it happens. If durationMax is present, this element indicates the lower bound of the allowed range of the duration. - durationMax: - type: number - description: If present, indicates that the duration is a range – so to perform the action between [duration] and [durationMax] time length. - durationUnit: - type: string - enum: - - s - - min - - h - - d - - wk - - mo - - a - description: The units of time for the duration, in UCUM units. - frequency: - type: integer - format: int32 - description: The number of times to repeat the action within the specified period. If frequencyMax is present, this element indicates the lower bound of the allowed range of the frequency. - frequencyMax: - type: integer - format: int32 - description: If present, indicates that the frequency is a range – so to repeat between [frequency] and [frequencyMax] times within the period or period range. - period: - type: number - description: Indicates the duration of time over which repetitions are to occur; e.g. to express "3 times per day", 3 would be the frequency and "1 day" would be the period. If periodMax is present, this element indicates the lower bound of the allowed range of the period length. - periodMax: - type: number - description: If present, indicates that the period is a range from [period] to [periodMax], allowing expressing concepts such as "do this once every 3–5 days. - periodUnit: - type: string - enum: - - s - - min - - h - - d - - wk - - mo - - a - description: The units of time for the period in UCUM units. - dayOfWeek: - type: array - items: - type: string - enum: - - mon - - tue - - wed - - thu - - fri - - sat - - sun - description: If one or more days of week is provided, then the action happens only on the specified day(s). - timeOfDay: - type: array - items: - type: string - pattern: ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)? - description: Specified time of day for action to take place. - when: - type: array - items: - type: string - enum: - - MORN - - MORN.early - - MORN.late - - NOON - - AFT - - AFT.early - - AFT.late - - EVE - - EVE.early - - EVE.late - - NIGHT - - PHS - - HS - - WAKE - - C - - CM - - CD - - CV - - AC - - ACM - - ACD - - ACV - - PC - - PCM - - PCD - - PCV - description: An approximate time period during the day, potentially linked to an event of daily living that indicates when the action should occur. - offset: - type: integer - format: int32 - description: The number of minutes from the event. If the event code does not indicate whether the minutes is before or after the event, then the offset is assumed to be after the event. - ContactDetail: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - name: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The name of an individual to contact. - telecom: - type: array - items: - $ref: "#/components/schemas/ContactPoint" - description: The contact details for the individual (if a name was provided) or the organization. - RelatedArtifact: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - type: - type: string - enum: - - documentation - - justification - - citation - - predecessor - - successor - - derived-from - - depends-on - - composed-of - description: The type of relationship to the related artifact. - label: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A short label that can be used to reference the citation from elsewhere in the containing artifact, such as a footnote index. - display: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A brief description of the document or knowledge resource being referenced, suitable for display to a consumer. - citation: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A bibliographic citation for the related artifact. This text SHOULD be formatted according to an accepted citation format. - url: - type: string - pattern: \S* - description: A url for the artifact that can be followed to access the actual content. - document: - $ref: "#/components/schemas/Attachment" - description: The document being referenced, represented as an attachment. This is exclusive with the resource element. - resource: - type: string - pattern: \S* - description: The related resource, such as a library, value set, profile, or other knowledge resource. - required: - - type - UsageContext: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - code: - $ref: "#/components/schemas/Coding" - description: A code that identifies the type of context being specified by this usage context. - valueCodeableConcept: - $ref: "#/components/schemas/CodeableConcept" - description: A value that defines the context specified in this context of use. The interpretation of the value is defined by the code. - valueQuantity: - $ref: "#/components/schemas/Quantity" - description: A value that defines the context specified in this context of use. The interpretation of the value is defined by the code. - valueRange: - $ref: "#/components/schemas/Range" - description: A value that defines the context specified in this context of use. The interpretation of the value is defined by the code. - valueReference: - $ref: "#/components/schemas/Reference" - description: A value that defines the context specified in this context of use. The interpretation of the value is defined by the code. - required: - - code - Meta: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - versionId: - type: string - pattern: "[A-Za-z0-9\\-\\.]{1,64}" - description: The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted. - lastUpdated: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)) - description: When the resource last changed – e.g. when the version changed. - source: - type: string - pattern: \S* - description: A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc. - profile: - type: array - items: - type: string - pattern: \S* - description: A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition–definitions.html#StructureDefinition.url). - security: - type: array - items: - $ref: "#/components/schemas/Coding" - description: Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure. - tag: - type: array - items: - $ref: "#/components/schemas/Coding" - description: Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource. - Narrative: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - status: - type: string - enum: - - generated - - extensions - - additional - - empty - description: The status of the narrative – whether it's entirely generated (from just the defined data or the extensions too), or whether a human authored it and it may contain additional data. - div: - type: string - description: The actual narrative content, a stripped down version of XHTML. - required: - - status - - div - Extension: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - url: - type: string - pattern: \S* - description: Source of the definition for the extension code – a logical name or a URL. - valueBase64Binary: - type: string - pattern: (\s*([0-9a-zA-Z\+/=]){4}\s*)+ - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueBoolean: - type: boolean - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueCanonical: - type: string - pattern: \S* - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueCode: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueDate: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1]))?)? - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueDateTime: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueDecimal: - type: number - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueId: - type: string - pattern: "[A-Za-z0-9\\-\\.]{1,64}" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueInstant: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)) - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueInteger: - type: integer - format: int32 - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueMarkdown: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueOid: - type: string - pattern: urn:oid:[0-2](\.(0|[1-9][0-9]*))+ - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valuePositiveInt: - type: integer - format: int32 - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueString: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueTime: - type: string - pattern: ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)? - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueUnsignedInt: - type: integer - format: int32 - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueUri: - type: string - pattern: \S* - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueUrl: - type: string - pattern: \S* - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueUuid: - type: string - pattern: urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueAddress: - $ref: "#/components/schemas/Address" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueAge: - $ref: "#/components/schemas/Age" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueAnnotation: - $ref: "#/components/schemas/Annotation" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueAttachment: - $ref: "#/components/schemas/Attachment" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueCodeableConcept: - $ref: "#/components/schemas/CodeableConcept" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueCoding: - $ref: "#/components/schemas/Coding" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueContactPoint: - $ref: "#/components/schemas/ContactPoint" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueCount: - $ref: "#/components/schemas/Count" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueDistance: - $ref: "#/components/schemas/Distance" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueDuration: - $ref: "#/components/schemas/Duration" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueHumanName: - $ref: "#/components/schemas/HumanName" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueIdentifier: - $ref: "#/components/schemas/Identifier" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueMoney: - $ref: "#/components/schemas/Money" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valuePeriod: - $ref: "#/components/schemas/Period" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueQuantity: - $ref: "#/components/schemas/Quantity" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueRange: - $ref: "#/components/schemas/Range" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueRatio: - $ref: "#/components/schemas/Ratio" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueReference: - $ref: "#/components/schemas/Reference" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueSampledData: - $ref: "#/components/schemas/SampledData" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueSignature: - $ref: "#/components/schemas/Signature" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueTiming: - $ref: "#/components/schemas/Timing" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueContactDetail: - $ref: "#/components/schemas/ContactDetail" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueRelatedArtifact: - $ref: "#/components/schemas/RelatedArtifact" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueUsageContext: - $ref: "#/components/schemas/UsageContext" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueMeta: - $ref: "#/components/schemas/Meta" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - required: - - url - Organization: - allOf: - - $ref: "#/components/schemas/DomainResource" - - type: object - properties: - identifier: - type: array - items: - $ref: "#/components/schemas/Identifier" - description: Identifier for the organization that is used to identify the organization across multiple disparate systems. - active: - type: boolean - description: Whether the organization's record is still in active use. - type: - type: array - items: - $ref: "#/components/schemas/CodeableConcept" - description: The kind(s) of organization that this is. - name: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A name associated with the organization. - alias: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A list of alternate names that the organization is known as, or was known as in the past. - telecom: - type: array - items: - $ref: "#/components/schemas/ContactPoint" - description: A contact detail for the organization. - address: - type: array - items: - $ref: "#/components/schemas/Address" - description: An address for the organization. - partOf: - $ref: "#/components/schemas/Reference" - description: The organization of which this organization forms a part. - contact: - type: array - items: - $ref: "#/components/schemas/OrganizationContact" - description: Contact for the organization for a certain purpose. - endpoint: - type: array - items: - $ref: "#/components/schemas/Reference" - description: Technical endpoints providing access to services operated for the organization. - example: - resourceType: Organization - meta: - versionId: MkhCKF3NPs - lastUpdated: "2020-11-04T11:22:55.495627-05:00" - source: zrGPPE8DJH - profile: - - z3pU0zspXr - security: - - system: oC2Jc7y4Zf - version: EQHqJLdyML - code: zBvY_yWgVY - display: GsL8gnlzvu - userSelected: true - tag: - - system: aNNTmndRB8 - version: E7tloLtD33 - code: kMOXjB2zxk - display: 9ugg6ChWzh - userSelected: true - - code: ibm/complete-mock - implicitRules: 011v9tCoKf - language: en-US - text: - status: additional - div:
- identifier: - - use: old - type: - coding: - - system: 1SUEu2dRCO - version: SqWkXr_J9k - code: 9aTcdpFSZ8 - display: weo1p1jIrt - userSelected: true - text: b_lOMGm6ta - system: XxeSGme8g0 - value: EVVScECcrs - period: - start: "2020-11-04T11:22:55.498156-05:00" - end: "2020-11-04T11:22:55.498323-05:00" - active: true - type: - - coding: - - system: GJz7DeJAID - version: SoNWcpaGaO - code: VqNBaGgdd8 - display: D_01X4Yhro - userSelected: true - text: _da3dnjC1g - name: _Yghclpf6e - alias: - - v6TGkG3UzA - telecom: - - system: fax - value: XUXar8gIJw - use: old - rank: 6.04214668e+08 - period: - start: "2020-11-04T11:22:55.500697-05:00" - end: "2020-11-04T11:22:55.500991-05:00" - address: - - use: billing - type: postal - text: KRPWrCLw0J - line: - - Y0UGna670q - city: T9ymhEJMWe - district: CsINuTto0Y - state: _5_y00xVnB - postalCode: JPMLnjxKN8 - country: 1xSh_aRALw - period: - start: "2020-11-04T11:22:55.503025-05:00" - end: "2020-11-04T11:22:55.503358-05:00" - partOf: - reference: Organization/sBzEw2QIM9 - type: Organization - identifier: - use: official - type: - coding: - - system: 3lk1UxUrO1 - version: gxRtW6o8rV - code: N1PckpnwPx - display: ZWYPZB4ypF - userSelected: true - text: wGMie0kDM0 - system: 4Acfpp1Qus - value: sTkfzvUNRc - period: - start: "2020-11-04T11:22:55.505211-05:00" - end: "2020-11-04T11:22:55.505435-05:00" - display: fi35hwOFFC - contact: - - purpose: - coding: - - system: gXJWNpvPYH - version: ixSX6ZizQU - code: iYvO1m8ZdT - display: 7xT105543A - userSelected: true - text: xka69Q61Dz - name: - use: usual - text: DfxDNX8On5 - family: ozZugaAElu - given: - - v_ww8YMzVs - prefix: - - _hBm2j1wTY - suffix: - - DgzwLOgfj_ - period: - start: "2020-11-04T11:22:55.507967-05:00" - end: "2020-11-04T11:22:55.508327-05:00" - telecom: - - system: email - value: HE9t3cWC8v - use: work - rank: 1.386494584e+09 - period: - start: "2020-11-04T11:22:55.508975-05:00" - end: "2020-11-04T11:22:55.50928-05:00" - address: - use: billing - type: both - text: hy6FvAwKUf - line: - - y8f7C2_rKu - city: PAj0k3xx6m - district: ETBhWSq3V3 - state: 78AvjHfIfy - postalCode: 3NGE0wSbNy - country: PT_vsjai4f - period: - start: "2020-11-04T11:22:55.510249-05:00" - end: "2020-11-04T11:22:55.510429-05:00" - endpoint: - - reference: Endpoint/IQlLQrnkp9 - type: Endpoint - identifier: - use: secondary - type: - coding: - - system: bflJysEUwb - version: wXmVSZF3xN - code: uLMS2MG468 - display: 7iCeHMVBnr - userSelected: true - text: vkMjQ4BX4w - system: h5wLHJqvsB - value: 1GAC_uwdo4 - period: - start: "2020-11-04T11:22:55.511516-05:00" - end: "2020-11-04T11:22:55.511804-05:00" - display: pcy6U9Fxm0 - OrganizationContact: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - purpose: - $ref: "#/components/schemas/CodeableConcept" - description: Indicates a purpose for which the contact can be reached. - name: - $ref: "#/components/schemas/HumanName" - description: A name associated with the contact. - telecom: - type: array - items: - $ref: "#/components/schemas/ContactPoint" - description: A contact detail (e.g. a telephone number or an email address) by which the party may be contacted. - address: - $ref: "#/components/schemas/Address" - description: Visiting or postal addresses for the contact. - Version: - type: string - pattern: "^[1-9][0-9]+$" - RequestId: - type: string - pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" - example: 60E0B220-8136-4CA5-AE46-1D97EF59D068 - CorrelationId: - type: string - example: 11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA - securitySchemes: - app-level0: - $ref: https://proxygen.prod.api.platform.nhs.uk/components/securitySchemes/app-level0 - responses: {} diff --git a/docs/public_swagger/tests/test_swagger.py b/docs/public_swagger/tests/test_swagger.py deleted file mode 100644 index a052619d..00000000 --- a/docs/public_swagger/tests/test_swagger.py +++ /dev/null @@ -1,30 +0,0 @@ -from pathlib import Path - -import pytest - -PATH_TO_HERE = Path(__file__).parent -PATH_TO_ROOT = PATH_TO_HERE.parent.parent -PATH_TO_COPIED_PUBLIC_SWAGGER = PATH_TO_HERE.parent / "swagger.yaml" -PATH_TO_DIST_PUBLIC_SWAGGER = ( - PATH_TO_ROOT.parent - / "infrastructure" - / "swagger" - / "dist" - / "public" - / "swagger.yaml" -) - -# Should this test be failing, you need to copy the new swagger file from dist into this public_swagger location -# This is just a version controlled version of that file. - - -@pytest.mark.unit -def test_swagger_public_matches_dist(): - dist_swagger_file = PATH_TO_DIST_PUBLIC_SWAGGER - copied_swagger_file = PATH_TO_COPIED_PUBLIC_SWAGGER - - with open(dist_swagger_file, "r") as file1, open(copied_swagger_file, "r") as file2: - content1 = file1.read() - content2 = file2.read() - - assert content1 == content2, "Swagger files are not identical" diff --git a/scripts/infrastructure/apigee.mk b/scripts/infrastructure/apigee.mk index 096922a6..6d8cea11 100644 --- a/scripts/infrastructure/apigee.mk +++ b/scripts/infrastructure/apigee.mk @@ -58,5 +58,3 @@ $(PROXYGEN_TIMESTAMP): aws--login $(SWAGGER_APIGEE) $(WORKSPACE_OUTPUT_JSON) AWS_SECRET_ACCESS_KEY=$(AWS_SECRET_ACCESS_KEY) \ AWS_SESSION_TOKEN=$(AWS_SESSION_TOKEN) \ bash $(PATH_TO_INFRASTRUCTURE)/apigee/proxygen.sh generate_proxy - - touch $(PROXYGEN_TIMESTAMP) diff --git a/scripts/infrastructure/apigee/proxygen.sh b/scripts/infrastructure/apigee/proxygen.sh index 196b3868..b6f76bb7 100644 --- a/scripts/infrastructure/apigee/proxygen.sh +++ b/scripts/infrastructure/apigee/proxygen.sh @@ -166,5 +166,51 @@ function delete_proxy(){ --no-confirm } + +function publish_swagger(){ + if [[ -z ${SWAGGER_PUBLIC} ]]; then + echo "SWAGGER_PUBLIC not set" + exit 1 + fi + + + _workspace_name=$(get_workspace_name) + _aws_environment=$(get_aws_environment) + _apigee_environment=$(get_apigee_environment ${_workspace_name} ${_aws_environment}) + _apigee_stage=$(get_apigee_stage ${_workspace_name}) + + if [[ ${_aws_environment} == "prod" ]]; then + _flags="" + #elif [[ ${_aws_environment} == "int" ]]; then + else + _flags="--uat" + # else + # echo "ERROR: only environments to deploy to are 'prod' and 'int'" + # exit 1; + fi + + echo " + Publishing swagger + -------------------- ---------------------------------------- + workspace_name ${_workspace_name} + aws_environment ${_aws_environment} + apigee_environment ${_apigee_environment} + apigee_stage ${_apigee_stage} + flags ${_flags} +" + + # Download the pem file if it does not exist + if [ ! -f "${APIGEE_CONFIG_PATH}/${_apigee_stage}/.proxygen/private_key.pem" ]; then + poetry run python ${PATH_TO_HERE}/download_pem.py ${_apigee_stage} ${APIGEE_DEPLOYMENT_ROLE} + fi + + DOT_PROXYGEN=${APIGEE_CONFIG_PATH}/${_apigee_stage} \ + poetry run \ + python ${PATH_TO_HERE}/proxygen.py spec publish \ + ${SWAGGER_PUBLIC} \ + ${_flags} \ + --no-confirm +} + # Expose functions publicly $@ diff --git a/scripts/infrastructure/swagger.mk b/scripts/infrastructure/swagger.mk index 280350d4..9954bc1f 100644 --- a/scripts/infrastructure/swagger.mk +++ b/scripts/infrastructure/swagger.mk @@ -16,6 +16,8 @@ SWAGGER_AWS = $(SWAGGER_DIST)/aws/swagger.yaml SWAGGER_PUBLIC = $(SWAGGER_DIST)/public/swagger.yaml SWAGGER_APIGEE = $(SWAGGER_DIST)/apigee/swagger.yaml _CLEANED_SWAGGER_FILE = $(SWAGGER_DIST)/build/_02_clean.yaml +PROXYGEN_TIMESTAMP = $(TIMESTAMP_DIR)/.proxygen.stamp +SWAGGER_PUBLISH_TIMESTAMP = $(TIMESTAMP_DIR)/.swagger.publish.stamp TOOL_VERSIONS_COPY = $(TIMESTAMP_DIR)/tool-versions.copy SWAGGER_DEPENDENCIES = $(FHIR_BASE_TIMESTAMP) $(shell find infrastructure/swagger -type f -name "*.yaml" -not -path "*/dist/*.yaml" ) $(shell find scripts/infrastructure/swagger -type f -name "*.sh") $(TOOL_VERSIONS_COPY) @@ -29,6 +31,8 @@ swagger--clean: ## Removes swagger builds. [[ -f $(PATH_TO_SWAGGER_GENERATOR_JAR) ]] && rm $(PATH_TO_SWAGGER_GENERATOR_JAR) || : swagger--generate-fhir-base: $(FHIR_BASE_TIMESTAMP) swagger--download-generator: $(PATH_TO_SWAGGER_GENERATOR_JAR) ## Downloads the latest swagger fhir generator +swagger--publish: $(SWAGGER_PUBLISH_TIMESTAMP) ## Publish swagger docs via proxygen to API Catalogue + $(PATH_TO_SWAGGER_GENERATOR_JAR): $(INIT_TIMESTAMP) @@ -61,3 +65,17 @@ $(SWAGGER_PUBLIC): $(SWAGGER_DEPENDENCIES) $(_CLEANED_SWAGGER_FILE) $(SWAGGER_APIGEE): $(SWAGGER_DEPENDENCIES) $(_CLEANED_SWAGGER_FILE) $(WORKSPACE_OUTPUT_JSON) @env bash $(PATH_TO_INFRASTRUCTURE)/swagger/merge.sh generate_apigee_swagger npx --yes @redocly/cli lint $(SWAGGER_APIGEE) --skip-rule security-defined || ([[ -f $(FHIR_BASE_TIMESTAMP) ]] && rm $(FHIR_BASE_TIMESTAMP) || :; exit 1) + +$(SWAGGER_PUBLISH_TIMESTAMP): aws--login $(SWAGGER_PUBLIC) $(WORKSPACE_OUTPUT_JSON) + [[ -f $(SWAGGER_PUBLISH_TIMESTAMP) ]] && rm $(SWAGGER_PUBLISH_TIMESTAMP) || : + + WORKSPACE_OUTPUT_JSON=$(WORKSPACE_OUTPUT_JSON) \ + ENVIRONMENT_MAPPING_YAML=$(ENVIRONMENT_MAPPING_YAML) \ + STAGE_MAPPING_YAML=$(STAGE_MAPPING_YAML) \ + APIGEE_CONFIG_PATH=$(APIGEE_CONFIG_PATH) \ + SWAGGER_APIGEE=$(SWAGGER_APIGEE) \ + SWAGGER_PUBLIC=$(SWAGGER_PUBLIC) \ + AWS_ACCESS_KEY_ID=$(AWS_ACCESS_KEY_ID) \ + AWS_SECRET_ACCESS_KEY=$(AWS_SECRET_ACCESS_KEY) \ + AWS_SESSION_TOKEN=$(AWS_SESSION_TOKEN) \ + bash $(PATH_TO_INFRASTRUCTURE)/apigee/proxygen.sh publish_swagger From f1a3ec3c565ff6cefa10845af329bcb41df5346e Mon Sep 17 00:00:00 2001 From: megan-bower4 Date: Fri, 13 Sep 2024 13:40:53 +0100 Subject: [PATCH 03/38] [feature/PI-501-device_ref_data] create device reference data feature/PI-477-query_by_tag_ignore_chunky_fields Ability to drop specific device fields feature/PI-506-upgrade_lambdas Upgrade lambda memory size release/2024-09-19 Created release branch feature/PI-496-create_cpm_product CreateCpmProduct class feature/PI-495-generating_product_ids Generate productId release/2024-09-19 Update changelog feature/PI-519-terraform_base_build_failure Add dependency for bucket release/2024-09-19 Update changelog [release/2024-09-19] fix forward: moto table spec bug [release/2024-09-25] create release [feature/PI-479-sds_endpoint_error_message] sds endpoint error message [feature/PI-520-no_dev_sandbox_sds_smoke_test] no dev sandbox sds smoke test [feature/PI-465-extract_worker_test_bug] dont delete dataclass property [feature/PI-515-query_by_tag_default] drop tags by default [feature/PI-515-query_by_tag_default] optionally dont drop tags [release/2024-09-25] fix forward: empty query params treated as empty mapping [release/2024-09-25] fix forward: empty query params treated as empty mapping Release 2024-09-26 Change all instances of Organization in a path to ProductTeam Change Organization to ProductTeam Latest feature test changes update response in ProductTeam swagger Fix CpmProduct Failure feature tests Fix tests Add comment about id for Organization SonarCloud Set Device to use Organization fix Device unit tests [release/2024-09-30] create release [feature/PI-522-rename_lambda] rename lambdas [feature/PI-473-url_encode_tags] urlencode tags poetry: update nhs-context-logging requirement from ^0.5.1 to ^0.6.7 Updates the requirements on [nhs-context-logging](https://github.com/NHSDigital/nhs-context-logging) to permit the latest version. - [Release notes](https://github.com/NHSDigital/nhs-context-logging/releases) - [Commits](https://github.com/NHSDigital/nhs-context-logging/compare/v0.5.1...v0.6.7) --- updated-dependencies: - dependency-name: nhs-context-logging dependency-type: direct:production ... Signed-off-by: dependabot[bot] [release/2024-09-30] fix-forward: update logger version poetry: update nhs-context-logging requirement from ^0.5.1 to ^0.6.8 Updates the requirements on [nhs-context-logging](https://github.com/NHSDigital/nhs-context-logging) to permit the latest version. - [Release notes](https://github.com/NHSDigital/nhs-context-logging/releases) - [Commits](https://github.com/NHSDigital/nhs-context-logging/compare/v0.5.1...v0.6.8) --- updated-dependencies: - dependency-name: nhs-context-logging dependency-type: direct:production ... Signed-off-by: dependabot[bot] release/2024-10-02 Create release branch feature/PI-497-read_cpm_product Persist and Read CPM Product feature/PI-543-remove_snapshot Remove s3 export from ETL and turn changelog trigger off in qa release/2024-10-02 Update changelog [feature/PI-505-create_epr_product_with_refactor] create epr product [feature/PI-505-create_epr_product_with_refactor] update error message [release/2024-10-07] create release feature/PI-538-increase_rate_limiting Add rate limiting to proxy poetry: update pre-commit requirement from ^3.4.0 to ^4.0.0 Updates the requirements on [pre-commit](https://github.com/pre-commit/pre-commit) to permit the latest version. - [Release notes](https://github.com/pre-commit/pre-commit/releases) - [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md) - [Commits](https://github.com/pre-commit/pre-commit/compare/v3.4.0...v4.0.0) --- updated-dependencies: - dependency-name: pre-commit dependency-type: direct:development ... Signed-off-by: dependabot[bot] [release/2024-10-07] update release branch with more features [release/2024-10-07] fix-forward: party key written to db [release/2024-10-09] create release [feature/PI-504-delete_product] delete product [feature/PI-504-delete_product] delete product [feature/PI-504-delete_product] update tests [feature/PI-504-delete_product] type hints [feature/PI-504-delete_product] permissions [feature/PI-504-delete_product] resolve merge conflict feature/PI-497-read_cpm_product readCpmProduct lambda and repository changes feature/PI-497-read_cpm_product Update swagger feature/PI-497-read_cpm_product Add cpm product repo tests feature/PI-497-read_cpm_product Serialize cpm product feature/PI-497-read_cpm_product Api readCpmProduct tests feature/PI-497-read_cpm_product Refactor manual trigger test feature/PI-497-read_cpm_product Update syntax of product to CpmProduct feature/PI-497-read_cpm_product Update bulk trigger test feature/PI-497-read_cpm_product Merge cpm sys id changes feature/PI-497-read_cpm_product Cpm system id changes feature/PI-497-read_cpm_product More Cpm system id changes feature/PI-497-read_cpm_product More test cases feature/PI-497-read_cpm_product Update table keys for CpmProduct feature/PI-497-read_cpm_product Update swagger for readCpmProduct feature/PI-497-read_cpm_product Peer review changes - rename product_id -> id, split read_cpm_poduct function, move state() to root feature/PI-497-read_cpm_product WIP - readCpmProduct feature tests feature/PI-497-read_cpm_product Update feature tests cpmProduct feature/PI-497-read_cpm_product Update unit test path param name feature/PI-497-read_cpm_product Add pydantic model for path param validation, clean up feature test feature/PI-497-read_cpm_product Revert product_team_id removal feature/PI-497-read_cpm_product Create request models feature/PI-497-read_cpm_product Update feature test for refactored step feature/PI-497-read_cpm_product Check for product team exsistence feature/PI-497-read_cpm_product Add unit test for readCpmProduct endpoint feature/PI-497-read_cpm_product Check for product team exsistence before reading cpm product feature/PI-497-read_cpm_product Move ordering of test setup searchCpmProducts ProductKeys Update product repository Latest search CPM Product tests ready for rebase Feature tests Public swagger Add unit test Remove unwanted code change Fix rebase PR changes Ignore all index files for duplication Remove SonarCloud config Fix Sonarcloud complaints [release/2024-10-09] merge conflicts [feature/PI-534-errors_without_fhir] errors without fhir [feature/PI-534-errors_without_fhir] update error message ProductTeam Create Endpoint Product Team tests Test data for CPM Product Add in product_team_key new render response error stuff Rebase and fix tests Remove imports that are not needed Starting Feature Tests readCpmProduct Test Fix feature tests handle keys add key row Fix productTeamKey Creation Fix zero results test Fix rebase PR changes Fix feature tests searchCPm test Remove gevent [feature/PI-501-device_ref_data] create device reference data --- docs/public_swagger/swagger.yaml | 52 ++++++ infrastructure/swagger/05_paths.yaml | 43 +++++ src/api/createCpmProduct/src/v1/steps.py | 2 +- .../createCpmProductForEpr/src/v1/steps.py | 2 +- src/api/createDeviceReferenceData/index.py | 26 +++ .../createDeviceReferenceData/make/make.py | 4 + .../policies/dynamodb.json | 1 + .../policies/kms.json | 1 + .../createDeviceReferenceData/src/v1/steps.py | 51 ++++++ .../tests/test_index.py | 151 ++++++++++++++++++ src/api/deleteCpmProduct/src/v1/steps.py | 2 +- src/api/readCpmProduct/src/v1/steps.py | 2 +- .../createDeviceReferenceData.failure.feature | 86 ++++++++++ .../createDeviceReferenceData.success.feature | 56 +++++++ .../steps/endpoint_lambda_mapping.py | 7 +- src/api/tests/feature_tests/steps/steps.py | 12 +- src/api/tests/feature_tests/steps/table.py | 3 - .../{ => api}/common_steps/create_product.py | 20 +-- src/layers/domain/api/common_steps/general.py | 9 ++ .../{ => api}/common_steps/read_product.py | 0 .../common_steps/tests/test_create_product.py | 2 +- .../common_steps/tests/test_read_product.py | 2 +- .../cpm_product/tests/test_cpm_product_v1.py | 9 ++ src/layers/domain/core/cpm_product/v1.py | 16 ++ .../core/device_reference_data/__init__.py | 1 + .../domain/core/device_reference_data/v1.py | 35 ++++ .../tests/v3/conftest.py | 2 +- .../__init__.py | 1 + .../tests/conftest.py | 24 +++ ...est_device_reference_data_repository_v3.py | 71 ++++++++ .../device_reference_data_repository/v1.py | 36 +++++ .../device_repository/tests/utils.py | 5 +- src/layers/domain/repository/keys/v3.py | 1 + src/layers/domain/request_models/v1.py | 4 + src/layers/domain/response/render_response.py | 2 + 35 files changed, 712 insertions(+), 29 deletions(-) create mode 100644 src/api/createDeviceReferenceData/index.py create mode 100644 src/api/createDeviceReferenceData/make/make.py create mode 100644 src/api/createDeviceReferenceData/policies/dynamodb.json create mode 100644 src/api/createDeviceReferenceData/policies/kms.json create mode 100644 src/api/createDeviceReferenceData/src/v1/steps.py create mode 100644 src/api/createDeviceReferenceData/tests/test_index.py create mode 100644 src/api/tests/feature_tests/features/createDeviceReferenceData.failure.feature create mode 100644 src/api/tests/feature_tests/features/createDeviceReferenceData.success.feature rename src/layers/domain/{ => api}/common_steps/create_product.py (84%) create mode 100644 src/layers/domain/api/common_steps/general.py rename src/layers/domain/{ => api}/common_steps/read_product.py (100%) rename src/layers/domain/{ => api}/common_steps/tests/test_create_product.py (97%) rename src/layers/domain/{ => api}/common_steps/tests/test_read_product.py (97%) create mode 100644 src/layers/domain/core/device_reference_data/__init__.py create mode 100644 src/layers/domain/core/device_reference_data/v1.py create mode 100644 src/layers/domain/repository/device_reference_data_repository/__init__.py create mode 100644 src/layers/domain/repository/device_reference_data_repository/tests/conftest.py create mode 100644 src/layers/domain/repository/device_reference_data_repository/tests/test_device_reference_data_repository_v3.py create mode 100644 src/layers/domain/repository/device_reference_data_repository/v1.py diff --git a/docs/public_swagger/swagger.yaml b/docs/public_swagger/swagger.yaml index d17a6cd8..c2f49dfa 100644 --- a/docs/public_swagger/swagger.yaml +++ b/docs/public_swagger/swagger.yaml @@ -582,6 +582,58 @@ paths: application/fhir+json: schema: $ref: "#/components/schemas/OperationOutcome" + /ProductTeam/{product_team_id}/Product/{product_id}/DeviceReferenceData: + post: + operationId: createDeviceReferenceData + summary: createDeviceReferenceData endpoint for APIGEE integration + parameters: + - name: product_team_id + in: path + required: true + description: logical identifier + schema: + type: string + - name: product_id + in: path + required: true + description: logical identifier + schema: + type: string + - in: header + name: version + schema: + $ref: "#/components/schemas/Version" + - in: header + name: x-request-id + schema: + $ref: "#/components/schemas/RequestId" + - in: header + name: x-correlation-id + schema: + $ref: "#/components/schemas/CorrelationId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: Name of the DeviceReferenceData + responses: + "201": + description: Create operation successful + content: + application/fhir+json: + schema: + $ref: "#/components/schemas/OperationOutcome" + "4XX": + description: "Client Error" + content: + application/fhir+json: + schema: + $ref: "#/components/schemas/OperationOutcome" /searchSdsDevice: get: operationId: searchsdsdevice diff --git a/infrastructure/swagger/05_paths.yaml b/infrastructure/swagger/05_paths.yaml index 2e4c9f24..0b61e6a7 100644 --- a/infrastructure/swagger/05_paths.yaml +++ b/infrastructure/swagger/05_paths.yaml @@ -367,6 +367,49 @@ paths: - ${authoriser_name}: [] - app-level0: [] + /ProductTeam/{product_team_id}/Product/{product_id}/DeviceReferenceData: + post: + operationId: createDeviceReferenceData + summary: createDeviceReferenceData endpoint for APIGEE integration + parameters: + - name: product_team_id + in: path + required: true + description: logical identifier + schema: + type: string + - name: product_id + in: path + required: true + description: logical identifier + schema: + type: string + - *RequestHeaderVersion + - *RequestHeaderRequestId + - *RequestHeaderCorrelationId + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: Name of the DeviceReferenceData + responses: + responses: + "201": + <<: *Response201 + "4XX": + <<: *Response4XX + x-amazon-apigateway-integration: + <<: *ApiGatewayIntegration + uri: ${method_createDeviceReferenceData} + security: + - ${authoriser_name}: [] + - app-level0: [] + /Device/{id}: get: parameters: diff --git a/src/api/createCpmProduct/src/v1/steps.py b/src/api/createCpmProduct/src/v1/steps.py index 68729bac..fc86aac1 100644 --- a/src/api/createCpmProduct/src/v1/steps.py +++ b/src/api/createCpmProduct/src/v1/steps.py @@ -1,3 +1,3 @@ -from domain.common_steps.create_product import after_steps, before_steps +from domain.api.common_steps.create_product import after_steps, before_steps steps = [*before_steps, *after_steps] diff --git a/src/api/createCpmProductForEpr/src/v1/steps.py b/src/api/createCpmProductForEpr/src/v1/steps.py index f322ee82..c4d88582 100644 --- a/src/api/createCpmProductForEpr/src/v1/steps.py +++ b/src/api/createCpmProductForEpr/src/v1/steps.py @@ -1,6 +1,6 @@ from types import FunctionType -from domain.common_steps.create_product import ( +from domain.api.common_steps.create_product import ( after_steps, before_steps, create_cpm_product, diff --git a/src/api/createDeviceReferenceData/index.py b/src/api/createDeviceReferenceData/index.py new file mode 100644 index 00000000..c2a0bfcf --- /dev/null +++ b/src/api/createDeviceReferenceData/index.py @@ -0,0 +1,26 @@ +from api_utils.api_step_chain import execute_step_chain +from event.aws.client import dynamodb_client +from event.environment import BaseEnvironment +from event.logging.logger import setup_logger + +from .src.v1.steps import steps as v1_steps + + +class Environment(BaseEnvironment): + DYNAMODB_TABLE: str + + +versioned_steps = {"1": v1_steps} +cache = { + **Environment.build().dict(), + "DYNAMODB_CLIENT": dynamodb_client(), +} + + +def handler(event: dict, context=None): + setup_logger(service_name=__file__) + return execute_step_chain( + event=event, + cache=cache, + versioned_steps=versioned_steps, + ) diff --git a/src/api/createDeviceReferenceData/make/make.py b/src/api/createDeviceReferenceData/make/make.py new file mode 100644 index 00000000..f33cd706 --- /dev/null +++ b/src/api/createDeviceReferenceData/make/make.py @@ -0,0 +1,4 @@ +from builder.lambda_build import build + +if __name__ == "__main__": + build(__file__) diff --git a/src/api/createDeviceReferenceData/policies/dynamodb.json b/src/api/createDeviceReferenceData/policies/dynamodb.json new file mode 100644 index 00000000..a10a2207 --- /dev/null +++ b/src/api/createDeviceReferenceData/policies/dynamodb.json @@ -0,0 +1 @@ +["dynamodb:Query", "dynamodb:PutItem", "dynamodb:GetItem"] diff --git a/src/api/createDeviceReferenceData/policies/kms.json b/src/api/createDeviceReferenceData/policies/kms.json new file mode 100644 index 00000000..f34357e2 --- /dev/null +++ b/src/api/createDeviceReferenceData/policies/kms.json @@ -0,0 +1 @@ +["kms:Decrypt"] diff --git a/src/api/createDeviceReferenceData/src/v1/steps.py b/src/api/createDeviceReferenceData/src/v1/steps.py new file mode 100644 index 00000000..6e6f49da --- /dev/null +++ b/src/api/createDeviceReferenceData/src/v1/steps.py @@ -0,0 +1,51 @@ +from http import HTTPStatus + +from domain.api.common_steps.general import parse_event_body +from domain.api.common_steps.read_product import ( + parse_path_params, + read_product, + read_product_team, +) +from domain.core.cpm_product.v1 import CpmProduct +from domain.core.device_reference_data.v1 import DeviceReferenceData +from domain.repository.device_reference_data_repository.v1 import ( + DeviceReferenceDataRepository, +) +from domain.request_models.v1 import CreateDeviceReferenceDataParams +from domain.response.validation_errors import mark_validation_errors_as_inbound + + +@mark_validation_errors_as_inbound +def parse_device_reference_data_payload(data, cache) -> DeviceReferenceData: + payload: dict = data[parse_event_body] + return CreateDeviceReferenceDataParams(**payload) + + +def create_device_reference_data(data, cache) -> DeviceReferenceData: + product: CpmProduct = data[read_product] + payload: CreateDeviceReferenceDataParams = data[parse_device_reference_data_payload] + return product.create_device_reference_data(**payload.dict()) + + +def write_device_reference_data(data: dict[str, CpmProduct], cache) -> CpmProduct: + device_reference_data: DeviceReferenceData = data[create_device_reference_data] + repo = DeviceReferenceDataRepository( + table_name=cache["DYNAMODB_TABLE"], dynamodb_client=cache["DYNAMODB_CLIENT"] + ) + return repo.write(device_reference_data) + + +def set_http_status(data, cache) -> tuple[HTTPStatus, str]: + device_reference_data: DeviceReferenceData = data[create_device_reference_data] + return HTTPStatus.CREATED, device_reference_data.state() + + +steps = [ + parse_event_body, + parse_path_params, + parse_device_reference_data_payload, + read_product_team, + read_product, + create_device_reference_data, + set_http_status, +] diff --git a/src/api/createDeviceReferenceData/tests/test_index.py b/src/api/createDeviceReferenceData/tests/test_index.py new file mode 100644 index 00000000..ca2d1057 --- /dev/null +++ b/src/api/createDeviceReferenceData/tests/test_index.py @@ -0,0 +1,151 @@ +import json +import os +from contextlib import contextmanager +from datetime import datetime +from types import ModuleType +from typing import Any, Generator +from unittest import mock + +import pytest +from domain.core.cpm_product.v1 import CpmProduct +from domain.core.cpm_system_id.v1 import ProductId +from domain.core.device_reference_data.v1 import DeviceReferenceData +from domain.core.root.v3 import Root +from domain.repository.cpm_product_repository.v3 import CpmProductRepository +from domain.repository.device_reference_data_repository.v1 import ( + DeviceReferenceDataRepository, +) +from domain.repository.product_team_repository.v2 import ProductTeamRepository +from event.json import json_loads + +from test_helpers.dynamodb import mock_table +from test_helpers.uuid import consistent_uuid + +TABLE_NAME = "hiya" + +DEVICE_REFERENCE_DATA_NAME = "My DeviceReferenceData" +ODS_CODE = "AAA" +PRODUCT_ID = ProductId.create() +PRODUCT_NAME = "My Product" +VERSION = 1 + + +@contextmanager +def mock_product() -> Generator[tuple[ModuleType, CpmProduct], Any, None]: + org = Root.create_ods_organisation(ods_code=ODS_CODE) + product_team = org.create_product_team(name=PRODUCT_NAME) + + with mock_table(table_name=TABLE_NAME) as client, mock.patch.dict( + os.environ, + {"DYNAMODB_TABLE": TABLE_NAME, "AWS_DEFAULT_REGION": "eu-west-2"}, + clear=True, + ): + product_team_repo = ProductTeamRepository( + table_name=TABLE_NAME, dynamodb_client=client + ) + product_team_repo.write(entity=product_team) + + product = product_team.create_cpm_product( + name=PRODUCT_NAME, product_id=PRODUCT_ID + ) + product_repo = CpmProductRepository( + table_name=TABLE_NAME, dynamodb_client=client + ) + product_repo.write(entity=product) + + import api.createDeviceReferenceData.index as index + + index.cache["DYNAMODB_CLIENT"] = client + + yield index, product + + +def test_index() -> None: + with mock_product() as (index, product): + # Execute the lambda + response = index.handler( + event={ + "headers": {"version": VERSION}, + "body": json.dumps({"name": DEVICE_REFERENCE_DATA_NAME}), + "pathParameters": { + "product_team_id": str(product.product_team_id), + "product_id": str(product.id), + }, + } + ) + + # Validate that the response indicates that a resource was created + assert response["statusCode"] == 201 + + _device_reference_data = json_loads(response["body"]) + device_reference_data = DeviceReferenceData(**_device_reference_data) + assert device_reference_data.product_id == product.id + assert device_reference_data.product_team_id == product.product_team_id + assert device_reference_data.name == DEVICE_REFERENCE_DATA_NAME + assert device_reference_data.ods_code == ODS_CODE + assert device_reference_data.created_on.date() == datetime.today().date() + assert device_reference_data.updated_on is None + assert device_reference_data.deleted_on is None + + # Retrieve the created resource + repo = DeviceReferenceDataRepository( + table_name=TABLE_NAME, dynamodb_client=index.cache["DYNAMODB_CLIENT"] + ) + if hasattr(repo, "read"): + raise Exception( + "uncomment the following code now that you've implemented read" + ) + created_device_reference_data = repo.read( + product_team_id=device_reference_data.product_team_id, + product_id=device_reference_data.product_id, + device_reference_data_id=device_reference_data.id, + ) + assert created_device_reference_data == device_reference_data + + +@pytest.mark.parametrize( + ["body", "path_parameters", "error_code", "status_code"], + [ + ( + {}, + {"product_team_id": consistent_uuid(1)}, + "MISSING_VALUE", + 400, + ), + ( + {"name": DEVICE_REFERENCE_DATA_NAME}, + {}, + "MISSING_VALUE", + 400, + ), + ( + {"name": DEVICE_REFERENCE_DATA_NAME, "forbidden_extra_param": "foo"}, + {"product_id": str(PRODUCT_ID), "product_team_id": consistent_uuid(1)}, + "VALIDATION_ERROR", + 400, + ), + ( + {"name": DEVICE_REFERENCE_DATA_NAME}, + { + "product_id": str(PRODUCT_ID), + "product_team_id": "id_that_does_not_exist", + }, + "RESOURCE_NOT_FOUND", + 404, + ), + ], +) +def test_incoming_errors(body, path_parameters, error_code, status_code): + with mock_product() as (index, _): + # Execute the lambda + response = index.handler( + event={ + "headers": {"version": VERSION}, + "body": json.dumps(body), + "pathParameters": path_parameters, + } + ) + + # Validate that the response indicates that the expected error + assert response["statusCode"] == status_code + assert error_code in response["body"] diff --git a/src/api/deleteCpmProduct/src/v1/steps.py b/src/api/deleteCpmProduct/src/v1/steps.py index 7234c7ed..3a5cf2a1 100644 --- a/src/api/deleteCpmProduct/src/v1/steps.py +++ b/src/api/deleteCpmProduct/src/v1/steps.py @@ -1,6 +1,6 @@ from http import HTTPStatus -from domain.common_steps.read_product import before_steps, read_product +from domain.api.common_steps.read_product import before_steps, read_product from domain.core.cpm_product import CpmProduct from domain.repository.cpm_product_repository.v3 import CpmProductRepository diff --git a/src/api/readCpmProduct/src/v1/steps.py b/src/api/readCpmProduct/src/v1/steps.py index 3526136f..a828a8b1 100644 --- a/src/api/readCpmProduct/src/v1/steps.py +++ b/src/api/readCpmProduct/src/v1/steps.py @@ -1,3 +1,3 @@ -from domain.common_steps.read_product import after_steps, before_steps +from domain.api.common_steps.read_product import after_steps, before_steps steps = [*before_steps, *after_steps] diff --git a/src/api/tests/feature_tests/features/createDeviceReferenceData.failure.feature b/src/api/tests/feature_tests/features/createDeviceReferenceData.failure.feature new file mode 100644 index 00000000..ee08ec8a --- /dev/null +++ b/src/api/tests/feature_tests/features/createDeviceReferenceData.failure.feature @@ -0,0 +1,86 @@ +Feature: Create Device Reference Data - failure scenarios + These scenarios demonstrate failures to create a new Device Reference Data + + Background: + Given "default" request headers: + | name | value | + | version | 1 | + | Authorization | letmein | + + Scenario: Cannot create a Device Reference Data with a Device Reference Data that is missing fields (no name) and has extra param + Given I have already made a "POST" request with "default" headers to "ProductTeam" with body: + | path | value | + | name | My Great Product Team | + | ods_code | F5H1R | + And I note the response field "$.id" as "product_team_id" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: + | path | value | + | product_name | My Great Product | + And I note the response field "$.id" as "product_id" + When I make a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/DeviceReferenceData" with body: + | path | value | + | bad_field | My Device Reference Data | + Then I receive a status code "400" with body + | path | value | + | errors.0.code | MISSING_VALUE | + | errors.0.message | CreateDeviceReferenceDataParams.name: field required | + | errors.1.code | VALIDATION_ERROR | + | errors.1.message | CreateDeviceReferenceDataParams.bad_field: extra fields not permitted | + And the response headers contain: + | name | value | + | Content-Type | application/json | + | Content-Length | 220 | + + Scenario: Cannot create a Device Reference Data with a Device Reference Data with a corrupt body + Given I have already made a "POST" request with "default" headers to "ProductTeam" with body: + | path | value | + | name | My Great Product Team | + | ods_code | F5H1R | + And I note the response field "$.id" as "product_team_id" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: + | path | value | + | product_name | My Great Product | + And I note the response field "$.id" as "product_id" + When I make a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/DeviceReferenceData" with body: + """ + {"invalid_array": [} + """ + Then I receive a status code "400" with body + | path | value | + | errors.0.code | VALIDATION_ERROR | + | errors.0.message | Invalid JSON body was provided: line 1 column 20 (char 19) | + And the response headers contain: + | name | value | + | Content-Type | application/json | + | Content-Length | 115 | + + Scenario: Cannot create a Device Reference Data with a Product Team that does not exist + When I make a "POST" request with "default" headers to "ProductTeam/not-a-product-team/Product/not-a-product/DeviceReferenceData" with body: + | path | value | + | name | My Device Reference Data | + Then I receive a status code "404" with body + | path | value | + | errors.0.code | RESOURCE_NOT_FOUND | + | errors.0.message | Could not find ProductTeam for key ('not-a-product-team') | + And the response headers contain: + | name | value | + | Content-Type | application/json | + | Content-Length | 116 | + + Scenario: Cannot create a Device Reference Data with a Product that does not exist + Given I have already made a "POST" request with "default" headers to "ProductTeam" with body: + | path | value | + | name | My Great Product Team | + | ods_code | F5H1R | + And I note the response field "$.id" as "product_team_id" + When I make a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/not-a-product/DeviceReferenceData" with body: + | path | value | + | name | My Device Reference Data | + Then I receive a status code "404" with body + | path | value | + | errors.0.code | RESOURCE_NOT_FOUND | + | errors.0.message | Could not find CpmProduct for key ('${ note(product_team_id) }', 'not-a-product') | + And the response headers contain: + | name | value | + | Content-Type | application/json | + | Content-Length | 156 | diff --git a/src/api/tests/feature_tests/features/createDeviceReferenceData.success.feature b/src/api/tests/feature_tests/features/createDeviceReferenceData.success.feature new file mode 100644 index 00000000..b6c85a9a --- /dev/null +++ b/src/api/tests/feature_tests/features/createDeviceReferenceData.success.feature @@ -0,0 +1,56 @@ +Feature: Create Device Reference Data - success scenarios + These scenarios demonstrate successful Device Reference Data creation + + Background: + Given "default" request headers: + | name | value | + | version | 1 | + | Authorization | letmein | + + Scenario: Successfully create a Device Reference Data + Given I have already made a "POST" request with "default" headers to "ProductTeam" with body: + | path | value | + | name | My Great Product Team | + | ods_code | F5H1R | + And I note the response field "$.id" as "product_team_id" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: + | path | value | + | product_name | My Great Product | + # ####### TODO: CAN REMOVE THE FOLLOWING LINE AFTER PI-536 completed + When I make a "GET" request with "default" headers to the id in the location response header to the endpoint prefix "ProductTeam/${ note(product_team_id) }/Product/" + And I note the response field "$.id" as "product_id" + When I make a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/DeviceReferenceData" with body: + | path | value | + | name | My Device Reference Data | + Then I receive a status code "201" with body + | path | value | + | id | << ignore >> | + | name | My Device Reference Data | + | product_id | ${ note(product_id) } | + | product_team_id | ${ note(product_team_id) } | + | ods_code | F5H1R | + | created_on | << ignore >> | + | updated_on | << ignore >> | + | deleted_on | << ignore >> | + And the response headers contain: + | name | value | + | Content-Type | application/json | + | Content-Length | 285 | + And I note the response field "$.id" as "device_reference_data_id" + +# ### TODO: UNCOMMENT THIS FOR PI-503 +# When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/${ note(device_reference_data_id) }" +# Then I receive a status code "200" with body +# | path | value | +# | id | ${ note(device_reference_data_id) } | +# | name | My Device Reference Data | +# | product_id | ${ note(product_id) } | +# | product_team_id | ${ note(product_team_id) } | +# | ods_code | F5H1R | +# | created_on | << ignore >> | +# | updated_on | << ignore >> | +# | deleted_on | << ignore >> | +# And the response headers contain: +# | name | value | +# | Content-Type | application/json | +# | Content-Length | 285 | diff --git a/src/api/tests/feature_tests/steps/endpoint_lambda_mapping.py b/src/api/tests/feature_tests/steps/endpoint_lambda_mapping.py index 70bbff34..ba2e2892 100644 --- a/src/api/tests/feature_tests/steps/endpoint_lambda_mapping.py +++ b/src/api/tests/feature_tests/steps/endpoint_lambda_mapping.py @@ -1,7 +1,7 @@ import re -from ast import FunctionType +from types import ModuleType -ENDPOINT_LAMBDA_MAPPING = dict[str, dict[str, FunctionType]] +ENDPOINT_LAMBDA_MAPPING = dict[str, dict[str, ModuleType]] class EndpointConfigurationError(Exception): @@ -24,6 +24,7 @@ def get_endpoint_lambda_mapping() -> ENDPOINT_LAMBDA_MAPPING: import api.createCpmProduct.index import api.createCpmProductForEpr.index import api.createDevice.index + import api.createDeviceReferenceData.index import api.createProductTeam.index import api.deleteCpmProduct.index import api.readCpmProduct.index @@ -38,6 +39,7 @@ def get_endpoint_lambda_mapping() -> ENDPOINT_LAMBDA_MAPPING: "ProductTeam": api.createProductTeam.index, "ProductTeam/{product_team_id}/Product": api.createCpmProduct.index, "ProductTeam/{product_team_id}/Product/Epr": api.createCpmProductForEpr.index, + "ProductTeam/{product_team_id}/Product/{product_id}/DeviceReferenceData": api.createDeviceReferenceData.index, "Device": api.createDevice.index, }, "GET": { @@ -48,7 +50,6 @@ def get_endpoint_lambda_mapping() -> ENDPOINT_LAMBDA_MAPPING: "Device?device_type={device_type}": api.searchDevice.index, "Device?device_type={device_type}&foo={foo}": api.searchDevice.index, "Device?foo={foo}": api.searchDevice.index, - # "Organization/{id}": api.readProductTeam.index, "_status": api.status.index, }, "DELETE": { diff --git a/src/api/tests/feature_tests/steps/steps.py b/src/api/tests/feature_tests/steps/steps.py index a339fc2b..d2e963e4 100644 --- a/src/api/tests/feature_tests/steps/steps.py +++ b/src/api/tests/feature_tests/steps/steps.py @@ -279,8 +279,10 @@ def then_response(context: Context): ) -@given('I note the response field "{jsonpath}" as "{alias}"') -def note_response_field(context: Context, jsonpath: str, alias: str): - context.notes[alias] = extract_from_response_by_jsonpath( - response=context.response.json(), jsonpath=jsonpath - ) +for decorator in (given, when, then): + + @decorator('I note the response field "{jsonpath}" as "{alias}"') + def note_response_field(context: Context, jsonpath: str, alias: str): + context.notes[alias] = extract_from_response_by_jsonpath( + response=context.response.json(), jsonpath=jsonpath + ) diff --git a/src/api/tests/feature_tests/steps/table.py b/src/api/tests/feature_tests/steps/table.py index e4d24e48..fbe6de06 100644 --- a/src/api/tests/feature_tests/steps/table.py +++ b/src/api/tests/feature_tests/steps/table.py @@ -11,9 +11,6 @@ EMPTY_TYPES_AS_STRING = { "[]": list, } -EMPTY_TYPES_AS_STRING = { - "[]": list, -} EXPAND_FUNCTIONS = { diff --git a/src/layers/domain/common_steps/create_product.py b/src/layers/domain/api/common_steps/create_product.py similarity index 84% rename from src/layers/domain/common_steps/create_product.py rename to src/layers/domain/api/common_steps/create_product.py index 1576e9f9..7bbeaa51 100644 --- a/src/layers/domain/common_steps/create_product.py +++ b/src/layers/domain/api/common_steps/create_product.py @@ -1,6 +1,7 @@ from http import HTTPStatus from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEvent +from domain.api.common_steps.general import parse_event_body from domain.core.cpm_product import CpmProduct from domain.core.product_team.v3 import ProductTeam from domain.repository.cpm_product_repository.v3 import CpmProductRepository @@ -9,10 +10,7 @@ CreateCpmProductIncomingParams, ProductTeamPathParams, ) -from domain.response.validation_errors import ( - mark_json_decode_errors_as_inbound, - mark_validation_errors_as_inbound, -) +from domain.response.validation_errors import mark_validation_errors_as_inbound from event.step_chain import StepChain @@ -22,12 +20,6 @@ def parse_path_params(data, cache) -> ProductTeamPathParams: return ProductTeamPathParams(**event.path_parameters) -@mark_json_decode_errors_as_inbound -def parse_event_body(data, cache) -> dict: - event = APIGatewayProxyEvent(data[StepChain.INIT]) - return event.json_body if event.body else {} - - @mark_validation_errors_as_inbound def parse_incoming_cpm_product(data, cache) -> CreateCpmProductIncomingParams: json_body = data[parse_event_body] @@ -60,6 +52,14 @@ def write_cpm_product(data: dict[str, CpmProduct], cache) -> CpmProduct: return product_repo.write(product) +def write_cpm_product(data: dict[str, CpmProduct], cache) -> CpmProduct: + product: CpmProduct = data[create_cpm_product] + product_repo = CpmProductRepository( + table_name=cache["DYNAMODB_TABLE"], dynamodb_client=cache["DYNAMODB_CLIENT"] + ) + return product_repo.write(product) + + def set_http_status(data, cache) -> tuple[HTTPStatus, str]: product: CpmProduct = data[create_cpm_product] return HTTPStatus.CREATED, str(product.id) diff --git a/src/layers/domain/api/common_steps/general.py b/src/layers/domain/api/common_steps/general.py new file mode 100644 index 00000000..611914f4 --- /dev/null +++ b/src/layers/domain/api/common_steps/general.py @@ -0,0 +1,9 @@ +from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEvent +from domain.response.validation_errors import mark_json_decode_errors_as_inbound +from event.step_chain import StepChain + + +@mark_json_decode_errors_as_inbound +def parse_event_body(data, cache) -> dict: + event = APIGatewayProxyEvent(data[StepChain.INIT]) + return event.json_body if event.body else {} diff --git a/src/layers/domain/common_steps/read_product.py b/src/layers/domain/api/common_steps/read_product.py similarity index 100% rename from src/layers/domain/common_steps/read_product.py rename to src/layers/domain/api/common_steps/read_product.py diff --git a/src/layers/domain/common_steps/tests/test_create_product.py b/src/layers/domain/api/common_steps/tests/test_create_product.py similarity index 97% rename from src/layers/domain/common_steps/tests/test_create_product.py rename to src/layers/domain/api/common_steps/tests/test_create_product.py index ac0dcf75..b15979f1 100644 --- a/src/layers/domain/common_steps/tests/test_create_product.py +++ b/src/layers/domain/api/common_steps/tests/test_create_product.py @@ -1,7 +1,7 @@ import json import pytest -from domain.common_steps.create_product import before_steps +from domain.api.common_steps.create_product import before_steps from domain.core.cpm_product.v1 import CpmProduct from domain.core.root.v3 import Root from domain.repository.errors import ItemNotFound diff --git a/src/layers/domain/common_steps/tests/test_read_product.py b/src/layers/domain/api/common_steps/tests/test_read_product.py similarity index 97% rename from src/layers/domain/common_steps/tests/test_read_product.py rename to src/layers/domain/api/common_steps/tests/test_read_product.py index a2dbf75b..e9039c99 100644 --- a/src/layers/domain/common_steps/tests/test_read_product.py +++ b/src/layers/domain/api/common_steps/tests/test_read_product.py @@ -1,5 +1,5 @@ import pytest -from domain.common_steps.read_product import before_steps +from domain.api.common_steps.read_product import before_steps from domain.core.cpm_product.v1 import CpmProduct from domain.core.root.v3 import Root from domain.repository.cpm_product_repository.v3 import CpmProductRepository diff --git a/src/layers/domain/core/cpm_product/tests/test_cpm_product_v1.py b/src/layers/domain/core/cpm_product/tests/test_cpm_product_v1.py index 950ee402..df45a145 100644 --- a/src/layers/domain/core/cpm_product/tests/test_cpm_product_v1.py +++ b/src/layers/domain/core/cpm_product/tests/test_cpm_product_v1.py @@ -41,3 +41,12 @@ def test_invalid_product_id(invalid_product_id): ods_code="ABC123", product_team_id="ABC123.18934119-5780-4d28-b9be-0e6dff3908ba", ) + + +def test_cpm_product_create_device_reference_data(cpm_product: CpmProduct): + device_reference_data = cpm_product.create_device_reference_data(name="foo") + assert isinstance(device_reference_data.id, UUID) + assert device_reference_data.name == "foo" + assert device_reference_data.product_id == cpm_product.id + assert device_reference_data.product_team_id == cpm_product.product_team_id + assert device_reference_data.ods_code == cpm_product.ods_code diff --git a/src/layers/domain/core/cpm_product/v1.py b/src/layers/domain/core/cpm_product/v1.py index e6e4941a..d060a125 100644 --- a/src/layers/domain/core/cpm_product/v1.py +++ b/src/layers/domain/core/cpm_product/v1.py @@ -5,6 +5,10 @@ from domain.core.aggregate_root import AggregateRoot from domain.core.cpm_system_id.v1 import ProductId from domain.core.device.v2 import UPDATED_ON, event +from domain.core.device_reference_data.v1 import ( + DeviceReferenceData, + DeviceReferenceDataCreatedEvent, +) from domain.core.enum import Status from domain.core.error import DuplicateError from domain.core.event import Event @@ -68,6 +72,18 @@ class CpmProduct(AggregateRoot): deleted_on: datetime = Field(default=None) keys: list[ProductKey] = Field(default_factory=list) + def create_device_reference_data(self, name: str) -> DeviceReferenceData: + device_reference_data = DeviceReferenceData( + name=name, + product_id=self.id, + product_team_id=self.product_team_id, + ods_code=self.ods_code, + ) + event = DeviceReferenceDataCreatedEvent(**device_reference_data.dict()) + self.add_event(event) + device_reference_data.add_event(event) + return device_reference_data + @event def add_key(self, key_type: str, key_value: str) -> CpmProductKeyAddedEvent: product_key = ProductKey(key_value=key_value, key_type=key_type) diff --git a/src/layers/domain/core/device_reference_data/__init__.py b/src/layers/domain/core/device_reference_data/__init__.py new file mode 100644 index 00000000..e0d08e67 --- /dev/null +++ b/src/layers/domain/core/device_reference_data/__init__.py @@ -0,0 +1 @@ +from .v1 import * # noqa diff --git a/src/layers/domain/core/device_reference_data/v1.py b/src/layers/domain/core/device_reference_data/v1.py new file mode 100644 index 00000000..1be78580 --- /dev/null +++ b/src/layers/domain/core/device_reference_data/v1.py @@ -0,0 +1,35 @@ +from datetime import datetime +from uuid import UUID, uuid4 + +from attr import dataclass +from domain.core.aggregate_root import AggregateRoot +from domain.core.cpm_system_id.v1 import ProductId +from domain.core.event import Event +from domain.core.timestamp import now +from domain.core.validation import DEVICE_NAME_REGEX +from pydantic import Field + + +@dataclass(kw_only=True, slots=True) +class DeviceReferenceDataCreatedEvent(Event): + id: str + name: str + product_id: ProductId + product_team_id: UUID + ods_code: str + created_on: str + updated_on: str = None + deleted_on: str = None + + +class DeviceReferenceData(AggregateRoot): + """An object to hold boilerplate Device QuestionnaireResponses""" + + id: UUID = Field(default_factory=uuid4, immutable=True) + name: str = Field(regex=DEVICE_NAME_REGEX) + product_id: ProductId = Field(immutable=True) + product_team_id: str = Field(immutable=True) + ods_code: str = Field(immutable=True) + created_on: datetime = Field(default_factory=now, immutable=True) + updated_on: datetime = Field(default=None) + deleted_on: datetime = Field(default=None) diff --git a/src/layers/domain/repository/cpm_product_repository/tests/v3/conftest.py b/src/layers/domain/repository/cpm_product_repository/tests/v3/conftest.py index 841e28a8..7e51dc2c 100644 --- a/src/layers/domain/repository/cpm_product_repository/tests/v3/conftest.py +++ b/src/layers/domain/repository/cpm_product_repository/tests/v3/conftest.py @@ -1,4 +1,4 @@ -from typing import Generator +from collections.abc import Generator import pytest from domain.core.root.v3 import Root diff --git a/src/layers/domain/repository/device_reference_data_repository/__init__.py b/src/layers/domain/repository/device_reference_data_repository/__init__.py new file mode 100644 index 00000000..e0d08e67 --- /dev/null +++ b/src/layers/domain/repository/device_reference_data_repository/__init__.py @@ -0,0 +1 @@ +from .v1 import * # noqa diff --git a/src/layers/domain/repository/device_reference_data_repository/tests/conftest.py b/src/layers/domain/repository/device_reference_data_repository/tests/conftest.py new file mode 100644 index 00000000..33d0d312 --- /dev/null +++ b/src/layers/domain/repository/device_reference_data_repository/tests/conftest.py @@ -0,0 +1,24 @@ +from collections.abc import Generator + +import pytest +from domain.core.root.v3 import Root +from domain.repository.device_reference_data_repository.v1 import ( + DeviceReferenceDataRepository, +) +from domain.repository.device_repository.tests.utils import repository_fixture + + +@pytest.fixture +def repository(request) -> Generator[DeviceReferenceDataRepository, None, None]: + yield from repository_fixture( + is_integration_test=request.node.get_closest_marker("integration"), + repository_class=DeviceReferenceDataRepository, + ) + + +@pytest.fixture +def device_reference_data(): + org = Root.create_ods_organisation(ods_code="ABC") + product_team = org.create_product_team(name="product-team-name") + product = product_team.create_cpm_product(name="product") + return product.create_device_reference_data(name="device-reference-data") diff --git a/src/layers/domain/repository/device_reference_data_repository/tests/test_device_reference_data_repository_v3.py b/src/layers/domain/repository/device_reference_data_repository/tests/test_device_reference_data_repository_v3.py new file mode 100644 index 00000000..cf0a3335 --- /dev/null +++ b/src/layers/domain/repository/device_reference_data_repository/tests/test_device_reference_data_repository_v3.py @@ -0,0 +1,71 @@ +import pytest +from domain.core.cpm_product.v1 import CpmProduct +from domain.repository.device_reference_data_repository.v1 import ( + DeviceReferenceDataRepository, +) +from domain.repository.errors import AlreadyExistsError + + +@pytest.mark.integration +def test__cpm_device_reference_data_repository( + device_reference_data: CpmProduct, repository: DeviceReferenceDataRepository +): + repository.write(device_reference_data) + + # TODO: UNCOMMENT FOR PI-503 + # result = repository.read( + # product_team_id=device_reference_data.product_team_id, + # product_id=device_reference_data.id, + # ) + # assert result == device_reference_data + + +@pytest.mark.integration +def test__cpm_device_reference_data_repository_already_exists( + device_reference_data: CpmProduct, repository: DeviceReferenceDataRepository +): + repository.write(device_reference_data) + with pytest.raises(AlreadyExistsError): + repository.write(device_reference_data) + + +# TODO: UNCOMMENT FOR PI-503 +# @pytest.mark.integration +# def test__cpm_device_reference_data_repository__device_reference_data_does_not_exist( +# repository: DeviceReferenceDataRepository, +# ): +# product_team_id = consistent_uuid(1) +# product_id = "P.XXX-YYY" +# device_reference_data_id = consistent_uuid(2) +# with pytest.raises(ItemNotFound): +# repository.read( +# product_team_id=product_team_id, +# product_id=product_id, +# device_reference_data_id=device_reference_data_id, +# ) + + +def test__cpm_product_repository_local( + device_reference_data: CpmProduct, repository: DeviceReferenceDataRepository +): + repository.write(device_reference_data) + # TODO: UNCOMMENT FOR PI-503 + # result = repository.read( + # product_team_id=device_reference_data.product_team_id, product_id=product.id + # ) + # assert result == device_reference_data + + +# TODO: UNCOMMENT FOR PI-503 +# def test__cpm_device_reference_data_repository__device_reference_data_does_not_exist_local( +# repository: DeviceReferenceDataRepository, +# ): +# product_team_id = consistent_uuid(1) +# product_id = "P.XXX-YYY" +# device_reference_data_id = consistent_uuid(2) +# with pytest.raises(ItemNotFound): +# repository.read( +# product_team_id=product_team_id, +# product_id=product_id, +# device_reference_data_id=device_reference_data_id, +# ) diff --git a/src/layers/domain/repository/device_reference_data_repository/v1.py b/src/layers/domain/repository/device_reference_data_repository/v1.py new file mode 100644 index 00000000..a75a5493 --- /dev/null +++ b/src/layers/domain/repository/device_reference_data_repository/v1.py @@ -0,0 +1,36 @@ +from attr import asdict +from domain.core.device_reference_data.v1 import ( + DeviceReferenceData, + DeviceReferenceDataCreatedEvent, +) +from domain.repository.device_repository.v2 import create_device_index +from domain.repository.keys.v3 import TableKey +from domain.repository.repository.v2 import Repository +from domain.repository.transaction import TransactItem + + +def create_device_reference_data(table_name: str, id: str, data: dict, root: bool): + return create_device_index( + table_name=table_name, + pk_key_parts=(id,), + pk_table_key=TableKey.DEVICE_REFERENCE_DATA, + sk_table_key=TableKey.DEVICE_REFERENCE_DATA, + device_data=data, + root=root, + ) + + +class DeviceReferenceDataRepository(Repository[DeviceReferenceData]): + def __init__(self, table_name, dynamodb_client): + super().__init__( + table_name=table_name, + model=DeviceReferenceData, + dynamodb_client=dynamodb_client, + ) + + def handle_DeviceReferenceDataCreatedEvent( + self, event: DeviceReferenceDataCreatedEvent + ) -> TransactItem: + return create_device_reference_data( + table_name=self.table_name, id=event.id, data=asdict(event), root=True + ) diff --git a/src/layers/domain/repository/device_repository/tests/utils.py b/src/layers/domain/repository/device_repository/tests/utils.py index 446feaf6..da36fd87 100644 --- a/src/layers/domain/repository/device_repository/tests/utils.py +++ b/src/layers/domain/repository/device_repository/tests/utils.py @@ -1,6 +1,9 @@ from typing import Generator from domain.core.device import Device +from domain.repository.device_reference_data_repository.v1 import ( + DeviceReferenceDataRepository, +) from domain.repository.device_repository import DeviceRepository from event.aws.client import dynamodb_client @@ -11,7 +14,7 @@ def repository_fixture[ - T: DeviceRepository + T: DeviceRepository | DeviceReferenceDataRepository ](is_integration_test: bool, repository_class: type[T]) -> Generator[T, None, None]: if is_integration_test: table_name = read_terraform_output("dynamodb_table_name.value") diff --git a/src/layers/domain/repository/keys/v3.py b/src/layers/domain/repository/keys/v3.py index 3cdee561..002fcb9c 100644 --- a/src/layers/domain/repository/keys/v3.py +++ b/src/layers/domain/repository/keys/v3.py @@ -10,3 +10,4 @@ class TableKey(TableKeyAction, StrEnum): CPM_PRODUCT = "P" CPM_PRODUCT_KEY = "PK" CPM_PRODUCT_STATUS = "PS" + DEVICE_REFERENCE_DATA = "DRD" diff --git a/src/layers/domain/request_models/v1.py b/src/layers/domain/request_models/v1.py index 74201ae4..2ce6d887 100644 --- a/src/layers/domain/request_models/v1.py +++ b/src/layers/domain/request_models/v1.py @@ -26,3 +26,7 @@ def __init__(self, **data): self.keys = list( {frozenset(key.dict().items()): key for key in self.keys}.values() ) + + +class CreateDeviceReferenceDataParams(BaseModel, extra=Extra.forbid): + name: str = Field(...) diff --git a/src/layers/domain/response/render_response.py b/src/layers/domain/response/render_response.py index 410f765d..7ed52381 100644 --- a/src/layers/domain/response/render_response.py +++ b/src/layers/domain/response/render_response.py @@ -46,6 +46,8 @@ def render_response[ # Implicit failure from all other Exceptions outcome = ErrorResponse.from_exception(exception=response).dict() http_status = http_status_from_exception(exception=response) + elif isinstance(response, tuple): + http_status, outcome = response else: if isinstance(response, tuple): http_status, outcome = response From 9284f54d8ee89123f8334a762b2ce9cd7a113232 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Tue, 15 Oct 2024 14:18:00 +0100 Subject: [PATCH 04/38] [feature/PI-501-device_ref_data] update render response --- src/layers/domain/response/render_response.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/layers/domain/response/render_response.py b/src/layers/domain/response/render_response.py index 7ed52381..49bf7829 100644 --- a/src/layers/domain/response/render_response.py +++ b/src/layers/domain/response/render_response.py @@ -49,12 +49,9 @@ def render_response[ elif isinstance(response, tuple): http_status, outcome = response else: - if isinstance(response, tuple): - http_status, outcome = response - else: - # Implicit success (e.g. SEARCH, READ operations) - http_status = HTTPStatus.OK - outcome = response + # Implicit success (e.g. SEARCH, READ operations) + http_status = HTTPStatus.OK + outcome = response body = json.dumps(outcome) if outcome is not None else "" return AwsLambdaResponse( From 4d8bbadbd85e5da3bf455d6ad91f8b55f161d182 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Tue, 15 Oct 2024 14:47:50 +0100 Subject: [PATCH 05/38] [feature/PI-501-device_ref_data] rebase conflict --- src/layers/domain/core/cpm_product/tests/test_cpm_product_v1.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/layers/domain/core/cpm_product/tests/test_cpm_product_v1.py b/src/layers/domain/core/cpm_product/tests/test_cpm_product_v1.py index df45a145..a139d162 100644 --- a/src/layers/domain/core/cpm_product/tests/test_cpm_product_v1.py +++ b/src/layers/domain/core/cpm_product/tests/test_cpm_product_v1.py @@ -1,4 +1,5 @@ from datetime import datetime +from uuid import UUID import pytest from domain.core.cpm_product import CpmProduct From 81f0e0e9142adeec0623e8881536960ff1a38254 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Tue, 15 Oct 2024 15:46:38 +0100 Subject: [PATCH 06/38] [feature/PI-501-device_ref_data] rename file --- src/api/createDeviceReferenceData/src/v1/steps.py | 1 + ...ository_v3.py => test_device_reference_data_repository_v1.py} | 0 2 files changed, 1 insertion(+) rename src/layers/domain/repository/device_reference_data_repository/tests/{test_device_reference_data_repository_v3.py => test_device_reference_data_repository_v1.py} (100%) diff --git a/src/api/createDeviceReferenceData/src/v1/steps.py b/src/api/createDeviceReferenceData/src/v1/steps.py index 6e6f49da..cbde916a 100644 --- a/src/api/createDeviceReferenceData/src/v1/steps.py +++ b/src/api/createDeviceReferenceData/src/v1/steps.py @@ -47,5 +47,6 @@ def set_http_status(data, cache) -> tuple[HTTPStatus, str]: read_product_team, read_product, create_device_reference_data, + write_device_reference_data, set_http_status, ] diff --git a/src/layers/domain/repository/device_reference_data_repository/tests/test_device_reference_data_repository_v3.py b/src/layers/domain/repository/device_reference_data_repository/tests/test_device_reference_data_repository_v1.py similarity index 100% rename from src/layers/domain/repository/device_reference_data_repository/tests/test_device_reference_data_repository_v3.py rename to src/layers/domain/repository/device_reference_data_repository/tests/test_device_reference_data_repository_v1.py From abaf72952261d63dc8c89b725f5508fb7a1df5e5 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Tue, 15 Oct 2024 14:44:43 +0100 Subject: [PATCH 07/38] [feature/PI-536-create_product_without_fhir] create product without fhir --- src/api/createCpmProduct/index.py | 4 +- src/api/createCpmProduct/tests/test_index.py | 35 ++++------ src/api/createCpmProductForEpr/index.py | 6 +- .../tests/test_index.py | 45 +++---------- .../features/createCpmProduct.success.feature | 27 ++++---- .../createCpmProductForEpr.success.feature | 66 +++++++++---------- .../createDeviceReferenceData.success.feature | 2 - .../features/deleteCpmProduct.failure.feature | 3 +- .../features/deleteCpmProduct.success.feature | 3 +- .../features/readCpmProduct.failure.feature | 3 +- .../features/readCpmProduct.success.feature | 6 +- src/api/tests/feature_tests/steps/steps.py | 26 -------- .../domain/api/common_steps/create_product.py | 12 +++- 13 files changed, 89 insertions(+), 149 deletions(-) diff --git a/src/api/createCpmProduct/index.py b/src/api/createCpmProduct/index.py index 596a900b..c2a0bfcf 100644 --- a/src/api/createCpmProduct/index.py +++ b/src/api/createCpmProduct/index.py @@ -1,4 +1,4 @@ -from api_utils.api_step_chain import execute_step_chain_with_location +from api_utils.api_step_chain import execute_step_chain from event.aws.client import dynamodb_client from event.environment import BaseEnvironment from event.logging.logger import setup_logger @@ -19,7 +19,7 @@ class Environment(BaseEnvironment): def handler(event: dict, context=None): setup_logger(service_name=__file__) - return execute_step_chain_with_location( + return execute_step_chain( event=event, cache=cache, versioned_steps=versioned_steps, diff --git a/src/api/createCpmProduct/tests/test_index.py b/src/api/createCpmProduct/tests/test_index.py index 28faf376..e7ac3137 100644 --- a/src/api/createCpmProduct/tests/test_index.py +++ b/src/api/createCpmProduct/tests/test_index.py @@ -5,7 +5,7 @@ import pytest from domain.core.root.v3 import Root from domain.repository.product_team_repository.v2 import ProductTeamRepository -from nhs_context_logging import app_logger +from event.json import json_loads from test_helpers.dynamodb import mock_table from test_helpers.response_assertions import _response_assertions @@ -57,31 +57,18 @@ def _mock_test(version, params): def test_index(version): result = _mock_test(version=version, params=json.dumps(product_payload)) + product = json_loads(result["body"]) expected_body = json.dumps( { - "resourceType": "OperationOutcome", - "id": app_logger.service_name, - "meta": { - "profile": [ - "https://fhir.nhs.uk/StructureDefinition/NHSDigital-OperationOutcome" - ] - }, - "issue": [ - { - "severity": "information", - "code": "informational", - "details": { - "coding": [ - { - "system": "https://fhir.nhs.uk/StructureDefinition/NHSDigital-OperationOutcome", - "code": "RESOURCE_CREATED", - "display": "Resource created", - } - ] - }, - "diagnostics": "Resource created", - } - ], + "id": product["id"], + "product_team_id": product["product_team_id"], + "name": "Foobar product", + "ods_code": "F5H1R", + "status": "active", + "created_on": product["created_on"], + "updated_on": None, + "deleted_on": None, + "keys": [], } ) expected = { diff --git a/src/api/createCpmProductForEpr/index.py b/src/api/createCpmProductForEpr/index.py index 19f8514e..c4f92e78 100644 --- a/src/api/createCpmProductForEpr/index.py +++ b/src/api/createCpmProductForEpr/index.py @@ -1,4 +1,4 @@ -from api_utils.api_step_chain import execute_step_chain_with_location +from api_utils.api_step_chain import execute_step_chain from event.aws.client import dynamodb_client from event.environment import BaseEnvironment from event.logging.logger import setup_logger @@ -19,6 +19,4 @@ class Environment(BaseEnvironment): def handler(event: dict, context=None): setup_logger(service_name=__file__) - return execute_step_chain_with_location( - event=event, cache=cache, versioned_steps=versioned_steps - ) + return execute_step_chain(event=event, cache=cache, versioned_steps=versioned_steps) diff --git a/src/api/createCpmProductForEpr/tests/test_index.py b/src/api/createCpmProductForEpr/tests/test_index.py index ca9cd9bc..0ed41ac6 100644 --- a/src/api/createCpmProductForEpr/tests/test_index.py +++ b/src/api/createCpmProductForEpr/tests/test_index.py @@ -1,7 +1,6 @@ import json import os from contextlib import contextmanager -from datetime import datetime from unittest import mock import pytest @@ -11,7 +10,6 @@ from domain.repository.cpm_product_repository.v3 import CpmProductRepository from domain.repository.product_team_repository.v2 import ProductTeamRepository from event.json import json_loads -from nhs_context_logging import app_logger from test_helpers.dynamodb import mock_table from test_helpers.sample_data import CPM_PRODUCT_TEAM_NO_ID @@ -23,30 +21,6 @@ PRODUCT_NAME = "My Product" PRODUCT_TEAM_KEYS = CPM_PRODUCT_TEAM_NO_ID["keys"] VERSION = 1 -RESOURCE_CREATED = { - "resourceType": "OperationOutcome", - "meta": { - "profile": [ - "https://fhir.nhs.uk/StructureDefinition/NHSDigital-OperationOutcome" - ] - }, - "issue": [ - { - "severity": "information", - "code": "informational", - "details": { - "coding": [ - { - "system": "https://fhir.nhs.uk/StructureDefinition/NHSDigital-OperationOutcome", - "code": "RESOURCE_CREATED", - "display": "Resource created", - } - ] - }, - "diagnostics": "Resource created", - } - ], -} @contextmanager @@ -85,22 +59,23 @@ def test_index(): ) # Validate that the response indicates that a resource was created assert response["statusCode"] == 201 - assert json_loads(response["body"]) == { - "id": app_logger.service_name, - **RESOURCE_CREATED, - } + created_product = json_loads(response["body"]) # Retrieve the created resource repo = CpmProductRepository( table_name=TABLE_NAME, dynamodb_client=index.cache["DYNAMODB_CLIENT"] ) - created_product = repo.read( - product_team_id=product_team.id, product_id=response["headers"]["Location"] - ).dict() + read_product = repo.read( + product_team_id=product_team.id, product_id=created_product["id"] + ).state() + + assert created_product == read_product + + # Don't check dates + created_product.pop("created_on") + created_product.pop("updated_on") # Sense checks on the created resource - assert isinstance(created_product.pop("created_on"), datetime) - assert isinstance(created_product.pop("updated_on"), datetime) assert ProductId.validate_cpm_system_id(created_product.pop("id")) assert PartyKeyId.validate_cpm_system_id( created_product.pop("keys")[0]["key_value"] diff --git a/src/api/tests/feature_tests/features/createCpmProduct.success.feature b/src/api/tests/feature_tests/features/createCpmProduct.success.feature index c0384675..5566d43f 100644 --- a/src/api/tests/feature_tests/features/createCpmProduct.success.feature +++ b/src/api/tests/feature_tests/features/createCpmProduct.success.feature @@ -19,24 +19,25 @@ Feature: Create CPM Product - success scenarios | path | value | | product_name | My Great Product | Then I receive a status code "201" with body - | path | value | - | resourceType | OperationOutcome | - | id | << ignore >> | - | meta.profile.0 | https://fhir.nhs.uk/StructureDefinition/NHSDigital-OperationOutcome | - | issue.0.severity | information | - | issue.0.code | informational | - | issue.0.details.coding.0.system | https://fhir.nhs.uk/StructureDefinition/NHSDigital-OperationOutcome | - | issue.0.details.coding.0.code | RESOURCE_CREATED | - | issue.0.details.coding.0.display | Resource created | - | issue.0.diagnostics | Resource created | + | path | value | + | id | << ignore >> | + | name | My Great Product | + | product_team_id | ${ note(product_team_id) } | + | ods_code | F5H1R | + | status | active | + | keys | [] | + | created_on | << ignore >> | + | updated_on | << ignore >> | + | deleted_on | << ignore >> | And the response headers contain: | name | value | | Content-Type | application/json | - | Content-Length | 460 | - When I make a "GET" request with "default" headers to the id in the location response header to the endpoint prefix "ProductTeam/${ note(product_team_id) }/Product/" + | Content-Length | 255 | + And I note the response field "$.id" as "product_id" + When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }" Then I receive a status code "200" with body | path | value | - | id | << ignore >> | + | id | ${ note(product_id) } | | name | My Great Product | | product_team_id | ${ note(product_team_id) } | | ods_code | F5H1R | diff --git a/src/api/tests/feature_tests/features/createCpmProductForEpr.success.feature b/src/api/tests/feature_tests/features/createCpmProductForEpr.success.feature index 913ed5ee..ca701b14 100644 --- a/src/api/tests/feature_tests/features/createCpmProductForEpr.success.feature +++ b/src/api/tests/feature_tests/features/createCpmProductForEpr.success.feature @@ -19,24 +19,26 @@ Feature: Create CPM Product for EPR - success scenarios | path | value | | product_name | My Great Product | Then I receive a status code "201" with body - | path | value | - | resourceType | OperationOutcome | - | id | << ignore >> | - | meta.profile.0 | https://fhir.nhs.uk/StructureDefinition/NHSDigital-OperationOutcome | - | issue.0.severity | information | - | issue.0.code | informational | - | issue.0.details.coding.0.system | https://fhir.nhs.uk/StructureDefinition/NHSDigital-OperationOutcome | - | issue.0.details.coding.0.code | RESOURCE_CREATED | - | issue.0.details.coding.0.display | Resource created | - | issue.0.diagnostics | Resource created | + | path | value | + | id | << ignore >> | + | name | My Great Product | + | product_team_id | ${ note(product_team_id) } | + | ods_code | F5H1R | + | status | active | + | keys.0.key_value | F5H1R-850000 | + | keys.0.key_type | party_key | + | created_on | << ignore >> | + | updated_on | << ignore >> | + | deleted_on | << ignore >> | And the response headers contain: | name | value | | Content-Type | application/json | - | Content-Length | 466 | - When I make a "GET" request with "default" headers to the id in the location response header to the endpoint prefix "ProductTeam/${ note(product_team_id) }/Product/" + | Content-Length | 339 | + And I note the response field "$.id" as "product_id" + When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }" Then I receive a status code "200" with body | path | value | - | id | << ignore >> | + | id | ${ note(product_id) } | | name | My Great Product | | product_team_id | ${ note(product_team_id) } | | ods_code | F5H1R | @@ -62,28 +64,28 @@ Feature: Create CPM Product for EPR - success scenarios When I make a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/Epr" with body: | path | value | | product_name | My Great Product | + And I note the response field "$.id" as "product_id_1" When I make a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/Epr" with body: | path | value | | product_name | My Other Great Product | - Then I receive a status code "201" with body - | path | value | - | resourceType | OperationOutcome | - | id | << ignore >> | - | meta.profile.0 | https://fhir.nhs.uk/StructureDefinition/NHSDigital-OperationOutcome | - | issue.0.severity | information | - | issue.0.code | informational | - | issue.0.details.coding.0.system | https://fhir.nhs.uk/StructureDefinition/NHSDigital-OperationOutcome | - | issue.0.details.coding.0.code | RESOURCE_CREATED | - | issue.0.details.coding.0.display | Resource created | - | issue.0.diagnostics | Resource created | - And the response headers contain: - | name | value | - | Content-Type | application/json | - | Content-Length | 466 | - When I make a "GET" request with "default" headers to the id in the location response header to the endpoint prefix "ProductTeam/${ note(product_team_id) }/Product/" + And I note the response field "$.id" as "product_id_2" + When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id_1) }" Then I receive a status code "200" with body | path | value | - | id | << ignore >> | + | id | ${ note(product_id_1) } | + | name | My Great Product | + | product_team_id | ${ note(product_team_id) } | + | ods_code | F5H1R | + | keys.0.key_value | F5H1R-850000 | + | keys.0.key_type | party_key | + | status | active | + | created_on | << ignore >> | + | updated_on | << ignore >> | + | deleted_on | << ignore >> | + When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id_2) }" + Then I receive a status code "200" with body + | path | value | + | id | ${ note(product_id_2) } | | name | My Other Great Product | | product_team_id | ${ note(product_team_id) } | | ods_code | F5H1R | @@ -93,7 +95,3 @@ Feature: Create CPM Product for EPR - success scenarios | created_on | << ignore >> | | updated_on | << ignore >> | | deleted_on | << ignore >> | - And the response headers contain: - | name | value | - | Content-Type | application/json | - | Content-Length | 345 | diff --git a/src/api/tests/feature_tests/features/createDeviceReferenceData.success.feature b/src/api/tests/feature_tests/features/createDeviceReferenceData.success.feature index b6c85a9a..d02dcf36 100644 --- a/src/api/tests/feature_tests/features/createDeviceReferenceData.success.feature +++ b/src/api/tests/feature_tests/features/createDeviceReferenceData.success.feature @@ -16,8 +16,6 @@ Feature: Create Device Reference Data - success scenarios And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: | path | value | | product_name | My Great Product | - # ####### TODO: CAN REMOVE THE FOLLOWING LINE AFTER PI-536 completed - When I make a "GET" request with "default" headers to the id in the location response header to the endpoint prefix "ProductTeam/${ note(product_team_id) }/Product/" And I note the response field "$.id" as "product_id" When I make a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/DeviceReferenceData" with body: | path | value | diff --git a/src/api/tests/feature_tests/features/deleteCpmProduct.failure.feature b/src/api/tests/feature_tests/features/deleteCpmProduct.failure.feature index 0addfc78..d56ed681 100644 --- a/src/api/tests/feature_tests/features/deleteCpmProduct.failure.feature +++ b/src/api/tests/feature_tests/features/deleteCpmProduct.failure.feature @@ -18,7 +18,8 @@ Feature: Delete CPM Product - failure scenarios Given I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: | path | value | | product_name | My Great CpmProduct | - When I make a "DELETE" request with "default" headers to the id in the location response header to the endpoint prefix "ProductTeam/123/Product/" + And I note the response field "$.id" as "product_id" + When I make a "DELETE" request with "default" headers to "ProductTeam/123/Product/${ note(product_id) }" Then I receive a status code "404" with body | path | value | | errors.0.code | RESOURCE_NOT_FOUND | diff --git a/src/api/tests/feature_tests/features/deleteCpmProduct.success.feature b/src/api/tests/feature_tests/features/deleteCpmProduct.success.feature index 972c1e19..ff3f985f 100644 --- a/src/api/tests/feature_tests/features/deleteCpmProduct.success.feature +++ b/src/api/tests/feature_tests/features/deleteCpmProduct.success.feature @@ -18,7 +18,8 @@ Feature: Delete CPM Product - success scenarios And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: | path | value | | product_name | My Great Product | - When I make a "DELETE" request with "default" headers to the id in the location response header to the endpoint prefix "ProductTeam/${ note(product_team_id) }/Product/" + And I note the response field "$.id" as "product_id" + When I make a "DELETE" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }" Then I receive a status code "204" And the response headers contain: | name | value | diff --git a/src/api/tests/feature_tests/features/readCpmProduct.failure.feature b/src/api/tests/feature_tests/features/readCpmProduct.failure.feature index b9ed1d79..ec0375f2 100644 --- a/src/api/tests/feature_tests/features/readCpmProduct.failure.feature +++ b/src/api/tests/feature_tests/features/readCpmProduct.failure.feature @@ -18,7 +18,8 @@ Feature: Read CPM Product - failure scenarios When I make a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: | path | value | | product_name | My Great CpmProduct | - When I make a "GET" request with "default" headers to the id in the location response header to the endpoint prefix "ProductTeam/123/Product/" + And I note the response field "$.id" as "product_id" + When I make a "GET" request with "default" headers to "ProductTeam/123/Product/${ note(product_id) }" Then I receive a status code "404" with body | path | value | | errors.0.code | RESOURCE_NOT_FOUND | diff --git a/src/api/tests/feature_tests/features/readCpmProduct.success.feature b/src/api/tests/feature_tests/features/readCpmProduct.success.feature index 305c63b9..aba38cb4 100644 --- a/src/api/tests/feature_tests/features/readCpmProduct.success.feature +++ b/src/api/tests/feature_tests/features/readCpmProduct.success.feature @@ -18,11 +18,11 @@ Feature: Read CPM Product - success scenarios When I make a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/Epr" with body: | path | value | | product_name | My Great Product | - Given I note the response field "$.id" as "product_id" - When I make a "GET" request with "default" headers to the id in the location response header to the endpoint prefix "ProductTeam/${ note(product_team_id) }/Product/" + And I note the response field "$.id" as "product_id" + When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }" Then I receive a status code "200" with body | path | value | - | id | << ignore >> | + | id | ${ note(product_id) } | | name | My Great Product | | product_team_id | ${ note(product_team_id) } | | ods_code | F5H1R | diff --git a/src/api/tests/feature_tests/steps/steps.py b/src/api/tests/feature_tests/steps/steps.py index d2e963e4..b587e1d2 100644 --- a/src/api/tests/feature_tests/steps/steps.py +++ b/src/api/tests/feature_tests/steps/steps.py @@ -139,32 +139,6 @@ def when_make_request( ) -@when( - 'I make a "{http_method}" request with "{header_name}" headers to the id in the location response header to the endpoint prefix "{endpoint}"' -) -def when_make_request_with_id( - context: Context, http_method: str, header_name: str, endpoint: str -): - endpoint = endpoint.replace("", context.response.headers.get("Location")) - context.response = make_request( - base_url=context.base_url, - http_method=http_method, - endpoint=endpoint, - headers=context.headers[header_name], - ) - context.postman_step.request = PostmanRequest( - url=Url( - raw=context.response.url, - host=[context.base_url.rstrip("/")], - path=[endpoint], - ), - method=http_method, - header=[ - HeaderItem(key=k, value=v) for k, v in context.headers[header_name].items() - ], - ) - - @then('I receive a status code "{status_code}" with body') def then_response(context: Context, status_code: str): expected_body = parse_table(table=context.table, context=context) diff --git a/src/layers/domain/api/common_steps/create_product.py b/src/layers/domain/api/common_steps/create_product.py index 7bbeaa51..968893c9 100644 --- a/src/layers/domain/api/common_steps/create_product.py +++ b/src/layers/domain/api/common_steps/create_product.py @@ -1,4 +1,5 @@ from http import HTTPStatus +from typing import TYPE_CHECKING from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEvent from domain.api.common_steps.general import parse_event_body @@ -13,6 +14,9 @@ from domain.response.validation_errors import mark_validation_errors_as_inbound from event.step_chain import StepChain +if TYPE_CHECKING: + from mypy_boto3_dynamodb.type_defs import TransactWriteItemsOutputTypeDef + @mark_validation_errors_as_inbound def parse_path_params(data, cache) -> ProductTeamPathParams: @@ -52,7 +56,9 @@ def write_cpm_product(data: dict[str, CpmProduct], cache) -> CpmProduct: return product_repo.write(product) -def write_cpm_product(data: dict[str, CpmProduct], cache) -> CpmProduct: +def write_cpm_product( + data: dict[str, CpmProduct], cache +) -> list["TransactWriteItemsOutputTypeDef"]: product: CpmProduct = data[create_cpm_product] product_repo = CpmProductRepository( table_name=cache["DYNAMODB_TABLE"], dynamodb_client=cache["DYNAMODB_CLIENT"] @@ -60,9 +66,9 @@ def write_cpm_product(data: dict[str, CpmProduct], cache) -> CpmProduct: return product_repo.write(product) -def set_http_status(data, cache) -> tuple[HTTPStatus, str]: +def set_http_status(data, cache) -> tuple[HTTPStatus, CpmProduct]: product: CpmProduct = data[create_cpm_product] - return HTTPStatus.CREATED, str(product.id) + return HTTPStatus.CREATED, product.state() before_steps = [ From 8372db8bba5e3fd80a8c4f80feda49876df5b52a Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Tue, 15 Oct 2024 16:35:19 +0100 Subject: [PATCH 08/38] [feature/PI-536-create_product_without_fhir] use note --- .../feature_tests/features/createCpmProduct.success.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/tests/feature_tests/features/createCpmProduct.success.feature b/src/api/tests/feature_tests/features/createCpmProduct.success.feature index 5566d43f..01b19513 100644 --- a/src/api/tests/feature_tests/features/createCpmProduct.success.feature +++ b/src/api/tests/feature_tests/features/createCpmProduct.success.feature @@ -18,9 +18,10 @@ Feature: Create CPM Product - success scenarios When I make a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: | path | value | | product_name | My Great Product | + And I note the response field "$.id" as "product_id" Then I receive a status code "201" with body | path | value | - | id | << ignore >> | + | id | ${ note(product_id) } | | name | My Great Product | | product_team_id | ${ note(product_team_id) } | | ods_code | F5H1R | @@ -33,7 +34,6 @@ Feature: Create CPM Product - success scenarios | name | value | | Content-Type | application/json | | Content-Length | 255 | - And I note the response field "$.id" as "product_id" When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }" Then I receive a status code "200" with body | path | value | From 28d03b4e51e1be3b04e5425be02ae1d78984d1d9 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Tue, 15 Oct 2024 16:18:56 +0100 Subject: [PATCH 09/38] [feature/PI-503-read_device_reference_data] read device reference data --- .../tests/test_index.py | 17 +- src/api/readDeviceReferenceData/index.py | 26 ++ src/api/readDeviceReferenceData/make/make.py | 4 + .../policies/dynamodb.json | 1 + .../readDeviceReferenceData/policies/kms.json | 1 + .../readDeviceReferenceData/src/v1/steps.py | 63 ++++ .../tests/test_index.py | 300 ++++++++++++++++++ .../createDeviceReferenceData.success.feature | 32 +- .../readDeviceReferenceData.success.feature | 38 +++ .../steps/endpoint_lambda_mapping.py | 2 + ...est_device_reference_data_repository_v1.py | 91 +++--- .../device_reference_data_repository/v1.py | 26 ++ src/layers/domain/request_models/v1.py | 6 + 13 files changed, 536 insertions(+), 71 deletions(-) create mode 100644 src/api/readDeviceReferenceData/index.py create mode 100644 src/api/readDeviceReferenceData/make/make.py create mode 100644 src/api/readDeviceReferenceData/policies/dynamodb.json create mode 100644 src/api/readDeviceReferenceData/policies/kms.json create mode 100644 src/api/readDeviceReferenceData/src/v1/steps.py create mode 100644 src/api/readDeviceReferenceData/tests/test_index.py create mode 100644 src/api/tests/feature_tests/features/readDeviceReferenceData.success.feature diff --git a/src/api/createDeviceReferenceData/tests/test_index.py b/src/api/createDeviceReferenceData/tests/test_index.py index ca2d1057..703cda35 100644 --- a/src/api/createDeviceReferenceData/tests/test_index.py +++ b/src/api/createDeviceReferenceData/tests/test_index.py @@ -91,16 +91,13 @@ def test_index() -> None: repo = DeviceReferenceDataRepository( table_name=TABLE_NAME, dynamodb_client=index.cache["DYNAMODB_CLIENT"] ) - if hasattr(repo, "read"): - raise Exception( - "uncomment the following code now that you've implemented read" - ) - created_device_reference_data = repo.read( - product_team_id=device_reference_data.product_team_id, - product_id=device_reference_data.product_id, - device_reference_data_id=device_reference_data.id, - ) - assert created_device_reference_data == device_reference_data + + created_device_reference_data = repo.read( + product_team_id=device_reference_data.product_team_id, + product_id=device_reference_data.product_id, + device_reference_data_id=device_reference_data.id, + ) + assert created_device_reference_data == device_reference_data @pytest.mark.parametrize( diff --git a/src/api/readDeviceReferenceData/index.py b/src/api/readDeviceReferenceData/index.py new file mode 100644 index 00000000..c2a0bfcf --- /dev/null +++ b/src/api/readDeviceReferenceData/index.py @@ -0,0 +1,26 @@ +from api_utils.api_step_chain import execute_step_chain +from event.aws.client import dynamodb_client +from event.environment import BaseEnvironment +from event.logging.logger import setup_logger + +from .src.v1.steps import steps as v1_steps + + +class Environment(BaseEnvironment): + DYNAMODB_TABLE: str + + +versioned_steps = {"1": v1_steps} +cache = { + **Environment.build().dict(), + "DYNAMODB_CLIENT": dynamodb_client(), +} + + +def handler(event: dict, context=None): + setup_logger(service_name=__file__) + return execute_step_chain( + event=event, + cache=cache, + versioned_steps=versioned_steps, + ) diff --git a/src/api/readDeviceReferenceData/make/make.py b/src/api/readDeviceReferenceData/make/make.py new file mode 100644 index 00000000..f33cd706 --- /dev/null +++ b/src/api/readDeviceReferenceData/make/make.py @@ -0,0 +1,4 @@ +from builder.lambda_build import build + +if __name__ == "__main__": + build(__file__) diff --git a/src/api/readDeviceReferenceData/policies/dynamodb.json b/src/api/readDeviceReferenceData/policies/dynamodb.json new file mode 100644 index 00000000..a1dd6640 --- /dev/null +++ b/src/api/readDeviceReferenceData/policies/dynamodb.json @@ -0,0 +1 @@ +["dynamodb:Query"] diff --git a/src/api/readDeviceReferenceData/policies/kms.json b/src/api/readDeviceReferenceData/policies/kms.json new file mode 100644 index 00000000..f34357e2 --- /dev/null +++ b/src/api/readDeviceReferenceData/policies/kms.json @@ -0,0 +1 @@ +["kms:Decrypt"] diff --git a/src/api/readDeviceReferenceData/src/v1/steps.py b/src/api/readDeviceReferenceData/src/v1/steps.py new file mode 100644 index 00000000..596c874a --- /dev/null +++ b/src/api/readDeviceReferenceData/src/v1/steps.py @@ -0,0 +1,63 @@ +from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEvent +from domain.core.cpm_product.v1 import CpmProduct +from domain.core.device_reference_data.v1 import DeviceReferenceData +from domain.core.product_team.v3 import ProductTeam +from domain.repository.cpm_product_repository.v3 import CpmProductRepository +from domain.repository.device_reference_data_repository.v1 import ( + DeviceReferenceDataRepository, +) +from domain.repository.product_team_repository.v2 import ProductTeamRepository +from domain.request_models.v1 import DeviceReferenceDataPathParams +from domain.response.validation_errors import mark_validation_errors_as_inbound +from event.step_chain import StepChain + + +@mark_validation_errors_as_inbound +def parse_path_params(data, cache) -> DeviceReferenceDataPathParams: + event = APIGatewayProxyEvent(data[StepChain.INIT]) + return DeviceReferenceDataPathParams(**event.path_parameters) + + +def read_product_team(data, cache) -> ProductTeam: + path_params: DeviceReferenceDataPathParams = data[parse_path_params] + product_team_repo = ProductTeamRepository( + table_name=cache["DYNAMODB_TABLE"], dynamodb_client=cache["DYNAMODB_CLIENT"] + ) + return product_team_repo.read(id=path_params.product_team_id) + + +def read_product(data, cache) -> CpmProduct: + path_params: DeviceReferenceDataPathParams = data[parse_path_params] + product_repo = CpmProductRepository( + table_name=cache["DYNAMODB_TABLE"], dynamodb_client=cache["DYNAMODB_CLIENT"] + ) + cpm_product = product_repo.read( + product_id=path_params.product_id, product_team_id=path_params.product_team_id + ) + return cpm_product + + +def read_device_reference_data(data, cache) -> DeviceReferenceData: + path_params: DeviceReferenceDataPathParams = data[parse_path_params] + product_repo = DeviceReferenceDataRepository( + table_name=cache["DYNAMODB_TABLE"], dynamodb_client=cache["DYNAMODB_CLIENT"] + ) + return product_repo.read( + product_id=path_params.product_id, + product_team_id=path_params.product_team_id, + device_reference_data_id=path_params.device_reference_data_id, + ) + + +def device_reference_data_to_dict(data, cache) -> dict: + device_reference_data: DeviceReferenceData = data[read_device_reference_data] + return device_reference_data.state() + + +steps = [ + parse_path_params, + read_product_team, + read_product, + read_device_reference_data, + device_reference_data_to_dict, +] diff --git a/src/api/readDeviceReferenceData/tests/test_index.py b/src/api/readDeviceReferenceData/tests/test_index.py new file mode 100644 index 00000000..7dc739a8 --- /dev/null +++ b/src/api/readDeviceReferenceData/tests/test_index.py @@ -0,0 +1,300 @@ +import json +import os +from unittest import mock + +import pytest +from domain.core.root.v3 import Root +from domain.repository.cpm_product_repository.v3 import CpmProductRepository +from domain.repository.device_reference_data_repository.v1 import ( + DeviceReferenceDataRepository, +) +from domain.repository.product_team_repository.v2 import ProductTeamRepository +from event.json import json_loads + +from test_helpers.dynamodb import mock_table +from test_helpers.response_assertions import _response_assertions + +TABLE_NAME = "hiya" +ODS_CODE = "F5H1R" +PRODUCT_TEAM_ID = "F5H1R.641be376-3954-4339-822c-54071c9ff1a0" +PRODUCT_TEAM_NAME = "product-team-name" +PRODUCT_ID = "P.XXX-YYY" +PRODUCT_NAME = "cpm-product-name" +PRODUCT_TEAM_KEYS = [{"key_type": "product_team_id_alias", "key_value": "BAR"}] +DEVICE_REFERENCE_DATA_NAME = "device-reference-data" + + +@pytest.mark.parametrize( + "version", + [ + "1", + ], +) +def test_index(version): + org = Root.create_ods_organisation(ods_code=ODS_CODE) + product_team = org.create_product_team( + name=PRODUCT_TEAM_NAME, keys=PRODUCT_TEAM_KEYS + ) + + with mock_table(TABLE_NAME) as client, mock.patch.dict( + os.environ, + { + "DYNAMODB_TABLE": TABLE_NAME, + "AWS_DEFAULT_REGION": "eu-west-2", + }, + clear=True, + ): + # Set up ProductTeam in DB + product_team_repo = ProductTeamRepository( + table_name=TABLE_NAME, dynamodb_client=client + ) + product_team_repo.write(entity=product_team) + + # Set up Product in DB + cpm_product = product_team.create_cpm_product( + name=PRODUCT_NAME, product_id=PRODUCT_ID + ) + product_repo = CpmProductRepository( + table_name=TABLE_NAME, dynamodb_client=client + ) + product_repo.write(cpm_product) + + # Set up DeviceReferenceData in DB + device_reference_data = cpm_product.create_device_reference_data( + name=DEVICE_REFERENCE_DATA_NAME + ) + device_reference_data_repo = DeviceReferenceDataRepository( + table_name=TABLE_NAME, dynamodb_client=client + ) + device_reference_data_repo.write(device_reference_data) + + from api.readDeviceReferenceData.index import handler + + result = handler( + event={ + "headers": {"version": version}, + "pathParameters": { + "product_team_id": str(product_team.id), + "product_id": str(cpm_product.id.id), + "device_reference_data_id": str(device_reference_data.id), + }, + } + ) + + response_body = json_loads(result["body"]) + + # Assertions for fields that must exactly match + assert response_body["id"] == str(device_reference_data.id) + assert response_body["product_id"] == str(cpm_product.id) + assert response_body["product_team_id"] == str(product_team.id) + assert response_body["name"] == device_reference_data.name + assert response_body["ods_code"] == device_reference_data.ods_code + assert response_body["updated_on"] is None + assert response_body["deleted_on"] is None + + # Assertions for fields that only need to be included + assert "product_team_id" in response_body + assert "created_on" in response_body + + expected_headers = { + "Content-Type": "application/json", + "Version": version, + "Location": None, + } + + # Check response headers + assert result["statusCode"] == 200 + assert result["headers"]["Content-Length"] == str(len(result["body"])) + for key, value in expected_headers.items(): + assert result["headers"][key] == value + + +@pytest.mark.parametrize( + "version", + [ + "1", + ], +) +def test_index_no_such_device_reference_data(version): + org = Root.create_ods_organisation(ods_code=ODS_CODE) + product_team = org.create_product_team( + name=PRODUCT_TEAM_NAME, keys=PRODUCT_TEAM_KEYS + ) + with mock_table(TABLE_NAME) as client, mock.patch.dict( + os.environ, + { + "DYNAMODB_TABLE": TABLE_NAME, + "AWS_DEFAULT_REGION": "eu-west-2", + }, + clear=True, + ): + # Set up ProductTeam in DB + product_team_repo = ProductTeamRepository( + table_name=TABLE_NAME, dynamodb_client=client + ) + product_team_repo.write(entity=product_team) + + # Set up Product in DB + cpm_product = product_team.create_cpm_product( + name=PRODUCT_NAME, product_id=PRODUCT_ID + ) + product_repo = CpmProductRepository( + table_name=TABLE_NAME, dynamodb_client=client + ) + product_repo.write(cpm_product) + + from api.readDeviceReferenceData.index import handler + + result = handler( + event={ + "headers": {"version": version}, + "pathParameters": { + "product_team_id": str(product_team.id), + "product_id": str(cpm_product.id), + "device_reference_data_id": "does not exist", + }, + } + ) + + expected_result = json.dumps( + { + "errors": [ + { + "code": "RESOURCE_NOT_FOUND", + "message": f"Could not find DeviceReferenceData for key ('{product_team.id}', '{cpm_product.id}', 'does not exist')", + } + ], + } + ) + + expected = { + "statusCode": 404, + "body": expected_result, + "headers": { + "Content-Length": str(len(expected_result)), + "Content-Type": "application/json", + "Version": version, + "Location": None, + }, + } + _response_assertions( + result=result, expected=expected, check_body=True, check_content_length=True + ) + + +@pytest.mark.parametrize( + "version", + [ + "1", + ], +) +def test_index_no_such_product(version): + org = Root.create_ods_organisation(ods_code=ODS_CODE) + product_team = org.create_product_team( + name=PRODUCT_TEAM_NAME, keys=PRODUCT_TEAM_KEYS + ) + with mock_table(TABLE_NAME) as client, mock.patch.dict( + os.environ, + { + "DYNAMODB_TABLE": TABLE_NAME, + "AWS_DEFAULT_REGION": "eu-west-2", + }, + clear=True, + ): + # Set up ProductTeam in DB + product_team_repo = ProductTeamRepository( + table_name=TABLE_NAME, dynamodb_client=client + ) + product_team_repo.write(entity=product_team) + + from api.readDeviceReferenceData.index import handler + + result = handler( + event={ + "headers": {"version": version}, + "pathParameters": { + "product_team_id": str(product_team.id), + "product_id": "product that doesnt exist", + "device_reference_data_id": "does not exist", + }, + } + ) + + expected_result = json.dumps( + { + "errors": [ + { + "code": "RESOURCE_NOT_FOUND", + "message": f"Could not find CpmProduct for key ('{product_team.id}', 'product that doesnt exist')", + } + ], + } + ) + + expected = { + "statusCode": 404, + "body": expected_result, + "headers": { + "Content-Length": str(len(expected_result)), + "Content-Type": "application/json", + "Version": version, + "Location": None, + }, + } + _response_assertions( + result=result, expected=expected, check_body=True, check_content_length=True + ) + + +@pytest.mark.parametrize( + "version", + [ + "1", + ], +) +def test_index_no_such_product_team(version): + with mock_table(TABLE_NAME) as client, mock.patch.dict( + os.environ, + { + "DYNAMODB_TABLE": TABLE_NAME, + "AWS_DEFAULT_REGION": "eu-west-2", + }, + clear=True, + ): + from api.readDeviceReferenceData.index import handler + + result = handler( + event={ + "headers": {"version": version}, + "pathParameters": { + "product_id": str(PRODUCT_ID), + "product_team_id": str(PRODUCT_TEAM_ID), + "device_reference_data_id": "123", + }, + } + ) + + expected_result = json.dumps( + { + "errors": [ + { + "code": "RESOURCE_NOT_FOUND", + "message": f"Could not find ProductTeam for key ('{PRODUCT_TEAM_ID}')", + } + ], + } + ) + + expected = { + "statusCode": 404, + "body": expected_result, + "headers": { + "Content-Length": str(len(expected_result)), + "Content-Type": "application/json", + "Version": version, + "Location": None, + }, + } + _response_assertions( + result=result, expected=expected, check_body=True, check_content_length=True + ) diff --git a/src/api/tests/feature_tests/features/createDeviceReferenceData.success.feature b/src/api/tests/feature_tests/features/createDeviceReferenceData.success.feature index d02dcf36..08909a64 100644 --- a/src/api/tests/feature_tests/features/createDeviceReferenceData.success.feature +++ b/src/api/tests/feature_tests/features/createDeviceReferenceData.success.feature @@ -35,20 +35,18 @@ Feature: Create Device Reference Data - success scenarios | Content-Type | application/json | | Content-Length | 285 | And I note the response field "$.id" as "device_reference_data_id" - -# ### TODO: UNCOMMENT THIS FOR PI-503 -# When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/${ note(device_reference_data_id) }" -# Then I receive a status code "200" with body -# | path | value | -# | id | ${ note(device_reference_data_id) } | -# | name | My Device Reference Data | -# | product_id | ${ note(product_id) } | -# | product_team_id | ${ note(product_team_id) } | -# | ods_code | F5H1R | -# | created_on | << ignore >> | -# | updated_on | << ignore >> | -# | deleted_on | << ignore >> | -# And the response headers contain: -# | name | value | -# | Content-Type | application/json | -# | Content-Length | 285 | + When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/DeviceReferenceData/${ note(device_reference_data_id) }" + Then I receive a status code "200" with body + | path | value | + | id | ${ note(device_reference_data_id) } | + | name | My Device Reference Data | + | product_id | ${ note(product_id) } | + | product_team_id | ${ note(product_team_id) } | + | ods_code | F5H1R | + | created_on | << ignore >> | + | updated_on | << ignore >> | + | deleted_on | << ignore >> | + And the response headers contain: + | name | value | + | Content-Type | application/json | + | Content-Length | 285 | diff --git a/src/api/tests/feature_tests/features/readDeviceReferenceData.success.feature b/src/api/tests/feature_tests/features/readDeviceReferenceData.success.feature new file mode 100644 index 00000000..6b8fdc7c --- /dev/null +++ b/src/api/tests/feature_tests/features/readDeviceReferenceData.success.feature @@ -0,0 +1,38 @@ +Feature: Read Device Reference Data - success scenarios + These scenarios demonstrate successful Device Reference Data reading + + Background: + Given "default" request headers: + | name | value | + | version | 1 | + | Authorization | letmein | + + Scenario: Successfully read a Device Reference Data + Given I have already made a "POST" request with "default" headers to "ProductTeam" with body: + | path | value | + | name | My Great Product Team | + | ods_code | F5H1R | + And I note the response field "$.id" as "product_team_id" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: + | path | value | + | product_name | My Great Product | + And I note the response field "$.id" as "product_id" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/DeviceReferenceData" with body: + | path | value | + | name | My Device Reference Data | + And I note the response field "$.id" as "device_reference_data_id" + When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/DeviceReferenceData/${ note(device_reference_data_id) }" + Then I receive a status code "200" with body + | path | value | + | id | ${ note(device_reference_data_id) } | + | name | My Device Reference Data | + | product_id | ${ note(product_id) } | + | product_team_id | ${ note(product_team_id) } | + | ods_code | F5H1R | + | created_on | << ignore >> | + | updated_on | << ignore >> | + | deleted_on | << ignore >> | + And the response headers contain: + | name | value | + | Content-Type | application/json | + | Content-Length | 285 | diff --git a/src/api/tests/feature_tests/steps/endpoint_lambda_mapping.py b/src/api/tests/feature_tests/steps/endpoint_lambda_mapping.py index ba2e2892..0524e93c 100644 --- a/src/api/tests/feature_tests/steps/endpoint_lambda_mapping.py +++ b/src/api/tests/feature_tests/steps/endpoint_lambda_mapping.py @@ -29,6 +29,7 @@ def get_endpoint_lambda_mapping() -> ENDPOINT_LAMBDA_MAPPING: import api.deleteCpmProduct.index import api.readCpmProduct.index import api.readDevice.index + import api.readDeviceReferenceData.index import api.readProductTeam.index import api.searchCpmProduct.index import api.searchDevice.index @@ -46,6 +47,7 @@ def get_endpoint_lambda_mapping() -> ENDPOINT_LAMBDA_MAPPING: "ProductTeam/{product_team_id}": api.readProductTeam.index, "ProductTeam/{product_team_id}/Product": api.searchCpmProduct.index, "ProductTeam/{product_team_id}/Product/{product_id}": api.readCpmProduct.index, + "ProductTeam/{product_team_id}/Product/{product_id}/DeviceReferenceData/{device_reference_data_id}": api.readDeviceReferenceData.index, "Device/{id}": api.readDevice.index, "Device?device_type={device_type}": api.searchDevice.index, "Device?device_type={device_type}&foo={foo}": api.searchDevice.index, diff --git a/src/layers/domain/repository/device_reference_data_repository/tests/test_device_reference_data_repository_v1.py b/src/layers/domain/repository/device_reference_data_repository/tests/test_device_reference_data_repository_v1.py index cf0a3335..01085a85 100644 --- a/src/layers/domain/repository/device_reference_data_repository/tests/test_device_reference_data_repository_v1.py +++ b/src/layers/domain/repository/device_reference_data_repository/tests/test_device_reference_data_repository_v1.py @@ -1,71 +1,74 @@ import pytest -from domain.core.cpm_product.v1 import CpmProduct +from domain.core.device_reference_data.v1 import DeviceReferenceData from domain.repository.device_reference_data_repository.v1 import ( DeviceReferenceDataRepository, ) -from domain.repository.errors import AlreadyExistsError +from domain.repository.errors import AlreadyExistsError, ItemNotFound + +from test_helpers.uuid import consistent_uuid @pytest.mark.integration def test__cpm_device_reference_data_repository( - device_reference_data: CpmProduct, repository: DeviceReferenceDataRepository + device_reference_data: DeviceReferenceData, + repository: DeviceReferenceDataRepository, ): repository.write(device_reference_data) - - # TODO: UNCOMMENT FOR PI-503 - # result = repository.read( - # product_team_id=device_reference_data.product_team_id, - # product_id=device_reference_data.id, - # ) - # assert result == device_reference_data + result = repository.read( + product_team_id=device_reference_data.product_team_id, + product_id=device_reference_data.product_id, + device_reference_data_id=device_reference_data.id, + ) + assert result == device_reference_data @pytest.mark.integration def test__cpm_device_reference_data_repository_already_exists( - device_reference_data: CpmProduct, repository: DeviceReferenceDataRepository + device_reference_data: DeviceReferenceData, + repository: DeviceReferenceDataRepository, ): repository.write(device_reference_data) with pytest.raises(AlreadyExistsError): repository.write(device_reference_data) -# TODO: UNCOMMENT FOR PI-503 -# @pytest.mark.integration -# def test__cpm_device_reference_data_repository__device_reference_data_does_not_exist( -# repository: DeviceReferenceDataRepository, -# ): -# product_team_id = consistent_uuid(1) -# product_id = "P.XXX-YYY" -# device_reference_data_id = consistent_uuid(2) -# with pytest.raises(ItemNotFound): -# repository.read( -# product_team_id=product_team_id, -# product_id=product_id, -# device_reference_data_id=device_reference_data_id, -# ) +@pytest.mark.integration +def test__cpm_device_reference_data_repository__device_reference_data_does_not_exist( + repository: DeviceReferenceDataRepository, +): + product_team_id = consistent_uuid(1) + product_id = "P.XXX-YYY" + device_reference_data_id = consistent_uuid(2) + with pytest.raises(ItemNotFound): + repository.read( + product_team_id=product_team_id, + product_id=product_id, + device_reference_data_id=device_reference_data_id, + ) def test__cpm_product_repository_local( - device_reference_data: CpmProduct, repository: DeviceReferenceDataRepository + device_reference_data: DeviceReferenceData, + repository: DeviceReferenceDataRepository, ): repository.write(device_reference_data) - # TODO: UNCOMMENT FOR PI-503 - # result = repository.read( - # product_team_id=device_reference_data.product_team_id, product_id=product.id - # ) - # assert result == device_reference_data + result = repository.read( + product_team_id=device_reference_data.product_team_id, + product_id=device_reference_data.product_id, + device_reference_data_id=device_reference_data.id, + ) + assert result == device_reference_data -# TODO: UNCOMMENT FOR PI-503 -# def test__cpm_device_reference_data_repository__device_reference_data_does_not_exist_local( -# repository: DeviceReferenceDataRepository, -# ): -# product_team_id = consistent_uuid(1) -# product_id = "P.XXX-YYY" -# device_reference_data_id = consistent_uuid(2) -# with pytest.raises(ItemNotFound): -# repository.read( -# product_team_id=product_team_id, -# product_id=product_id, -# device_reference_data_id=device_reference_data_id, -# ) +def test__cpm_device_reference_data_repository__device_reference_data_does_not_exist_local( + repository: DeviceReferenceDataRepository, +): + product_team_id = consistent_uuid(1) + product_id = "P.XXX-YYY" + device_reference_data_id = consistent_uuid(2) + with pytest.raises(ItemNotFound): + repository.read( + product_team_id=product_team_id, + product_id=product_id, + device_reference_data_id=device_reference_data_id, + ) diff --git a/src/layers/domain/repository/device_reference_data_repository/v1.py b/src/layers/domain/repository/device_reference_data_repository/v1.py index a75a5493..95a7129d 100644 --- a/src/layers/domain/repository/device_reference_data_repository/v1.py +++ b/src/layers/domain/repository/device_reference_data_repository/v1.py @@ -4,7 +4,9 @@ DeviceReferenceDataCreatedEvent, ) from domain.repository.device_repository.v2 import create_device_index +from domain.repository.errors import ItemNotFound from domain.repository.keys.v3 import TableKey +from domain.repository.marshall import marshall, unmarshall from domain.repository.repository.v2 import Repository from domain.repository.transaction import TransactItem @@ -34,3 +36,27 @@ def handle_DeviceReferenceDataCreatedEvent( return create_device_reference_data( table_name=self.table_name, id=event.id, data=asdict(event), root=True ) + + def read( + self, product_team_id: str, product_id: str, device_reference_data_id: str + ) -> DeviceReferenceData: + # TODO: in future switch the pk / sk to pk_read / sk_read on the GSI + pk = TableKey.DEVICE_REFERENCE_DATA.key(device_reference_data_id) + sk = TableKey.DEVICE_REFERENCE_DATA.key(device_reference_data_id) + args = { + "TableName": self.table_name, + "KeyConditionExpression": "pk = :pk AND sk = :sk", + "ExpressionAttributeValues": marshall(**{":pk": pk, ":sk": sk}), + } + result = self.client.query(**args) + + try: + (item,) = result["Items"] + except ValueError: + raise ItemNotFound( + product_team_id, + product_id, + device_reference_data_id, + item_type=DeviceReferenceData, + ) + return DeviceReferenceData(**unmarshall(item)) diff --git a/src/layers/domain/request_models/v1.py b/src/layers/domain/request_models/v1.py index 2ce6d887..cfe6907b 100644 --- a/src/layers/domain/request_models/v1.py +++ b/src/layers/domain/request_models/v1.py @@ -30,3 +30,9 @@ def __init__(self, **data): class CreateDeviceReferenceDataParams(BaseModel, extra=Extra.forbid): name: str = Field(...) + + +class DeviceReferenceDataPathParams(BaseModel, extra=Extra.forbid): + product_id: str = Field(...) + product_team_id: str = Field(...) + device_reference_data_id: str = Field(...) From f7a9a7ebd3e3e372a66e139f3236b4aea72df28e Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Wed, 16 Oct 2024 15:06:36 +0100 Subject: [PATCH 10/38] [feature/PI-562-test_deleted_product] add deleted product tests --- .../features/readCpmProduct.failure.feature | 23 +++++++++ .../features/searchCpmProduct.success.feature | 49 ++++++++++++++++++- src/api/tests/feature_tests/steps/steps.py | 2 +- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/api/tests/feature_tests/features/readCpmProduct.failure.feature b/src/api/tests/feature_tests/features/readCpmProduct.failure.feature index ec0375f2..af1f792f 100644 --- a/src/api/tests/feature_tests/features/readCpmProduct.failure.feature +++ b/src/api/tests/feature_tests/features/readCpmProduct.failure.feature @@ -46,3 +46,26 @@ Feature: Read CPM Product - failure scenarios | name | value | | Content-Type | application/json | | Content-Length | 152 | + + Scenario: Can't read a deleted Product + Given I have already made a "POST" request with "default" headers to "ProductTeam" with body: + | path | value | + | name | My Great Product Team | + | ods_code | F5H1R | + | keys.0.key_type | product_team_id_alias | + | keys.0.key_value | FOOBAR | + Given I note the response field "$.id" as "product_team_id" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: + | path | value | + | product_name | My Great Product | + And I note the response field "$.id" as "product_id" + And I have already made a "DELETE" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }" + When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }" + Then I receive a status code "404" with body + | path | value | + | errors.0.code | RESOURCE_NOT_FOUND | + | errors.0.message | Could not find CpmProduct for key ('${ note(product_team_id) }', '${ note(product_id) }') | + And the response headers contain: + | name | value | + | Content-Type | application/json | + | Content-Length | 152 | diff --git a/src/api/tests/feature_tests/features/searchCpmProduct.success.feature b/src/api/tests/feature_tests/features/searchCpmProduct.success.feature index a08d722a..19c53043 100644 --- a/src/api/tests/feature_tests/features/searchCpmProduct.success.feature +++ b/src/api/tests/feature_tests/features/searchCpmProduct.success.feature @@ -68,7 +68,7 @@ Feature: Search CPM Products - success scenarios | path | value | | product_name | My Great Product 3 | When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" - Then I receive a status code "200" with a "product" search body reponse that contains + Then I receive a status code "200" with a "product" search body response that contains | path | value | | 0.id | << ignore >> | | 0.product_team_id | ${ note(product_team_id) } | @@ -101,3 +101,50 @@ Feature: Search CPM Products - success scenarios | name | value | | Content-Type | application/json | | Content-Length | 777 | + + Scenario: Deleted Products not returned in search + Given I have already made a "POST" request with "default" headers to "ProductTeam" with body: + | path | value | + | name | My Great Product Team | + | ods_code | F5H1R | + | keys.0.key_type | product_team_id_alias | + | keys.0.key_value | FOOBAR | + And I note the response field "$.id" as "product_team_id" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: + | path | value | + | product_name | My Great Product 1 | + And I note the response field "$.id" as "product_id_1" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: + | path | value | + | product_name | My Great Product 2 | + And I note the response field "$.id" as "product_id_2" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: + | path | value | + | product_name | My Great Product 3 | + And I note the response field "$.id" as "product_id_3" + And I have already made a "DELETE" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id_2) }" + When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" + Then I receive a status code "200" with a "product" search body response that contains + | path | value | + | 0.id | ${ note(product_id_1) } | + | 0.product_team_id | ${ note(product_team_id) } | + | 0.name | My Great Product 1 | + | 0.ods_code | F5H1R | + | 0.status | active | + | 0.keys | [] | + | 0.created_on | << ignore >> | + | 0.updated_on | << ignore >> | + | 0.deleted_on | << ignore >> | + | 1.id | ${ note(product_id_3) } | + | 1.product_team_id | ${ note(product_team_id) } | + | 1.name | My Great Product 3 | + | 1.ods_code | F5H1R | + | 1.status | active | + | 1.keys | [] | + | 1.created_on | << ignore >> | + | 1.updated_on | << ignore >> | + | 1.deleted_on | << ignore >> | + And the response headers contain: + | name | value | + | Content-Type | application/json | + | Content-Length | 518 | diff --git a/src/api/tests/feature_tests/steps/steps.py b/src/api/tests/feature_tests/steps/steps.py index b587e1d2..e7c218c7 100644 --- a/src/api/tests/feature_tests/steps/steps.py +++ b/src/api/tests/feature_tests/steps/steps.py @@ -195,7 +195,7 @@ def then_response(context: Context, status_code: str, list_to_check: str, count: @then( - 'I receive a status code "{status_code}" with a "{entity_type}" search body reponse that contains' + 'I receive a status code "{status_code}" with a "{entity_type}" search body response that contains' ) def then_response(context: Context, status_code: str, entity_type: str): expected_body = parse_table(table=context.table, context=context) From b539a8dbbf3356f14cb658d8641dc9739fcc184a Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Wed, 16 Oct 2024 15:51:47 +0100 Subject: [PATCH 11/38] [release/2024-10-16] create release --- CHANGELOG.md | 5 +++++ VERSION | 2 +- changelog/2024-10-16.md | 3 +++ pyproject.toml | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 changelog/2024-10-16.md diff --git a/CHANGELOG.md b/CHANGELOG.md index afbaf074..8eaa4591 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 2024-10-16 +- [PI-501] Create Device Reference Data +- [PI-503] Read Device Reference Data +- [PI-536] Create Cpm Product without FHIR + ## 2024-10-15 - [PI-533] Create Product Team without FHIR diff --git a/VERSION b/VERSION index 97e1fa46..78c17c89 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2024.10.15 +2024.10.16 diff --git a/changelog/2024-10-16.md b/changelog/2024-10-16.md new file mode 100644 index 00000000..06d713ae --- /dev/null +++ b/changelog/2024-10-16.md @@ -0,0 +1,3 @@ +- [PI-501] Create Device Reference Data +- [PI-503] Read Device Reference Data +- [PI-536] Create Cpm Product without FHIR diff --git a/pyproject.toml b/pyproject.toml index 2856bf14..8f6309a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "connecting-party-manager" -version = "2024.10.15" +version = "2024.10.16" description = "Repository for the Connecting Party Manager API and related services" authors = ["NHS England"] license = "LICENSE.md" From 9aff6add656140f6941531d75522212bfbb33b52 Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Mon, 14 Oct 2024 17:59:56 +0100 Subject: [PATCH 12/38] Initial read Product Team --- infrastructure/swagger/05_paths.yaml | 51 ++++++++++--------- .../endpoints.yaml | 1 - pyproject.toml | 1 + src/api/readProductTeam/index.py | 2 +- src/api/readProductTeam/src/v1/steps.py | 32 ++++++------ .../domain/fhir_translation/product_team.py | 15 ------ .../tests/test_fhir_product_team.py | 26 ---------- 7 files changed, 43 insertions(+), 85 deletions(-) delete mode 100644 src/layers/domain/fhir_translation/product_team.py delete mode 100644 src/layers/domain/fhir_translation/tests/test_fhir_product_team.py diff --git a/infrastructure/swagger/05_paths.yaml b/infrastructure/swagger/05_paths.yaml index 2e4c9f24..5839f527 100644 --- a/infrastructure/swagger/05_paths.yaml +++ b/infrastructure/swagger/05_paths.yaml @@ -67,34 +67,35 @@ paths: - ${authoriser_name}: [] - app-level0: [] - /Organization/{id}: - get: - parameters: - - name: id - in: path - required: true - description: logical identifier - schema: - type: string - - *RequestHeaderVersion - - *RequestHeaderRequestId - - *RequestHeaderCorrelationId - responses: - "4XX": - <<: *Response4XX - x-amazon-apigateway-integration: - <<: *ApiGatewayIntegration - uri: ${method_readProductTeam} - security: - - ${authoriser_name}: [] - - app-level0: [] - /ProductTeam: post: operationId: createproductteam summary: createProductTeam endpoint for APIGEE integration requestBody: - $ref: "#/components/requestBodies/Organization" + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: Name of the product team + ods_code: + type: string + description: ODS code associated with the product team + keys: + type: array + description: List of keys associated with the product team + items: + type: object + properties: + key_type: + type: string + description: The type of the key (e.g., product_team_id_alias) + key_value: + type: string + description: The value of the key responses: "201": <<: *Response201 @@ -130,11 +131,11 @@ paths: - *RequestHeaderCorrelationId responses: "200": - description: Read Product Team operation successful + description: Read Product operation successful content: application/fhir+json: schema: - $ref: "#/components/schemas/Organization" + $ref: "#/components/schemas/Bundle" "4XX": <<: *Response4XX x-amazon-apigateway-integration: diff --git a/infrastructure/swagger/swagger-fhir-generator-definitions/endpoints.yaml b/infrastructure/swagger/swagger-fhir-generator-definitions/endpoints.yaml index cf094a17..392574f2 100644 --- a/infrastructure/swagger/swagger-fhir-generator-definitions/endpoints.yaml +++ b/infrastructure/swagger/swagger-fhir-generator-definitions/endpoints.yaml @@ -9,6 +9,5 @@ # RESTful API "Instance Level" or "Type Level" interactions # described in https://hl7.org/fhir/r4b/http.html -Organization: [read] Device: [create, read, search] Product: [create, read] diff --git a/pyproject.toml b/pyproject.toml index 2856bf14..dd389f74 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,6 +55,7 @@ boto3-stubs = { extras = [ ], version = "^1.34.37" } pytest-timeout = "^2.2.0" lz4 = "^4.3.3" +gevent = "<24.10.2" [tool.poetry.group.local] optional = true diff --git a/src/api/readProductTeam/index.py b/src/api/readProductTeam/index.py index 0ae82723..ed38f854 100644 --- a/src/api/readProductTeam/index.py +++ b/src/api/readProductTeam/index.py @@ -1,4 +1,4 @@ -from api_utils.api_step_chain import execute_step_chain_fhir as execute_step_chain +from api_utils.api_step_chain import execute_step_chain from event.aws.client import dynamodb_client from event.environment import BaseEnvironment from event.logging.logger import setup_logger diff --git a/src/api/readProductTeam/src/v1/steps.py b/src/api/readProductTeam/src/v1/steps.py index c79d8aab..29d196d7 100644 --- a/src/api/readProductTeam/src/v1/steps.py +++ b/src/api/readProductTeam/src/v1/steps.py @@ -1,31 +1,29 @@ +from http import HTTPStatus + from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEvent from domain.core.product_team.v3 import ProductTeam -from domain.fhir_translation.product_team import create_fhir_model_from_product_team from domain.repository.product_team_repository.v2 import ProductTeamRepository +from domain.request_models.v1 import ProductTeamPathParams from event.step_chain import StepChain -def read_product_team(data, cache) -> ProductTeam: +@mark_validation_errors_as_inbound +def parse_path_params(data, cache) -> ProductTeamPathParams: event = APIGatewayProxyEvent(data[StepChain.INIT]) - if "product_team_id" in event.path_parameters: - id = event.path_parameters["product_team_id"] - else: - id = event.path_parameters["id"] - # The conditonal statement is here because the Organization endpoint still exists whcih will be removed with the FHIR removal tickets. - # Remove the "id" path param once Organization and FHIR have been removed. + return ProductTeamPathParams(**event.path_parameters) + + +def read_product_team(data, cache) -> ProductTeam: + path_params: ProductTeamPathParams = data[parse_path_params] product_team_repo = ProductTeamRepository( table_name=cache["DYNAMODB_TABLE"], dynamodb_client=cache["DYNAMODB_CLIENT"] ) - return product_team_repo.read(id=id) + return product_team_repo.read(id=path_params.product_team_id) -def product_team_to_fhir_org(data, cache) -> dict: - product_team = data[read_product_team] - fhir_org = create_fhir_model_from_product_team(product_team=product_team) - return fhir_org.dict() +def return_product_team(data, cache) -> tuple[HTTPStatus, dict]: + product_team: ProductTeam = data[read_product_team] + return HTTPStatus.OK, product_team.state() -steps = [ - read_product_team, - product_team_to_fhir_org, -] +steps = [parse_path_params, read_product_team, return_product_team] diff --git a/src/layers/domain/fhir_translation/product_team.py b/src/layers/domain/fhir_translation/product_team.py deleted file mode 100644 index 335f1f37..00000000 --- a/src/layers/domain/fhir_translation/product_team.py +++ /dev/null @@ -1,15 +0,0 @@ -from domain.core.product_team import ProductTeam -from domain.fhir.r4.cpm_model import OdsIdentifier, OdsReference -from domain.fhir.r4.cpm_model import Organization as ProductTeamOrganization -from domain.fhir.r4.cpm_model import ProductTeamIdentifier - - -def create_fhir_model_from_product_team( - product_team: ProductTeam, -) -> ProductTeamOrganization: - return ProductTeamOrganization( - resourceType=ProductTeamOrganization.__name__, - identifier=[ProductTeamIdentifier(value=product_team.id)], - name=product_team.name, - partOf=OdsReference(identifier=OdsIdentifier(value=product_team.ods_code)), - ) diff --git a/src/layers/domain/fhir_translation/tests/test_fhir_product_team.py b/src/layers/domain/fhir_translation/tests/test_fhir_product_team.py deleted file mode 100644 index 2bcbccce..00000000 --- a/src/layers/domain/fhir_translation/tests/test_fhir_product_team.py +++ /dev/null @@ -1,26 +0,0 @@ -from domain.core.product_team.v3 import ProductTeam -from domain.fhir.r4.cpm_model import Organization as ProductTeamOrganization -from domain.fhir_translation.product_team import create_fhir_model_from_product_team - -from test_helpers.sample_data import CPM_PRODUCT_TEAM_NO_ID - - -def test_product_team_translation(): - """ - Tests that 'non FHIR ProductTeam' - is the compliment of 'create_fhir_model_from_product_team' - """ - product_team = ProductTeam( - name=CPM_PRODUCT_TEAM_NO_ID["name"], - ods_code=CPM_PRODUCT_TEAM_NO_ID["ods_code"], - keys=CPM_PRODUCT_TEAM_NO_ID["keys"], - ) - assert isinstance(product_team, ProductTeam) - - fhir_org = create_fhir_model_from_product_team(product_team=product_team) - assert isinstance(fhir_org, ProductTeamOrganization) - - org = fhir_org.dict() - assert CPM_PRODUCT_TEAM_NO_ID["ods_code"] in org["identifier"][0]["value"] - assert org["partOf"]["identifier"]["value"] == CPM_PRODUCT_TEAM_NO_ID["ods_code"] - assert org["name"] == CPM_PRODUCT_TEAM_NO_ID["name"] From 775efc498e795fa967eeacff62c01f75588e0b72 Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Tue, 15 Oct 2024 11:31:28 +0100 Subject: [PATCH 13/38] Remove Organization --- src/api/readProductTeam/src/v1/steps.py | 1 + src/api/readProductTeam/tests/test_index.py | 50 +++++++++---------- .../createProductTeam.success.feature | 17 ++++--- .../features/readProductTeam.failure.feature | 2 +- .../features/readProductTeam.success.feature | 21 ++++---- src/layers/domain/fhir/r4/__init__.py | 2 - 6 files changed, 47 insertions(+), 46 deletions(-) diff --git a/src/api/readProductTeam/src/v1/steps.py b/src/api/readProductTeam/src/v1/steps.py index 29d196d7..ebe59be4 100644 --- a/src/api/readProductTeam/src/v1/steps.py +++ b/src/api/readProductTeam/src/v1/steps.py @@ -4,6 +4,7 @@ from domain.core.product_team.v3 import ProductTeam from domain.repository.product_team_repository.v2 import ProductTeamRepository from domain.request_models.v1 import ProductTeamPathParams +from domain.response.validation_errors import mark_validation_errors_as_inbound from event.step_chain import StepChain diff --git a/src/api/readProductTeam/tests/test_index.py b/src/api/readProductTeam/tests/test_index.py index 46be1140..1a00ab15 100644 --- a/src/api/readProductTeam/tests/test_index.py +++ b/src/api/readProductTeam/tests/test_index.py @@ -3,12 +3,13 @@ from unittest import mock import pytest -from domain.core.root import Root -from domain.repository.product_team_repository.v1 import ProductTeamRepository +from domain.core.root.v3 import Root +from domain.repository.product_team_repository.v2 import ProductTeamRepository +from event.json import json_loads from test_helpers.dynamodb import mock_table from test_helpers.response_assertions import _response_assertions -from test_helpers.uuid import consistent_uuid +from test_helpers.sample_data import CPM_PRODUCT_TEAM_NO_ID TABLE_NAME = "hiya" @@ -20,9 +21,10 @@ ], ) def test_index(version): - product_team_id = consistent_uuid(seed=1) - org = Root.create_ods_organisation(ods_code="ABC") - product_team = org.create_product_team(id=product_team_id, name="product-team-name") + org = Root.create_ods_organisation(ods_code=CPM_PRODUCT_TEAM_NO_ID["ods_code"]) + product_team = org.create_product_team( + name=CPM_PRODUCT_TEAM_NO_ID["name"], keys=CPM_PRODUCT_TEAM_NO_ID["keys"] + ) with mock_table(TABLE_NAME) as client, mock.patch.dict( os.environ, @@ -44,26 +46,20 @@ def test_index(version): result = handler( event={ "headers": {"version": version}, - "pathParameters": {"id": product_team_id}, + "pathParameters": {"product_team_id": product_team.id}, } ) - + result_body = json_loads(result["body"]) expected_result = json.dumps( { - "resourceType": "Organization", - "identifier": [ - { - "system": "connecting-party-manager/product-team-id", - "value": product_team_id, - } - ], - "name": "product-team-name", - "partOf": { - "identifier": { - "system": "https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations", - "value": "ABC", - } - }, + "id": result_body["id"], + "name": "FOOBAR Product Team", + "ods_code": "F5H1R", + "status": "active", + "created_on": result_body["created_on"], + "updated_on": None, + "deleted_on": None, + "keys": [{"key_type": "product_team_id_alias", "key_value": "BAR"}], } ) @@ -89,10 +85,10 @@ def test_index(version): ], ) def test_index_no_such_product_team(version): - product_team_id = consistent_uuid(seed=1) - - org = Root.create_ods_organisation(ods_code="ABC") - product_team = org.create_product_team(id=product_team_id, name="product-team-name") + org = Root.create_ods_organisation(ods_code=CPM_PRODUCT_TEAM_NO_ID["ods_code"]) + product_team = org.create_product_team( + name=CPM_PRODUCT_TEAM_NO_ID["name"], keys=CPM_PRODUCT_TEAM_NO_ID["keys"] + ) with mock_table(TABLE_NAME) as client, mock.patch.dict( os.environ, @@ -114,7 +110,7 @@ def test_index_no_such_product_team(version): result = handler( event={ "headers": {"version": version}, - "pathParameters": {"id": "123"}, + "pathParameters": {"product_team_id": "123"}, } ) diff --git a/src/api/tests/feature_tests/features/createProductTeam.success.feature b/src/api/tests/feature_tests/features/createProductTeam.success.feature index 0f9ae009..0491fbb1 100644 --- a/src/api/tests/feature_tests/features/createProductTeam.success.feature +++ b/src/api/tests/feature_tests/features/createProductTeam.success.feature @@ -32,13 +32,16 @@ Feature: Create Product Team - success scenarios Given I note the response field "$.id" as "product_team_id" When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }" Then I receive a status code "200" with body - | path | value | - | resourceType | Organization | - | identifier.0.system | connecting-party-manager/product-team-id | - | identifier.0.value | ${ note(product_team_id) } | - | name | My Great Product Team | - | partOf.identifier.system | https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations | - | partOf.identifier.value | F5H1R | + | path | value | + | id | ${ note(product_team_id) } | + | name | My Great Product Team | + | ods_code | F5H1R | + | status | active | + | created_on | << ignore >> | + | updated_on | << ignore >> | + | deleted_on | << ignore >> | + | keys.0.key_type | product_team_id_alias | + | keys.0.key_value | FOOBAR | Scenario: Successfully create a ProductTeam with duplicated keys When I make a "POST" request with "default" headers to "ProductTeam" with body: diff --git a/src/api/tests/feature_tests/features/readProductTeam.failure.feature b/src/api/tests/feature_tests/features/readProductTeam.failure.feature index fb668a32..d561a1cb 100644 --- a/src/api/tests/feature_tests/features/readProductTeam.failure.feature +++ b/src/api/tests/feature_tests/features/readProductTeam.failure.feature @@ -1,5 +1,5 @@ Feature: Read Product Team - failure scenarios - These scenarios demonstrate failures from the GET Organization (i.e. Product Team) endpoint + These scenarios demonstrate failures from the GET Product Team endpoint Background: Given "default" request headers: diff --git a/src/api/tests/feature_tests/features/readProductTeam.success.feature b/src/api/tests/feature_tests/features/readProductTeam.success.feature index 26102937..0fbab2a5 100644 --- a/src/api/tests/feature_tests/features/readProductTeam.success.feature +++ b/src/api/tests/feature_tests/features/readProductTeam.success.feature @@ -1,5 +1,5 @@ Feature: Read Product Team - success scenarios - These scenarios demonstrate successful reads from the GET Organization (i.e. Product Team) endpoint + These scenarios demonstrate successful reads from the GET Product Team endpoint Background: Given "default" request headers: @@ -17,14 +17,17 @@ Feature: Read Product Team - success scenarios Given I note the response field "$.id" as "product_team_id" When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }" Then I receive a status code "200" with body - | path | value | - | resourceType | Organization | - | identifier.0.system | connecting-party-manager/product-team-id | - | identifier.0.value | ${ note(product_team_id) } | - | name | My Great Product Team | - | partOf.identifier.system | https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations | - | partOf.identifier.value | F5H1R | + | path | value | + | id | ${ note(product_team_id) } | + | name | My Great Product Team | + | ods_code | F5H1R | + | status | active | + | created_on | << ignore >> | + | updated_on | << ignore >> | + | deleted_on | << ignore >> | + | keys.0.key_type | product_team_id_alias | + | keys.0.key_value | FOOBAR | And the response headers contain: | name | value | | Content-Type | application/json | - | Content-Length | 314 | + | Content-Length | 288 | diff --git a/src/layers/domain/fhir/r4/__init__.py b/src/layers/domain/fhir/r4/__init__.py index 47c25535..b54f13eb 100644 --- a/src/layers/domain/fhir/r4/__init__.py +++ b/src/layers/domain/fhir/r4/__init__.py @@ -6,7 +6,5 @@ Meta, OperationOutcome, OperationOutcomeIssue, - Organization, ) from .strict_models import Device as StrictDevice # noqa: F401 -from .strict_models import Organization as StrictOrganization # noqa: F401 From 305d14573b58f47fd1bed3dd242a81b2dad2df78 Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Tue, 15 Oct 2024 11:57:57 +0100 Subject: [PATCH 14/38] Update Paths --- infrastructure/swagger/05_paths.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure/swagger/05_paths.yaml b/infrastructure/swagger/05_paths.yaml index 5839f527..11abcd93 100644 --- a/infrastructure/swagger/05_paths.yaml +++ b/infrastructure/swagger/05_paths.yaml @@ -131,7 +131,7 @@ paths: - *RequestHeaderCorrelationId responses: "200": - description: Read Product operation successful + description: Read Product Team operation successful content: application/fhir+json: schema: From 64e660c32e1f1cd995e6f8f03b25b53339c20390 Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Tue, 15 Oct 2024 13:33:20 +0100 Subject: [PATCH 15/38] Add check for id alias --- src/api/readProductTeam/tests/test_index.py | 73 ++++++++++++++++--- .../createProductTeam.success.feature | 20 ++--- .../repository/product_team_repository/v2.py | 7 +- 3 files changed, 80 insertions(+), 20 deletions(-) diff --git a/src/api/readProductTeam/tests/test_index.py b/src/api/readProductTeam/tests/test_index.py index 1a00ab15..0f851a95 100644 --- a/src/api/readProductTeam/tests/test_index.py +++ b/src/api/readProductTeam/tests/test_index.py @@ -10,6 +10,7 @@ from test_helpers.dynamodb import mock_table from test_helpers.response_assertions import _response_assertions from test_helpers.sample_data import CPM_PRODUCT_TEAM_NO_ID +from test_helpers.uuid import consistent_uuid TABLE_NAME = "hiya" @@ -78,13 +79,63 @@ def test_index(version): ) +@pytest.mark.parametrize( + "version, product_id", + [("1", "123"), ("1", f"F5H1R.{consistent_uuid(1)}")], +) +def test_index_no_such_product_team(version, product_id): + with mock_table(TABLE_NAME) as client, mock.patch.dict( + os.environ, + { + "DYNAMODB_TABLE": TABLE_NAME, + "AWS_DEFAULT_REGION": "eu-west-2", + }, + clear=True, + ): + from api.readProductTeam.index import cache, handler + + cache["DYNAMODB_CLIENT"] = client + + result = handler( + event={ + "headers": {"version": version}, + "pathParameters": {"product_team_id": product_id}, + } + ) + + expected_result = json.dumps( + { + "errors": [ + { + "code": "RESOURCE_NOT_FOUND", + "message": f"Could not find ProductTeam for key ('{product_id}')", + } + ], + } + ) + + expected = { + "statusCode": 404, + "body": expected_result, + "headers": { + "Content-Length": str(len(expected_result)), + "Content-Type": "application/json", + "Version": version, + "Location": None, + }, + } + _response_assertions( + result=result, expected=expected, check_body=True, check_content_length=True + ) + + @pytest.mark.parametrize( "version", [ "1", ], ) -def test_index_no_such_product_team(version): +def test_index_by_alias(version): org = Root.create_ods_organisation(ods_code=CPM_PRODUCT_TEAM_NO_ID["ods_code"]) product_team = org.create_product_team( name=CPM_PRODUCT_TEAM_NO_ID["name"], keys=CPM_PRODUCT_TEAM_NO_ID["keys"] @@ -110,23 +161,25 @@ def test_index_no_such_product_team(version): result = handler( event={ "headers": {"version": version}, - "pathParameters": {"product_team_id": "123"}, + "pathParameters": {"product_team_id": "BAR"}, } ) - + result_body = json_loads(result["body"]) expected_result = json.dumps( { - "errors": [ - { - "code": "RESOURCE_NOT_FOUND", - "message": "Could not find ProductTeam for key ('123')", - } - ], + "id": result_body["id"], + "name": "FOOBAR Product Team", + "ods_code": "F5H1R", + "status": "active", + "created_on": result_body["created_on"], + "updated_on": None, + "deleted_on": None, + "keys": [{"key_type": "product_team_id_alias", "key_value": "BAR"}], } ) expected = { - "statusCode": 404, + "statusCode": 200, "body": expected_result, "headers": { "Content-Length": str(len(expected_result)), diff --git a/src/api/tests/feature_tests/features/createProductTeam.success.feature b/src/api/tests/feature_tests/features/createProductTeam.success.feature index 0491fbb1..bd25a4e1 100644 --- a/src/api/tests/feature_tests/features/createProductTeam.success.feature +++ b/src/api/tests/feature_tests/features/createProductTeam.success.feature @@ -103,12 +103,14 @@ Feature: Create Product Team - success scenarios | Content-Type | application/json | | Content-Length | 288 | When I make a "GET" request with "default" headers to "ProductTeam/FOOBAR" - -# Then I receive a status code "200" with body -# | path | value | -# | resourceType | Organization | -# | identifier.0.system | connecting-party-manager/product-team-id | -# | identifier.0.value | ${ note(product_team_id) } | -# | name | My Great Product Team | -# | partOf.identifier.system | https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations | -# | partOf.identifier.value | F5H1R | + Then I receive a status code "200" with body + | path | value | + | id | << ignore >> | + | name | My Great Product Team | + | ods_code | F5H1R | + | status | active | + | created_on | << ignore >> | + | updated_on | << ignore >> | + | deleted_on | << ignore >> | + | keys.0.key_type | product_team_id_alias | + | keys.0.key_value | FOOBAR | diff --git a/src/layers/domain/repository/product_team_repository/v2.py b/src/layers/domain/repository/product_team_repository/v2.py index 17bee136..355be1e3 100644 --- a/src/layers/domain/repository/product_team_repository/v2.py +++ b/src/layers/domain/repository/product_team_repository/v2.py @@ -1,4 +1,5 @@ from attr import asdict +from domain.core.cpm_system_id.v1 import ProductTeamId from domain.core.product_team.v3 import ProductTeam, ProductTeamCreatedEvent from domain.core.product_team_key import ProductTeamKey from domain.repository.errors import ItemNotFound @@ -72,7 +73,11 @@ def handle_ProductTeamCreatedEvent(self, event: ProductTeamCreatedEvent): return [create_transaction] + transactions def read(self, id) -> ProductTeam: - pk = TableKey.PRODUCT_TEAM.key(id) + pk = ( + TableKey.PRODUCT_TEAM.key(id) + if ProductTeamId.validate_cpm_system_id(id) + else TableKey.PRODUCT_TEAM_KEY.key(f"ProductTeamIdAlias#{id}") + ) args = { "TableName": self.table_name, "KeyConditionExpression": "pk = :pk AND sk = :sk", From aac1f6688b17734dfcfb68688409961294768c0d Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Tue, 15 Oct 2024 15:33:03 +0100 Subject: [PATCH 16/38] swagger responses --- docs/public_swagger/swagger.yaml | 357 ++++-------------- infrastructure/swagger/05_paths.yaml | 33 +- .../swagger/11_components--requestBodies.yaml | 38 ++ .../swagger/12_components--responses.yaml | 41 ++ 4 files changed, 160 insertions(+), 309 deletions(-) diff --git a/docs/public_swagger/swagger.yaml b/docs/public_swagger/swagger.yaml index d17a6cd8..848ff42e 100644 --- a/docs/public_swagger/swagger.yaml +++ b/docs/public_swagger/swagger.yaml @@ -256,55 +256,15 @@ paths: application/fhir+json: schema: $ref: "#/components/schemas/OperationOutcome" - /Organization/{id}: - get: - summary: Read an Organization resource - operationId: readOrganization - parameters: - - name: id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Read Organization operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Organization" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" /ProductTeam: post: operationId: createproductteam summary: createProductTeam endpoint for APIGEE integration requestBody: - $ref: "#/components/requestBodies/Organization" + $ref: "#/components/requestBodies/ProductTeamRequest" responses: "201": - description: Create operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" + $ref: "#/components/responses/ProductTeamResponse" "4XX": description: "Client Error" content: @@ -355,11 +315,7 @@ paths: $ref: "#/components/schemas/CorrelationId" responses: "200": - description: Read Product Team operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Organization" + $ref: "#/components/responses/ProductTeamResponse" "4XX": description: "Client Error" content: @@ -747,12 +703,42 @@ components: schema: $ref: "#/components/schemas/Device" required: true - Organization: + ProductTeamRequest: + description: Request body to create a Product Team + required: true content: - application/fhir+json: + application/json: schema: - $ref: "#/components/schemas/Organization" - required: true + type: object + properties: + name: + type: string + description: Name of the product team + ods_code: + type: string + description: ODS code associated with the product team + keys: + type: array + description: List of keys associated with the product team + items: + type: object + properties: + key_type: + type: string + description: The type of the key (e.g., product_team_id_alias) + key_value: + type: string + description: The value of the key + required: + - name + - ods_code + - keys + example: + name: "Sample Product Team" + ods_code: "F5H1R" + keys: + - key_type: "product_team_id_alias" + key_value: "BAR" schemas: Resource: type: object @@ -2769,233 +2755,6 @@ components: description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). required: - url - Organization: - allOf: - - $ref: "#/components/schemas/DomainResource" - - type: object - properties: - identifier: - type: array - items: - $ref: "#/components/schemas/Identifier" - description: Identifier for the organization that is used to identify the organization across multiple disparate systems. - active: - type: boolean - description: Whether the organization's record is still in active use. - type: - type: array - items: - $ref: "#/components/schemas/CodeableConcept" - description: The kind(s) of organization that this is. - name: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A name associated with the organization. - alias: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A list of alternate names that the organization is known as, or was known as in the past. - telecom: - type: array - items: - $ref: "#/components/schemas/ContactPoint" - description: A contact detail for the organization. - address: - type: array - items: - $ref: "#/components/schemas/Address" - description: An address for the organization. - partOf: - $ref: "#/components/schemas/Reference" - description: The organization of which this organization forms a part. - contact: - type: array - items: - $ref: "#/components/schemas/OrganizationContact" - description: Contact for the organization for a certain purpose. - endpoint: - type: array - items: - $ref: "#/components/schemas/Reference" - description: Technical endpoints providing access to services operated for the organization. - example: - resourceType: Organization - meta: - versionId: MkhCKF3NPs - lastUpdated: "2020-11-04T11:22:55.495627-05:00" - source: zrGPPE8DJH - profile: - - z3pU0zspXr - security: - - system: oC2Jc7y4Zf - version: EQHqJLdyML - code: zBvY_yWgVY - display: GsL8gnlzvu - userSelected: true - tag: - - system: aNNTmndRB8 - version: E7tloLtD33 - code: kMOXjB2zxk - display: 9ugg6ChWzh - userSelected: true - - code: ibm/complete-mock - implicitRules: 011v9tCoKf - language: en-US - text: - status: additional - div:
- identifier: - - use: old - type: - coding: - - system: 1SUEu2dRCO - version: SqWkXr_J9k - code: 9aTcdpFSZ8 - display: weo1p1jIrt - userSelected: true - text: b_lOMGm6ta - system: XxeSGme8g0 - value: EVVScECcrs - period: - start: "2020-11-04T11:22:55.498156-05:00" - end: "2020-11-04T11:22:55.498323-05:00" - active: true - type: - - coding: - - system: GJz7DeJAID - version: SoNWcpaGaO - code: VqNBaGgdd8 - display: D_01X4Yhro - userSelected: true - text: _da3dnjC1g - name: _Yghclpf6e - alias: - - v6TGkG3UzA - telecom: - - system: fax - value: XUXar8gIJw - use: old - rank: 6.04214668e+08 - period: - start: "2020-11-04T11:22:55.500697-05:00" - end: "2020-11-04T11:22:55.500991-05:00" - address: - - use: billing - type: postal - text: KRPWrCLw0J - line: - - Y0UGna670q - city: T9ymhEJMWe - district: CsINuTto0Y - state: _5_y00xVnB - postalCode: JPMLnjxKN8 - country: 1xSh_aRALw - period: - start: "2020-11-04T11:22:55.503025-05:00" - end: "2020-11-04T11:22:55.503358-05:00" - partOf: - reference: Organization/sBzEw2QIM9 - type: Organization - identifier: - use: official - type: - coding: - - system: 3lk1UxUrO1 - version: gxRtW6o8rV - code: N1PckpnwPx - display: ZWYPZB4ypF - userSelected: true - text: wGMie0kDM0 - system: 4Acfpp1Qus - value: sTkfzvUNRc - period: - start: "2020-11-04T11:22:55.505211-05:00" - end: "2020-11-04T11:22:55.505435-05:00" - display: fi35hwOFFC - contact: - - purpose: - coding: - - system: gXJWNpvPYH - version: ixSX6ZizQU - code: iYvO1m8ZdT - display: 7xT105543A - userSelected: true - text: xka69Q61Dz - name: - use: usual - text: DfxDNX8On5 - family: ozZugaAElu - given: - - v_ww8YMzVs - prefix: - - _hBm2j1wTY - suffix: - - DgzwLOgfj_ - period: - start: "2020-11-04T11:22:55.507967-05:00" - end: "2020-11-04T11:22:55.508327-05:00" - telecom: - - system: email - value: HE9t3cWC8v - use: work - rank: 1.386494584e+09 - period: - start: "2020-11-04T11:22:55.508975-05:00" - end: "2020-11-04T11:22:55.50928-05:00" - address: - use: billing - type: both - text: hy6FvAwKUf - line: - - y8f7C2_rKu - city: PAj0k3xx6m - district: ETBhWSq3V3 - state: 78AvjHfIfy - postalCode: 3NGE0wSbNy - country: PT_vsjai4f - period: - start: "2020-11-04T11:22:55.510249-05:00" - end: "2020-11-04T11:22:55.510429-05:00" - endpoint: - - reference: Endpoint/IQlLQrnkp9 - type: Endpoint - identifier: - use: secondary - type: - coding: - - system: bflJysEUwb - version: wXmVSZF3xN - code: uLMS2MG468 - display: 7iCeHMVBnr - userSelected: true - text: vkMjQ4BX4w - system: h5wLHJqvsB - value: 1GAC_uwdo4 - period: - start: "2020-11-04T11:22:55.511516-05:00" - end: "2020-11-04T11:22:55.511804-05:00" - display: pcy6U9Fxm0 - OrganizationContact: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - purpose: - $ref: "#/components/schemas/CodeableConcept" - description: Indicates a purpose for which the contact can be reached. - name: - $ref: "#/components/schemas/HumanName" - description: A name associated with the contact. - telecom: - type: array - items: - $ref: "#/components/schemas/ContactPoint" - description: A contact detail (e.g. a telephone number or an email address) by which the party may be contacted. - address: - $ref: "#/components/schemas/Address" - description: Visiting or postal addresses for the contact. Version: type: string pattern: "^[1-9][0-9]+$" @@ -3009,4 +2768,44 @@ components: securitySchemes: app-level0: $ref: https://proxygen.prod.api.platform.nhs.uk/components/securitySchemes/app-level0 - responses: {} + responses: + ProductTeamResponse: + description: Read Product Team operation successful + content: + application/json: + schema: + type: object + properties: + id: + type: string + name: + type: string + ods_code: + type: string + status: + type: string + created_on: + type: string + updated_on: + type: string + deleted_on: + type: string + keys: + type: array + items: + type: object + properties: + key_type: + type: string + key_value: + type: string + example: + id: "F5H1R" + name: "Sample Product Team" + ods_code: "F5H1R" + status: "active" + created_on: "2024-10-15T10:00:00Z" + updated_on: "2024-10-15T10:00:00Z" + keys: + - key_type: "product_team_id_alias" + key_value: "FOOBAR" diff --git a/infrastructure/swagger/05_paths.yaml b/infrastructure/swagger/05_paths.yaml index 11abcd93..9524dfc1 100644 --- a/infrastructure/swagger/05_paths.yaml +++ b/infrastructure/swagger/05_paths.yaml @@ -72,33 +72,10 @@ paths: operationId: createproductteam summary: createProductTeam endpoint for APIGEE integration requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - name: - type: string - description: Name of the product team - ods_code: - type: string - description: ODS code associated with the product team - keys: - type: array - description: List of keys associated with the product team - items: - type: object - properties: - key_type: - type: string - description: The type of the key (e.g., product_team_id_alias) - key_value: - type: string - description: The value of the key + $ref: "#/components/requestBodies/ProductTeamRequest" responses: "201": - <<: *Response201 + $ref: "#/components/responses/ProductTeamResponse" "4XX": <<: *Response4XX <<: *RequestHeaders @@ -131,11 +108,7 @@ paths: - *RequestHeaderCorrelationId responses: "200": - description: Read Product Team operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Bundle" + $ref: "#/components/responses/ProductTeamResponse" "4XX": <<: *Response4XX x-amazon-apigateway-integration: diff --git a/infrastructure/swagger/11_components--requestBodies.yaml b/infrastructure/swagger/11_components--requestBodies.yaml index ed97d539..29e61f0e 100644 --- a/infrastructure/swagger/11_components--requestBodies.yaml +++ b/infrastructure/swagger/11_components--requestBodies.yaml @@ -1 +1,39 @@ --- +components: + requestBodies: + ProductTeamRequest: + description: Request body to create a Product Team + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: Name of the product team + ods_code: + type: string + description: ODS code associated with the product team + keys: + type: array + description: List of keys associated with the product team + items: + type: object + properties: + key_type: + type: string + description: The type of the key (e.g., product_team_id_alias) + key_value: + type: string + description: The value of the key + required: + - name + - ods_code + - keys + example: + name: "Sample Product Team" + ods_code: "F5H1R" + keys: + - key_type: "product_team_id_alias" + key_value: "BAR" diff --git a/infrastructure/swagger/12_components--responses.yaml b/infrastructure/swagger/12_components--responses.yaml index 80600a86..636f173e 100644 --- a/infrastructure/swagger/12_components--responses.yaml +++ b/infrastructure/swagger/12_components--responses.yaml @@ -24,3 +24,44 @@ components: enum: ["OK"] headers: <<: *ResponseHeaders + ProductTeamResponse: + description: Read Product Team operation successful + content: + application/json: + schema: + type: object + properties: + id: + type: string + name: + type: string + ods_code: + type: string + status: + type: string + created_on: + type: string + updated_on: + type: string + deleted_on: + type: string + keys: + type: array + items: + type: object + properties: + key_type: + type: string + key_value: + type: string + example: + id: "F5H1R" + name: "Sample Product Team" + ods_code: "F5H1R" + status: "active" + created_on: "2024-10-15T10:00:00Z" + updated_on: "2024-10-15T10:00:00Z" + deleted_on: "null" + keys: + - key_type: "product_team_id_alias" + key_value: "FOOBAR" From 993a1ff54da5335a996e0d347ea6e8cd3720c289 Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Tue, 15 Oct 2024 16:14:11 +0100 Subject: [PATCH 17/38] remove endpoint mapping --- .../feature_tests/steps/endpoint_lambda_mapping.py | 1 - .../steps/tests/test_endpoint_lambda_mapping.py | 13 ------------- 2 files changed, 14 deletions(-) diff --git a/src/api/tests/feature_tests/steps/endpoint_lambda_mapping.py b/src/api/tests/feature_tests/steps/endpoint_lambda_mapping.py index 70bbff34..fdb9b413 100644 --- a/src/api/tests/feature_tests/steps/endpoint_lambda_mapping.py +++ b/src/api/tests/feature_tests/steps/endpoint_lambda_mapping.py @@ -48,7 +48,6 @@ def get_endpoint_lambda_mapping() -> ENDPOINT_LAMBDA_MAPPING: "Device?device_type={device_type}": api.searchDevice.index, "Device?device_type={device_type}&foo={foo}": api.searchDevice.index, "Device?foo={foo}": api.searchDevice.index, - # "Organization/{id}": api.readProductTeam.index, "_status": api.status.index, }, "DELETE": { diff --git a/src/api/tests/feature_tests/steps/tests/test_endpoint_lambda_mapping.py b/src/api/tests/feature_tests/steps/tests/test_endpoint_lambda_mapping.py index 152687e5..a7d23b44 100644 --- a/src/api/tests/feature_tests/steps/tests/test_endpoint_lambda_mapping.py +++ b/src/api/tests/feature_tests/steps/tests/test_endpoint_lambda_mapping.py @@ -152,19 +152,6 @@ def test_parse_path_search_product(): ) == ({"product_team_id": "123"}, {}, api.searchCpmProduct.index) -def test_parse_path_search_product(): - with api_lambda_environment_variables(): - import api.searchCpmProduct.index - - endpoint_lambda_mapping = get_endpoint_lambda_mapping() - - assert parse_api_path( - method="GET", - path="ProductTeam/123/Product", - endpoint_lambda_mapping=endpoint_lambda_mapping, - ) == ({"product_team_id": "123"}, {}, api.searchCpmProduct.index) - - def test_parse_path_error(): with pytest.raises(EndpointConfigurationError): parse_api_path(method="GET", path="ProductTeam/123", endpoint_lambda_mapping={}) From 02831169f6d6aa57b32d0ddb6d192a0a4dcf1bee Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Tue, 15 Oct 2024 16:31:30 +0100 Subject: [PATCH 18/38] Remove gevent --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index dd389f74..2856bf14 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,6 @@ boto3-stubs = { extras = [ ], version = "^1.34.37" } pytest-timeout = "^2.2.0" lz4 = "^4.3.3" -gevent = "<24.10.2" [tool.poetry.group.local] optional = true From 75bad6f5e1b9c5882d29de81ed0fa336d91907bf Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Wed, 16 Oct 2024 16:11:38 +0100 Subject: [PATCH 19/38] [release/2024-10-16] update changelog --- CHANGELOG.md | 1 + changelog/2024-10-16.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8eaa4591..6cc04d70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - [PI-501] Create Device Reference Data - [PI-503] Read Device Reference Data - [PI-536] Create Cpm Product without FHIR +- [PI-535] Read Product Team without FHIR ## 2024-10-15 - [PI-533] Create Product Team without FHIR diff --git a/changelog/2024-10-16.md b/changelog/2024-10-16.md index 06d713ae..fdd61c36 100644 --- a/changelog/2024-10-16.md +++ b/changelog/2024-10-16.md @@ -1,3 +1,4 @@ - [PI-501] Create Device Reference Data - [PI-503] Read Device Reference Data - [PI-536] Create Cpm Product without FHIR +- [PI-535] Read Product Team without FHIR From 419145cc0d5c532f8ad95816133276368ffea803 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Thu, 17 Oct 2024 10:20:40 +0100 Subject: [PATCH 20/38] [release/2024-10-16] fix-forward: merge conflict --- .../features/createProductTeam.success.feature | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/api/tests/feature_tests/features/createProductTeam.success.feature b/src/api/tests/feature_tests/features/createProductTeam.success.feature index bd25a4e1..e8a59b3d 100644 --- a/src/api/tests/feature_tests/features/createProductTeam.success.feature +++ b/src/api/tests/feature_tests/features/createProductTeam.success.feature @@ -72,13 +72,16 @@ Feature: Create Product Team - success scenarios Given I note the response field "$.id" as "product_team_id" When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }" Then I receive a status code "200" with body - | path | value | - | resourceType | Organization | - | identifier.0.system | connecting-party-manager/product-team-id | - | identifier.0.value | ${ note(product_team_id) } | - | name | My Great Product Team | - | partOf.identifier.system | https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations | - | partOf.identifier.value | F5H1R | + | path | value | + | id | ${ note(product_team_id) } | + | name | My Great Product Team | + | ods_code | F5H1R | + | keys.0.key_type | product_team_id_alias | + | keys.0.key_value | FOOBAR | + | status | active | + | created_on | << ignore >> | + | updated_on | << ignore >> | + | deleted_on | << ignore >> | Scenario: Successfully create a ProductTeam and view by alias When I make a "POST" request with "default" headers to "ProductTeam" with body: From 709a190f4372ad10be04484c9c5c7a4f7ab590d3 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Thu, 17 Oct 2024 13:43:39 +0100 Subject: [PATCH 21/38] [release/2024-10-16] fix-forward: lambda name length --- infrastructure/terraform/per_workspace/main.tf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/infrastructure/terraform/per_workspace/main.tf b/infrastructure/terraform/per_workspace/main.tf index 2e3bcf99..be7a3c51 100644 --- a/infrastructure/terraform/per_workspace/main.tf +++ b/infrastructure/terraform/per_workspace/main.tf @@ -70,7 +70,7 @@ module "layers" { source = "./modules/api_worker/api_layer" name = each.key python_version = var.python_version - layer_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--${replace(each.key, "_", "-")}-lambda-layer" + layer_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--${replace(each.key, "_", "-")}" source_path = "${path.module}/../../../src/layers/${each.key}/dist/${each.key}.zip" } @@ -79,7 +79,7 @@ module "third_party_layers" { source = "./modules/api_worker/api_layer" name = each.key python_version = var.python_version - layer_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--${replace(each.key, "_", "-")}-lambda-layer" + layer_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--${replace(each.key, "_", "-")}" source_path = "${path.module}/../../../src/layers/third_party/dist/${each.key}.zip" } @@ -88,7 +88,7 @@ module "lambdas" { source = "./modules/api_worker/api_lambda" python_version = var.python_version name = each.key - lambda_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--${replace(each.key, "_", "-")}-lambda" + lambda_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--${replace(replace(each.key, "_", "-"), "DeviceReferenceData", "DeviceRefData")}" //Compact will remove all nulls from the list and create a new one - this is because TF throws an error if there is a null item in the list. layers = concat( compact([for instance in module.layers : contains(var.api_lambda_layers, instance.name) ? instance.layer_arn : null]), @@ -119,7 +119,7 @@ module "authoriser" { name = "authoriser" source = "./modules/api_worker/api_lambda" python_version = var.python_version - lambda_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--authoriser-lambda" + lambda_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--authoriser" source_path = "${path.module}/../../../src/api/authoriser/dist/authoriser.zip" environment_variables = { ENVIRONMENT = var.environment @@ -145,7 +145,7 @@ module "authoriser" { { "Action": "lambda:InvokeFunction", "Effect": "Allow", - "Resource": "arn:aws:lambda:eu-west-2:${var.assume_account}:function:${local.project}--${replace(terraform.workspace, "_", "-")}--authoriser-lambda" + "Resource": "arn:aws:lambda:eu-west-2:${var.assume_account}:function:${local.project}--${replace(terraform.workspace, "_", "-")}--authoriser" }, { "Action": "secretsmanager:GetSecretValue", From 6d9154fbe52579b60dc36c0bac65ed4f356d4f46 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Thu, 17 Oct 2024 14:16:19 +0100 Subject: [PATCH 22/38] [release/2024-10-16] fix-forward: update swagger --- infrastructure/swagger/05_paths.yaml | 39 +++++++++++++++++++ .../swagger/12_components--responses.yaml | 25 ++++++++++++ .../api_entrypoint/api_gateway/locals.tf | 2 +- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/infrastructure/swagger/05_paths.yaml b/infrastructure/swagger/05_paths.yaml index 0292c1b2..b9e06c2f 100644 --- a/infrastructure/swagger/05_paths.yaml +++ b/infrastructure/swagger/05_paths.yaml @@ -384,6 +384,45 @@ paths: - ${authoriser_name}: [] - app-level0: [] + ? /ProductTeam/{product_team_id}/Product/{product_id}/DeviceReferenceData/{device_reference_data_id} + : get: + operationId: readDeviceReferenceData + summary: readDeviceReferenceData endpoint for APIGEE integration + parameters: + - name: product_team_id + in: path + required: true + description: logical identifier + schema: + type: string + - name: product_id + in: path + required: true + description: logical identifier + schema: + type: string + - name: device_reference_data_id + in: path + required: true + description: logical identifier + schema: + type: string + - *RequestHeaderVersion + - *RequestHeaderRequestId + - *RequestHeaderCorrelationId + responses: + responses: + "200": + $ref: "#/components/responses/DeviceReferenceDataResponse" + "4XX": + <<: *Response4XX + x-amazon-apigateway-integration: + <<: *ApiGatewayIntegration + uri: ${method_readDeviceReferenceData} + security: + - ${authoriser_name}: [] + - app-level0: [] + /Device/{id}: get: parameters: diff --git a/infrastructure/swagger/12_components--responses.yaml b/infrastructure/swagger/12_components--responses.yaml index 636f173e..a30ec1bd 100644 --- a/infrastructure/swagger/12_components--responses.yaml +++ b/infrastructure/swagger/12_components--responses.yaml @@ -65,3 +65,28 @@ components: keys: - key_type: "product_team_id_alias" key_value: "FOOBAR" + DeviceReferenceDataResponse: + description: Read Device Reference Data operation successful + content: + application/json: + schema: + type: object + properties: + id: + type: string + name: + type: string + product_id: + type: string + product_team_id: + type: string + ods_code: + type: string + status: + type: string + created_on: + type: string + updated_on: + type: string + deleted_on: + type: string diff --git a/infrastructure/terraform/per_workspace/modules/api_entrypoint/api_gateway/locals.tf b/infrastructure/terraform/per_workspace/modules/api_entrypoint/api_gateway/locals.tf index ca60b667..b2ec8be3 100644 --- a/infrastructure/terraform/per_workspace/modules/api_entrypoint/api_gateway/locals.tf +++ b/infrastructure/terraform/per_workspace/modules/api_entrypoint/api_gateway/locals.tf @@ -5,7 +5,7 @@ locals { } methods = [ for lambda_alias in setsubtract(var.lambdas, ["authoriser"]) : - { "method_${lambda_alias}" = "${local.apigateway_lambda_arn_prefix}:${var.assume_account}:function:${var.project}--${replace(terraform.workspace, "_", "-")}--${replace(lambda_alias, "_", "-")}-lambda/invocations" } + { "method_${lambda_alias}" = "${local.apigateway_lambda_arn_prefix}:${var.assume_account}:function:${var.project}--${replace(terraform.workspace, "_", "-")}--${replace(replace(lambda_alias, "_", "-"), "DeviceReferenceData", "DeviceRefData")}/invocations" } ] swagger_file = templatefile("${path.root}/../../swagger/dist/aws/swagger.yaml", merge({ lambda_invoke_arn = var.authoriser_metadata.lambda_invoke_arn, From e2ba793cb020fa228316c6b54bbdedf36792d8f5 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Thu, 17 Oct 2024 15:28:02 +0100 Subject: [PATCH 23/38] [release/2024-10-16] fix-forward: update swagger --- docs/public_swagger/swagger.yaml | 69 ++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/docs/public_swagger/swagger.yaml b/docs/public_swagger/swagger.yaml index 19715e01..2cfea6ff 100644 --- a/docs/public_swagger/swagger.yaml +++ b/docs/public_swagger/swagger.yaml @@ -590,6 +590,50 @@ paths: application/fhir+json: schema: $ref: "#/components/schemas/OperationOutcome" + ? /ProductTeam/{product_team_id}/Product/{product_id}/DeviceReferenceData/{device_reference_data_id} + : get: + operationId: readDeviceReferenceData + summary: readDeviceReferenceData endpoint for APIGEE integration + parameters: + - name: product_team_id + in: path + required: true + description: logical identifier + schema: + type: string + - name: product_id + in: path + required: true + description: logical identifier + schema: + type: string + - name: device_reference_data_id + in: path + required: true + description: logical identifier + schema: + type: string + - in: header + name: version + schema: + $ref: "#/components/schemas/Version" + - in: header + name: x-request-id + schema: + $ref: "#/components/schemas/RequestId" + - in: header + name: x-correlation-id + schema: + $ref: "#/components/schemas/CorrelationId" + responses: + "200": + $ref: "#/components/responses/DeviceReferenceDataResponse" + "4XX": + description: "Client Error" + content: + application/fhir+json: + schema: + $ref: "#/components/schemas/OperationOutcome" /searchSdsDevice: get: operationId: searchsdsdevice @@ -2861,3 +2905,28 @@ components: keys: - key_type: "product_team_id_alias" key_value: "FOOBAR" + DeviceReferenceDataResponse: + description: Read Device Reference Data operation successful + content: + application/json: + schema: + type: object + properties: + id: + type: string + name: + type: string + product_id: + type: string + product_team_id: + type: string + ods_code: + type: string + status: + type: string + created_on: + type: string + updated_on: + type: string + deleted_on: + type: string From 6a3445c006bc56fe61ca11bbfae58a4f75009a81 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Thu, 17 Oct 2024 16:05:18 +0100 Subject: [PATCH 24/38] [release/2024-10-16] fix-forward: delete public swagger in anticipation of next release --- docs/public_swagger/swagger.yaml | 2932 --------------------- docs/public_swagger/tests/test_swagger.py | 30 - 2 files changed, 2962 deletions(-) delete mode 100644 docs/public_swagger/swagger.yaml delete mode 100644 docs/public_swagger/tests/test_swagger.py diff --git a/docs/public_swagger/swagger.yaml b/docs/public_swagger/swagger.yaml deleted file mode 100644 index 2cfea6ff..00000000 --- a/docs/public_swagger/swagger.yaml +++ /dev/null @@ -1,2932 +0,0 @@ -servers: - - url: https://sandbox.api.service.nhs.uk/connecting-party-manager/FHIR/R4 - description: Sandbox environment. - - url: https://int.api.service.nhs.uk/connecting-party-manager/FHIR/R4 - description: Integration test environment. - - url: https://api.service.nhs.uk/connecting-party-manager/FHIR/R4 - description: Production environment. -info: - version: 1.0.0 - contact: - name: NHS Digital API Management - url: "https://digital.nhs.uk/developer/help-and-support" - email: api.management@nhs.net - title: Connecting Party Manager - FHIR API - description: | - ## Overview - - API to configure internal systems to allow a Connecting Party to connect. A source of information about Connecting Parties (systems that connect to NHSE) that helps provide system identity attributes that ensure NHSE services know what systems they are connecting to and the legal entities they are sharing data with. This service is driven by APIs that enable self-service for activities such as certificate management and environment access. It also is a store of end-to-end onboarding/integration data and a catalogue of endpoints. - - ## Who can use this API - - This API can only be used where there is a legal basis to do so. Make sure you have a valid use case before you go too far with your development. You must demonstrate you have a valid use case as part of digital onboarding. Connecting Parties must have an appointed Clinical Safety Officer and undertake a Clinical Safety Assessment. - - ## API status and roadmap - - This API is in [development](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#statuses). - - To see our roadmap, or to suggest, comment or vote on features for this API, see our interactive [product backlog](https://nhs-digital-api-management.featureupvote.com/). - - If you have any other queries, [contact us](https://digital.nhs.uk/developer/help-and-support). - - ## Service level - - This API is a platinum service, meaning it is operational and supported 24 hours a day, 365 days a year. - - For more details, see [service levels](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#service-levels). - - ## Technology - - This API is [RESTful](https://digital.nhs.uk/developer/guides-and-documentation/our-api-technologies#basic-rest). - - It conforms to the [FHIR](https://digital.nhs.uk/developer/guides-and-documentation/our-api-technologies#fhir) global standard for health care data exchange, specifically to [FHIR R4 (v4.0.1)](https://hl7.org/fhir/r4/), except that it does not support the [capabilities](http://hl7.org/fhir/R4/http.html#capabilities) interaction. - - It includes some country-specific FHIR extensions, which conform to [FHIR UK Core](https://digital.nhs.uk/services/fhir-uk-core), specifically [fhir.r4.ukcore.stu1 0.5.1](https://simplifier.net/packages/fhir.r4.ukcore.stu1/0.5.1). - - You do not need to know much about FHIR to use this API - FHIR APIs are just RESTful APIs that follow specific rules. - - In particular: - - * resource names are capitalised and singular, and use US spellings, for example `Organization` not `organisations` - * array names are singular, for example `entry` not `entries` for address lines - * data items that are country-specific and thus not included in the FHIR global base resources are usually wrapped in an `extension` object - - There are [libraries and SDKs available](https://digital.nhs.uk/developer/guides-and-documentation/api-technologies-at-nhs-digital#fhir-libraries-and-sdks) to help with FHIR API integration. - - ## Network access - - This API is available on the internet and, indirectly, on the [Health and Social Care Network (HSCN)](https://digital.nhs.uk/services/health-and-social-care-network). - - For more details see [Network access for APIs](https://digital.nhs.uk/developer/guides-and-documentation/network-access-for-apis). - - ## Security and authorisation - - This API uses the following access modes: - - * [Application-restricted RESTful API - signed JWT authentication](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/application-restricted-restful-apis-signed-jwt-authentication) - - ## Errors - - We use standard HTTP status codes to show whether an API request succeeded or not. They are usually in the range: - - * 200 to 299 if it succeeded, including code 202 if it was accepted by an API that needs to wait for further action - * 400 to 499 if it failed because of a client error by your application - * 500 to 599 if it failed because of an error on our server - - Errors specific to each API are shown in the Endpoints section, under Response. See our [reference guide](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#http-status-codes) for more on errors. - - ## Open source - - You might find the following open source resources useful: - - | Resource | Description | Links | - |--------------------------------|--------------------------------------------|--------------------------------------------------------------------------| - | Connecting Party Manager | Source code for the core API and sandbox | [GitHub repo](https://github.com/NHSDigital/connecting-party-manager) | - | Connecting Party Manager - CI | Source code for the Github Actions runners | [GitHub repo](https://github.com/NHSDigital/connecting-party-manager-CI) | - - We currently don't have any open source client libraries or sample code for this API. If you think this would be useful, you can [upvote the suggestion on our Interactive Product Backlog](https://nhs-digital-api-management.featureupvote.com/suggestions/107439/client-libraries-and-reference-implementations). - - ## Environments and testing - - | Environment | Base URL | - | ----------------- | --------------------------------------------------------------------------- | - | Sandbox | `https://sandbox.api.service.nhs.uk/connecting-party-manager/FHIR/R4/` | - | Integration | `https://int.api.service.nhs.uk/connecting-party-manager/consumer/FHIR/R4/` | - | Production | `https://api.service.nhs.uk/connecting-party-manager/consumer/FHIR/R4/` | - - ### Sandbox and Integration environments - - Our [sandbox environment](https://digital.nhs.uk/developer/guides-and-documentation/testing#sandbox-testing): - - * is for early developer testing, - * is open access, so does not allow you to test authorisation, - * includes ready-to-use test data - for details [contact us](https://digital.nhs.uk/developer/help-and-support), - * underpins our `Try this API` feature; see the documentation for each endpoint for more details. - - Our [integration test environment](https://digital.nhs.uk/developer/guides-and-documentation/testing#integration-testing): - - * is for formal integration testing, - * includes authorisation, - * includes ready-to-use test data - for details [contact us](https://digital.nhs.uk/developer/help-and-support). - - For more details see [integration testing with our RESTful APIs](https://digital.nhs.uk/developer/guides-and-documentation/testing#integration-testing-with-our-restful-apis). - - ## Onboarding - - You need to get your software approved by us before it can go live with this API. We call this onboarding. The onboarding process can sometimes be quite long, so it’s worth planning well ahead. - - As part of this process, you need to demonstrate that you can manage risks and that your software conforms technically with the requirements for this API. - - Information on this page might impact the design of your software. For details, see [Onboarding support information](https://digital.nhs.uk/developer/api-catalogue/national-record-locator-consumer-fhir/onboarding-support-information). - - To understand how our online digital onboarding process works, see [digital onboarding](https://digital.nhs.uk/developer/guides-and-documentation/digital-onboarding#using-the-digital-onboarding-portal). - -
-
-
-
- - - -
-
-
-

To get started, sign in or create a developer account, then select 'product onboarding'.

-
-
-
- - ## Change log - - For details of how this API has changed over time, see the [change log](https://github.com/NHSDigital/connecting-party-manager/blob/main/CHANGELOG.md). - license: - name: MIT - url: https://github.com/NHSDigital/connecting-party-manager/blob/main/LICENCE.md -openapi: 3.0.3 -paths: - /Device: - post: - summary: Create a Device resource - operationId: createDevice - responses: - "201": - description: Create operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - requestBody: - $ref: "#/components/requestBodies/Device" - parameters: - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - get: - summary: Search for Device resources - operationId: searchDevice - parameters: - - name: device_type - in: query - required: true - description: "Type of device (product or endpoint)" - schema: - type: string - enum: - - product - - endpoint - - $ref: "#/components/parameters/profileParam" - - $ref: "#/components/parameters/lastUpdatedParam" - - $ref: "#/components/parameters/tagParam" - - $ref: "#/components/parameters/securityParam" - - $ref: "#/components/parameters/sourceParam" - - $ref: "#/components/parameters/idParam" - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Search Device operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Bundle" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /Device/{id}: - get: - summary: Read a Device resource - operationId: readDevice - parameters: - - name: id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Read Device operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Device" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /ProductTeam: - post: - operationId: createproductteam - summary: createProductTeam endpoint for APIGEE integration - requestBody: - $ref: "#/components/requestBodies/ProductTeamRequest" - responses: - "201": - $ref: "#/components/responses/ProductTeamResponse" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - parameters: - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - /ProductTeam/{product_team_id}: - get: - operationId: readproductteam - summary: readProductTeam endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - $ref: "#/components/parameters/profileParam" - - $ref: "#/components/parameters/lastUpdatedParam" - - $ref: "#/components/parameters/tagParam" - - $ref: "#/components/parameters/securityParam" - - $ref: "#/components/parameters/sourceParam" - - $ref: "#/components/parameters/idParam" - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - $ref: "#/components/responses/ProductTeamResponse" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /ProductTeam/{product_team_id}/Product: - get: - operationId: searchCpmProduct - summary: searchCpmProduct endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - $ref: "#/components/parameters/profileParam" - - $ref: "#/components/parameters/lastUpdatedParam" - - $ref: "#/components/parameters/tagParam" - - $ref: "#/components/parameters/securityParam" - - $ref: "#/components/parameters/sourceParam" - - $ref: "#/components/parameters/idParam" - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Search CpmProducts operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Bundle" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - post: - operationId: createproductendpoint - summary: createProduct endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - product_name: - type: string - description: Name of the product - responses: - "201": - description: Create operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /ProductTeam/{product_team_id}/Product/{product_id}: - get: - operationId: readproductendpoint - summary: readProduct endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - name: product_id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Read Product operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Bundle" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - delete: - operationId: deleteproductendpoint - summary: deleteProduct endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - name: product_id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "204": - description: Delete Product operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Bundle" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /ProductTeam/{product_team_id}/Product/Epr: - post: - operationId: createproductforeprendpoint - summary: createCpmProductForEpr endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - product_name: - type: string - description: Name of the product - responses: - "201": - description: Create operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /ProductTeam/{product_team_id}/Product/{product_id}/DeviceReferenceData: - post: - operationId: createDeviceReferenceData - summary: createDeviceReferenceData endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - name: product_id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - name: - type: string - description: Name of the DeviceReferenceData - responses: - "201": - description: Create operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - ? /ProductTeam/{product_team_id}/Product/{product_id}/DeviceReferenceData/{device_reference_data_id} - : get: - operationId: readDeviceReferenceData - summary: readDeviceReferenceData endpoint for APIGEE integration - parameters: - - name: product_team_id - in: path - required: true - description: logical identifier - schema: - type: string - - name: product_id - in: path - required: true - description: logical identifier - schema: - type: string - - name: device_reference_data_id - in: path - required: true - description: logical identifier - schema: - type: string - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - $ref: "#/components/responses/DeviceReferenceDataResponse" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /searchSdsDevice: - get: - operationId: searchsdsdevice - summary: searchSdsDevice endpoint for APIGEE integration - parameters: - - name: nhs_as_client - in: query - required: false - description: "Accredited System Client" - schema: - type: string - - name: nhs_as_svc_ia - in: query - required: false - description: "Accredited System Client Interaction" - schema: - type: string - - name: nhs_mhs_manufacturer_org - in: query - required: false - description: "Manufacturer Organisation" - schema: - type: string - - name: nhs_mhs_party_key - in: query - required: false - description: "Party Key" - schema: - type: string - - $ref: "#/components/parameters/profileParam" - - $ref: "#/components/parameters/lastUpdatedParam" - - $ref: "#/components/parameters/tagParam" - - $ref: "#/components/parameters/securityParam" - - $ref: "#/components/parameters/sourceParam" - - $ref: "#/components/parameters/idParam" - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Search Device operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Bundle" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" - /searchSdsEndpoint: - get: - operationId: searchsdsendpoint - summary: searchSdsEndpoint endpoint for APIGEE integration - parameters: - - name: nhs_id_code - in: query - required: false - description: "NHS ID Code" - schema: - type: string - - name: nhs_mhs_svc_ia - in: query - required: false - description: "Endpoint Interaction" - schema: - type: string - - name: nhs_mhs_party_key - in: query - required: false - description: "Party Key" - schema: - type: string - - $ref: "#/components/parameters/profileParam" - - $ref: "#/components/parameters/lastUpdatedParam" - - $ref: "#/components/parameters/tagParam" - - $ref: "#/components/parameters/securityParam" - - $ref: "#/components/parameters/sourceParam" - - $ref: "#/components/parameters/idParam" - - in: header - name: version - schema: - $ref: "#/components/schemas/Version" - - in: header - name: x-request-id - schema: - $ref: "#/components/schemas/RequestId" - - in: header - name: x-correlation-id - schema: - $ref: "#/components/schemas/CorrelationId" - responses: - "200": - description: Search Device operation successful - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Bundle" - "4XX": - description: "Client Error" - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/OperationOutcome" -components: - parameters: - profileParam: - name: _profile - description: Profiles this resource claims to conform to - in: query - required: false - schema: - type: string - lastUpdatedParam: - name: _lastUpdated - description: When the resource version last changed - in: query - required: false - schema: - type: string - tagParam: - name: _tag - description: Tags applied to this resource - in: query - required: false - schema: - type: string - securityParam: - name: _security - description: Security Labels applied to this resource - in: query - required: false - schema: - type: string - sourceParam: - name: _source - description: Identifies where the resource comes from - in: query - required: false - schema: - type: string - idParam: - name: _id - description: Logical id of this artifact - in: query - required: false - schema: - type: string - requestBodies: - Device: - content: - application/fhir+json: - schema: - $ref: "#/components/schemas/Device" - required: true - ProductTeamRequest: - description: Request body to create a Product Team - required: true - content: - application/json: - schema: - type: object - properties: - name: - type: string - description: Name of the product team - ods_code: - type: string - description: ODS code associated with the product team - keys: - type: array - description: List of keys associated with the product team - items: - type: object - properties: - key_type: - type: string - description: The type of the key (e.g., product_team_id_alias) - key_value: - type: string - description: The value of the key - required: - - name - - ods_code - - keys - example: - name: "Sample Product Team" - ods_code: "F5H1R" - keys: - - key_type: "product_team_id_alias" - key_value: "BAR" - schemas: - Resource: - type: object - properties: - resourceType: - type: string - enum: - - Account - - ActivityDefinition - - AdverseEvent - - AllergyIntolerance - - Appointment - - AppointmentResponse - - AuditEvent - - Basic - - Binary - - BiologicallyDerivedProduct - - BodyStructure - - Bundle - - CapabilityStatement - - CarePlan - - CareTeam - - CatalogEntry - - ChargeItem - - ChargeItemDefinition - - Claim - - ClaimResponse - - ClinicalImpression - - CodeSystem - - Communication - - CommunicationRequest - - CompartmentDefinition - - Composition - - ConceptMap - - Condition - - Consent - - Contract - - Coverage - - CoverageEligibilityRequest - - CoverageEligibilityResponse - - DetectedIssue - - Device - - DeviceDefinition - - DeviceMetric - - DeviceRequest - - DeviceUseStatement - - DiagnosticReport - - DocumentManifest - - DocumentReference - - DomainResource - - EffectEvidenceSynthesis - - Encounter - - Endpoint - - EnrollmentRequest - - EnrollmentResponse - - EpisodeOfCare - - EventDefinition - - Evidence - - EvidenceVariable - - ExampleScenario - - ExplanationOfBenefit - - FamilyMemberHistory - - Flag - - Goal - - GraphDefinition - - Group - - GuidanceResponse - - HealthcareService - - ImagingStudy - - Immunization - - ImmunizationEvaluation - - ImmunizationRecommendation - - ImplementationGuide - - InsurancePlan - - Invoice - - Library - - Linkage - - List - - Location - - Measure - - MeasureReport - - Media - - Medication - - MedicationAdministration - - MedicationDispense - - MedicationKnowledge - - MedicationRequest - - MedicationStatement - - MedicinalProduct - - MedicinalProductAuthorization - - MedicinalProductContraindication - - MedicinalProductIndication - - MedicinalProductIngredient - - MedicinalProductInteraction - - MedicinalProductManufactured - - MedicinalProductPackaged - - MedicinalProductPharmaceutical - - MedicinalProductUndesirableEffect - - MessageDefinition - - MessageHeader - - MolecularSequence - - NamingSystem - - NutritionOrder - - Observation - - ObservationDefinition - - OperationDefinition - - OperationOutcome - - Organization - - OrganizationAffiliation - - Parameters - - Patient - - PaymentNotice - - PaymentReconciliation - - Person - - PlanDefinition - - Practitioner - - PractitionerRole - - Procedure - - Provenance - - Questionnaire - - QuestionnaireResponse - - RelatedPerson - - RequestGroup - - ResearchDefinition - - ResearchElementDefinition - - ResearchStudy - - ResearchSubject - - Resource - - RiskAssessment - - RiskEvidenceSynthesis - - Schedule - - SearchParameter - - ServiceRequest - - Slot - - Specimen - - SpecimenDefinition - - StructureDefinition - - StructureMap - - Subscription - - Substance - - SubstanceNucleicAcid - - SubstancePolymer - - SubstanceProtein - - SubstanceReferenceInformation - - SubstanceSourceMaterial - - SubstanceSpecification - - SupplyDelivery - - SupplyRequest - - Task - - TerminologyCapabilities - - TestReport - - TestScript - - ValueSet - - VerificationResult - - VisionPrescription - id: - type: string - pattern: "[A-Za-z0-9\\-\\.]{1,64}" - description: The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes. - meta: - $ref: "#/components/schemas/Meta" - description: The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource. - implicitRules: - type: string - pattern: \S* - description: A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc. - language: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: The base language in which the resource is written. - required: - - resourceType - DomainResource: - allOf: - - $ref: "#/components/schemas/Resource" - - type: object - properties: - text: - $ref: "#/components/schemas/Narrative" - description: A human–readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it "clinically safe" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety. - contained: - type: array - items: - $ref: "#/components/schemas/Resource" - description: These resources do not have an independent existence apart from the resource that contains them – they cannot be identified independently, and nor can they have their own independent transaction scope. - extension: - type: array - items: - $ref: "#/components/schemas/Extension" - description: May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. - modifierExtension: - type: array - items: - $ref: "#/components/schemas/Extension" - description: |- - May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. - - Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself). - Device: - allOf: - - $ref: "#/components/schemas/DomainResource" - - type: object - properties: - identifier: - type: array - items: - $ref: "#/components/schemas/Identifier" - description: Unique instance identifiers assigned to a device by manufacturers other organizations or owners. - definition: - $ref: "#/components/schemas/Reference" - description: The reference to the definition for the device. - udiCarrier: - type: array - items: - $ref: "#/components/schemas/DeviceUdiCarrier" - description: Unique device identifier (UDI) assigned to device label or package. Note that the Device may include multiple udiCarriers as it either may include just the udiCarrier for the jurisdiction it is sold, or for multiple jurisdictions it could have been sold. - status: - type: string - enum: - - active - - inactive - - entered-in-error - - unknown - description: Status of the Device availability. - statusReason: - type: array - items: - $ref: "#/components/schemas/CodeableConcept" - description: Reason for the dtatus of the Device availability. - distinctIdentifier: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The distinct identification string as required by regulation for a human cell, tissue, or cellular and tissue–based product. - manufacturer: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A name of the manufacturer. - manufactureDate: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: The date and time when the device was manufactured. - expirationDate: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: The date and time beyond which this device is no longer valid or should not be used (if applicable). - lotNumber: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Lot number assigned by the manufacturer. - serialNumber: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The serial number assigned by the organization when the device was manufactured. - deviceName: - type: array - items: - $ref: "#/components/schemas/DeviceDeviceName" - description: This represents the manufacturer's name of the device as provided by the device, from a UDI label, or by a person describing the Device. This typically would be used when a person provides the name(s) or when the device represents one of the names available from DeviceDefinition. - modelNumber: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The model number for the device. - partNumber: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The part number of the device. - type: - $ref: "#/components/schemas/CodeableConcept" - description: |- - The type of deviceName. - UDILabelName | UserFriendlyName | PatientReportedName | ManufactureDeviceName | ModelName. - specialization: - type: array - items: - $ref: "#/components/schemas/DeviceSpecialization" - description: The capabilities supported on a device, the standards to which the device conforms for a particular purpose, and used for the communication. - version: - type: array - items: - $ref: "#/components/schemas/DeviceVersion" - description: The version of the standard that is used to operate and communicate. - property: - type: array - items: - $ref: "#/components/schemas/DeviceProperty" - description: The actual configuration settings of a device as it actually operates, e.g., regulation status, time properties. - patient: - $ref: "#/components/schemas/Reference" - description: Patient information, If the device is affixed to a person. - owner: - $ref: "#/components/schemas/Reference" - description: An organization that is responsible for the provision and ongoing maintenance of the device. - contact: - type: array - items: - $ref: "#/components/schemas/ContactPoint" - description: Contact details for an organization or a particular human that is responsible for the device. - location: - $ref: "#/components/schemas/Reference" - description: The place where the device can be found. - url: - type: string - pattern: \S* - description: A network address on which the device may be contacted directly. - note: - type: array - items: - $ref: "#/components/schemas/Annotation" - description: Descriptive information, usage information or implantation information that is not captured in an existing element. - safety: - type: array - items: - $ref: "#/components/schemas/CodeableConcept" - description: Provides additional safety characteristics about a medical device. For example devices containing latex. - parent: - $ref: "#/components/schemas/Reference" - description: The parent device. - example: - resourceType: Device - meta: - versionId: leAx-ab3l3 - lastUpdated: "2020-11-04T11:22:43.963014-05:00" - source: yOjqeCo0bv - profile: - - Z7pJUfqU6t - security: - - system: 5wvbYyTKjt - version: wfYhQqDqvR - code: fsuby16DBu - display: XUC_83exZs - userSelected: true - tag: - - system: rW_khzpssy - version: z9LyFhRYvf - code: qPlH1wpJTv - display: wLhj3rWEFb - userSelected: true - - code: ibm/complete-mock - implicitRules: EY3J2qd657 - language: en-US - text: - status: additional - div:
- identifier: - - use: temp - type: - coding: - - system: 2NnKDj0XAP - version: kowcO4_ibR - code: o_qjfWR1E4 - display: wYXJaKt_KP - userSelected: true - text: jJdgrpRSLO - system: kYVnOGpPz1 - value: 3VT6Q1la6l - period: - start: "2020-11-04T11:22:43.966349-05:00" - end: "2020-11-04T11:22:43.96665-05:00" - definition: - reference: DeviceDefinition/0iz1m36ZqT - type: DeviceDefinition - identifier: - use: old - type: - coding: - - system: OTscJIufV8 - version: I8wNZsOCgm - code: KpiL5ZvBe5 - display: VKdG88p1aR - userSelected: true - text: KuSxhlgLYM - system: FcXewtum1O - value: ft0VUZ5axC - period: - start: "2020-11-04T11:22:43.968256-05:00" - end: "2020-11-04T11:22:43.968431-05:00" - display: c7rPPL3q1K - udiCarrier: - - deviceIdentifier: 5_yGXOVzlZ - issuer: ctRAL2MENY - jurisdiction: 2XSxq5Q5y9 - carrierAIDC: aTZfAVA= - carrierHRF: GwKJEb2UCd - entryType: card - status: active - statusReason: - - coding: - - system: MAb0Kyat4R - version: PUnRaXzCOB - code: p6bo2NaOkq - display: 2wb3XMKYkC - userSelected: true - text: qnlahiKNH4 - distinctIdentifier: EtpCekS5ug - manufacturer: c0cXF0rkid - manufactureDate: "2020-11-04T11:22:43.971972-05:00" - expirationDate: "2020-11-04T11:22:43.972144-05:00" - lotNumber: GlPVAmvgfX - serialNumber: UW8XQT_T8f - deviceName: - - name: 8EqKlRy_yO - type: patient-reported-name - modelNumber: QbStiBsInX - partNumber: 0FLeLYIh9j - type: - coding: - - system: pVH61hMZ_7 - version: Ym58JrWbnW - code: OgYEL_SpMs - display: wpDPKyN213 - userSelected: true - text: 7QfkFIJgpQ - specialization: - - systemType: - coding: - - system: VfhTWTWEfq - version: RC50TO6Cqd - code: I7kYlWxkV9 - display: EvRlmuXclO - userSelected: true - text: 2kVAmKpHVs - version: hV9MlnjJOL - version: - - type: - coding: - - system: PlURX9yHqf - version: Z43HjFOG4n - code: Eb6jJbeQIi - display: aQqE9qlvUD - userSelected: true - text: N4pyV2sdOJ - component: - use: usual - type: - coding: - - system: 74u6CAqeKT - version: E7p3ozfUut - code: ii15Kf5ScQ - display: oUYOGoD92f - userSelected: true - text: OYzBklTNKx - system: WGx_ohb6b9 - value: vkE_QfvSaK - period: - start: "2020-11-04T11:22:43.976086-05:00" - end: "2020-11-04T11:22:43.976259-05:00" - value: fWWMVmjtNX - property: - - type: - coding: - - system: ATwcqz7UcD - version: ykvNaWcVZV - code: _DBffQxSd4 - display: 2ApwgE3YfV - userSelected: true - text: f8uQAjqrhp - valueQuantity: - - value: 0.5877067255449361 - comparator: <= - unit: 7wLeVdJkhT - system: 72b4FQk2t1 - code: 6aVpwGwaaW - valueCode: - - coding: - - system: nXMhN7nH07 - version: CyD__CA_WP - code: qpdZVSHj36 - display: rRQLOwfvD8 - userSelected: true - text: ZYFB2Ufe5R - patient: - reference: Patient/TqL2pL98gA - type: Patient - identifier: - use: secondary - type: - coding: - - system: P2PK0tK6V9 - version: OrESnC4jsJ - code: QqMZU6DqG5 - display: XlGeotrgMG - userSelected: true - text: xEXDseHkip - system: NTHRO2OZDt - value: eoRXk6X9Pr - period: - start: "2020-11-04T11:22:43.979104-05:00" - end: "2020-11-04T11:22:43.979266-05:00" - display: yGWttxdCia - owner: - reference: Organization/JIX1Dk6PAC - type: Organization - identifier: - use: usual - type: - coding: - - system: uaqEtS8sNB - version: 1W8XBAjFAT - code: iHVSugMYKD - display: CCk69MgMGW - userSelected: true - text: aEfa7a5wh3 - system: stVF7jEeSP - value: jlifbu4zbx - period: - start: "2020-11-04T11:22:43.980235-05:00" - end: "2020-11-04T11:22:43.980404-05:00" - display: Nu_u2FD_dT - contact: - - system: other - value: JFzCk8sShT - use: old - rank: 1.917455768e+09 - period: - start: "2020-11-04T11:22:43.980769-05:00" - end: "2020-11-04T11:22:43.980915-05:00" - location: - reference: Location/xpkwiiYA4U - type: Location - identifier: - use: official - type: - coding: - - system: pCFDnsZMjg - version: weiCRuKs87 - code: gCmknogj7c - display: JlQr_Y5Diy - userSelected: true - text: oUQVwdjR7n - system: igZLLInYvJ - value: RXuSd3x7Kn - period: - start: "2020-11-04T11:22:43.983113-05:00" - end: "2020-11-04T11:22:43.983285-05:00" - display: bcgajGFE6f - url: arZRapDYp_ - note: - - authorReference: - reference: Practitioner/2ci2Lv99EG - type: Practitioner - identifier: - use: secondary - type: - coding: - - system: x8D7d6u4wp - version: uEjUR7XG2Q - code: VgUQBAyio4 - display: qMDU9hbJCE - userSelected: true - text: bsHPggO95l - system: 12Y6tNgx1B - value: Fxafvym0mI - period: - start: "2020-11-04T11:22:43.984583-05:00" - end: "2020-11-04T11:22:43.984747-05:00" - display: icpyr8sCM5 - time: "2020-11-04T11:22:43.984961-05:00" - text: JyDVmzuT2F - safety: - - coding: - - system: n24W87b8CN - version: McPNdd8p8E - code: 7UXjXlUQ1n - display: vDlZ4y5Rcu - userSelected: true - text: PgGlM0rU_z - parent: - reference: Device/13x_MypWi2 - type: Device - identifier: - use: secondary - type: - coding: - - system: xFI4BESbB0 - version: ok5uyHpmCL - code: ltvv_3oObD - display: NE8QkVBRIW - userSelected: true - text: uOS0kmo3ZP - system: aHn4gLNrsa - value: mjdYRXyVLu - period: - start: "2020-11-04T11:22:43.986647-05:00" - end: "2020-11-04T11:22:43.986859-05:00" - display: d49bgelgmI - Bundle: - allOf: - - $ref: "#/components/schemas/Resource" - - type: object - properties: - identifier: - $ref: "#/components/schemas/Identifier" - description: A persistent identifier for the bundle that won't change as a bundle is copied from server to server. - type: - type: string - enum: - - document - - message - - transaction - - transaction-response - - batch - - batch-response - - history - - searchset - - collection - description: Indicates the purpose of this bundle – how it is intended to be used. - timestamp: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)) - description: The date/time that the bundle was assembled – i.e. when the resources were placed in the bundle. - total: - type: integer - format: int32 - description: If a set of search matches, this is the total number of entries of type 'match' across all pages in the search. It does not include search.mode = 'include' or 'outcome' entries and it does not provide a count of the number of entries in the Bundle. - link: - type: array - items: - $ref: "#/components/schemas/BundleLink" - description: A series of links that provide context to this bundle. - entry: - type: array - items: - $ref: "#/components/schemas/BundleEntry" - description: An entry in a bundle resource – will either contain a resource or information about a resource (transactions and history only). - signature: - $ref: "#/components/schemas/Signature" - description: Digital Signature – base64 encoded. XML–DSig or a JWT. - required: - - type - example: - resourceType: Bundle - meta: - versionId: F7bitzw1Hj - lastUpdated: "2020-11-04T11:22:43.502316-05:00" - source: JRkgOa8bwm - profile: - - i4gpGowr6Y - security: - - system: lTnQF4OV3w - version: hTth0i4Ivs - code: P6iXDX6DcV - display: rMonvtKiO8 - userSelected: true - tag: - - system: 4HA_3UN6ab - version: FvMU1dv9n6 - code: AjrpSN9l0q - display: V3cjH6t7zX - userSelected: true - - code: ibm/complete-mock - implicitRules: IUOLjdM2gr - language: en-US - identifier: - use: temp - type: - coding: - - system: GG7NhXNGqZ - version: hTXMVyhLkS - code: fimixp8PMa - display: aYmxIkjI7w - userSelected: true - text: znbNwNNzOo - system: zxGBnkW0WU - value: lpcL4XUHKZ - period: - start: "2020-11-04T11:22:43.507146-05:00" - end: "2020-11-04T11:22:43.507335-05:00" - type: document - timestamp: "2020-11-04T11:22:43.507779-05:00" - total: 8.04618139e+08 - link: - - relation: 0h9oqVMQIt - url: N6t6uzHuIy - entry: - - link: - - relation: IWG3UO5Awa - url: MJBFG1zxnb - fullUrl: PKkErHU9RX - search: - mode: match - score: 0.7827620245063741 - request: - method: DELETE - url: EX5t3mSMJh - ifNoneMatch: TXPgvN30LK - ifModifiedSince: "2020-11-04T11:22:43.514903-05:00" - ifMatch: ESkJi0jaVC - ifNoneExist: fuSskChKIq - response: - status: avVXy1xkRq - location: v0Ub50vvWL - etag: BmCLcXDNuX - lastModified: "2020-11-04T11:22:43.516375-05:00" - signature: - type: - - system: YievdsQnmM - version: 3um1GW4GVD - code: sNUnxWccmG - display: pqCTozifNV - userSelected: true - when: "2020-11-04T11:22:43.518017-05:00" - who: - reference: Practitioner/7tLbieRmnA - type: Practitioner - identifier: - use: secondary - type: - coding: - - system: 9BzciHf_0T - version: em1dSVwNdC - code: LD7gU1VdIa - display: l_je45PsqP - userSelected: true - text: Kd2TxyCZR7 - system: pACafNTDh7 - value: _hcXO_NlZg - period: - start: "2020-11-04T11:22:43.519783-05:00" - end: "2020-11-04T11:22:43.520066-05:00" - display: l79nsD4sN6 - onBehalfOf: - reference: Practitioner/LiWB2VJ2UG - type: Practitioner - identifier: - use: official - type: - coding: - - system: 64W3kvPnCz - version: 1LnrLVgWre - code: oHtu3WoiKi - display: gMKD8fdCjt - userSelected: true - text: bu5V13p166 - system: Graf7De_yt - value: UWJRgHe9wr - period: - start: "2020-11-04T11:22:43.544663-05:00" - end: "2020-11-04T11:22:43.545138-05:00" - display: kQ5612idGd - targetFormat: AQCVaUpSER - sigFormat: FxtGIjypV6 - data: dUUnF3I= - OperationOutcome: - allOf: - - $ref: "#/components/schemas/DomainResource" - - type: object - properties: - issue: - type: array - items: - $ref: "#/components/schemas/OperationOutcomeIssue" - description: An error, warning, or information message that results from a system action. - minItems: 1 - required: - - issue - example: - resourceType: OperationOutcome - meta: - versionId: q63JAUPuUM - lastUpdated: "2020-11-04T11:22:40.494613-05:00" - source: lwnaIGbKJn - profile: - - XGQPxL1j9k - security: - - system: sPgaKWp0jQ - version: wZHLBfjatw - code: DMQqy4R3E8 - display: mmxOeLn3hG - userSelected: true - tag: - - system: MtLYCBYPWS - version: 8Ak7HZQrke - code: 0DRWc7UuJB - display: 6NXvm6cEoG - userSelected: true - - code: ibm/complete-mock - implicitRules: siFyYo720q - language: en-US - text: - status: generated - div:
- issue: - - severity: fatal - code: required - details: - coding: - - system: YAwo1XN_fv - version: 9ycWn1vQBR - code: Y4ci7ASL_1 - display: lq_CJ5bq6Z - userSelected: true - text: aWHd4ZkhaW - diagnostics: yew1JE2w0X - location: - - ZDqBVS3Xgx - expression: - - yYfbNaNi8V - BundleEntry: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - link: - type: array - items: - $ref: "#/components/schemas/BundleLink" - description: A series of links that provide context to this entry. - fullUrl: - type: string - pattern: \S* - description: "The Absolute URL for the resource. The fullUrl SHALL NOT disagree with the id in the resource – i.e. if the fullUrl is not a urn:uuid, the URL shall be version–independent URL consistent with the Resource.id. The fullUrl is a version independent reference to the resource. The fullUrl element SHALL have a value except that: \n* fullUrl can be empty on a POST (although it does not need to when specifying a temporary id for reference in the bundle)\n* Results from operations might involve resources that are not identified." - resource: - $ref: "#/components/schemas/Resource" - description: The Resource for the entry. The purpose/meaning of the resource is determined by the Bundle.type. - search: - $ref: "#/components/schemas/BundleEntrySearch" - description: Information about the search process that lead to the creation of this entry. - request: - $ref: "#/components/schemas/BundleEntryRequest" - description: Additional information about how this entry should be processed as part of a transaction or batch. For history, it shows how the entry was processed to create the version contained in the entry. - response: - $ref: "#/components/schemas/BundleEntryResponse" - description: Indicates the results of processing the corresponding 'request' entry in the batch or transaction being responded to or what the results of an operation where when returning history. - BundleEntryResponse: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - status: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The status code returned by processing this entry. The status SHALL start with a 3 digit HTTP code (e.g. 404) and may contain the standard HTTP description associated with the status code. - location: - type: string - pattern: \S* - description: The location header created by processing this operation, populated if the operation returns a location. - etag: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The Etag for the resource, if the operation for the entry produced a versioned resource (see [Resource Metadata and Versioning](http.html#versioning) and [Managing Resource Contention](http.html#concurrency)). - lastModified: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)) - description: The date/time that the resource was modified on the server. - outcome: - $ref: "#/components/schemas/Resource" - description: An OperationOutcome containing hints and warnings produced as part of processing this entry in a batch or transaction. - required: - - status - BundleEntryRequest: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - method: - type: string - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - PATCH - description: In a transaction or batch, this is the HTTP action to be executed for this entry. In a history bundle, this indicates the HTTP action that occurred. - url: - type: string - pattern: \S* - description: The URL for this entry, relative to the root (the address to which the request is posted). - ifNoneMatch: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: If the ETag values match, return a 304 Not Modified status. See the API documentation for ["Conditional Read"](http.html#cread). - ifModifiedSince: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)) - description: Only perform the operation if the last updated date matches. See the API documentation for ["Conditional Read"](http.html#cread). - ifMatch: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Only perform the operation if the Etag value matches. For more information, see the API section ["Managing Resource Contention"](http.html#concurrency). - ifNoneExist: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Instruct the server not to perform the create if a specified resource already exists. For further information, see the API documentation for ["Conditional Create"](http.html#ccreate). This is just the query portion of the URL – what follows the "?" (not including the "?"). - required: - - method - - url - BundleEntrySearch: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - mode: - type: string - enum: - - match - - include - - outcome - description: Why this entry is in the result set – whether it's included as a match or because of an _include requirement, or to convey information or warning information about the search process. - score: - type: number - description: When searching, the server's search ranking score for the entry. - BundleLink: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - relation: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A name which details the functional use for this link – see [http://www.iana.org/assignments/link–relations/link–relations.xhtml#link–relations–1](http://www.iana.org/assignments/link–relations/link–relations.xhtml#link–relations–1). - url: - type: string - pattern: \S* - description: The reference details for the link. - required: - - relation - - url - DeviceProperty: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - type: - $ref: "#/components/schemas/CodeableConcept" - description: Code that specifies the property DeviceDefinitionPropetyCode (Extensible). - valueQuantity: - type: array - items: - $ref: "#/components/schemas/Quantity" - description: Property value as a quantity. - valueCode: - type: array - items: - $ref: "#/components/schemas/CodeableConcept" - description: Property value as a code, e.g., NTP4 (synced to NTP). - required: - - type - DeviceVersion: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - type: - $ref: "#/components/schemas/CodeableConcept" - description: The type of the device version. - component: - $ref: "#/components/schemas/Identifier" - description: A single component of the device version. - value: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The version text. - required: - - value - DeviceSpecialization: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - systemType: - $ref: "#/components/schemas/CodeableConcept" - description: The standard that is used to operate and communicate. - version: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The version of the standard that is used to operate and communicate. - required: - - systemType - DeviceDeviceName: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - name: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The name of the device. - type: - type: string - enum: - - udi-label-name - - user-friendly-name - - patient-reported-name - - manufacturer-name - - model-name - - other - description: |- - The type of deviceName. - UDILabelName | UserFriendlyName | PatientReportedName | ManufactureDeviceName | ModelName. - required: - - name - - type - DeviceUdiCarrier: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - deviceIdentifier: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The device identifier (DI) is a mandatory, fixed portion of a UDI that identifies the labeler and the specific version or model of a device. - issuer: - type: string - pattern: \S* - description: "Organization that is charged with issuing UDIs for devices. For example, the US FDA issuers include :\n1) GS1: \nhttp://hl7.org/fhir/NamingSystem/gs1–di, \n2) HIBCC:\nhttp://hl7.org/fhir/NamingSystem/hibcc–dI, \n3) ICCBBA for blood containers:\nhttp://hl7.org/fhir/NamingSystem/iccbba–blood–di, \n4) ICCBA for other devices:\nhttp://hl7.org/fhir/NamingSystem/iccbba–other–di." - jurisdiction: - type: string - pattern: \S* - description: The identity of the authoritative source for UDI generation within a jurisdiction. All UDIs are globally unique within a single namespace with the appropriate repository uri as the system. For example, UDIs of devices managed in the U.S. by the FDA, the value is http://hl7.org/fhir/NamingSystem/fda–udi. - carrierAIDC: - type: string - pattern: (\s*([0-9a-zA-Z\+/=]){4}\s*)+ - description: The full UDI carrier of the Automatic Identification and Data Capture (AIDC) technology representation of the barcode string as printed on the packaging of the device – e.g., a barcode or RFID. Because of limitations on character sets in XML and the need to round–trip JSON data through XML, AIDC Formats *SHALL* be base64 encoded. - carrierHRF: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The full UDI carrier as the human readable form (HRF) representation of the barcode string as printed on the packaging of the device. - entryType: - type: string - enum: - - barcode - - rfid - - manual - - card - - self-reported - - unknown - description: A coded entry to indicate how the data was entered. - OperationOutcomeIssue: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - severity: - type: string - enum: - - fatal - - error - - warning - - information - description: Indicates whether the issue indicates a variation from successful processing. - code: - type: string - enum: - - invalid - - structure - - required - - value - - invariant - - security - - login - - unknown - - expired - - forbidden - - suppressed - - processing - - not-supported - - duplicate - - multiple-matches - - not-found - - deleted - - too-long - - code-invalid - - extension - - too-costly - - business-rule - - conflict - - transient - - lock-error - - no-store - - exception - - timeout - - incomplete - - throttled - - informational - description: Describes the type of the issue. The system that creates an OperationOutcome SHALL choose the most applicable code from the IssueType value set, and may additional provide its own code for the error in the details element. - details: - $ref: "#/components/schemas/CodeableConcept" - description: Additional details about the error. This may be a text description of the error or a system code that identifies the error. - diagnostics: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Additional diagnostic information about the issue. - location: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: "This element is deprecated because it is XML specific. It is replaced by issue.expression, which is format independent, and simpler to parse. \n\nFor resource issues, this will be a simple XPath limited to element names, repetition indicators and the default child accessor that identifies one of the elements in the resource that caused this issue to be raised. For HTTP errors, will be \"http.\" + the parameter name." - expression: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A [simple subset of FHIRPath](fhirpath.html#simple) limited to element names, repetition indicators and the default child accessor that identifies one of the elements in the resource that caused this issue to be raised. - required: - - severity - - code - Element: - type: object - properties: - id: - type: string - pattern: "[A-Za-z0-9\\-\\.]{1,64}" - description: Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces. - extension: - type: array - items: - $ref: "#/components/schemas/Extension" - description: May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. - example: - - url: http://example.com - valueString: text value - BackboneElement: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - modifierExtension: - type: array - items: - $ref: "#/components/schemas/Extension" - description: |- - May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. - - Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself). - Address: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - use: - type: string - enum: - - home - - work - - temp - - old - - billing - description: The purpose of this address. - type: - type: string - enum: - - postal - - physical - - both - description: Distinguishes between physical addresses (those you can visit) and mailing addresses (e.g. PO Boxes and care–of addresses). Most addresses are both. - text: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Specifies the entire address as it should be displayed e.g. on a postal label. This may be provided instead of or as well as the specific parts. - line: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: This component contains the house number, apartment number, street name, street direction, P.O. Box number, delivery hints, and similar address information. - city: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The name of the city, town, suburb, village or other community or delivery center. - district: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The name of the administrative area (county). - state: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Sub–unit of a country with limited sovereignty in a federally organized country. A code may be used if codes are in common use (e.g. US 2 letter state codes). - postalCode: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A postal code designating a region defined by the postal service. - country: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Country – a nation as commonly understood or generally accepted. - period: - $ref: "#/components/schemas/Period" - description: Time period when address was/is in use. - Age: - allOf: - - $ref: "#/components/schemas/Quantity" - - type: object - properties: {} - Annotation: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - authorReference: - $ref: "#/components/schemas/Reference" - description: The individual responsible for making the annotation. - authorString: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The individual responsible for making the annotation. - time: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: Indicates when this particular annotation was made. - text: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The text of the annotation in markdown format. - required: - - text - Attachment: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - contentType: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: Identifies the type of the data in the attachment and allows a method to be chosen to interpret or render the data. Includes mime type parameters such as charset where appropriate. - language: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: The human language of the content. The value can be any valid value according to BCP 47. - data: - type: string - pattern: (\s*([0-9a-zA-Z\+/=]){4}\s*)+ - description: The actual data of the attachment – a sequence of bytes, base64 encoded. - url: - type: string - pattern: \S* - description: A location where the data can be accessed. - size: - type: integer - format: int32 - description: The number of bytes of data that make up this attachment (before base64 encoding, if that is done). - hash: - type: string - pattern: (\s*([0-9a-zA-Z\+/=]){4}\s*)+ - description: The calculated hash of the data using SHA–1. Represented using base64. - title: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A label or set of text to display in place of the data. - creation: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: The date that the attachment was first created. - CodeableConcept: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - coding: - type: array - items: - $ref: "#/components/schemas/Coding" - description: A reference to a code defined by a terminology system. - text: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A human language representation of the concept as seen/selected/uttered by the user who entered the data and/or which represents the intended meaning of the user. - Coding: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - system: - type: string - pattern: \S* - description: The identification of the code system that defines the meaning of the symbol in the code. - version: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The version of the code system which was used when choosing this code. Note that a well–maintained code system does not need the version reported, because the meaning of codes is consistent across versions. However this cannot consistently be assured, and when the meaning is not guaranteed to be consistent, the version SHOULD be exchanged. - code: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: A symbol in syntax defined by the system. The symbol may be a predefined code or an expression in a syntax defined by the coding system (e.g. post–coordination). - display: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A representation of the meaning of the code in the system, following the rules of the system. - userSelected: - type: boolean - description: Indicates that this coding was chosen by a user directly – e.g. off a pick list of available items (codes or displays). - ContactPoint: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - system: - type: string - enum: - - phone - - fax - - email - - pager - - url - - sms - - other - description: Telecommunications form for contact point – what communications system is required to make use of the contact. - value: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The actual contact point details, in a form that is meaningful to the designated communication system (i.e. phone number or email address). - use: - type: string - enum: - - home - - work - - temp - - old - - mobile - description: Identifies the purpose for the contact point. - rank: - type: integer - format: int32 - description: Specifies a preferred order in which to use a set of contacts. ContactPoints with lower rank values are more preferred than those with higher rank values. - period: - $ref: "#/components/schemas/Period" - description: Time period when the contact point was/is in use. - Count: - allOf: - - $ref: "#/components/schemas/Quantity" - - type: object - properties: {} - Distance: - allOf: - - $ref: "#/components/schemas/Quantity" - - type: object - properties: {} - Duration: - allOf: - - $ref: "#/components/schemas/Quantity" - - type: object - properties: {} - HumanName: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - use: - type: string - enum: - - usual - - official - - temp - - nickname - - anonymous - - old - - maiden - description: Identifies the purpose for this name. - text: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Specifies the entire name as it should be displayed e.g. on an application UI. This may be provided instead of or as well as the specific parts. - family: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The part of a name that links to the genealogy. In some cultures (e.g. Eritrea) the family name of a son is the first name of his father. - given: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Given name. - prefix: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Part of the name that is acquired as a title due to academic, legal, employment or nobility status, etc. and that appears at the start of the name. - suffix: - type: array - items: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Part of the name that is acquired as a title due to academic, legal, employment or nobility status, etc. and that appears at the end of the name. - period: - $ref: "#/components/schemas/Period" - description: Indicates the period of time when this name was valid for the named person. - Identifier: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - use: - type: string - enum: - - usual - - official - - temp - - secondary - - old - description: The purpose of this identifier. - type: - $ref: "#/components/schemas/CodeableConcept" - description: A coded type for the identifier that can be used to determine which identifier to use for a specific purpose. - system: - type: string - pattern: \S* - description: Establishes the namespace for the value – that is, a URL that describes a set values that are unique. - value: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The portion of the identifier typically relevant to the user and which is unique within the context of the system. - period: - $ref: "#/components/schemas/Period" - description: Time period during which identifier is/was valid for use. - assigner: - $ref: "#/components/schemas/Reference" - description: Organization that issued/manages the identifier. - example: - reference: Organization/123 - type: Organization - display: The Assigning Organization - Money: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - value: - type: number - description: Numerical value (with implicit precision). - currency: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: ISO 4217 Currency Code. - MoneyQuantity: - allOf: - - $ref: "#/components/schemas/Quantity" - - type: object - properties: {} - Period: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - start: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: The start of the period. The boundary is inclusive. - end: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: The end of the period. If the end of the period is missing, it means no end was known or planned at the time the instance was created. The start may be in the past, and the end date in the future, which means that period is expected/planned to end at that time. - Quantity: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - value: - type: number - description: The value of the measured amount. The value includes an implicit precision in the presentation of the value. - comparator: - type: string - enum: - - < - - <= - - ">=" - - ">" - description: How the value should be understood and represented – whether the actual value is greater or less than the stated value due to measurement issues; e.g. if the comparator is "<" , then the real value is < stated value. - unit: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A human–readable form of the unit. - system: - type: string - pattern: \S* - description: The identification of the system that provides the coded form of the unit. - code: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: A computer processable form of the unit in some unit representation system. - Range: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - low: - $ref: "#/components/schemas/SimpleQuantity" - description: The low limit. The boundary is inclusive. - high: - $ref: "#/components/schemas/SimpleQuantity" - description: The high limit. The boundary is inclusive. - Ratio: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - numerator: - $ref: "#/components/schemas/Quantity" - description: The value of the numerator. - denominator: - $ref: "#/components/schemas/Quantity" - description: The value of the denominator. - Reference: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - reference: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A reference to a location at which the other resource is found. The reference may be a relative reference, in which case it is relative to the service base URL, or an absolute URL that resolves to the location where the resource is found. The reference may be version specific or not. If the reference is not to a FHIR RESTful server, then it should be assumed to be version specific. Internal fragment references (start with '#') refer to contained resources. - type: - type: string - pattern: \S* - description: |- - The expected type of the target of the reference. If both Reference.type and Reference.reference are populated and Reference.reference is a FHIR URL, both SHALL be consistent. - - The type is the Canonical URL of Resource Definition that is the type this reference refers to. References are URLs that are relative to http://hl7.org/fhir/StructureDefinition/ e.g. "Patient" is a reference to http://hl7.org/fhir/StructureDefinition/Patient. Absolute URLs are only allowed for logical models (and can only be used in references in logical models, not resources). - identifier: - $ref: "#/components/schemas/Identifier" - description: An identifier for the target resource. This is used when there is no way to reference the other resource directly, either because the entity it represents is not available through a FHIR server, or because there is no way for the author of the resource to convert a known identifier to an actual location. There is no requirement that a Reference.identifier point to something that is actually exposed as a FHIR instance, but it SHALL point to a business concept that would be expected to be exposed as a FHIR instance, and that instance would need to be of a FHIR resource type allowed by the reference. - display: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Plain text narrative that identifies the resource in addition to the resource reference. - SampledData: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - origin: - $ref: "#/components/schemas/SimpleQuantity" - description: The base quantity that a measured value of zero represents. In addition, this provides the units of the entire measurement series. - period: - type: number - description: The length of time between sampling times, measured in milliseconds. - factor: - type: number - description: A correction factor that is applied to the sampled data points before they are added to the origin. - lowerLimit: - type: number - description: The lower limit of detection of the measured points. This is needed if any of the data points have the value "L" (lower than detection limit). - upperLimit: - type: number - description: The upper limit of detection of the measured points. This is needed if any of the data points have the value "U" (higher than detection limit). - dimensions: - type: integer - format: int32 - description: The number of sample points at each time point. If this value is greater than one, then the dimensions will be interlaced – all the sample points for a point in time will be recorded at once. - data: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A series of data points which are decimal values separated by a single space (character u20). The special values "E" (error), "L" (below detection limit) and "U" (above detection limit) can also be used in place of a decimal value. - required: - - origin - - period - - dimensions - SimpleQuantity: - allOf: - - $ref: "#/components/schemas/Quantity" - - type: object - properties: {} - Signature: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - type: - type: array - items: - $ref: "#/components/schemas/Coding" - description: An indication of the reason that the entity signed this document. This may be explicitly included as part of the signature information and can be used when determining accountability for various actions concerning the document. - minItems: 1 - when: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)) - description: When the digital signature was signed. - who: - $ref: "#/components/schemas/Reference" - description: A reference to an application–usable description of the identity that signed (e.g. the signature used their private key). - onBehalfOf: - $ref: "#/components/schemas/Reference" - description: A reference to an application–usable description of the identity that is represented by the signature. - targetFormat: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: A mime type that indicates the technical format of the target resources signed by the signature. - sigFormat: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: A mime type that indicates the technical format of the signature. Important mime types are application/signature+xml for X ML DigSig, application/jose for JWS, and image/* for a graphical image of a signature, etc. - data: - type: string - pattern: (\s*([0-9a-zA-Z\+/=]){4}\s*)+ - description: The base64 encoding of the Signature content. When signature is not recorded electronically this element would be empty. - required: - - type - - when - - who - Timing: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - event: - type: array - items: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: Identifies specific times when the event occurs. - repeat: - $ref: "#/components/schemas/TimingRepeat" - description: A set of rules that describe when the event is scheduled. - code: - $ref: "#/components/schemas/CodeableConcept" - description: A code for the timing schedule (or just text in code.text). Some codes such as BID are ubiquitous, but many institutions define their own additional codes. If a code is provided, the code is understood to be a complete statement of whatever is specified in the structured timing data, and either the code or the data may be used to interpret the Timing, with the exception that .repeat.bounds still applies over the code (and is not contained in the code). - TimingRepeat: - allOf: - - $ref: "#/components/schemas/BackboneElement" - - type: object - properties: - boundsDuration: - $ref: "#/components/schemas/Duration" - description: Either a duration for the length of the timing schedule, a range of possible length, or outer bounds for start and/or end limits of the timing schedule. - boundsRange: - $ref: "#/components/schemas/Range" - description: Either a duration for the length of the timing schedule, a range of possible length, or outer bounds for start and/or end limits of the timing schedule. - boundsPeriod: - $ref: "#/components/schemas/Period" - description: Either a duration for the length of the timing schedule, a range of possible length, or outer bounds for start and/or end limits of the timing schedule. - count: - type: integer - format: int32 - description: A total count of the desired number of repetitions across the duration of the entire timing specification. If countMax is present, this element indicates the lower bound of the allowed range of count values. - countMax: - type: integer - format: int32 - description: If present, indicates that the count is a range – so to perform the action between [count] and [countMax] times. - duration: - type: number - description: How long this thing happens for when it happens. If durationMax is present, this element indicates the lower bound of the allowed range of the duration. - durationMax: - type: number - description: If present, indicates that the duration is a range – so to perform the action between [duration] and [durationMax] time length. - durationUnit: - type: string - enum: - - s - - min - - h - - d - - wk - - mo - - a - description: The units of time for the duration, in UCUM units. - frequency: - type: integer - format: int32 - description: The number of times to repeat the action within the specified period. If frequencyMax is present, this element indicates the lower bound of the allowed range of the frequency. - frequencyMax: - type: integer - format: int32 - description: If present, indicates that the frequency is a range – so to repeat between [frequency] and [frequencyMax] times within the period or period range. - period: - type: number - description: Indicates the duration of time over which repetitions are to occur; e.g. to express "3 times per day", 3 would be the frequency and "1 day" would be the period. If periodMax is present, this element indicates the lower bound of the allowed range of the period length. - periodMax: - type: number - description: If present, indicates that the period is a range from [period] to [periodMax], allowing expressing concepts such as "do this once every 3–5 days. - periodUnit: - type: string - enum: - - s - - min - - h - - d - - wk - - mo - - a - description: The units of time for the period in UCUM units. - dayOfWeek: - type: array - items: - type: string - enum: - - mon - - tue - - wed - - thu - - fri - - sat - - sun - description: If one or more days of week is provided, then the action happens only on the specified day(s). - timeOfDay: - type: array - items: - type: string - pattern: ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)? - description: Specified time of day for action to take place. - when: - type: array - items: - type: string - enum: - - MORN - - MORN.early - - MORN.late - - NOON - - AFT - - AFT.early - - AFT.late - - EVE - - EVE.early - - EVE.late - - NIGHT - - PHS - - HS - - WAKE - - C - - CM - - CD - - CV - - AC - - ACM - - ACD - - ACV - - PC - - PCM - - PCD - - PCV - description: An approximate time period during the day, potentially linked to an event of daily living that indicates when the action should occur. - offset: - type: integer - format: int32 - description: The number of minutes from the event. If the event code does not indicate whether the minutes is before or after the event, then the offset is assumed to be after the event. - ContactDetail: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - name: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: The name of an individual to contact. - telecom: - type: array - items: - $ref: "#/components/schemas/ContactPoint" - description: The contact details for the individual (if a name was provided) or the organization. - RelatedArtifact: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - type: - type: string - enum: - - documentation - - justification - - citation - - predecessor - - successor - - derived-from - - depends-on - - composed-of - description: The type of relationship to the related artifact. - label: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A short label that can be used to reference the citation from elsewhere in the containing artifact, such as a footnote index. - display: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A brief description of the document or knowledge resource being referenced, suitable for display to a consumer. - citation: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: A bibliographic citation for the related artifact. This text SHOULD be formatted according to an accepted citation format. - url: - type: string - pattern: \S* - description: A url for the artifact that can be followed to access the actual content. - document: - $ref: "#/components/schemas/Attachment" - description: The document being referenced, represented as an attachment. This is exclusive with the resource element. - resource: - type: string - pattern: \S* - description: The related resource, such as a library, value set, profile, or other knowledge resource. - required: - - type - UsageContext: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - code: - $ref: "#/components/schemas/Coding" - description: A code that identifies the type of context being specified by this usage context. - valueCodeableConcept: - $ref: "#/components/schemas/CodeableConcept" - description: A value that defines the context specified in this context of use. The interpretation of the value is defined by the code. - valueQuantity: - $ref: "#/components/schemas/Quantity" - description: A value that defines the context specified in this context of use. The interpretation of the value is defined by the code. - valueRange: - $ref: "#/components/schemas/Range" - description: A value that defines the context specified in this context of use. The interpretation of the value is defined by the code. - valueReference: - $ref: "#/components/schemas/Reference" - description: A value that defines the context specified in this context of use. The interpretation of the value is defined by the code. - required: - - code - Meta: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - versionId: - type: string - pattern: "[A-Za-z0-9\\-\\.]{1,64}" - description: The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted. - lastUpdated: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)) - description: When the resource last changed – e.g. when the version changed. - source: - type: string - pattern: \S* - description: A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc. - profile: - type: array - items: - type: string - pattern: \S* - description: A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition–definitions.html#StructureDefinition.url). - security: - type: array - items: - $ref: "#/components/schemas/Coding" - description: Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure. - tag: - type: array - items: - $ref: "#/components/schemas/Coding" - description: Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource. - Narrative: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - status: - type: string - enum: - - generated - - extensions - - additional - - empty - description: The status of the narrative – whether it's entirely generated (from just the defined data or the extensions too), or whether a human authored it and it may contain additional data. - div: - type: string - description: The actual narrative content, a stripped down version of XHTML. - required: - - status - - div - Extension: - allOf: - - $ref: "#/components/schemas/Element" - - type: object - properties: - url: - type: string - pattern: \S* - description: Source of the definition for the extension code – a logical name or a URL. - valueBase64Binary: - type: string - pattern: (\s*([0-9a-zA-Z\+/=]){4}\s*)+ - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueBoolean: - type: boolean - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueCanonical: - type: string - pattern: \S* - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueCode: - type: string - pattern: "[^\\s]+(\\s[^\\s]+)*" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueDate: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1]))?)? - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueDateTime: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)? - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueDecimal: - type: number - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueId: - type: string - pattern: "[A-Za-z0-9\\-\\.]{1,64}" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueInstant: - type: string - pattern: ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)) - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueInteger: - type: integer - format: int32 - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueMarkdown: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueOid: - type: string - pattern: urn:oid:[0-2](\.(0|[1-9][0-9]*))+ - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valuePositiveInt: - type: integer - format: int32 - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueString: - type: string - pattern: "[ \\r\\n\\t\\S]+" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueTime: - type: string - pattern: ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)? - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueUnsignedInt: - type: integer - format: int32 - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueUri: - type: string - pattern: \S* - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueUrl: - type: string - pattern: \S* - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueUuid: - type: string - pattern: urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueAddress: - $ref: "#/components/schemas/Address" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueAge: - $ref: "#/components/schemas/Age" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueAnnotation: - $ref: "#/components/schemas/Annotation" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueAttachment: - $ref: "#/components/schemas/Attachment" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueCodeableConcept: - $ref: "#/components/schemas/CodeableConcept" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueCoding: - $ref: "#/components/schemas/Coding" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueContactPoint: - $ref: "#/components/schemas/ContactPoint" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueCount: - $ref: "#/components/schemas/Count" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueDistance: - $ref: "#/components/schemas/Distance" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueDuration: - $ref: "#/components/schemas/Duration" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueHumanName: - $ref: "#/components/schemas/HumanName" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueIdentifier: - $ref: "#/components/schemas/Identifier" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueMoney: - $ref: "#/components/schemas/Money" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valuePeriod: - $ref: "#/components/schemas/Period" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueQuantity: - $ref: "#/components/schemas/Quantity" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueRange: - $ref: "#/components/schemas/Range" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueRatio: - $ref: "#/components/schemas/Ratio" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueReference: - $ref: "#/components/schemas/Reference" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueSampledData: - $ref: "#/components/schemas/SampledData" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueSignature: - $ref: "#/components/schemas/Signature" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueTiming: - $ref: "#/components/schemas/Timing" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueContactDetail: - $ref: "#/components/schemas/ContactDetail" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueRelatedArtifact: - $ref: "#/components/schemas/RelatedArtifact" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueUsageContext: - $ref: "#/components/schemas/UsageContext" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - valueMeta: - $ref: "#/components/schemas/Meta" - description: Value of extension – must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list). - required: - - url - Version: - type: string - pattern: "^[1-9][0-9]+$" - RequestId: - type: string - pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" - example: 60E0B220-8136-4CA5-AE46-1D97EF59D068 - CorrelationId: - type: string - example: 11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA - securitySchemes: - app-level0: - $ref: https://proxygen.prod.api.platform.nhs.uk/components/securitySchemes/app-level0 - responses: - ProductTeamResponse: - description: Read Product Team operation successful - content: - application/json: - schema: - type: object - properties: - id: - type: string - name: - type: string - ods_code: - type: string - status: - type: string - created_on: - type: string - updated_on: - type: string - deleted_on: - type: string - keys: - type: array - items: - type: object - properties: - key_type: - type: string - key_value: - type: string - example: - id: "F5H1R" - name: "Sample Product Team" - ods_code: "F5H1R" - status: "active" - created_on: "2024-10-15T10:00:00Z" - updated_on: "2024-10-15T10:00:00Z" - keys: - - key_type: "product_team_id_alias" - key_value: "FOOBAR" - DeviceReferenceDataResponse: - description: Read Device Reference Data operation successful - content: - application/json: - schema: - type: object - properties: - id: - type: string - name: - type: string - product_id: - type: string - product_team_id: - type: string - ods_code: - type: string - status: - type: string - created_on: - type: string - updated_on: - type: string - deleted_on: - type: string diff --git a/docs/public_swagger/tests/test_swagger.py b/docs/public_swagger/tests/test_swagger.py deleted file mode 100644 index a052619d..00000000 --- a/docs/public_swagger/tests/test_swagger.py +++ /dev/null @@ -1,30 +0,0 @@ -from pathlib import Path - -import pytest - -PATH_TO_HERE = Path(__file__).parent -PATH_TO_ROOT = PATH_TO_HERE.parent.parent -PATH_TO_COPIED_PUBLIC_SWAGGER = PATH_TO_HERE.parent / "swagger.yaml" -PATH_TO_DIST_PUBLIC_SWAGGER = ( - PATH_TO_ROOT.parent - / "infrastructure" - / "swagger" - / "dist" - / "public" - / "swagger.yaml" -) - -# Should this test be failing, you need to copy the new swagger file from dist into this public_swagger location -# This is just a version controlled version of that file. - - -@pytest.mark.unit -def test_swagger_public_matches_dist(): - dist_swagger_file = PATH_TO_DIST_PUBLIC_SWAGGER - copied_swagger_file = PATH_TO_COPIED_PUBLIC_SWAGGER - - with open(dist_swagger_file, "r") as file1, open(copied_swagger_file, "r") as file2: - content1 = file1.read() - content2 = file2.read() - - assert content1 == content2, "Swagger files are not identical" From 8261e75f118236721786d0771a10c5c044a507b8 Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Wed, 18 Sep 2024 15:27:26 +0100 Subject: [PATCH 25/38] refactor load test --- load_test/locustfile.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/load_test/locustfile.py b/load_test/locustfile.py index 9ece99bc..5622419a 100644 --- a/load_test/locustfile.py +++ b/load_test/locustfile.py @@ -2,6 +2,8 @@ from locust import HttpUser, events, task +from src.api.tests.sds_data_tests.test_sds_data import _generate_test_data + class QueryParams: LDAP_UNIQUE_IDENTIFIER = "ldap_unique_identifier" @@ -77,6 +79,12 @@ def read_device_by_id(self): url=url_path, headers=_get_headers(version=API_VERSION, apikey=APIKEY) ) + @task + def search_devices(self): + test_data = _generate_test_data("queries.json") + url_path = f"/Device?{QueryParams.LDAP_UNIQUE_IDENTIFIER}={unique_identifier}" + self.client.get(url=url_path) + # @task # def search_cpm_for_unique_identifier(self): # unique_identifier = random.choice(unique_identifiers) From cf7870fb70c0d1af0e0ee5eb3de2f5bb164f287d Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Wed, 18 Sep 2024 15:46:01 +0100 Subject: [PATCH 26/38] queries --- load_test/speed_test_queries.py | 4796 +++++++++++++++++++++++++++++++ 1 file changed, 4796 insertions(+) create mode 100644 load_test/speed_test_queries.py diff --git a/load_test/speed_test_queries.py b/load_test/speed_test_queries.py new file mode 100644 index 00000000..fca78c67 --- /dev/null +++ b/load_test/speed_test_queries.py @@ -0,0 +1,4796 @@ +queries = [ + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|R8J3N"], + "identifier": ["https://fhir.nhs.uk/Id/nhsMhsPartyKey|R8J3N-830217"], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code| D83078"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|c83007"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": ["https://fhir.nhs.uk/Id/nhsMhsPartyKey|Y04933-814028"], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y04933"], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": ["https://fhir.nhs.uk/Id/nhsMhsPartyKey|R8J3N-830217"], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|R8J3N"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|YEA"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:pds:PRPA_IN160000UK01" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M85634"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81119"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C81051"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|C81051-825628", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|D82070"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|D82070-826979", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L84018"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|TP9EM"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B86100"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|B86100-824344", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B81054"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|B81054-829183", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L83013"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M85634"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M85634-826444", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G83006"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|G83006-827933", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A83016"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|A83016-811315", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G85633"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y02571"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|Y02571-827521", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L83101"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J83042"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N85620"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N82078"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|N82078-810449", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L85042"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K82040"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N82024"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|N82024-810421", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M91637"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M91637-827621", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P84051"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|P84051-810715", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|W93022"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B81017"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:location-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A84022"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|C82082-825974", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C82082"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|N81637-827237", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N81637"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C84091"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M91032"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E82652"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|E82652-826971", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H81094"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81186"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F81186-829267", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M83015"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y02289"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G8706201"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N85032"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81732"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L84048"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M81018"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:slot-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|DQ302"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E84067"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|E84067-828958", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81006"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|P81006-829805", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M84016"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M84016-828058", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L81132"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|L81132-829309", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G84029"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|G84029-827969", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A83637"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|A83637-811335", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H82067"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81726"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P82624"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C84036"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N82108"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:slot-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K81014"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N82024"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|N82024-810421", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N82001"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|N82001-810401", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J81027"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82095"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E82032"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|E82032-826933", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|D81081"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|D81081-827800", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|G85716-828240", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G85716"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F82001-827899", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F82001"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y01163"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B83062"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C86003"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|C86003-827861", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M86016"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M86016-828077", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C82010"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|C82010-826014", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J82089"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M85046"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B85652"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|B85652-827097", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F85666"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F85666-826216", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B81112"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|B81112-829147", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L84029"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|L84029-830442", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P84030"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K81042"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H85076"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F82660-827919", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F82660"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81735"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81704"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|P81704-829383", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F82014"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C81067"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|C81067-825610", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K82610"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J82104"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|J82104-824959", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P83623"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|P83623-831388", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A81039"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|A81039-831564", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C82056"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81732"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F81732-829277", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C84005"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|C84005-825635", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E81014"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E81037"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|E81037-829337", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J82113"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C86609"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getstructuredrecord-1" + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N81101"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M83054"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M83054-811176", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P84059"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|P84059-810718", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F84118"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F84118-828592", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|TP135"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A81041"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|A81041-829986", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M88003"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M88003-826395", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L85048"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|L85048-811682", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N82009"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|N82009-810411", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M81008"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M81008-827191", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B85005"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|B85005-826879", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|D83054"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|D83054-810585", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y04886"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:slot-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|Y04886-814026", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A86037"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G9307964"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A82023"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|RBL"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P86013"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|P86013-810245", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E85124"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P83011"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|P83011-830510", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C84086"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|C84086-825975", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A86029"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|A86029-834028", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A89028"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|A89028-812123", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A91151"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|TP59D"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|E85091-828449", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E85091"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|W93028"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81171"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|E85697-828825", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E85697"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H81123"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J83618"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B85022"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F85044"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F85044-813725", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|G82028-812960", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82028"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82037"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:create:appointment-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82025"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:slot-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82112"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J83045"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|J83045-812907", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L81125"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|L81125-826863", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H84639"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L82006"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:cancel:appointment-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C88084"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y02594"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B82035"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|B82035-829966", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|W92033"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient_appointments-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K83047"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82019"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M89026"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M89026-814840", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M81007"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y02718"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L81644"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N81074"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|N81074-812383", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C86023"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|C86023-827850", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N82668"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F82011"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F82011-828129", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M88620"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K83047"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|K83047-825745", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81141"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F81141-811343", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J81076"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81192"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F81192-812569", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M82005"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M82005-827363", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A87006"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C83060"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G84025"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|G84025-827966", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P84645"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|P84645-810732", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H85022"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C88052"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|C88052-826340", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|D81012"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M81016"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M81016-827139", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M91611"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M91611-827610", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A87007"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|A87007-811357", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M92016"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H81133"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|H81133-812159", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H84032"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|H84032-830695", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E81007"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A83030"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|A83030-811320", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82634"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|G82634-812172", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82027"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|G82027-829507", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E81003"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|E81003-829316", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G8508496"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81058"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|P81058-829372", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N82062"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N82054"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B81051"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81108"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F81108-829263", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M86039"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M86039-828092", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A81608"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M85676"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M85676-826446", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L82023"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K81087"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|L83059-826602", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L83059"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|W94030"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L83607"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|L83607-826565", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M81600"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M81600-827153", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81681"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:slot-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F81681-811347", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G83654"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|G83654-830444", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K81656"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F86020"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F86020-828328", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G81012"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E87046"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E82005"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|E82005-829857", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M87621"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B81009"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|B81009-829197", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E82046"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|W91034"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C87603"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F84692"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F84692-832694", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|TP0CY"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J83039"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H85682"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|H85682-829030", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P86620"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|P86620-810292", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P83001"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|P83001-831608", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F82627"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E87691"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H84017"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|H84017-828989", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L84016"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M88013"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M88013-826399", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A86021"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F82609"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F82609-828144", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81113"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|P81113-810867", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C84115"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N85040"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|N85040-812774", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N81041"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|N81041-827123", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M87623"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M87623-827576", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:slot-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K83007"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N82053"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|N82053-810436", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J83024"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|J83024-827042", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H82031"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|H82031-825381", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|E85032-828772", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E85032"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P84033"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M81090"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F85076"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K82068"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A86031"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|A86031-811075", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G8500065"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E84663"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H81020"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|H81020-811226", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y05525"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A82005"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|A82005-810834", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C83023"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|C83023-825947", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y03545"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E82027"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|E82027-826930", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J82628"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|J82628-810560", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P89006"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|P89006-811417", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F84034"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F84034-828579", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J81003"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|J81003-829571", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L83021"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|A83024-832174", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A83024"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|TP58N"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|ARX02-832069", + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|ARX02" + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B81031"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|B81031-826057", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N83002"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|N83002-811943", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E85685"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C88052"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M84009"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|M84009-813743", + ], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81697"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|F81697-812581", + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y02767"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H82033"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N85629"], + }, + "path": "/Device", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81027"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81123"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|D83017"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A84020"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E81635"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G85001"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|D83016"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N84037"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|D83005"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L82028"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M83706"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B83015"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A82055"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K84058"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82091"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L85001"], + "identifier": ["https://fhir.nhs.uk/Id/nhsMhsPartyKey|8JT17-834536"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81208"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E82644"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L84067"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P86015"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81700"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K81001"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E82038"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y03366"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P82627"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E83668"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B81064"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y00078"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y02476"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:appointment-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|C83035-825848", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|c83035"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M87007"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:cancel:appointment-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|K83047-825745", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K83047"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N82094"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|D82079"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G81694"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F85014"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B85660"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M87003"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J82126"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F83044"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|D83030"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G85696"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K82029"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F86626"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N84627"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F85013"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82162"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G84010"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81183"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F84003"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y07484"], + "identifier": ["https://fhir.nhs.uk/Id/nhsMhsPartyKey|Y07484-832158"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F82019"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G83029"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E81033"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J83041"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H85075"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B82028"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P92607"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y02589"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K81052"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C83040"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N84020"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P89005"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M88630"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G81034"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E86005"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:practitioner-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|G82022-812501", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82022"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H81025"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E86003"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B84021"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B82098"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M88023"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G84604"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C88655"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81014"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:cancel:appointment-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|K81014-826763", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K81014"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B86081"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B81002"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M84070"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient_appointments-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|G82152-812518", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82152"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82020"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A88010"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A84036"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G84011"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C83001"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E85719"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J82063"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E85122"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H84061"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F84731"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E84680"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|D83026-810572", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|D83026"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K83014"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C81096"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P88009"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81055"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N81031"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y01652"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N82049"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A82007"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J83618"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E85014"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A84008"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H82088"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A82055"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F84658"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A85616"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A81013"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M85020"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M82606"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M81084"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81742"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C87022"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L84045"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E82001"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E86017"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L82620"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y03079"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A88613"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C82651"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B85033"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F86044"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81171"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K82070"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F83025"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y03103"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H84010"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K82012"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P92626"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A83027"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81105"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F82686"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81213"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B81056"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P92028"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N85634"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K82038"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81066"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81699"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F82017"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C84084"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|D83041"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C86013"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C86611"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M87025"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H85075"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K82058"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y06345"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A81042"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M83035"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82158"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B85606"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L81004"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H84025"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L81051"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N85019"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C82053"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|D81618"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C84010"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A81630"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81141"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M82028"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L83070"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N81053"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:create:appointment-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|L85066-811696", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L85066"], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K81636"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C82059"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F84097"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C84014"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M85794"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|D83006"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K81050"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C82080"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M85179"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P85028"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81107"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|W93009"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82141"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y00758"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A89020"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81711"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81724"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:create:appointment-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|H85095-828561", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H85095"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C88051"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C84691"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81674"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient_appointments-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|K83616-825984", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K83616"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N83021"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J81083"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F82013"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P82004"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81690"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G85105"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F84681"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F86042"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G85084"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E87002"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A83040"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P81741"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H84034"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J81068"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81749"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:slot-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|K81070-815637", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K81070"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B83040"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P88016"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L84049"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82093"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C82092"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B82069"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J83645"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H81638"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82139"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P88623"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y01924"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M86041"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P88016"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|C88034"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E84083"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|H85637"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F81046"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M83719"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y05525"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:search:patient-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F86012"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F84047"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|P85004"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E87016"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M83017"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N83635"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N82076"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y02692"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|J82180"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E84075"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A81029"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G85005"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A84014"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N84021"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:appointment-1", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|G82741-810807", + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82741"], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B86044"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|N81065"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F82634"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|K81082"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:documents:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|F84111"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A81016"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|A84016"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|B81042"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M85145"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|M92629"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:structured:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|L83094"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|G82013"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata-1" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y01690"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|Y01690"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:rest:read:metadata" + ], + }, + "path": "/Endpoint", + }, + { + "params": { + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|FOOBAR" + ], + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|FOOBAR"], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:psisquery:FOO" + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|FOOBAR" + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:psisquery:FOO" + ], + "manufacturing-organization": [ + "https://fhir.nhs.uk/Id/ods-organization-code|FOOBAR" + ], + }, + "path": "/Device", + }, + { + "params": { + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:psisquery:FOO" + ] + }, + "path": "/Endpoint", + }, + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|FOOBAR"] + }, + "path": "/Endpoint", + }, +] From 263c73045e7da06b0b9bdf04a21cfab03367e651 Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Wed, 18 Sep 2024 17:55:54 +0100 Subject: [PATCH 27/38] method in locust script to use real queries --- infrastructure/terraform/locust/ec2_instances.tf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/infrastructure/terraform/locust/ec2_instances.tf b/infrastructure/terraform/locust/ec2_instances.tf index 948de2a5..0db6bc9d 100644 --- a/infrastructure/terraform/locust/ec2_instances.tf +++ b/infrastructure/terraform/locust/ec2_instances.tf @@ -44,6 +44,7 @@ resource "aws_instance" "locust_master" { sudo apt-get update sudo apt-get install -y python3-pip sudo apt-get install -y awscli + aws s3 cp s3://nhse-cpm--mgmt--locust-file/speed_test_queries.py . aws s3 cp s3://nhse-cpm--mgmt--locust-file/locustfile.py . pip3 install locust EOF @@ -68,6 +69,7 @@ resource "aws_instance" "locust_worker" { sudo apt-get update sudo apt-get install -y python3-pip sudo apt-get install -y awscli + aws s3 cp s3://nhse-cpm--mgmt--locust-file/speed_test_queries.py . aws s3 cp s3://nhse-cpm--mgmt--locust-file/locustfile.py . pip3 install locust EOF From ec4656ffe3a1e2ad78bf994ea41b12a4fc5eaf90 Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Wed, 18 Sep 2024 17:58:46 +0100 Subject: [PATCH 28/38] method in locust script to use real queries --- load_test/locustfile.py | 46 ++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/load_test/locustfile.py b/load_test/locustfile.py index 5622419a..946ddeda 100644 --- a/load_test/locustfile.py +++ b/load_test/locustfile.py @@ -1,8 +1,7 @@ import random from locust import HttpUser, events, task - -from src.api.tests.sds_data_tests.test_sds_data import _generate_test_data +from speed_test_queries import queries class QueryParams: @@ -59,6 +58,14 @@ def _(parser): required=True, help="apikey for hitting desired host", ) + parser.add_argument( + "--usecpm", + choices=["TRUE", "FALSE"], + default="FALSE", + env_var="USE_CPM", + required=False, + help="use_cpm for hitting cpm", + ) def _get_headers(version: str, apikey: str): @@ -68,22 +75,33 @@ def _get_headers(version: str, apikey: str): class CPMUser(HttpUser): - @task - def read_device_by_id(self): - device_id = random.choice(device_ids) - url_path = f"/Device/{device_id}" - APIKEY = self.environment.parsed_options.apikey - API_VERSION = self.environment.parsed_options.api_version + # @task + # def read_device_by_id(self): + # device_id = random.choice(device_ids) + # url_path = f"/Device/{device_id}" + # APIKEY = self.environment.parsed_options.apikey + # API_VERSION = self.environment.parsed_options.api_version - self.client.get( - url=url_path, headers=_get_headers(version=API_VERSION, apikey=APIKEY) - ) + # self.client.get( + # url=url_path, headers=_get_headers(version=API_VERSION, apikey=APIKEY) + # ) @task def search_devices(self): - test_data = _generate_test_data("queries.json") - url_path = f"/Device?{QueryParams.LDAP_UNIQUE_IDENTIFIER}={unique_identifier}" - self.client.get(url=url_path) + apikey = self.environment.parsed_options.apikey + API_VERSION = self.environment.parsed_options.api_version + USE_CPM = self.environment.parsed_options.usecpm + random_queries = random.sample(queries, 100) + for query in random_queries: + params = query["params"] + if USE_CPM == "TRUE": + params["use_cpm"] = "iwanttogetdatafromcpm" + url_path = f"{query['path']}" + self.client.get( + url=url_path, + params=params, + headers=_get_headers(version=API_VERSION, apikey=apikey), + ) # @task # def search_cpm_for_unique_identifier(self): From 9dbc08d0ea455a74ff53529f2bab8a2cec2a1bb6 Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Thu, 19 Sep 2024 09:35:30 +0100 Subject: [PATCH 29/38] Change task name --- load_test/locustfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/load_test/locustfile.py b/load_test/locustfile.py index 946ddeda..98f50e05 100644 --- a/load_test/locustfile.py +++ b/load_test/locustfile.py @@ -87,7 +87,7 @@ class CPMUser(HttpUser): # ) @task - def search_devices(self): + def search(self): apikey = self.environment.parsed_options.apikey API_VERSION = self.environment.parsed_options.api_version USE_CPM = self.environment.parsed_options.usecpm From f75ab131a76a0cf00181e8ead7f899ff10bf8a78 Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Thu, 19 Sep 2024 11:45:11 +0100 Subject: [PATCH 30/38] Remove unwanted --- load_test/locustfile.py | 108 ---------------------------------------- 1 file changed, 108 deletions(-) diff --git a/load_test/locustfile.py b/load_test/locustfile.py index 98f50e05..d0269e96 100644 --- a/load_test/locustfile.py +++ b/load_test/locustfile.py @@ -4,43 +4,6 @@ from speed_test_queries import queries -class QueryParams: - LDAP_UNIQUE_IDENTIFIER = "ldap_unique_identifier" - DEVICE_ID = "device_id" - DEVICE_KEY = "device_key" - PARTY_KEY = "party_key" - INTERACTION_ID = "interaction_id" - ODS_CODE = "ods_code" - - -unique_identifiers = ["1234567", "7654321"] - -device_keys = ["D81631:200000035358"] - -device_ids = ["3b9ced88-e2c2-4496-8ade-7fc3d5a8aba5"] - -interaction_ids = [ - "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:lrs:REPC_IN010000UK01" -] - -party_keys = ["https://fhir.nhs.uk/Id/nhsMhsPartyKey|5NR-801831"] - -ods_codes = ["https://fhir.nhs.uk/Id/ods-organization-code|5NR"] - - -sds_accredited_system_query_combinations = [ - {QueryParams.INTERACTION_ID, QueryParams.ODS_CODE, QueryParams.PARTY_KEY}, - {QueryParams.INTERACTION_ID, QueryParams.ODS_CODE}, -] - -sds_mhs_query_combinations = [ - {QueryParams.INTERACTION_ID, QueryParams.ODS_CODE, QueryParams.PARTY_KEY}, - {QueryParams.INTERACTION_ID, QueryParams.PARTY_KEY}, - {QueryParams.INTERACTION_ID, QueryParams.ODS_CODE}, - {QueryParams.PARTY_KEY, QueryParams.ODS_CODE}, -] - - @events.init_command_line_parser.add_listener def _(parser): parser.add_argument( @@ -75,17 +38,6 @@ def _get_headers(version: str, apikey: str): class CPMUser(HttpUser): - # @task - # def read_device_by_id(self): - # device_id = random.choice(device_ids) - # url_path = f"/Device/{device_id}" - # APIKEY = self.environment.parsed_options.apikey - # API_VERSION = self.environment.parsed_options.api_version - - # self.client.get( - # url=url_path, headers=_get_headers(version=API_VERSION, apikey=APIKEY) - # ) - @task def search(self): apikey = self.environment.parsed_options.apikey @@ -102,63 +54,3 @@ def search(self): params=params, headers=_get_headers(version=API_VERSION, apikey=apikey), ) - - # @task - # def search_cpm_for_unique_identifier(self): - # unique_identifier = random.choice(unique_identifiers) - # url_path = f"/Device?{QueryParams.LDAP_UNIQUE_IDENTIFIER}={unique_identifier}" - # apikey = self.environment.parsed_options.apikey - # API_VERSION = self.environment.parsed_options.api_version - - # self.client.get( - # url=url_path, - # headers=_get_headers(version=API_VERSION, apikey=apikey) - # ) - - # @task - # def search_cpm_for_accredited_system(self): - # selected_combination = random.choice(sds_accredited_system_query_combinations) - # selected_values = {} - # if QueryParams.INTERACTION_ID in selected_combination: - # selected_values['interaction'] = random.choice(interaction_ids) - - # if QueryParams.ODS_CODE in selected_combination: - # selected_values['code'] = random.choice(ods_codes) - - # if QueryParams.PARTY_KEY in selected_combination: - # selected_values['key'] = random.choice(party_keys) - - # query_params = urlencode(selected_values) - # url_path = f"/Device?{query_params}" - - # apikey = self.environment.parsed_options.apikey - # API_VERSION = self.environment.parsed_options.api_version - - # self.client.get( - # url=url_path, - # headers=_get_headers(version=API_VERSION, apikey=apikey) - # ) - - # @task - # def search_cpm_for_mhs(self): - # selected_combination = random.choice(sds_mhs_query_combinations) - # selected_values = {} - # if QueryParams.INTERACTION_ID in selected_combination: - # selected_values['interaction'] = random.choice(interaction_ids) - - # if QueryParams.ODS_CODE in selected_combination: - # selected_values['code'] = random.choice(ods_codes) - - # if QueryParams.PARTY_KEY in selected_combination: - # selected_values['key'] = random.choice(party_keys) - - # query_params = urlencode(selected_values) - # url_path = f"/Device?{query_params}" - - # apikey = self.environment.parsed_options.apikey - # API_VERSION = self.environment.parsed_options.api_version - - # self.client.get( - # url=url_path, - # headers=_get_headers(version=API_VERSION, apikey=apikey) - # ) From 8aba1009ee7e0bda256859f592b3b6fe5f0d54d5 Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Tue, 24 Sep 2024 10:25:35 +0100 Subject: [PATCH 31/38] Update locust to call 1 random endpoint --- load_test/locustfile.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/load_test/locustfile.py b/load_test/locustfile.py index d0269e96..551df11d 100644 --- a/load_test/locustfile.py +++ b/load_test/locustfile.py @@ -1,7 +1,21 @@ -import random +# import random from locust import HttpUser, events, task -from speed_test_queries import queries + +# from speed_test_queries import queries + +queries = [ + { + "params": { + "organization": ["https://fhir.nhs.uk/Id/ods-organization-code|E82652"], + "identifier": [ + "https://fhir.nhs.uk/Id/nhsServiceInteractionId|urn:nhs:names:services:gpconnect:fhir:operation:gpc.getcarerecord", + "https://fhir.nhs.uk/Id/nhsMhsPartyKey|E82652-826971", + ], + }, + "path": "/Device", + } +] @events.init_command_line_parser.add_listener @@ -43,8 +57,8 @@ def search(self): apikey = self.environment.parsed_options.apikey API_VERSION = self.environment.parsed_options.api_version USE_CPM = self.environment.parsed_options.usecpm - random_queries = random.sample(queries, 100) - for query in random_queries: + # random_queries = random.sample(queries, 100) + for query in queries: params = query["params"] if USE_CPM == "TRUE": params["use_cpm"] = "iwanttogetdatafromcpm" From 5d244ba3c164b4e4afdd02a84e243c526c2756f8 Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Thu, 17 Oct 2024 16:26:33 +0100 Subject: [PATCH 32/38] Fix something --- load_test/locustfile.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/load_test/locustfile.py b/load_test/locustfile.py index 551df11d..70db0c82 100644 --- a/load_test/locustfile.py +++ b/load_test/locustfile.py @@ -59,9 +59,10 @@ def search(self): USE_CPM = self.environment.parsed_options.usecpm # random_queries = random.sample(queries, 100) for query in queries: - params = query["params"] + params = query["params"].copy() if USE_CPM == "TRUE": params["use_cpm"] = "iwanttogetdatafromcpm" + url_path = f"{query['path']}" self.client.get( url=url_path, From 3a460b4acf494e69c5deca92eb69f4ceb9808a47 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Fri, 18 Oct 2024 13:36:44 +0100 Subject: [PATCH 33/38] [release/2024-10-16] fix-forward: update read device ref data tests --- .../readDeviceReferenceData.failure.feature | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/api/tests/feature_tests/features/readDeviceReferenceData.failure.feature diff --git a/src/api/tests/feature_tests/features/readDeviceReferenceData.failure.feature b/src/api/tests/feature_tests/features/readDeviceReferenceData.failure.feature new file mode 100644 index 00000000..d4a595aa --- /dev/null +++ b/src/api/tests/feature_tests/features/readDeviceReferenceData.failure.feature @@ -0,0 +1,57 @@ +Feature: Read Device Reference Data - failure scenarios + These scenarios demonstrate failure reading Device Reference Data + + Background: + Given "default" request headers: + | name | value | + | version | 1 | + | Authorization | letmein | + + Scenario: Read a deleted Product's DeviceReferenceData + Given I have already made a "POST" request with "default" headers to "ProductTeam" with body: + | path | value | + | name | My Great Product Team | + | ods_code | F5H1R | + And I note the response field "$.id" as "product_team_id" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: + | path | value | + | product_name | My Great Product | + And I note the response field "$.id" as "product_id" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/DeviceReferenceData" with body: + | path | value | + | name | My Device Reference Data | + And I note the response field "$.id" as "device_reference_data_id" + And I have already made a "DELETE" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }" + When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/DeviceReferenceData/${ note(device_reference_data_id) }" + Then I receive a status code "404" with body + | path | value | + | errors.0.code | RESOURCE_NOT_FOUND | + | errors.0.message | Could not find CpmProduct for key ('${ note(product_team_id) }', '${ note(product_id) }') | + And the response headers contain: + | name | value | + | Content-Type | application/json | + | Content-Length | 152 | + + Scenario: Read an unknown product teams DeviceReferenceData + Given I have already made a "POST" request with "default" headers to "ProductTeam" with body: + | path | value | + | name | My Great Product Team | + | ods_code | F5H1R | + And I note the response field "$.id" as "product_team_id" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: + | path | value | + | product_name | My Great Product | + And I note the response field "$.id" as "product_id" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/DeviceReferenceData" with body: + | path | value | + | name | My Device Reference Data | + And I note the response field "$.id" as "device_reference_data_id" + When I make a "GET" request with "default" headers to "ProductTeam/F5H1R.f63ba1d2-99b3-4e7f-83b4-a98178f1e4fe/Product/${ note(product_id) }/DeviceReferenceData/${ note(device_reference_data_id) }" + Then I receive a status code "404" with body + | path | value | + | errors.0.code | RESOURCE_NOT_FOUND | + | errors.0.message | Could not find ProductTeam for key ('F5H1R.f63ba1d2-99b3-4e7f-83b4-a98178f1e4fe') | + And the response headers contain: + | name | value | + | Content-Type | application/json | + | Content-Length | 140 | From 6dd5c55374cc74b7cc9ce78c13063ff2df7a7345 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Fri, 18 Oct 2024 16:56:55 +0100 Subject: [PATCH 34/38] [release/2024-10-16] fix-forward: update read device ref data tests --- .../readDeviceReferenceData.failure.feature | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/api/tests/feature_tests/features/readDeviceReferenceData.failure.feature b/src/api/tests/feature_tests/features/readDeviceReferenceData.failure.feature index d4a595aa..fa5d8265 100644 --- a/src/api/tests/feature_tests/features/readDeviceReferenceData.failure.feature +++ b/src/api/tests/feature_tests/features/readDeviceReferenceData.failure.feature @@ -55,3 +55,27 @@ Feature: Read Device Reference Data - failure scenarios | name | value | | Content-Type | application/json | | Content-Length | 140 | + + Scenario: Read an unknown DeviceReferenceData + Given I have already made a "POST" request with "default" headers to "ProductTeam" with body: + | path | value | + | name | My Great Product Team | + | ods_code | F5H1R | + And I note the response field "$.id" as "product_team_id" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product" with body: + | path | value | + | product_name | My Great Product | + And I note the response field "$.id" as "product_id" + And I have already made a "POST" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/DeviceReferenceData" with body: + | path | value | + | name | My Device Reference Data | + And I note the response field "$.id" as "device_reference_data_id" + When I make a "GET" request with "default" headers to "ProductTeam/${ note(product_team_id) }/Product/${ note(product_id) }/DeviceReferenceData/not-a-device-reference-data" + Then I receive a status code "404" with body + | path | value | + | errors.0.code | RESOURCE_NOT_FOUND | + | errors.0.message | Could not find DeviceReferenceData for key ('${ note(product_team_id) }', '${ note(product_id) }', 'not-a-device-reference-data') | + And the response headers contain: + | name | value | + | Content-Type | application/json | + | Content-Length | 192 | From a60e5ad5355326af11e5fbd29943316e9c4dd9e2 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Mon, 21 Oct 2024 09:54:49 +0100 Subject: [PATCH 35/38] trigger workflow From 3a06d204da83d21ad48b86b28bbaa3b8b9167aaf Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Mon, 21 Oct 2024 10:10:53 +0100 Subject: [PATCH 36/38] Remove commented code --- load_test/locustfile.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/load_test/locustfile.py b/load_test/locustfile.py index 70db0c82..fbb55cf4 100644 --- a/load_test/locustfile.py +++ b/load_test/locustfile.py @@ -1,9 +1,5 @@ -# import random - from locust import HttpUser, events, task -# from speed_test_queries import queries - queries = [ { "params": { @@ -57,7 +53,6 @@ def search(self): apikey = self.environment.parsed_options.apikey API_VERSION = self.environment.parsed_options.api_version USE_CPM = self.environment.parsed_options.usecpm - # random_queries = random.sample(queries, 100) for query in queries: params = query["params"].copy() if USE_CPM == "TRUE": From aa4f390a11a2f43c9e2944e98bdd5cd126c401c2 Mon Sep 17 00:00:00 2001 From: jameslinnell Date: Mon, 21 Oct 2024 10:51:33 +0100 Subject: [PATCH 37/38] Merge PI-365, PI-276, PI-562, PI-548 --- CHANGELOG.md | 4 ++++ changelog/2024-10-16.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cc04d70..78c34214 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ - [PI-503] Read Device Reference Data - [PI-536] Create Cpm Product without FHIR - [PI-535] Read Product Team without FHIR +- [PI-548] Sonarcloud configuration +- [PI-365] Locust load testing +- [PI-276] Proxygen Spec +- [PI-562] Feature Tests for CpmProduct ## 2024-10-15 - [PI-533] Create Product Team without FHIR diff --git a/changelog/2024-10-16.md b/changelog/2024-10-16.md index fdd61c36..92e46a38 100644 --- a/changelog/2024-10-16.md +++ b/changelog/2024-10-16.md @@ -2,3 +2,7 @@ - [PI-503] Read Device Reference Data - [PI-536] Create Cpm Product without FHIR - [PI-535] Read Product Team without FHIR +- [PI-548] Sonarcloud configuration +- [PI-365] Locust load testing +- [PI-276] Proxygen Spec +- [PI-562] Feature Tests for CpmProduct From 954e0f3b9ec48aac5b07aaaef5095113fdbc26c6 Mon Sep 17 00:00:00 2001 From: Joel Klinger Date: Mon, 21 Oct 2024 13:37:31 +0100 Subject: [PATCH 38/38] [release/2024-10-16] fix-forward: remove key from smoke test --- src/api/tests/smoke_tests/test_smoke.py | 4 ++-- .../tests/data/cpm-product-team-example-no-id-no-keys.json | 4 ++++ src/test_helpers/sample_data.py | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 src/layers/domain/request_models/tests/data/cpm-product-team-example-no-id-no-keys.json diff --git a/src/api/tests/smoke_tests/test_smoke.py b/src/api/tests/smoke_tests/test_smoke.py index ab2e8081..25033827 100644 --- a/src/api/tests/smoke_tests/test_smoke.py +++ b/src/api/tests/smoke_tests/test_smoke.py @@ -4,14 +4,14 @@ import pytest import requests -from test_helpers.sample_data import CPM_PRODUCT_TEAM_NO_ID +from test_helpers.sample_data import CPM_PRODUCT_TEAM_NO_ID_NO_KEYS from test_helpers.terraform import read_terraform_output from .utils import execute_smoke_test, get_app_key, get_base_url, get_headers def create_and_read_product_team(base_url: str, headers: dict): - product_team_body = json.dumps(CPM_PRODUCT_TEAM_NO_ID) + product_team_body = json.dumps(CPM_PRODUCT_TEAM_NO_ID_NO_KEYS) url = f"{base_url}/ProductTeam" response = requests.post(url=url, headers=headers, data=product_team_body) response_body = response.json() diff --git a/src/layers/domain/request_models/tests/data/cpm-product-team-example-no-id-no-keys.json b/src/layers/domain/request_models/tests/data/cpm-product-team-example-no-id-no-keys.json new file mode 100644 index 00000000..9dc31715 --- /dev/null +++ b/src/layers/domain/request_models/tests/data/cpm-product-team-example-no-id-no-keys.json @@ -0,0 +1,4 @@ +{ + "ods_code": "F5H1R", + "name": "FOOBAR Product Team" +} diff --git a/src/test_helpers/sample_data.py b/src/test_helpers/sample_data.py index a5441c49..657a9def 100644 --- a/src/test_helpers/sample_data.py +++ b/src/test_helpers/sample_data.py @@ -28,6 +28,9 @@ def _read_core_test_data(file_name: str) -> dict | list: CPM_PRODUCT_TEAM_NO_ID = _read_core_test_data( f"{PATH_TO_CORE_CPM_TEST_DATA}/cpm-product-team-example-no-id.json" ) +CPM_PRODUCT_TEAM_NO_ID_NO_KEYS = _read_core_test_data( + f"{PATH_TO_CORE_CPM_TEST_DATA}/cpm-product-team-example-no-id-no-keys.json" +) CPM_PRODUCT_TEAM_NO_ID_KEYS_NOT_ALLOWED = _read_core_test_data( f"{PATH_TO_CORE_CPM_TEST_DATA}/cpm-product-team-example-no-id-keys-not-allowed.json" )