ЕСОЗ - публічна документація
(Deprecated) IL.Create declaration request
- 1 Validate request
- 1.1 JSON Schema
- 2 Authorize
- 3 Validate Legal Entity Type
- 4 Validate doctor
- 5 Check phone number
- 6 Search pending declaration requests
- 7 Cancel declaration requests
- 8 Search pending declaration requests
- 9 Calculate declaration end/start date
- 10 Validate confidant person
- 11 Save declaration request
- 12 Check "no_tax_id" flag
- 13 Validate person_id
- 14 Validate phone number limit
- 15 Validate declaration limit
- 16 Validate person authentication phone
- 17 Validate person documents
- 18 Determine auth method
- 19 Determine Channel
- 20 Generate printout form
- 20.1 cURL example
- 21 Generate upload URL
- 21.1 For On-line
- 21.2 For Offline
- 22 Generate verification code
- 22.1 cURL example
- 23 Generate human readable declaration number
Validate request
Validate request using JSON schema
JSON Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"phone": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Dictionary: PHONE_TYPE"
},
"number": {
"type": "string",
"pattern": "^\\+38[0-9]{10}$"
}
},
"required": [
"type",
"number"
],
"additionalProperties": false
},
"name": {
"type": "string",
"pattern": "^(?!.*[ЫЪЭЁыъэё@%&$^#])[a-zA-ZА-ЯҐЇІЄа-яґїіє0-9№\\\"!\\^\\*)\\]\\[(._-].*$"
},
"person_name": {
"type": "string",
"pattern": "^(?!.*[ЫЪЭЁыъэё@%&$^#])[А-ЯҐЇІЄа-яґїіє\\'\\- ]+$",
"minLength": 1,
"maxLength": 255
},
"tax_id": {
"type": "string",
"pattern": "^[0-9]{10}$",
"minLength": 10,
"maxLength": 255
},
"gender": {
"type": "string",
"description": "Dictionary: GENDER",
"maxLength": 255
},
"address": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Dictionary: ADDRESS_TYPE"
},
"country": {
"type": "string"
},
"area": {
"$ref": "#/definitions/name"
},
"region": {
"$ref": "#/definitions/name"
},
"settlement": {
"$ref": "#/definitions/name"
},
"settlement_type": {
"type": "string",
"description": "settlement type Dictionary: SETTLEMENT_TYPE"
},
"settlement_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
},
"street_type": {
"type": "string",
"description": "street type Dictionary: STREET_TYPE"
},
"street": {
"$ref": "#/definitions/name"
},
"building": {
"type": "string",
"pattern": "^[1-9]((?![ЫЪЭЁыъэё])()([А-ЯҐЇІЄа-яґїіє \\/\\'\\-0-9])){0,20}$"
},
"apartment": {
"type": "string"
},
"zip": {
"type": "string",
"pattern": "^[0-9]{5}$"
}
},
"required": [
"type",
"country",
"area",
"settlement",
"settlement_type",
"settlement_id"
],
"additionalProperties": false
},
"document": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Dictionary: DOCUMENT_TYPE"
},
"number": {
"type": "string",
"minLength": 1,
"maxLength": 255
},
"issued_by": {
"type": "string",
"minLength": 1
},
"issued_at": {
"type": "string",
"format": "date"
}
},
"required": [
"type",
"number"
],
"additionalProperties": false
},
"document_relationship": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Dictionary: DOCUMENT_RELATIONSHIP_TYPE",
"minLength": 1
},
"number": {
"type": "string",
"minLength": 1
},
"issued_by": {
"type": "string",
"minLength": 1
},
"issued_at": {
"type": "string",
"format": "date"
}
},
"required": [
"type",
"number"
],
"additionalProperties": false
},
"authentication_method": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Dictionary: AUTHENTICATION_METHOD"
},
"phone_number": {
"type": "string",
"pattern": "^\\+38[0-9]{10}$"
}
},
"required": [
"type"
],
"additionalProperties": false
}
},
"type": "object",
"properties": {
"declaration_request": {
"type": "object",
"properties": {
"start_date": {
"type": "string",
"format": "date-time",
"description": "Should be defined on the client side."
},
"person": {
"type": "object",
"properties": {
"first_name": {
"type": "string",
"$ref": "#/definitions/person_name"
},
"last_name": {
"type": "string",
"$ref": "#/definitions/person_name"
},
"second_name": {
"type": "string",
"$ref": "#/definitions/person_name"
},
"birth_date": {
"type": "string",
"format": "date"
},
"birth_country": {
"type": "string",
"minLength": 1,
"maxLength": 255
},
"birth_settlement": {
"type": "string",
"$ref": "#/definitions/name",
"minLength": 1,
"maxLength": 255
},
"gender": {
"$ref": "#/definitions/gender"
},
"email": {
"type": "string",
"format": "email",
"maxLength": 255
},
"tax_id": {
"type": "string",
"$ref": "#/definitions/tax_id"
},
"invalid_tax_id": {
"type": "boolean"
},
"secret": {
"type": "string",
"$ref": "#/definitions/name",
"minLength": 6,
"maxLength": 20
},
"preferred_way_communication": {
"type": "string",
"enum": [
"email",
"phone"
]
},
"documents": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/document"
}
},
"addresses": {
"type": "array",
"items": {
"$ref": "#/definitions/address"
},
"minItems": 2
},
"phones": {
"type": "array",
"items": {
"$ref": "#/definitions/phone"
}
},
"authentication_methods": {
"type": "array",
"items": {
"$ref": "#/definitions/authentication_method"
}
},
"emergency_contact": {
"type": "object",
"properties": {
"first_name": {
"type": "string",
"$ref": "#/definitions/person_name"
},
"last_name": {
"type": "string",
"$ref": "#/definitions/person_name"
},
"second_name": {
"type": "string",
"$ref": "#/definitions/person_name"
},
"phones": {
"type": "array",
"items": {
"$ref": "#/definitions/phone"
},
"minItems": 1
}
},
"required": [
"first_name",
"last_name",
"phones"
],
"additionalProperties": false
},
"confidant_person": {
"type": "array",
"items": {
"type": "object",
"properties": {
"relation_type": {
"type": "string",
"enum": [
"PRIMARY",
"SECONDARY"
]
},
"first_name": {
"type": "string",
"$ref": "#/definitions/person_name"
},
"last_name": {
"type": "string",
"$ref": "#/definitions/person_name"
},
"second_name": {
"type": "string",
"$ref": "#/definitions/person_name"
},
"birth_date": {
"type": "string",
"format": "date"
},
"birth_country": {
"type": "string",
"minLength": 1
},
"birth_settlement": {
"type": "string",
"$ref": "#/definitions/name",
"minLength": 1
},
"gender": {
"$ref": "#/definitions/gender"
},
"tax_id": {
"type": "string",
"$ref": "#/definitions/tax_id"
},
"secret": {
"type": "string",
"$ref": "#/definitions/name",
"minLength": 6
},
"documents_person": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/document"
}
},
"documents_relationship": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/document_relationship"
}
},
"phones": {
"type": "array",
"items": {
"$ref": "#/definitions/phone"
}
}
},
"required": [
"relation_type",
"first_name",
"last_name",
"birth_date",
"birth_country",
"birth_settlement",
"gender",
"secret",
"documents_person",
"documents_relationship"
],
"additionalProperties": false
},
"description": "Should be set if this Person is disabled, underage, etc."
},
"patient_signed": {
"type": "boolean",
"enum": [
false
]
},
"process_disclosure_data_consent": {
"type": "boolean",
"enum": [
true
]
}
},
"required": [
"first_name",
"last_name",
"birth_date",
"birth_country",
"birth_settlement",
"gender",
"secret",
"documents",
"addresses",
"authentication_methods",
"emergency_contact",
"patient_signed",
"process_disclosure_data_consent"
],
"additionalProperties": false,
"description": "Object that described a Patient. Confidant person should be set for disabled persons, underage persons, etc."
},
"employee_id": {
"type": "string",
"minLength": 36,
"description": "Employee ID with `type=DOCTOR` selected from available Employees as a third contract party."
},
"division_id": {
"type": "string",
"minLength": 36,
"description": "Registered Medical Service Provider Division identifier."
},
"scope": {
"type": "string",
"minLength": 1
},
"seed": {
"type": "string"
},
"overlimit": {
"type": "boolean",
"enum": [
false
]
}
},
"required": [
"person",
"employee_id",
"division_id",
"scope"
],
"additionalProperties": false
}
}
}
Authorize
Verify the validity of access token
Check user scope declaration_request:create in order to perform this action
Validate Legal Entity Type
Validate legal entity from token: legal_entities.type should be in DECLARATION_REQUEST_LEGAL_ENTITY_TYPES and legal_entities.status =='active'
Validate doctor
Get employee details
Invoke Get employee details
Validate Response $.data.employee_type == DOCTOR
Calculate patient age
Calculate patient age
age = MONTHS_BETWEEN (now(), $.declaration_request.person.birth_date) / 12
Get global parameters
Invoke Global parameters to get following parameters:
ADULT_AGE
DECLARATION_TERM
phone_number_auth_limit
cURL example
curl -X GET \
{:host}/prm/api/global_parameters
Response example
Check that doctor speciality meets the patient age requirements
Get doctor's speciality_officio (speciality object where speciality_officio == true)
Check age requirements according to global parameters
Speciality officio | Age |
---|---|
FAMILY DOCTOR | All ages |
THERAPIST | Greater or equal to $.data.adult_age |
PEDIATRICIAN | Less than $.data.adult_age |
Check phone number
Invoke Check phone number WS in order to check phone number exists in DB.
Phone number: $.declaration_request.person.phones.[0].number
cURL example
Successful response example
Failed response example
Search pending declaration requests
Search declarations in IL_DB.declaration_requests to prevent requests duplication:
if tax_id is not null
if tax_id is null
Cancel declaration requests
Change status of all found declarations:
Search pending declaration requests
Search persons request in IL_DB.person_requests to prevent requests duplication:
if tax_id is not null
if tax_id is null
If found person request - don't create person request. Return error "This person already has a person request"
Calculate declaration end/start date
Declaration
Start date:
Validate confidant person
If person age < 14 check existence of confidant_person
- in case error return 422 - msg "Confidant person is mandatory for children"
Save declaration request
Insert record to IL.declaration_request in status 'NEW'
Check "no_tax_id" flag
If "no_tax_id"= true, tax_id field should be empty, in case error return 422
If "no_tax_id"=false and age>14, tax_id should be present, in case error return 422
Validate person_id
USE_DEDUPLICATION_MODEL - is a flag in in ehealth.charts that turn on logic:
If person.id
is in request then
validate person.id is UUID
in case error return 422
search person by person.id in MPI
in case error return 422, "such person doesn't exist"
search persons in mpi (Пошук персон. Версія 3)
If new person's tax_id and authentication_number match with founded person by passed person.id - add mpi_id to declaration request
else validate person be deduplication model (if score > PERSON_ONLINE_DEDUPLICATION_MATCH_SCORE, then add mpi_id to declaration request)
else return error 409, "such person can't be updated. New person should be created instead"
If person.id
is not in request then
search persons in mpi (Пошук персон. Версія 3)
If we found person by tax_id and authentication_number
return error 409, "such person exists. Update this person."
In case authentication_method = OFFLINE, or don't found authentication_number, or we found authentication_number but tax_id don't match - We create pairs of new person with people from cluster and send to the model.
in case deduplication model gave score < PERSON_ONLINE_DEDUPLICATION_MATCH_SCORE, create new person
else return error 409, "such person exists. Update this person.
Validate phone number limit
USE_PHONE_NUMBER_AUTH_LIMIT is a flag in ehealth.charts that shows whether we count phones or not.
in case person is found, person_id will be saved to declaration_request, and person has the same authentication_methods.phone_number, we do not count phone numbers and do not compare the phone number with global_parameters.phone_number_auth_limit. So that we can update person, but still can not use phone over limit.
In case person is not found
Check if (SELECT count(*) from persons where authentication_methods::json->0->>'phone_number'='$.phone_number' and persons.status='active' and is_active=true)<global_parameters.phone_number_auth_limit
in case error return 422, msg "This phone number is present more then $.global_parameters.phone_number_auth_limit times in the system"
Validate declaration limit
Count all declarations in status
active
where OPS.declarations.employee_id==$.declaration_request.employee_id
1.1 If there is an active declaration with the current person, exclude it from the selection in order to let doctor resign declaration with current patientCount all declaration_requests in status
approved
where IL.declaration_requests.data($.employee.id) ==$.declaration_request.employee_idGet all specialities of current doctor
Select speciality from PRM.employees where PRM.employees.party_id == (select PRM.employees.party_id where PRM.employees.id=$.declaration_request.employee_id)
Select config parameter for declarations_limit where speciality == select 3
Compare the result of selections 1+2 with the lowest config parameter from select 4. In case count (declarations+declaration_requests )> config_parameter, return 409 "The employee has reached the declaration limit"
Validate person authentication phone
USE_DEDUPLICATION_MODEL - is a flag in in ehealth.charts that turn on logic:
If person have confidant_person, then person.auth_phone = person.confident_person.phone
in case error return 422 - msg "Person must have same phone as the confidant person"
Validate person documents
issued_at, issued_by is mandatory for documents
Validate dates
issued_at <= now() and issued_at => birth_date
in case `issued_at > now()` show error 422, "Document issued date should be in the past"
in case `issued_at < person.birth_date` show error 422, "Document issued date should greater than person.birth_date "
expiration_date > now()
in case error show 422, "Document expiration_date should be in future"
expiration_date is mandatory for document_type
NATIONAL_ID
COMPLEMENTARY_PROTECTION_CERTIFICATE
PERMANENT_RESIDENCE_PERMIT
REFUGEE_CERTIFICATE
TEMPORARY_CERTIFICATE
TEMPORARY_PASSPORT
in case error return 422, "expiration_date is mandatory for document_type $.documents.type"
Validate documents_type.number according to json schema
PASSPORT - `^((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{6}$`
NATIONAL_ID - `^[0-9]{9}$`
BIRTH_CERTIFICATE - ` ^(?![ЫЪЭЁыъэё@%&$^#`~:,.*|}{?!])[A-ZА-ЯҐЇІЄ0-9№\\/()-]+$ `
COMPLEMENTARY_PROTECTION_CERTIFICATE - `^((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{6}$`
PERMANENT_RESIDENCE_PERMIT - `^((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{6}$`
REFUGEE_CERTIFICATE - `^((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{6}$`
TEMPORARY_CERTIFICATE - `^((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{6}$`
TEMPORARY_PASSPORT - `` ^(?![ыъэ@%&$^#`~:,.*|}{?!])[А-ЯҐЇІЄа-яґїіє0-9 №\\\"()-]+$ `
if `unzr`exists and is not null and matches "^[0-9]{8}-[0-9]{5}$" check if first 8 symbols = birth_date
in case error return 422, msg "unzr or birthdate are not correct"
if documents.type=NATIONAL_ID
check if unzr exists in request, in case error return 422, msg "unzr is mandatory for document type NATIONAL_ID"
Document numbersmaxLength < 25
Determine auth method
Determine Channel
channel from url
if url is for cabinet сhannel set declaration_request.сhannel = CABINET
if not - set declaration_request.сhannel = MIS
Generate printout form
Invoke MAN to render print form.
Request mapping:
Parameter | Source |
---|---|
id | DECLARATION REQUEST |
cURL example
Set IL.declaration_request.printout_content:
Generate upload URL
Depending on the payload system generates list of signed urls for document scan-copies upload.
Signed URLs to be expired after some period of time (configurable `SECRETS_TTL`). If it has been expired - new declaration request should be created.
Each link is generated for one one-page document in jpeg format. Document should be no more than 10MB.
For On-line
if no_tax_id = true
Generate URL with type person.no_tax_id
For Offline
1. If $.declaration_request.person.tax_id not null:
Generate URL with type person.tax_id
2. For each $.declaration_request.person.documents:
Generate URL's with type person.{$.declaration_request.person.documents.[:].type}
3. If $.declaration_request.person.confidant_person.[:].tax_id not null, for each:
Generate URL with type confidant_person.{confidant_person.type}.tax_id
4. For each $.declaration_request.person.confidant_person.[:].documents_person:
Generate URL's with type confidant_person.{confidant_person.type}.{$.declaration_request.person.confidant_person.[:].documents_person.[:].type}
5. For each $.declaration_request.person.confidant_person.[:].documents_relationship:
Generate URL's with type confidant_person.{confidant_person.type}.{$.declaration_request.person.confidant_person.[:].documents_relationship.[:].type}
6. If no_tax_id = true
Generate URL with type person.no_tax_id
Invoke Media Content Storage to generate upload URL for each document obtained by executing logic above
IL.declaration_request.documents structure:
Save documents to DB.
Generate verification code
Invoke Initialize OTP to generate one time password and send it to client number.
Phone_number: IL.declaration_request.authentication_method_current.$.authentication_number
cURL example
Generate human readable declaration number
Use algorithm to generate declaration_number
Declaration number should consist of a 4 serial symbols and 8 number symbols and looks like XXXX-12H4-245D
Add field to ops.declarations and il.declaration_requests - declaration_number
Add declaration_number to print out form
Validate uniqueness of human readable declaration number
generate declaration_number
Search declaration_number in declaration_requests.declaration_number
if exists = go to 'generate declaration_number'
else save declaration_number to declaration_request
ЕСОЗ - публічна документація