Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Table of Contents

...

Page Properties
idAPI_Specification

Link

https://ehealthmedicaleventsapi.docs.apiary.io/#reference/device-dispenses/create-device-dispense/create-device-dispense

Посилання на Apiary або Swagger

Resource

/api/patients/{{patient_id}}/device_dispenses

Посилання на ресурс, наприклад: /api/persons/create

Scope

device_dispense:write

Scope для доступу

Components

Devices

Зазначається перелік бізнес компонентів, які використовують цей метод, наприклад: ePrescription

Microservices

Перелік мікросервісів, які використовує метод API, наприклад: Auth, ABAC

Protocol type

REST

Тип протоколу, який використовується запитом, наприклад: SOAP | REST

Request type

POST

Тип запиту API, наприклад: GET, POST, PATCH…

Sync/Async

Async

Метод є синхронним чи асинхронним?

Public/Private/Internal

Public

Потрібно зазначити тип методу за ступенем доступності

Logic

  • Fill in the following fields:

    • status = IN_PROGRESS

    • status_reason = null

    • subject. Set hashed patient_id from URL

    • performer_legal_entity. Set client_id from token

    • quantity.unit. Set description according to quantity code and system

    • inserted_at. Set current date and time

    • updated_at. Set current date and time

    • inserted_by. Set current user from token

    • updated_by. Set current user from token

  • Save data to device_dispenses collection in MongoDB according to /wiki/spaces/CSI/pages/17467572335

  • Send StatusChangeEvent to Event Manager

Input parameters

Input parameter

Values

Type

Description

Example

patient_id

String

Unique patient identifier

aff00bf6-68bf-4b49-b66d-f031d48922b3

Request structure

See on Apiary

...

Expand
titleRequest example
Code Block
{
  "id": "b075f148-7f93-4fc2-b2ec-2d81b19a9b7b",
  "based_on": {
    "identifier": {
      "type": {
        "coding": [
          {
            "system": "eHealth/resources",
            "code": "device_request"
          }
        ]
      },
      "value": "b4a6d991-0bf7-476f-b3cf-bec83f044b1b"
    },
    "display_value": "null"
  },
  "performer": {
    "identifier": {
      "type": {
        "coding": [
          {
            "system": "eHealth/resources",
            "code": "employee"
          }
        ]
      },
      "value": "b4a6d991-0bf7-476f-b3cf-bec83f044b1b"
    },
    "display_value": "Мельник Микола Микитович"
  },
  "location": {
    "identifier": {
      "type": {
        "coding": [
          {
            "system": "eHealth/resources",
            "code": "division"
          }
        ]
      },
      "value": "b4a6d991-0bf7-476f-b3cf-bec83f044b1b"
    },
    "display_value": "Перше відділення"
  },
  "note": "Some notes",
  "program": {
    "identifier": {
      "type": {
        "coding": [
          {
            "system": "eHealth/resources",
            "code": "medical_program"
          }
        ]
      },
      "value": "c5a6d991-0bf7-476f-b3cf-bec83f044b2a"
    },
    "display_value": "Доступні медичні вироби"
  },
  "details": [
    {
      "device": {
        "identifier": {
          "type": {
            "coding": [
              {
                "system": "eHealth/resources",
                "code": "device_definition"
              }
            ]
          },
          "value": "b4a6d991-0bf7-476f-b3cf-bec83f044b1b"
        },
        "display_value": "null"
      },
      "program_device": {
        "identifier": {
          "type": {
            "coding": [
              {
                "system": "eHealth/resources",
                "code": "program_device"
              }
            ]
          },
          "value": "b4a6d991-0bf7-476f-b3cf-bec83f044b1b"
        },
        "display_value": "null"
      },
      "quantity": {
        "value": 10,
        "system": "device_unit",
        "code": "piece"
      },
      "sell_price": 18.65,
      "discount_amount": 150
    }
  ],
  "verification_code": "102364",
  "status": "in_progress"
}

...

Authorization

  1. Verify the validity of access token

    • in case of error - return 401 (“Invalid access token”) in case of validation fails

  2. Verify that token is not expired

    • in case of error - return 401 (“Invalid access token”)

  3. Check user and client scopes in order to perform this action (scope = 'device_dispense:write')

    • return 403 (“Your scope does not allow to access this resource. Missing allowances: device_dispense:write”) in case of invalid scope(s)

  4. If BLOCK_UNVERIFIED_PARTY_USERS is true, then check party's data match following condition: verification_status != NOT_VERIFIED or (verification_status = NOT_VERIFIED and updated_at > current_date - UNVERIFIED_PARTY_PERIOD_DAYS_ALLOWED):

    1. in case not match - return 403 ("Access denied. Party is not verified")

  5. If BLOCK_DECEASED_PARTY_USERS is true, check that party is not deceased (party_verification record does not equal to: dracs_death_verification_status = VERIFIED and dracs_death_verification_reason = MANUAL_CONFIRMED):

    1. in case of error - return 403 ("Access denied. Party is deceased")

