ЕСОЗ - публічна документація
Create Device dispense
- 1 Purpose
- 1.1 Key points
- 2 Specification
- 3 Logic
- 4 Input parameters
- 5 Request structure
- 6 Authorization
- 7 Validate legal entity
- 8 Validate dispense
- 8.1 Validate performer
- 8.2 Validate location
- 8.3 Validate status
- 8.4 Validate Device request
- 8.5 Validate program
- 8.6 Validate when_handed_over
- 8.7 Validate Dispense details
- 8.8 Qualify Device request
- 8.9 Check for existing Device dispenses
- 8.10 Validate Dispense details
- 8.10.1 Validate device
- 8.10.2 Validate device_code
- 8.10.3 Validate program device
- 8.10.4 Valdate quantity
- 8.10.5 Validate discount
- 8.11 Validate verification code
- 9 Service logic
- 10 Response structure
- 11 HTTP status codes
Purpose
This WS is designed to create Device Dispense.
Method to create device dispense It can be processed in async way only
Key points
Only authenticated and authorized users with appropriate scope can invoke Create Device Dispense
Device Dispense is created in async way. Successful result of the job should return a link on the created Device Dispense (look at Get Device dispense details ).
Device Dispense can be created only under active Device Request within valid dispense period
Several devices of different manufacturers with the same code can be dispensed at a time
Multiple dispenses to the same Device Request is not allowed
It is allowed to create Device Dispense for not active or not verified persons (for the same reasons as in the medication reimbursement process)
Specification
Link | Посилання на Apiary або Swagger | |
Resource | /api/patients/{{patient_id}}/device_dispenses | Посилання на ресурс, наприклад: /api/persons/create |
Scope |
| 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 https://e-health-ua.atlassian.net/wiki/spaces/CSI/pages/17467572335
Send
StatusChangeEvent
to Event Manager
Input parameters
Input parameter | Values | Type | Description | Example |
---|---|---|---|---|
patient_id |
| String | Unique patient identifier |
|
Request structure
See on Apiary
Example:
Authorization
Verify the validity of access token
in case of error - return 401 (“Invalid access token”) in case of validation fails
Verify that token is not expired
in case of error - return 401 (“Invalid access token”)
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)
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):
in case not match - return 403 ("Access denied. Party is not verified")
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):
in case of error - return 403 ("Access denied. Party is deceased")
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 dispense for the performer')
Check performer is an active and approved employee.
in case of error - return 422 ('Employee is not active ')
Check performer employee.end_date is grater then today.
in case of error - return 422 ('end_date must be in future ')
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')
Validate location
Validate value in the field $.location, Reference on division resource, required.
Check that division exists and is_active = true
in case of error - return 409 ("Division not found")
Check that division status = “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"
Validate status
The target status value must be submitted in the order of display in the signed content (media storage)
Validate $.status is IN_PROGRESS if there are program specified in the dispense , else
in case status is COMPLETED - return 409 ("Status is not allowed for Device dispense with Medical program")
else - return 422 ("value is not allowed in enum")
Validate $.status is COMPLETED if no program specified
in case status is IN_PROGRESS - return 409 ("Status is not allowed for Device dispense without Medical program")
else - return 422 ("value is not allowed in enum")
Validate Device request
Validate value in the field $.based_on ($.based_on.identifier.value), Reference on device request, required.
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 422 error ('Device request is not active')
Check that dispense_valid_to is greater or equal to current date
in case of error - return 409 ('Device request is expired for dispense')
If medical_program specified in the Device dispense check that dispense_valid_to (whole day - time must be ignored) is greater or equal to current date
in case of error - return 409 ('Device request is expired for dispense')
Validate related Care plan
Verify Care Plan and Activity as described in Qualify Device Request by ID | Validate related Care plan
Validate program
Check that program in dispense is the same as program in device request or empty on both sides(request.program.identifier.value = device_requests.program.identifier.value)
in case of error - return 409 ('Program in dispense doesn't match the one in device request')
Check that program exists in DB
in case of error - return 422 ('Medical program not found')
Сheck that program has is_active set in true and status is 'ACTIVE'
in case of error - return 422 error ('Medical program is not active')
If the medical program has no setting skip_contract_provision_verify or it is set in false/null validate:
Check $.division participates in submitted program. Validate Provision for the medical program:
Medical program in the request has funding_source = NHS
In case of error - return reject_reason = "Program was configured incorrectly - incorrect source of funding"
Provision exist and active, relates to the $.location and to the actual reimbursement contract: contract.start_date <= current_date <= contract.end_date, is_active = true, status = VERIFIED, contracts.type==reimbursement, contracts.contractor_legal_entity_id=token.client_id, contracts.medical_program_id==$.medical_program_id
in case of error - return reject_reason = "Medical program provision is not related to any actual contract for the current date"
Сontract is_suspended = false
in case of error - return reject_reason="Contract with number <contract_number> is suspended"
else if skip_contract_provision_verify = true, then skip provision verification for the medical program
If the medical program has no setting skip_dispense_division_dls_verify or it is set in false/null validate:
Check $.division.dls_verify == true:
In case of error - return 409 "Division is not verified in DLS"
else if skip_dispense_division_dls_verify = true, then skip license verification for the division
Validate when_handed_over
If medical_program not specified in the Device dispense validate when_handed_over
check that when_handed_over is greater or equal to Device request. authored_on and less or equal to current date
in case of error - return 409 error ('Invalid dispense period')
Validate Dispense details
If Medical program($.program) is specified in the Device dispense, check that details.device is present in the Device dispense, not details.device_code
in case of error - return 409 ('Dispense with device code is not allowed for Device dispenses with a medical program')
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
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 for existing Device dispenses
Check that there is no other
IN_PROGRESS
device dispenses based on the same device requestFind all device dispenses related to the same device request ($.based_on)
Check that there are no records in status
in-progress
whereinserted_at
+ configdevice_dispense_ttl
>= current date-time()in case of error - return 422 "Other active device dispenses already exist"
Validate Dispense details
Validate device
Check device (device definition) to be dispensed ($.details.device)
Check code ($.details.device.identifier.type.coding.code) =
device_definition
in case of error - return 422 ('value is not allowed in enum')
Get device definition by id ($.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 contains reference to a device definition in device_request.code_reference
Check that
device_definition_id
in dispense is equal todevice_definition_id
in the request
If device_request.code is of type CodeableConcept If device request contains device_request.code
Check that
device_definition.classification_type
is equal to prescribed device definition code in device request (device_request.code
)
If device_request.code is of type Reference
Check that
device_definition_id
in dispense is equal todevice_definition_id
in request
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 ($.details.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”
Validate device_code
Check device_code to be dispensed ($.details.device_code)
Check system($.details.device_code.coding.system) = device_definition_classification_type
in case of error - return 422 ('value is not allowed in enum')
Get device_code from the dictionary
device_definition_classification_type
($.details.device_code.coding.code) and check parameter is_active = truein case of error - return 422 ('Device code not found')
Check that this device code is compliant with prescribed device code:
Check device_request.code_reference is not present in the request
return an error 422 ('Dispense with device code is not allowed, since the prescription is for device or device definition ')
Check device_request.code is equal to
device_dispense.device_code
in case of error - return 422 ('Dispensed device code doesn’t match with prescribed device code')
Validate program device
Check program device
Is applicable only if program was passed to request and program device passed to request
Check code ($.details.program_device.identifier.type.coding.code) =
program_device
in case of error - return 422 ('value is not allowed in enum')
Check that program device exists in DB and has is_active=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 program device relates to the device definition in $.details.device
in case of error - return 422 ('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
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
If Medical program is specified:
Check that dispensed device quantity is equal prescribed quantity in Device Request
sum($.details.quantity.value) == device_request.quantity
in case of error - return 422 ('Dispensed quantity must be equal to prescribed quantity in Device Request')
If Medical program is not specified:
Check that dispensed device quantity is equal or less then remaining_quantity in Device Request:
Select all Device dispenses in status completed related to the Device request
Sum
quantity
in the filtered Device dispenses as dispensed_quantityCalculate remaining_quantity = requested_quantity- dispensed_quantity
in case of error - return 422 ('Dispensed quantity must be equal or less then prescribed remaining quantity in Device Request')
Validate quantity units
Check that quantity.code matches with packaging_unit of the device_request
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
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 * ($.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 * ($.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>')
Validate verification code
This validation must be done only if medical_program is specified in the request($.program)
Check that $.verification_code in request is equal to verification_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“)
Service logic
Fill in the following fields:
status = IN_PROGRESS if there are program specified in the dispense OR
status = COMPLETED if no program specified
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
origin_episode_id. Set context_episode_id from device request referenced in based_on
If Device dispenses status is changed to completed and related Device request has a reference on an Activity as device_request.based_on, then
add the reference on the Device dispense resource to the outcome_reference attribute of the related Activity
if Activity.status is
scheduled
change it toin_progress
If there are no Medical program specified in Device dispense AND there is quantity specified in Device request:
calculate remaining quantity of the related Device request (same as on [UPD] Get Device request details | Service logic):
Select all Device dispenses in status completed related to the Device request
Sum
quantity
in the filtered Device dispenses as dispensed_qtyCalculate remaining_quantity = Device_request.quantity- dispensed_quantity
If remaining_quantity is equal to Device_dispense.quantity, change status of the related Device request($.based_on) to completed
Save data to device_dispenses collection in MongoDB according to https://e-health-ua.atlassian.net/wiki/spaces/CSI/pages/17467572335
Send
StatusChangeEvent
to Event Manager
Response structure
See on Apiary
Example:
HTTP status codes
HTTP status code | Message | What caused the error |
---|---|---|
202 |
|
|
ЕСОЗ - публічна документація