Table of Contents |
---|
Purpose
This method is designed to create hold (reservation) on medication in order to prevent multiple dispenses under the same Medication Request. This hold lasts certain time (configuration parameter MEDICATION_DISPENSE_EXPIRATION) after with it goes to EXPIRED status.
Specification
...
Link
...
...
Посилання на Apiary або Swagger
...
Resource
...
/api/medication_dispenses
...
Посилання на ресурс, наприклад: /api/persons/create
...
Scope
...
medication_dispense:write
...
Scope для доступу
...
Components
...
ePrescription, Reimbursement
...
Зазначається перелік бізнес компонентів, які використовують цей метод, наприклад: ePrescription
...
Microservices
...
API paragraph not found
...
Перелік мікросервісів, які використовує метод API, наприклад: Auth, ABAC
...
Protocol type
...
REST
...
Тип протоколу, який використовується запитом, наприклад: SOAP | REST
...
Request type
...
POST
...
Тип запиту API, наприклад: GET, POST, PATCH…
...
Sync/Async
...
Sync
...
Метод є синхронним чи асинхронним?
Logic
...
Dispense details - several medications of different manufacturers with the same substance can be dispensed at a time. Total of medication_qty should be less or equal to medication quantity specified in Medication Request
...
If patient wants to split medication dispense of his medication request into several parts, it is possible to create and process medication dispense of the medication request with the desired medication quantity.
If medical program has setting with parameter skip_medication_dispense_sign
= true then fields payment_amount
and payment_id
should be submitted. In this case process of medication dispense will be performed on create (w/o using digital sign)
Important In case medications are dispensed to patient under specific medical program, program participant id must be provided also.
Preconditions
No
Global and configurable parameters
No
Input parameters
No
Filters
...
Filter
...
Values
...
Type
...
Description
...
Example
...
code
...
Optional
...
3114
Request structure
See on Apiary
Example:
Expand | ||
---|---|---|
| ||
|
Authorize
Verify the validity of access token
return 401 in case validation fails.
Check user scopes in order to perform this action (scope = 'medication_dispense:write')
return 403 in case invalid scope(s).
Headers
Content-Type:application/json
Authorization:Bearer c2778f3064753ea70de870a53795f5c9
Validate request
Validate request according to JSON Schema
Return 422 with list of validation errors in case validation fails (422 EView)
Expand | ||
---|---|---|
| ||
|
Request data validation
Validate program medication
In case medications are dispensed to patient under specific medical program, program medication id must be provided provided by client or calculated by the system
In case program medication id exists in request:
Check that this program medication id relates to provided medical program and relates to provided medication
In case of error - return 422 (Invalid program medication id)
Calculate program medication id if it is absent in request:
Get last program_medication_id related to medical program and medication
In case of error - return 422 (There are no active program medications for this program and medication)
Get legal entity from token
Extract legal_entity_id (client_id) from token
Get Party from token
Extract party_user (user_id) from token.
Validate FK
Validate
legal_entity_id - legal_entity_id exists
In case error - return 422 error:
Code Block |
---|
{:error, [{%{
description: "Legal entity not found",
params: [],
rule: :invalid
}, "$.legal_entity_id"}]} |
Validate
medication_request_id - medication_request_id exists
Code Block |
---|
{:error, [{%{
description: "Medication request not found",
params: [],
rule: :invalid
}, "$.medication_request_id"}]} |
Validate
...
Table of Contents |
---|
Purpose
This method is designed to create a hold (reservation) on medication in order to prevent multiple dispenses under the same Medication Request. This hold lasts certain time (configuration parameter MEDICATION_DISPENSE_EXPIRATION) after which it goes to EXPIRED status.
Key features
Dispense of medication is possible only under Medication Request and during the period specified in Medication Request (dispense_valid_from,dispense_valid_to).
Dispense details - several medications of different manufacturers with the same substance can be dispensed at a time. The total of medication_qty should be less or equal to the medication quantity specified in the Medication Request.
Status Charts (reimbursement).
Specification
Page Properties | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Logic
Get skip_medication_dispense_sign from medical program settings.
If skip_medication_dispense_sign = false or absent:
2.1. Check payment_id, payment_amount is present in the request.
in case if absent - return 422 with path: $.<field_name> and message "schema does not allow additional properties"
2.2. Add record to medication_dispenses table:
Parameter | Source | Description |
---|---|---|
id | UUID | Autogenerated |
payment_id | NULL | NULL for new records |
payment_amount | NULL | NULL for new records. |
status | Const: NEW | NEW skip_medication_dispense_sign = false |
is_active | Const: TRUE | Alwayls TRUE for new records |
inserted_at | Timestamp: now() | Get current date-time |
inserted_by | Token: user_id | Extract user from token |
updated_at | Timestamp: now() | Get current date-time |
updated_by | Token: user_id | Extract user from token |
2.3. Add records to medication_dispense_details table:
Parameter | Source | Description |
---|---|---|
id | UUID | Autogenerated |
medication_dispense_id | FK: medication_dispense |
|
reimbursement_amount | Reimbursement |
|
2.4. Add records to medication_2d_codes table (for each 2d code object in array):
Parameter | Source | Description |
---|---|---|
id | UUID | Autogenerated |
medication_dispense_id | FK: medication_dispense |
|
medication_2d_code | Request: medication_2d_codes |
|
inserted_at | Timestamp: now() | Get current date-time |
If skip_medication_dispense_sign =
true:
3.1. Check if payment_amount in the request.
in case is absent - return 422 with path: $.payment_amount and message "required property payment_amount was not present"
3.1. Call Process Medication Dispense by Pharmacy User process, but without validation of the previously created (NEW) medication dispense, digital sign and storage signed content to the bucket.
3.2. Add records as described on steps 2.2-2.4, but with following differences:
medication_dispenses table
Parameter | Source | Description |
---|---|---|
payment_id | Request: payment_id | optional parameter |
payment_amount | Request: payment_amount | optional parameter |
status | Const: PROCESSED | PROCESSED skip_medication_dispense_sign = true |
Preconditions
No
Global and configurable parameters
No
Input parameters
No
Filters
Filter | Values | Type | Description | Example |
---|---|---|---|---|
code | Optional | 3114 |
Request structure
Example:
Expand | ||
---|---|---|
| ||
|
Authorize
Verify the validity of access token
return 401 in case validation fails.
Check user scopes in order to perform this action (scope = 'medication_dispense:write')
return 403 in case invalid scope(s).
Headers
Content-Type:application/json
Authorization:Bearer c2778f3064753ea70de870a53795f5c9
Validate request
API paragraph not found
Request data validation
Schema validation
Validate request according to JSON Schema
Return 422 with list of validation errors in case validation fails (422 EView).
Validate program medication
In case medications are dispensed to patient under specific medical program, program medication id must be provided provided by client or calculated by the system.
In case program medication id exists in request:
Check that this program medication id relates to provided medical program and relates to provided medication
In case of error - return 422 (Invalid program medication id).
Calculate program medication id if it is absent in request:
Get last program_medication_id related to medical program and medication
In case of error - return 422 (There are no active program medications for this program and medication).
Get legal entity from token
Extract legal_entity_id (client_id) from token.
Get Party from token
Extract party_user (user_id) from token.
Validate FK
Validate
legal_entity_id - legal_entity_id exists
In case error - return 422 error:
|
...
|
...
|
...
|
...
|
...
|
...
|
2. Validate
divisionmedication_request_id - divisionmedication_request_id exists
|
...
|
...
|
...
|
...
|
...
|
...
|
3. Validate
medical_programparty_id - medical_programparty_id exists
|
...
|
...
|
...
|
...
|
...
|
...
|
5.1 Validate there is a contract in PRM.contracts that meets following requirements:
...
contracts.type==reimbursement
...
contracts.status==VERIFIED
...
Contract dates: start_date <= current_date & end_date >= current_date
...
contracts.contractor_legal_entity_id=token.client_id
...
$division_id in contract_divisions
...
4. Validate
division_id - division_id exists
|
5. Validate
medical_program_id - medical_program_id
...
сontracts.is_suspended ==false
In case of error 409 - "Program cannot be used - no active contract exists"
exists
|
6. Validate all medication_id (brand_id) - brand_id exists
|
...
|
...
|
...
|
Validate code
Check that code in request is equal to code in medication_request (or both is empty)
In case code exists in request - it should match with code in medication_request
Return 401 in case code doesn't match (message = "Incorrect code").
In case code is missing in request - check that code in medication_request is NULL
Return 401 in case code in medication_request is not NULL (message = "Missing or Invalid code").
Validate related Care plan
If (medication_request.based_on is present and not null) AND medication_program is absent:
Verify Care plan:
It should be in active status
in case of error - return 409 (message: "Invalid care plan status").
Care plan's period end (if exist) should be greater than current date or equal
in case of error - return 409 (message: “Care plan expired“).
Verify care plan Activity:
It has scheduled, in_progress status
in case of error - return 409 (message: "Invalid activity status").
Validate division
If division_id submitted:
Validate division is active
in case of error - return 409 ("Division is not active").
Validate division belongs to user's legal entity
in case of error - return 409 ("Division does not belong to user's legal entity").
If chart parameter 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"
...
If chart parameter MEDICAL_PROGRAM_PROVISION_VERIFY, then check division provide each submitted program. For each medical program provision validate:
it is exist and active:
in case of error - return status=INVALID for a program, rejection_reason= "Division does not provide the medical program"
it relates to the actual reimbursement contract: contract.start_date <= current_date <= contract.end_date, is_active = true, status = VERIFIED.
in case of error - return status=INVALID for a program, rejection_reason="Medical program provision is not related to any actual contract for the current date"
Validate code
Check that code in request is equal to code in medication_request (or both are empty)
...
In case code exists in request - it should match with code in medication_request
Return 401 in case code doesn't match (message = "Incorrect code")
In case code is missing in request - check that code in medication_request is NULL
...
.
Get license_types_allowed parameter from settings of medical program from request $.medical_program_id:
if it is exists and not empty, get list of all license types from parameter.
Check that division has active healthcare services with following parameters:legal_entity_id = client_id from access token
division_id = division_id from request
status = 'ACTIVE'
licensed_healthcare_service.status = 'ACTIVE'
healthcare_service.license_id is not null and licenses.type = value from license_types_allowed parameter
in case of error - return 409 ('Division must have active licenses to dispense medication request').
Validate Medical Program
Get medical_program_change_on_dispense_allowed parameter from settings of medical program from medication request:
if it is false (absent), medical program in dispense must be the same as medical program in medication request (request.medical_program_id = medication_requests.medical_program_id)
in case of error - return 409 (`Medical program in dispense doesn't match the one in medication request`).
Qualify medication request
Important: This validation must be done only if medical_program exists in request:
Check that medication request is valid and available for dispense
Get medical_program_id from request of the medication dispense.
Invoke Qualify method
...
with medical_program_id
...
.
Check that program_medication_id is in Qualify response
...
.
Medication request is prohibited for dispense in case $.data[?(@.program_id=medication_requests.medical_program_id)].status = 'INVALID' or program_medication_id is absent in qualify response:
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
In case of error - return 409 error (message = "Medication request can not be dispensed. Invoke qualify medication request API to get detailed info").
Dispense is allowed
Medication request is allowed for dispense in case $.data[?(@.program_id=medication_requests.medical_program_id)].status = 'VALID' and program_medication_id is present in qualify response:
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
Validate statuses
Legal entity should be active in order to dispense medication
is_active = true
status = 'ACTIVE'
type in pharmacy_allowed_transactions_le_types
mis_verified = `VERIFIED`.
Medication request should be active in order to dispense medication
is_active = true
status = 'ACTIVE'
started_at <=current_date()and ended_at >=current_date().
Party should refer to active employee in current legal_entity
employees.is_active = true
employees.status = 'APPROVED'
employees.legal_entity_id = client_id (context).
Division should be active and refers to current legal_entity
is_active = true
status = 'ACTIVE'
divisions.legal_entity_id = client_id (context).
Medical Program should be active in order to dispense medication under this
...
program
is_active = true
...
.
...
Medication (brand) medication should be active
medications.is_active = true
medications.type = 'BRAND'
ingredients.medication_child_id = medication_request.medication_id and ingredients.is_primary = true
medication_id exists in program_medications (is_active = true).
Validate Medication request is_blocked flag
Get Medication request by $.medication
...
_request_id from OPS DB. Check that Medication request is not blocked (is_blocked = false or null)
in case of error - return 409 ("Medication request is blocked").
Validate division license
Division must have active pharmacy license in order to dispense medications
Check division parameters
division.dls_verified must be true
otherwise - return 409 error ('Invalid division dls status').
Validate dispense period
Check that dispense date is in period specified in Medication Request
dispense_valid_from <= current_date()
dispense_valid_to >= current_date().
Check other Medication
...
Check all connected medication dispenses
...
Dispenses
Check all connected medication dispenses
sum of medication_qty of all connected medication dispenses < medication_request.medication_qty
medictaion dispenses status in ('NEW', 'PROCESSED').
In case of error - return 403 error (message = "No more medication dispense could be done with this medication request").
Validate medication quantity
Get multi_medication_dispense_allowed parameter from medical program settings:
if it is true - check that requested medication quantity less or equal to medication quantity in Medication Request
sum(:medication_qty) <= medication_request.medication_qty
...
in
...
case of error - return
...
Validate medication quantity
...
422 "Dispensed medication quantity must be lower or equal to medication quantity in Medication Request. Available quantity is #{available_qty}".
if it is false (absent) - check that requested medication quantity equal to medication quantity in Medication Request
medication_qty = medication_request.medication_qty
in case of error - return 422 "Dispensed medication quantity must be equal to medication quantity in Medication Request
...
".
Validate medication multiplicity
Check that requested medication quantity in dispense for all medications is multiplier of package_min_qty for this medications.id
Mod($medication_qty, medications.package_min_qty) = 0
In case of error (if at least one of medication don't pass verification) - return 422 error:
|
...
|
...
|
...
|
...
Validate medication discount amount
Note: There are two different validation rules depending on medication package quantity and min quantity
If min quantity is equal to package quantity - there shouldn't be any tolerance during calculation.
...
|
Validate medication discount amount
Define reimbursement_type (get from program_medications by program_medication_id).
Validate percentage discount price.
Check if reimbursement_type == percentage and percentage_reimbursement_amount = 0
(the way how to calculate percentage_reimbursement_amount is following:
percentage_reimbursement_amount = sell_price (from request) * percentage_discount (from program_medications) /100)In case if discount_amount != 0 - return 422 ("Requested discount price must be equal to 0")
Else (if discount_amount = 0) - finish validation (do not validate 3, 4).
Validate allowed reimbursement amount.
Check that requested discount price is less or equal to allowed reimbursement amount for the requested medication quantity
(the way how to
...
calculate allowed reimbursement amount is below.
for type == percentage use percentage_reimbursement_amount, for fixed = use reimbusement_amount from program_medications)
...
:
discount_amount
...
<=
...
reimbursement_amount
...
*
...
(medication_qty/package_qty)
Validation 2: Min package quantity is not equal to package quantity
...
In case of error - return 422 ("Requested discount price must be less or equal to allowed reimbursement amount").
Validate the ratio of discount price to reimbursement amount.
Check that the ratio of requested discount price to allowed reimbursement amount is more or equal to allowed
...
rule (including deviation) for the requested medication quantity
...
(the way how to calculate allowed reimbursement amount is below.
for type = percentage use percentage_reimbursement_amount, for fixed - use reimbusement_amount from program_medications):
discount_amount/ (reimbursement_amount * (medication_qty/package_qty)) >= 1 - deviationIn case of
...
Code Block |
---|
{:error, [{%{
description: "Requested discount price doesn't not satisfy allowed reimbursement amount",
params: [],
rule: :invalid
}, "$.dispense_details[:index].discount_amount"}]} |
Medication dispense in a multi attempts
Validate medication multiplicity
Check that requested medication quantity in dispense for all medications is multiplier of package_min_qty for this medications.id
Mod($medication_qty, medications.package_min_qty) = 0
In case of error - return 422 error
Code Block |
---|
{:error, [{%{
description: "Requested medication brand quantity is not a multiplier of package minimal quantity",
params: [],
rule: :invalid
}, "$.dispense_details[:index].medication_qty"}]} |
Note: The medication_qty with each attempt can be divided only by an integer.
Validate medication quantity
Check that medication_qty on medication dispense should not exceed the sum of medication_qty already dispensed under this medication request.
Find existing medication dispenses by its medication_request_id
Count the amount of medication_qty dispensed for this medication request
$.medication_dispense.medication_request_id = $.medication_request.id
$.medication_dispense.status = PROCESSED
$.medication_dispense.medication_qty <= sumpreviously processed(medication_dispense_details.medication_qty)
In case of error - return 422 error
Code Block |
---|
{:error, [{%{
description: "Sum of dispense's medication quantity can not be more then medication_request.medication_qty",
params: [],
rule: :invalid
}, "$.dispense_details[:index].medication_qty"}]} |
Parameters that are used when processing the request
Configuration parameters
Access to the method is defined by the scope medication_dispense:reject. Permission for this scope is determined by the System administrator by configuring scopes in the context of clients and roles.
Dictionaries
API paragraph not found
Processing
Get reimbursement amount
There are two types of calculation of reimbursement amount:
FIXED - reimbursement rate defined here for package_qty without any calculations
EXTERNAL - reimbursement rate or amount should be calculated via API external call
Important: Only FIXED type is allowed during first phase
Get reimbursement amount for this medication_id according to medical_program_id
Determine calculation channel (FIXED, EXTERNAL)
Calculate reimbursement amount for the requested quantity of medications:
Get the reimbursement_amount from program_medications.reimbursement.reimbursement_amount (for the package)
Based on it, package_min_qty and requested medication_qty calculate the ratio and allowed reimbursement amount ((reimbursement_amount/package_qty)*medication_qty)
Create new entities
...
error - return 422 ("The ratio of requested discount price to allowed reimbursement amount must be greater or equal to <1 - deviation>").
Validate 2d codes
Important: This validation must be done only if medication_2d_codes field exists in request.
Check that medication_2d_codes array contains at least one element (array is not empty)
in case of error - return 422 ('Expected a minimum of %{min} items but got %{actual}').
For all objects in array check that string 'medication_2d_code' is not null or empty
in case of error - return 422 ('Not allowed to save empty 2d code').
Get reimbursement amount
There are two types of calculation of reimbursement amount:
FIXED - reimbursement rate defined here for package_qty without any calculations
EXTERNAL - reimbursement rate or amount should be calculated via API external call
Important: Only FIXED type is allowed during first phase
Get reimbursement amount for this medication_id according to medical_program_id
Determine calculation channel (FIXED, EXTERNAL)/
Calculate reimbursement amount for the requested quantity of medications:
Get the reimbursement_amount from program_medications.reimbursement.reimbursement_amount (for the package).
Based on it, package_min_qty and requested medication_qty calculate the ratio and allowed reimbursement amount ((reimbursement_amount/package_qty)*medication_qt.
Parameters that are used when processing the request
Configuration parameters
Access to the method is defined by the scope medication_dispense:write. Permission for this scope is determined by the System administrator by configuring scopes in the context of clients and roles.
Dictionaries
API paragraph not found
Processing
Get skip_medication_dispense_sign from medical program settings.
If skip_medication_dispense_sign = false or absent:
2.1. Check payment_id, payment_amount is absent in the request.
in case if present - return 422 with path: $.<field_name> and message "schema does not allow additional properties"
2.2. Add record to medication_dispenses table:
Parameter | Source | Description |
---|---|---|
id | UUID | Autogenerated |
payment_id | NULL | NULL for new records |
payment_amount | NULL | NULL for new records. |
status | Const: NEW | NEW skip_medication_dispense_sign = false |
is_active | Const: TRUE | Alwayls TRUE for new records |
inserted_at | Timestamp: now() | Get current date-time |
inserted_by | Token: user_id | Extract user from token |
updated_at | Timestamp: now() | Get current date-time |
updated_by | Token: user_id | Extract user from token |
2.3. Add records to medication_dispense_details table:
Parameter | Source | Description |
---|---|---|
id | UUID | Autogenerated |
medication_dispense_id | FK: medication_dispense | |
reimbursement_amount |
2.4. Add records to medication_2d_codes table (for each 2d code object in array):
Parameter | Source | Description |
---|---|---|
id | UUID | Autogenerated |
medication_dispense_id |
NULL
NULL for new records
status
Const: NEW
Always NEW for new records
is_active
Const: TRUE
FK: medication_dispense | ||
medication_2d_code | Request: medication_2d_codes | |
inserted_at | Timestamp: now() | Get current date-time |
inserted_by
Token: user_id
Extract user from token
updated_at
Timestamp: now()
Get current date-time
updated_by
Token: user_id
Extract user from token
...
If skip_medication_dispense_sign = true:
3.1. Check if payment_amount in the request
in case is absent - return 422 with path: $.payment_amount and message "required property payment_amount was not present"
3.2. Call Process Medication Dispense process, but without validation of the previously created (NEW) medication dispense, digital sign and storage signed content to the bucket.
3.3. Add records as described on steps 2.2-2.4, but with following differences:
medication_dispenses table:
Parameter | Source | Description |
---|---|---|
payment_id |
UUID
Autogenerated
medication_dispense_id
FK: medication_dispense
reimbursement_amount
Response structure
...
Request: payment_id | optional parameter | |
payment_amount | Request: payment_amount | required parameter |
status | Const: PROCESSED | PROCESSED skip_medication_dispense_sign = true |
Response structure
Example:
Expand | ||
---|---|---|
| ||
|
Post-processing processes
No
HTTP status codes
HTTP status code | Message | What caused the error |
---|---|---|
200201 | Response |
|
401 |
|
|
403 |
| |
409 |
| |
422 |
|
Backward compatibility
API paragraph not found