ЕСОЗ - публічна документація

RC_REHAB2_[UPD] Submit Diagnostic Report Package

Purpose

Using this web service you can submit Diagnostic Report Package

 

Specification

Link

https://medicaleventsmisapi.docs.apiary.io/#reference/medical-events/diagnostic-report-data-package/submit-diagnostic-report-package

Resource

/api/patients/{{id}}/diagnostic_report_package

Scope

diagnostic_report:write

Components

Diagnostic Report Data Package

Microservices

API paragraph not found

Protocol type

REST

Request type

POST

Sync/Async

Async

Public/Private/Internal

Public

 

Logic

Using this web service you can submit:

Object

Required

Part of Signed content

Object

Required

Part of Signed content

Observation

0-*

true

Diagnostic report

1-1

true

 

Global and configurable parameters

Variables | Medical Events

Request structure

See on Apiary

Example:

{ "signed_data": "'ew0KICAicGVyaW9kIjogew0KIC...'" }

 

Authorize

  1. Verify the validity of access token

    1. in case of error return 401 ('Access denied')

  2. Check user scope diagnostic_report:write in order to perform this action

    1. in case of error generate 403 response ('Invalid scopes')

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

Request to process the request using a token in the headers

 

Headers

Наприклад:

  • Content-Type:application/json

  • Authorization:Bearer mF_9.B5f-4.1JqM

 

Request data validation

Request validation

DS validation

  1. DS must be valid

  2. The document must be signed by recorder

    1. Select PRM.parties.tax_id from PRM where PRM.parties.id ==( Select  PRM.employees.party_id where PRM.employees.id==$.diagnostic_report.recorded_by.identifier.value)

    2. ds.drfo == select a

      1. in case of error retuert 409 "Document must be signed by the recorder of the diagnostic_report"

  3. Recorder must be a current user

    1. $.diagnostic_report.recorded_by.identifier.value is one of current user's employee

      1.  in case of error return 409 "Document must be sent by the recorder of the diagnostic_report"

Validate Legal Entity Type

Validate legal entity from token: legal_entities.type should be in me_allowed_transactions_le_types and legal_entities.status =='active' 

