Versions Compared

Key

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

Purpose

This WS is designed to create Device Request

Key points

  1. Only authenticated and authorized users with appropriate scope can invoke Create Device Request

  2. Device Request is created in async way. Successful result of the job should return a link on the created Device Request (look at [UPD] Get Device request details).

  3. Device Request should be signed with DS. Signed content stores in the media storage.

  4. All validations within Device request attributes should be executed by internal call of [UPD] PreQualify Device request function

  5. Device Request can be created for a person only

  6. Medical program is optional in the Device Request

Specification

Apiary

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_request:write')

    • return 403 (“Your scope does not allow to access this resource. Missing allowances: device_request: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")

Validate digital signature

  1. Validate request is signed

    1. in case of error - return 400 (“Invalid signed content”)

  2. Check DS is valid and not expired

  3. Validate that DS belongs to the requester

    1. Check that DRFO from DS and party.tax_id matches

      1. in case of error - return 422 (“Does not match the signer drfo“)

Validate request

Validate request using schema.

1. Validate requester

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#1.-Validate-requester

2. Validate based on

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#2.-Validate-based-on

3. Validate intent

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#3.-Validate-intent

4. Validate code or code_reference

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#4.-Validate-code-or-code_reference

Skip the following validation in case madical_program is not specified in the request

Note
  • Check that there is at least one active device_definition with the same type (device_definitions.classification_type)

    • device_definitions.is_active = true

      • in case of error - return 422 ('No active device_definitions with the same type')

5. Validate quantity

Info

If medical program is not specified in request then quantity is optional here

If quantity provided in request - execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#5.-Validate-quantity

  • Check that $.quantity.system is device_unit dictionary, required

    • in case of error - return 422 ('value is not allowed in enum')

  • Check that $.quantity.code comply with $.quantity.system, required

    • in case of error - return 422 ('value is not allowed in enum')

  • Check that $.quantity.value is integer, required

    • in case of error - return 422 ('Value should be an integer')

6. Validate encounter

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#6.-Validate-encounter

7. Validate authored on

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#7.-Validate-authored-on

8. Validate occurrence

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#8.-Validate-occurrence

9. Validate reason

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#9.-Validate-reason

10. Validate Package unit and quantity

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#10.-Validate-Package-unit-and-quantity

11. Validate Medical program

Info

If medical program is not specified in request then skip this step

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#11.-Validate-Medical-programs

12. Validate priority

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#12.-Validate-priority

13. Validate supporting info

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#13.-Validate-supporting-info

14. Validate performer

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#14.-Validate-performer

15. Validate parameter

Execute validation as described here

https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670537622/UPD+PreQualify+Device+request#15.-Validate-parameter

Validate status

The target status value must be submitted in the order of display in the signed content (media storage)

  1. Validate $.status is active

    1. in case of error - return 422 ("value is not allowed in enum")

Service logic

...

Save signed content to media storage, in bucket pointed in MEDIA_STORAGE_DEVICE_REQUEST_BUCKET chart parameter

Fill in the following fields:

...

requisition. Generate requisition number as described at Human readable Medication request number, but based on the Device Request identifier and put it in the field.

...

signed_content_links. Add string item in the array with a link on saved content in media storage

...

status = ACTIVE

...

status_reason = null

...

subject. Set hashed patient_id from URL

...

requester_legal_entity. Set client_id from token

...

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

...

dispense_valid_to. Set (current_date + dispense_period_day) if medical program was set and it has dispense_period_day setting. Otherwise, set the value using device_dispense_period global parameter.

...

verification_code. Generate random 4-digit code if medical program was set

...

context_episode_id. Set episode from the $.encounter

...

context_care_plan_id. Get Activity from $.based_on, set activity.care_plan as context_care_plan_id

...

based_on. Set based_on from the $.based_on

...

priority. Set priority from the $.priority

...

parameter. Set parameter from the $.parameter

...

performer. Set performer from the $.performer

...

Table of Contents

Purpose

This WS is designed to create Device Dispense

Key points

  1. Only authenticated and authorized users with appropriate scope can invoke Create Device Dispense

  2. Device Dispense is created in async way. Successful result of the job should return a link on the created Device Dispense (look at /wiki/spaces/RMDN/pages/17670997473).

  3. Device Dispense can be created only under active Device Request within valid dispense period

  4. Several devices of different manufacturers with the same code can be dispensed at a time

  5. Multiple dispenses to the same Device Request with medical program is not allowed

  6. It is allowed to create Device Dispense for not verified persons

Specification

Apiary

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")

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 performer 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 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"

  • Get license_types_allowed parameter from settings of medical program from request $.program:

    1. 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:

      1. legal_entity_id = client_id from access token

      2. division_id = division_id from request

      3. status = 'ACTIVE'

      4. licensed_healthcare_service.status = 'ACTIVE'

      5. healthcare_service.license_id is not null and licenses.type = value from license_types_allowed parameter

        1. in case of error - return 409 ('Division must have active licenses to create Device dispense')

Validate status

The target status value must be submitted in the order of display in the signed content (media storage)

  1. Validate $.status isIN_PROGRESS if there are program specified in the dispense , else

    1. in case status is COMPLETED - return 409 ("Status is not allowed for Device dispense with Medical program")

    2. else - return 422 ("value is not allowed in enum")

  2. Validate $.status is COMPLETED if no program specified

    1. in case status isIN_PROGRESS - return 409 ("Status is not allowed for Device dispense without Medical program")

    2. 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 409 error ('Device request is not active')

  • If medical_program specified in the Device dispensecheck that dispense_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 or empty (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

    1. in case of error - return 422 ('Medical program not found')

  • Сheck that program has is_active set in true and status is 'ACTIVE'

    1. in case of error - return 422 error ('Medical program is not active')

  • Check if medical program has setting skip_contract_provision_verify = true, than skip contract validation

    1. Else validate there is a contract in PRM.contracts that meets following requirements:

      1. contracts.type==reimbursement

      2. contracts.status==VERIFIED

      3. Contract dates: start_date <= current_date & end_date >= current_date

      4. contracts.contractor_legal_entity_id=token.client_id

      5. contracts.medical_program_id==$.program

      6. сontracts.is_suspended == false

    2. in case of error - return 409 ('Program cannot be used - no active contract exists')

Validate when_handed_over

  • If medical_program not specified in the Device dispense validate when_handed_over

    • Check that when_handed_over is in period specified in Device request (when_handed_over = current_date() and when_handed_over <= device_request.dispense_valid_to)

      • in case of error - return 409 error ('Invalid dispense period')

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 /wiki/spaces/RMDN/pages/17670996847

    • 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 request

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

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

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

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')

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 to device_definition_id in the request

      • 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)

      • 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 = true

      • in 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')

Validate 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 thenremaining_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_quantity

        • Calculate 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')

    • If allowed_reimbursement_amount > 0, then 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_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

...

inserted_by. Set current user from token

...

updated_by. Set current user from token

...

Send notification to patient:

  1. Determine patient's default authentication method as described at Determination of a default authentication method and return person's active auth_methods

  2. Get program from request and (if provided) get program setting request_notification_disabled:

    1. if program provided and request_notification_disabled == true:

      1. do not send SMS notification to patient

    2. if program provided and request_notification_disabled == false and OTP defined on patient:

      1. generate text according to CREATE_DEVICE_REQUEST_SMS_TEMPLATE and send SMS with verification_code

    3. if program not provided and OTP defined on patient:

      1. check config parameter DEVICE_REQUESTS_SMS_ENABLED is set to true

        1. generate text according to CREATE_DEVICE_REQUEST_SMS_TEMPLATE_WITHOUT_CODE and send SMS without verification_code

...

Save data to device_requests collection in MongoDB according to [UPD] Device request data model

If device request is based on activity - recalculate and set remaining_quantity for the activity

...

select all device requests based on current activity and calculate previously reserved quantity as sum of DR.quantity.value.

...

calculate reserved at the moment quantity as sum of previously reserved quantity and quantity from current DR

...

calculate remaining quantity by subtracting reserved at the moment quantity from activity's quantity

...

    • 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 there is a Medical program specified in the Device dispense($.program), change status of the related Device request($.based_on) to completed

  • If there are no Medical program specified AND there is quantity specified in Device dispense, calculate remaining quantity of the related Device request (same as on https://e-health-ua.atlassian.net/wiki/spaces/RMDN/pages/17670504740/UPD+Get+Device+request+details#Service-logic):

    1. Select all Device dispenses in status completed related to the Device request

    2. Sum quantity in the filtered Device dispenses as dispensed_qty

    3. Calculate remaining_quantity = requested_quantity- dispensed_quantity

    4. If remaining_quantity is 0, change status of the related Device request($.based_on) to completed

  • Save data to device_dispenses collection in MongoDB according to /wiki/spaces/RMDN/pages/17670799715

  • Send StatusChangeEvent to Event Manager