Headers

  • Content-Type:application/json

  • Authorization:Bearer mF_9.B5f-4.1JqM

  • api-key:aFBLVTZ6Z2dON1V

Request data validation

Validate legal entity

...

Extract client_id from token

...

Validate legal entity

  • Extract client_id from token

  • Check legal entity exists and its status is ACTIVE

    • In case of error - return 409 ('client_id refers to legal entity that is not active')

Validate dispense

Validate performer

Validate value in the field $.performer, Reference on employee resource, required.

  • Extract user_id from token. Check that requester belongs to one of the user’s employee.

    • in case of error - return 422 ('User is not allowed to create device request dispense for the requesterperformer')

  • Check performer is an active and approved employee.

    • in case of error - return 422 ('Employee is not active ')

  • Check performer relates to the legal entity (client_id from token).

    • in case of error - return 422 ('Employee does not belong to legal entity from token')

...

  • Check that division exists and is_active = true

    • in case of error - return 409 ("Division not found")

  • Check that division is activestatus = “ACTIVE”

    • in case of error - return 409 ("Division is not active")

  • Validate division belongs to user's legal entity (client_id from token)

    • in case of error - return 409 ("Division does not belong to user's legal entity")

  • If chart parameter DEVICE_DISPENSE_DIVISION_DLS_VERIFY is on, then validate division is DLS verified (dls_verified=true)

    • in case of error - return 409 "Division is not verified in DLS"

...

  • Check that device request exists

    • in case of error - return 422 ('Device request not found')

  • Check that intent specified in Device request is order

    • in case of error - return 409 error ('Only device request with intent = 'order' can be dispensed')

  • Сheck that Device request is in status 'ACTIVE'

    • in case of error - return 409 422 error ('Device request is not active')

...

  • Check that program in dispense is the same as program in device request _valid_to is greater or equal to current date

    • in case of error - return 409 ('Device request is expired for dispense')