Diagnostic report validation

  1. Validate diagnostic_report _id is unique for MongoDB.Diagnostic_reports

  2. Validate that diagnostic reports category corresponds to service category, that is references as code in DR

    1. $.diagnostic_report.category[?]=PRM.services.category where PRM.services.id=$.diagnostic_report.code.identifier.value

      1. in case of error return 422 "None of the diagnostic report categories matches with the service category"

  3. Validate that service, referenced as a code in DR, is active
    Note. For diagnostic_report.code pass only "service", and the "service_group" does not pass

    1. PRM.services.is_active = true where PRM.services.id=$.diagnostic_report.code.identifier.value

      1. in case of errror return 422 "Service is not active"

    2. If service_requests.code.identifier.value is service, validate $diagnostic_report.code.identifier.value = service_requests.code.identifier.value

      1. in case error return 409, "Service in diagnostic_report differ from service in service request"

    3. if service_requests.code.identifier.value is service_group, validate $diagnostic_report.code.identifier.value in (SELECT service_id from service_inclusions where service_group_id='service_requests.code.identifier.value')

      1. in case error return 409, "Service in diagnostic_report differ from services in service request's service_group"

  4. Validate referrals

    1. As a referral it can be referenced electronic (registered in the system) OR paper service request

    2. Validate ($.diagnostic_report.based_on OR $.diagnostic_report.paper_referral) or none in request

    3. Validate based on as Reference

    4. Validate paper referral as Object (paper_referral)

    5. Validate that service_request, referenced as based_on, is

      1. in status is active or program_processing_status=in_progress (any status is valid in case program_processing_status= in_progress)

        1. in case of error return 409 "Invalid service request status"

      2. used_by_legal_entity==token.client_id OR null

        1. in case of error return 409 "Service request is used by another legal_entity"

      3. if program is defined than used_by_legal_entity==token.client_id or NULL

        1. in case of error return 409 "Service request is used by another legal_entity"

      4. if program is defined than program_processing_status == new, in_queue or in_progress

      5. check that service_request contains based_on parameter

        1. in case based_on present in service_request

          1. verify care_plan:

            1. It should be in active status

            2. Care plan's period end (if exist) should be greater than current date or equal.

          2. verify activity:

            1. It has activity.detail.kind=service_request; activity.detail.product_reference=service_id. 

            2. It has scheduled, in_progress status

            3. For an old activities (has no units in quantity) validate remaining_quantity as described at Submit Encounter Data Package: Related care plan validation

        2. in case based_on not present in request skip previous validations.

      6. Check if service request quantity is not exhausted as described at Submit Encounter Data Package: Related service request validation

  5. Validate effective_period as a period (PeriodValidation)

  6. Validate that issued is within acceptable limits

    1. $.diagnostic_reports[*].issued<= current date_time

      1. in case of error 422 "Issued date  must be in past"

    2. $.diagnostic_reports[*].issued>=current_date-diagnostic_report_max_days_passed

      1. in case of error 422 "Issued must be greater than  {{current_date-diagnostic_report_max_days_passed}}" 

  7. Validate recorded_by as Employee:

    1. recorded_by employee_types allowed: DOCTOR, SPECIALIST, ASSISTANT, LABORANT

      1. in case of error 422 "Invalid employee type"

  8. Validate performer.identifier as Employee:

    1. check that performer.identifier field is mandatory and employee_types allowed: DOCTOR, SPECIALIST, ASSISTANT, LABORANT

      1. in case of error 422 "Invalid employee type"

  9. Validate managing_organization is a current legal_entity

    1. $.managing_organization.identifier.value==token.client_id

      1. in case of error 409 "Managing organization does not correspond to user's legal entity."

  10. Validate results_interpreter.identifier as Employee:

    1. if the category.coding.code is in (imagingdiagnostic_procedure) check that results_interpreter.identifier is an employee with employee_type = DOCTOR or SPECIALIST

      1. in case of error 422 "Invalid employee type"

    2. if the category.coding.code is in (diagnostic_curativelaboratory_procedure) - results_interpreter field is optional and the results_interpreter.identifier validation skipped

  11. Validate only One of the fields is filled:

    1. $.diagnostic_report[*].results_interpreter.reference OR $.diagnostic_report[*].results_interpreter.text

  12. Validate division

    1. Validate division as Reference(Referencevalidation)

    2. $division is an existing ID in PRM.divisions

      1. in case return 422, "Division with such id is not found"

    3. division.status=ACTIVE and is_active=true

      1. in case error return 409, "Division is not active"

    4. division.legal_entity_id = $client_id

      1. in case error return 409, "Division is not in current legal_entity"

  13. Patient must be active

    1. check that patients.status == active

      1. in case patients.status == inactive

        1. check mpi.persons(or mpi.prepersons if patients.preperson == true).updated_at and validate that now() - updated_at<=SUBMIT_DIAGNOSTIC_REPORT_PACKAGE_ALLOWED_PERIOD_MINUTES configuration (in minutes)

          1. in case of error return 409 (Person is not active more that the allowed time for data submitting)

  14. Validate patient verification status:

    1. If diagnostic report has based_on with valid and active service request, then skip this validation.

    2. Else check patient's verification_status is not equal to NOT_VERIFIED.

      1. in case of error return 409, "Patient is not verified"

  15. Validate for each element in specimens array, if submitted:

    1. Check the element is a Reference on a specimen resource

      1. in case of error return 422 “not allowed in enum”

    2. Check it exists in DB and belongs to the same patient:

      1. in case of error return 422 "Specimen not found"

    3. Check status is available

      1. in case of error return 422 "Invalid specimen status"

Observation validation

Several approaches are used for validating observations. This is driven by the natural growth of the system, which implies increased complexity and the different requirements for various groups, categories of observations and even the contexts in which they (observations) were created.

Currently, the following approaches are used:

  1. Basic validations for all observations

  2. Validation of observations for the encounter type "patient_identity".

  3. A set of validations for rehabilitation observations based on ICF (International Classification of Functioning, Disability, and Health) dictionaries.

  4. Validation of observations based on a configuration set defined for a specific observation code (new).

Basic validation and REHAB

  1. Validate observations ids as  primary keys (Primarykeyvalidation)

  1. Validate that diagnostic_report of ALL observation is a current DR

    1. $.observations[*].diagnostic_report.identifier.value==$.diagnostic_report.id

      1. in case of error return "Submitted diagnostic report is not allowed for the observation"

  2. $.observations[*].effective_period validate as PeriodValidation

  3. Validate that the date is within acceptable limits

    1. $.observations[*].issued <= current_time

      1. in case of error return "Issued date must be in past"

    2. $.observations[*].issued>=current_date-observation_max_days_passed

      1. in case of error "Issued must be greater than  {{current_date-observation_max_days_passed}}"

  4. Validate performer as Employee:

    1. performer employee_types allowed: DOCTOR, SPECIALIST, ASSISTANT, LABORANT

      1. in case of error 422 "Invalid employee type"

  5. Validate $.observations[*].value_period as a Period

  6. Validate component

    1. if $.observations[*].code.coding[*].system is "eHealth/ICF/classifiers":

      1. Check number of component items with $.observations[*].components[*].code.coding[*].system = "eHealth/ICF/qualifiers": 

        1. if $.observations[*].code.coding[*].code starts from "b" letter, then components must contain exact 1 item with:

          1. $.observations[*].components[*].code.coding[*].code = "extent_or_magnitude_of_impairment" 

            1. in case of missing qualifier - return 422 "Missing components with qualifiers <list of missing qualifiers>"

            2. in case of incorrect number of qualifiers - return 422 "Required 1 component, but got <number of items>"

            3. in case value is not active in dictionary - return 422 "Value is not active"

        2. if $.observations[*].code.coding[*].code starts from "s" letter, then components must contain exact 3 items with:

          1. $.observations[*].components[*].code.coding[*].code = "extent_or_magnitude_of_impairment"

          2. $.observations[*].components[*].code.coding[*].code = "nature_of_change_in_body_structure"

          3. $.observations[*].components[*].code.coding[*].code = "anatomical_localization"

            1. in case of missing qualifier - return 422 "Missing components with qualifiers <list of missing qualifiers>"

            2. in case of incorrect number of qualifiers - return 422 "Required 3 components, but got <number of items>"

            3. in case value is not active in dictionary - return 422 "Value is not active"

        3. if $.observations[*].code.coding[*].code starts from "d" letter, then components must contain exact 2 items with:

          1. $.observations[*].components[*].code.coding[*].code = "performance"

          2. $.observations[*].components[*].code.coding[*].code = "capacity"

            1. in case of missing qualifier - return 422 "Missing components with qualifiers <list of missing qualifiers>"

            2. in case of incorrect number of qualifiers - return 422 "Required 2 components, but got <number of items>"

            3. in case value is not active in dictionary - return 422 "Value is not active"

        4. if $.observations[*].code.coding[*].code starts from "e" letter, then components must contain exact 1 item with:

          1. $.observations[*].components[*].code.coding[*].code = "barrier_or_facilitator"

            1. in case of missing qualifier - return 422 "Missing components with qualifiers <list of missing qualifiers>"

            2. in case of incorrect number of qualifiers - return 422 "Required 1 component, but got <number of items>"

            3. in case value is not active in dictionary - return 422 "Value is not active"

      2. Check $.observations[*].components[*].value_codeable_concept is present in each item with $.observations[*].components[*].code.coding[*].system = "eHealth/ICF/qualifiers" and  $.observations[*].components[*].value_codeable_concept.coding[*].system corresponds to $.observations[*].components[*].code.coding[*].code

        1. in case not present or doesn't correspond return 422 "Doesn't correspond to $.observations[i].components[i].code"

        2. in case code value is not active in dictionary - return 422 "Value is not active"

    2. $.observations[*].components[*].value_period as a  Period

  7. Validate $.observations.code

    1. if observations.code.coding[*].code value is included in chart variables 'OBSERVATION_CODES_WITH_<VALUE_TYPE>_REQUIRED', <value_type> field is mandatory

      1.  in case of error return 422 “This field is required for code = <code>“

    2. if observations[*].code.coding[*].system is "eHealth/ICF/classifiers", then:

      1. Check observations[*].categories[*].coding[*].system should contain "eHealth/ICF/observation_categories"

        1. in case of error return 422 “Code doesn't match observation category“

      2. Check observations[*].components are presented

        1. in case of error return 422 “Components required“

  8. Validate $.observations[*].categories

    1. is an array with only one item

      1. in case of error return 422 "Expected a maximum of 1 items but got <number of elements>"

    2. $.observations[*].categories[*].coding[*].system is "eHealth/observation_categories" or "eHealth/ICF/observation_categories" 

      1. in case of error return 422 "Value is not allowed in enum"

    3. $.observations[*].categories[*].coding[*].code corresponds to the system

      1. in case of error return 422 "Value is not allowed in enum"

    4. If $.observations[*].categories[*].coding[*].system = "eHealth/ICF/observation_categories", then $.observations[*].code should be filled from "eHealth/ICF/classifiers" dictionary.

      1. in case of error return 422 “Code doesn't match observation category“

  9. Validate specimen, if submitted:

    1. Check the field is a Reference on a specimen resource

      1. in case of error return 422 “not allowed in enum”

    2. Check it exists in DB and belongs to the same patient:

      1. in case of error return 422 "Specimen not found"

    3. Check status is available

      1. in case of error return 422 "Invalid specimen status"