Validate program

  • Check that program in dispense is the same as program in device request (request.program.identifier.value = device_requests.program.identifier.value)

    • in case of error - return 409 422 ('"Program in dispense doesn't match the one in device from request 'params")

Qualify Device request

This validation must be done only if medical_program exists in request and medical_program is the same as in device request

  • Check that Device request is valid and available for dispense under this medical program

    • Invoke https://e-health-ua.atlassian.net/wiki/spaces/CSIEH/pages/17467834459Check that program/17492804914/RC+Qualify+Device+Request+by+ID

    • Check that program_id is in Qualify response

      • Device request is prohibited for dispense in case $.data[?(@.program_id=device_request.program.identifier.value)].status = 'INVALID' or program_id is absent in qualify response

        • In case of error - return 409 error ('Device request can not be dispensed. Invoke qualify dispense request API to get detailed info')

      • Device request is allowed for dispense in case $.data[?(@.program_id=device_request.program.identifier.value)].status = 'VALID' and program_id is present in qualify response

...

  • Check that there is no other IN_PROGRESS device dispenses based on the same device request

    • Find all device dispenses related to the same device request ($.based_on)

    • Check that there are no records in status in-progress where inserted_at + config device_dispense_ttl >= current date-time()

      • in case of error - return 422 "Other active device dispense dispenses already exist."

Validate Dispense details

...

  • Check device (device definition) to be dispensed ($.dispense_details.device)

    • Check code ($.dispense_details.device.identifier.type.coding.code) = device_definition

      • in case of error - return 422 ('Only device definition value is not allowed for dispensein enum')

    • Get device definition by id ($.dispense_details.device.identifier.value)

      • device_definition.is_active = true

        • in case of error - return 422 ('Device definition not found')

    • Check that this device definition is compliant with prescribed device

      • If device_request.code is of type Reference

        • Check that device_definition_id in dispense is equal to device_definition_id in request

      • If device_request.code is of type CodeableConcept

        • Check that device_definition.classification_type is equal to prescribed device definition code in device request (device_request.code)

      • in case of error - return 422 ('Dispensed device doesn’t match with prescribed device')

    • Check that packaging_unit matches with quantity.code of the Device Request

      • in case of error - return 422 (Dispensed packaging unit doesn’t match with prescribed packaging unit)

    • Check the remainder of the division ($.device_requestdetails.quantity.value/device_definition.packaging_count) is equal to 0

      • in case of error - return reject_reason = “The quantity must be divisible to packaging_count of prescribed Device Definition”

...

  • Check program device

    • Is applicable only if program was passed to request and program device passed to request

      • Check code ($.dispense_details.program_device.identifier.type.coding.code) = program_device

        • in case of error - return 422 ('Invalid code. Expected 'program_device'value is not allowed in enum')

      • Check that program device exists in DB and has is_activeCheck that program device has =true

        • in case of error - return 422 ('Program device not found')

      • Check that program device has validity period (start_date and end_date) within current date

        • in case of error - return 422 ('Program device is not active')

      • Check that max daily count is not exceeded - max_daily_count is null or max_daily_count >= quantity.value/(occurence_period.end - occurence_period.start) of the Device Requestprogram device relates to the device definition in $.details.device

        • in case of error - return 422 ('max daily count exceeded')

        Check that program device relates to the device definition in $.dispense_details.device

        • in case of error - return 422 ('Program device Program device doesn’t match with device')

      • Check that program device relates to the program in $.program

        • in case of error - return 422 ('Program device doesn’t match with program')

    • if program was passed to request and no program device specified

      • find program device related to dispensed device definition and selected program with:

        • active status

        • validity period (start_date and end_date) within current date

          max daily count is not exceeded: max_daily_count is null or max_daily_count >= quantity.value/(occurence_period.end - occurence_period.start) of the Device Request

          • in case not found - return 422 ('in case not found - return 422 ('No appropriate participants found for this medical program')

          • in case found more then one - return 422 ('More than one program_device was found. Specify the required in the request')

Valdate quantity

Perform the validation if Device request has quantity

  • Validate quantity value

    • Check that dispensed device quantity is equal to prescribed quantity in Device Request

    • sum($.dispense_details.quantity.value) = device_request.quantity

      • in case of error - return 422 ('Dispensed quantity must be equal to prescribed quantity in Device Request')

  • Validate

...

  • Validate sell_price

    Check it is present if medical program is present and has funding_source = "NHS"

    quantity units

    • Check that quantity.code matches with packaging_unit of the device

      • in case of error - return 422 (Does not match the packaging unit of the prescribed device)

Validate discount

  • Validate sell_price

    • Check it is present if medical program is present

      • in case of error - return 422 ('Required property sell_price was not present')

  • Validate discount_amount

    • Check it is present if medical program is present and has funding_source = "NHS"

      • in case of error - return 422 ('Required property discount_amount was not present')

    • Check it is absent if medical program is absent

      • in case of error - return 422 ('Property discount_amount shouldn’t be submitted if medical program is absent')

    • Calculate allowed reimbursement amount:

      • If reimbursement_type of program_device is PERCENTAGE:

        • If reimbursement_percentage_discount of program_device is zero, then check $.discount_amount is equal to zero too

          • in case of error - return 422 ('Requested discount amount must be equal to 0')

        • Calculate allowed_reimbursement_amount = $.sell_price * program_device.reimbursement_percentage_discount/100

      • If reimbursement_type of program_device is FIXED:

        • Get allowed_reimbursement_amount = program_device.reimbursement_amount

    • Check $.discount_amount <= allowed_reimbursement_amount * ($.dispense_details.quantity.value/device_definition.packaging_count) + DEVICE_DISPENSE_TOLERANCE

      • in case of error - return 422 ('Requested discount amount must be less or equal to allowed reimbursement amount')

    • Check the ratio of discount amount to reimbursement amount as $.discount_amount/ (allowed_reimbursement_amount * ($.dispense_details.quantity.value/device_definition.packaging_count)) >= 1 - DEVICE_DISPENSE_DEVIATION

      • In case of error - return 422 ('The ratio of requested discount amount to allowed reimbursement amount must be greater or equal to <1 - DEVICE_DISPENSE_DEVIATION>')

...

  • Check that $.verification_code in request is equal to verification_code in device_code in device_request

    • In case code exists in request - it should match with code in device_request

      • in case of error - return 403 (message: “Incorrect code“)

Processing

API paragraph not found

  • request

    • In case code exists in request - it should match with code in device_request

      • in case of error - return 403 (message: “Incorrect code“)

Service logic

  • Fill in the following fields:

    • status = IN_PROGRESS

    • status_reason = null

    • subject. Set hashed patient_id from URL

    • performer_legal_entity. Set client_id from token

    • details.quantity.unit. Set description according to quantity code and system

    • details.reimbursement_amount. Set calculated above allowed_reimbursement_amount from program_medication if program is present.

    • inserted_at. Set current date and time

    • updated_at. Set current date and time

    • inserted_by. Set current user from token

    • updated_by. Set current user from token

  • Save data to device_dispenses collection in MongoDB according to /wiki/spaces/CSI/pages/17467572335

  • Send StatusChangeEvent to Event Manager

Response structure

See on Apiary

...

Expand
titleResponse example
Code Block
{
  "data": {
    "status": "pending",
    "eta": "2018-08-02T10:45:16.000Z",
    "links": [
      {
        "entity": "job",
        "href": "/Jobs/NBXk9EyErUZv1RhXgyvgg"
      }
    ]
  },
  "meta": {
    "code": 202,
    "url": "http://example.com/resource",
    "type": "object",
    "request_id": "req-adasdoijasdojsda"
  }
}

Post-processing processes

...

HTTP status codes

Page Properties
idAPI_HTTP status codes

HTTP status code

Message

What caused the error

 202

 

 

...