Validate observations using configuration set

This validations must be done on top of Basic validations and only in case there is defined configuration set for such observation

Search for active configuration set (is_active = true) using observation code (code + system) and perform additional validation. If there is no configuration for such code then this additional validations must be skipped

Category
  1. Check that observation.categories.coding.system and observation.categories.coding.code matches with one of the options in CATEGORY configuration parameter

    1. values in CATEGORY.check means all allowed and observation category must match at least one

    2. If CATEGORY is missing or is empty then skip this validation

    3. in case of error return 422 “Category is not allowed for this observation code“

Components

  1. Check that all components in observation.components are unique and not duplicated if COMPONENTS_UNIQUE is set to true. Otherwise skip this step

    1. in case of error return 422 “Observation components must be unique“

  2. Check that all required components are present in observation.components (declared in COMPONENTS_REQUIRED)

    1. values in COMPONENTS_REQUIRED.check means all required and observation components must include all of them

    2. if COMPONENTS_REQUIRED is missing or is empty then skip this validation

    3. in case of error return 422 “Not all required components provided for this observation code“

  3. Check that there are no items in observation.components other than those allowed, which are defined by the COMPONENTS_OPTIONAL

    1. values in COMPONENTS_OPTIONAL.check means all allowed (except COMPONENTS_REQUIRED) observation components that could be used for this observation code

    2. if COMPONENTS_OPTIONAL is missing or is empty then no additional components are allowed

    3. in case of error return 422 “Component code is not allowed for this observation code“

  4. Check that component value type matches with COMPONENTS_TYPE configuration parameter

    1. search for related configuration in COMPONENTS_TYPE.condition using observation.component.code.coding.system and observation.component.code.coding.code

    2. check that observation.component.value[x] type matches with the type declared in COMPONENTS_TYPE.check

    3. if COMPONENTS_TYPE is missing or is empty or there is no matched configuration then skip this validation

    4. in case of error return 422 “type mismatch. Expected {COMPONENTS_TYPE.check} but got {entered type}“

  5. Check that dictionary used to represent component with value type codeable_concept matches with declared in COMPONENTS_BINDING configuration parameter

    1. Must be done only in case when component value type is codeable_concept (observation.component.value[x] type is codeable_concept)

    2. search for related configuration in COMPONENTS_BINDING.condition using observation.component.code.coding.system and observation.component.code.coding.code

    3. check that observation.component.value_codeable_concept.coding.system matches with the system (dictionary) declared in COMPONENTS_BINDING.check

    4. if COMPONENTS_BINDING is missing or is empty or there is no matched configuration then skip this validation

    5. in case of error return 422 “Incorrect dictionary. Expected {COMPONENTS_TYPE.check}“

  6. Check that code system and value used to represent quantity in component are allowed according to COMPONENTS_QUANTITY_CODES configuration parameter

    1. Must be done only in case when component value type is quantity (observation.component.value[x] type is quantity)

    2. search for related configuration in COMPONENTS_QUANTITY_CODES.condition using observation.component.code.coding.system and observation.component.code.coding.code

    3. check that observation.component.value_quantity.coding.system and observation.component.value_quantity.coding.code matches respectively with one of configurations in COMPONENTS_QUANTITY_CODES.check

    4. if COMPONENTS_QUANTITY_CODES is missing or is empty or there is no matched configuration then skip this validation

    5. in case of error return 422 “Such quantity system and quantity code are not allowed in this component“

  7. Check that component value is within the declared in COMPONENTS_QUANTITY_BOUNDARIES configuration parameter boundaries

    1. Must be done only in case when component value type is quantity (observation.component.value[x] type is quantity)

    2. search for related configuration in COMPONENTS_QUANTITY_BOUNDARIES.condition using (observation.component.code.coding.system and observation.component.code.coding.code for COMPONENTS_QUANTITY_BOUNDARIES.condition.component_code) and (observation.component.value_quantity.system and observation.component.value_quantity.code for COMPONENTS_QUANTITY_BOUNDARIES.condition.quantity_code)

    3. check that configuration.check.min <= observation.component.value_quantity.value >= configuration.check.max

    4. if COMPONENTS_QUANTITY_BOUNDARIES is missing or is empty or there is no matched configuration then skip this validation

    5. in case of error return 422 “Incorrect value. Expected value to be in range {configuration.check.min} and {configuration.check.max}“

  8. Check that only allowed extensions are used in components (declared in COMPONENTS_ALLOWED_EXTENSIONS)

    1. values not declared in COMPONENTS_ALLOWED_EXTENSIONS.check is prohibited and is not allowed in observation.components

    2. check that observation.component.value_codeable_concept.coding.extension contains only extensions declared in COMPONENTS_ALLOWED_EXTENSIONS.check

      1. in case of error return 422 “Extension {observation.component.value_codeable_concept.coding.extension} is not allowed“

    3. check that there are no duplicated extensions in observation.component.value_codeable_concept.coding.extension

      1. in case of error return 422 “Duplicated extension“

    4. check that extension is valid according to https://e-health-ua.atlassian.net/wiki/spaces/REHABILIT/pages/18431246564/UPD+Medical+Events+MongoDB+Data+Model#Predefined-extensions

      1. in case of error return 422 “Invalid extension“

  9. Check that extension value is correct according to COMPONENT_SCORE configuration parameter

    1. Must be done only in case when component value type is codeable_concept (observation.component.value[x] type is codeable_concept)

    2. search for the score associated with provided value (declared in COMPONENT_SCORE configuration parameter) using component value (observation.component.value_codeable_concept.coding.system and observation.component.value_codeable_concept.coding.code) and component code (observation.component.code.coding.system and observation.component.code.coding.code).

    3. check that extension value (observation.component.value_codeable_concept.coding.extension(code = item_weight).value_decimal) is equal value declared in COMPONENT_SCORE.check for such component

    4. in case of error return 422 “Incorrect component score“

Value

  1. Check that observation value type matches with RESULT_TYPE configuration parameter

    1. check that observation.value[x] type matches with the type declared in RESULT_TYPE.check

    2. if RESULT_TYPE is missing or is empty then skip this validation

    3. in case of error return 422 “type mismatch. Expected {RESULT_TYPE.check} but got {entered type}“

  2. Check that dictionary used to represent observation value matches with declared in RESULT_BINDING configuration parameter

    1. Must be done only in case when observation value type is codeable_concept (observation.value[x] type is codeable_concept)

    2. check that observation.value_codeable_concept.coding.system matches with the system (dictionary) declared in RESULT_BINDING.check

    3. if RESULT_BINDING is missing or is empty then skip this validation

    4. in case of error return 422 “Incorrect dictionary. Expected {RESULT_BINDING.check}“

  3. Check that code system and value used to represent quantity in observation are allowed according to RESULT_QUANTITY_CODES configuration parameter

    1. Must be done only in case when component value type is quantity (observation.value[x] type is quantity)

    2. check that observation.value_quantity.coding.system and observation.value_quantity.coding.code matches respectively with one of configurations in RESULT_QUANTITY_CODES.check

    3. if RESULT_QUANTITY_CODES is missing or is empty or there is no matched configuration then skip this validation

    4. in case of error return 422 “Such quantity system and quantity code are not allowed in observation result“

  4. Check that observation value is within the declared in RESULT_BOUNDARIES configuration parameter boundaries

    1. Must be done only in case when observation value type is quantity (observation.value[x] type is quantity)

    2. search for related configuration in RESULT_BOUNDARIES.condition using observation.value_quantity.coding.system and observation.value_quantity.coding.code

    3. check that configuration.check.min <= observation.value_quantity.value >= configuration.check.max

    4. if RESULT_BOUNDARIES is missing or is empty or there is no matched configuration then skip this validation

    5. in case of error return 422 “Incorrect value. Expected value to be in range {RESULT_BOUNDARIES.check.min} and {RESULT_BOUNDARIES.check.max}“

  5. Check that observation value calculated correctly according to the method declared in RESULT_SCORE_CALCULATION configuration parameter

    1. There are different supported methods to calculate and control result (“SUM”)

    2. If `SUM` specified

      1. go through all observation.components

      2. sum all scores provided in item_weight extension observation.component.value_codeable_concept.coding.extension(code = item_weight).value_decimal and all components where component value type is quantity and quantity system = eHealth/ucum/units and quantity code = ScoreOf

    3. ensure that this result is equal to observation.component.value_quantity.value

    4. if RESULT_SCORE_CALCULATION is missing or is empty then skip this validation

    5. in case of error return 422 “Incorrect observation result“

Processing

API paragraph not found

 

Response structure

See on Apiary

Example:

{ "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" } }

 

{ "meta": { "code": 404, "url": "http://example.com/resource", "type": "object", "request_id": "req-adasdoijasdojsda" }, "error": { "type": "NOT_FOUND", "message": "Patient not found" } }

 

Post-processing processes

Set managing_organization for submitted observations

  1. ME.conditions{cond_id}.managing_organization=token.client_id.

  2. in case service request has reference on care plan and diagnostic report.based_on was filled set $.diagnostic_report.id to related to $.service_request $.activity[].outcome_reference

  3. Update $ .activity.status to in_progress if previous activity status was scheduled

  4. Update the $ .activity.remaining_quantity parameter by the value achieved at Submit Encounter Data Package: Related care plan validation (for an old activities only that has no quantity units)

  5. Update remaining_quantity in the service request with a value that was calculated in the Submit Encounter Data Package: Related service request validation

  6. Set origin_episode (if $.based_on in request and $.based_on.service_request.context != null) for Diagnostic Report:

    1. origin_episode is an object from the $.service_request.context.episode

 

HTTP status codes

HTTP status code

Message

What caused the error

HTTP status code

Message

What caused the error

 202

 Response

 

401

Access denied

 

403

Invalid scope

 

 404

 Patient not found

 

409

 

Validation error

422

 

Validation error

 

 

ЕСОЗ - публічна документація