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

RC_Create/Update person request v2 (DMS)

Purpose

This WS is used to create Person Request (as part of Person creation w/o declaration process). Upon successful completion of the whole process, a person is created in MPI. Also this WS allows to update the person’s data according to his id, which was previously found.

Specification

Apiary

Key points

  1. This WS can be used for both creating new person and updating existing person.

  2. Person authentication method shouldnt be passed in request for update person.

Main differences from V1

  1. Confidant_person is an object, not an array.

  2. It is allowed to submit confidant person when person is created.

  3. It is not allowed to submit confidant person when person is updated.

  4. Validation of confidant person is updated: age, verification status and auth methods are important.

  5. Validation of auth methods is updated: in case if person has confidant, as THIRD_PERSON in auth methods must be submitted confidant.

  6. Validation of person documents is updated: if person`s age is between no_self_registration_age and person_full_legal_capacity_age, documents that prove legal capacity can be sumbitted. In case if legal capacity is provenoven by document, person can not have confidant.

  7. Validate necessity of confidant person is added: in some cases (view on validations below) it is necessary to have confidant if person is created (in the request body) and if person is updated (in db MPI | confidant_person_relationships#confidant_person_relationships ).

  8. Links to save documents for confidant persons are updated.

  9. When person, that is updated, must be authorized by confidant person - authentication method with type = THIRD_PERSON must be passed in authorize_with field.

Authorization

  • Verify the validity of access token

    • 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 scopes in order to perform this action (scope = 'person_request:write')

    • Return (403, 'Your scope does not allow to access this resource. Missing allowances: person_request: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")

Determine person request process

Check existence of $.person.id field in request:

Create person request

Validate request

Validate request according to JSON Schema

  • Check absence of extra parameters

    • In case of error - return 422 ('schema does not allow additional properties')

  • Check presence of required parameters

    • In case of error - return 422 ('required property %{property} was not present')

{ "$schema": "http://json-schema.org/person_request/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": "^(?!.*[ЫЪЭЁыъэё@%&$^#])[А-ЯҐЇІЄа-яґїіє\\'\\-]+(\\s(?!.*[ЫЪЭЁыъэё@%&$^#])[А-ЯҐЇІЄа-яґїіє\\'\\-]+)*$", "minLength": 1, "maxLength": 255 }, "unzr": { "type": "string", "pattern": "^[0-9]{8}-[0-9]{5}$" }, "tax_id": { "type": "string", "pattern": "^[0-9]{10}$", "minLength": 10, "maxLength": 255 }, "no_tax_id": { "type": "boolean", "description": "Status person refused tax_id" }, "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}$" }, "inserted_by": { "type": "string" }, "updated_by": { "type": "string" }, "inserted_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": [ "type", "country", "area", "settlement", "settlement_type", "settlement_id", "inserted_by", "updated_by" ], "additionalProperties": false }, "series_number_document": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "PASSPORT", "COMPLEMENTARY_PROTECTION_CERTIFICATE", "REFUGEE_CERTIFICATE", "TEMPORARY_CERTIFICATE" ], "description": "Dictionary: DOCUMENT_TYPE" }, "number": { "type": "string", "pattern": "^((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{6}$" }, "issued_by": { "type": "string", "minLength": 1 }, "issued_at": { "type": "string", "format": "date" } }, "required": [ "type", "number" ], "additionalProperties": false }, "number_document": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "BIRTH_CERTIFICATE", "TEMPORARY_PASSPORT" ], "description": "Dictionary: DOCUMENT_TYPE" }, "number": { "type": "string", "pattern": "^(?![ЫЪЭЁыъэё@%&$^#`~:,.*|}{?!])[A-ZА-ЯҐЇІЄ0-9№\\/()-]+$", "minLength": 1, "maxLength": 255 }, "issued_by": { "type": "string", "minLength": 1 }, "issued_at": { "type": "string", "format": "date" } }, "required": [ "type", "number" ], "additionalProperties": false }, "id_card": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "NATIONAL_ID" ], "description": "Dictionary: DOCUMENT_TYPE" }, "number": { "type": "string", "pattern": "^[0-9]{9}$" }, "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 } }, "type": "object", "properties": { "person": { "type": "object", "properties": { "first_name": { "type": "string" }, "last_name": { "type": "string" }, "second_name": { "type": "string" }, "birth_date": { "type": "string" }, "birth_country": { "type": "string" }, "birth_settlement": { "type": "string" }, "gender": { "enum": [ "MALE", "FEMALE" ] }, "email": { "type": "string" }, "no_tax_id": { "type": "boolean" }, "tax_id": { "type": "string" }, "secret": { "type": "string" }, "documents": { "type": "array" }, "addresses": { "type": "array" }, "phones": { "type": "array" }, "authentication_methods": { "type": "array" }, "unzr": { "type": "string" }, "emergency_contact": { "type": "object", "properties": { "first_name": { "type": "string" }, "last_name": { "type": "string" }, "second_name": { "type": "string" }, "phones": { "type": "array" } }, "required": [ "first_name", "last_name", "phones" ] }, "confidant_person": { "type": "array" }, "preferred_way_communication": { "enum": [ "email", "phone" ] } }, "required": [ "first_name", "last_name", "birth_date", "birth_country", "birth_settlement", "gender", "no_tax_id", "tax_id", "secret", "documents", "addresses", "emergency_contact" ] }, "patient_signed": { "type": "boolean" }, "process_disclosure_data_consent": { "type": "boolean" } }, "required": [ "person", "patient_signed", "process_disclosure_data_consent" ] }

Validate client

  • Check that client_id belongs to legal entity with type from PERSON_REQUEST_LEGAL_ENTITY_TYPES config parameter

    • in case of error - return 409 ('Invalid legal entity type')

  • Check that client_id belongs to active legal entity (status = active and is_active = true)

    • in case of error - return 409 ('Legal entity is not active')

Validate tax id

  • Check that tax_id field matches pattern ^[0-9]{10}$

    • in case of error - return 422 ('string does not match pattern’) with the corresponding regexp

  • If VALIDATE_PERSON_TAX_ID_UNIQUENESS chart param is true, then check there is no another active person with the same tax_id in the system

    • in case of error - return 422 ('tax_id is already used by another person')

Validate no_tax_id flag

  • If no_tax_id = true, check that tax_id field is empty

    • in case of error - return 422 ('Persons who refused the tax_id should be without tax_id')

  • If no_tax_id = false and persons age > no_self_auth_age global parameter, check that tax_id is present

    • in case of error - return 422 ('Only persons who refused the tax_id could be without tax_id')

Validate patient_signed flag

  • Check patient_signed field is present in request

    • in case of error - return 422 ('required property patient_signed was not present')

  • Check that patient_signed = false in request

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

Validate process_disclosure_data_consent flag

  • Check process_disclosure_data_consent field is present in request

    • in case of error - return 422 ('required property process_disclosure_data_consent was not present')

  • Check that process_disclosure_data_consent = true in request

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

Validate person addresses

  • Check that at least one address record with type = 'RESIDENCE' is submitted

    • in case of error - return 422 ('one and only one residence address is required')

Validate necessity of confidant person

A block with information about confidant person must be transferred when the person is created.
New endpoints RC_(CSI-1323)_Confidant Persons technical specification must be used to manage list of persons confidants.

 

confidant_persons-Validate necessity of confidant person.drawio.png

 

Source:

  • In case if persons age < no_self_registration_age global parameter - check that confidant_person is submitted

    • in case of error - return 422 ('Confidant person is mandatory for children.')

  • In case if persons age is greater then no_self_registration_age global parameter, but less then person_full_legal_capacity_age global parameter:

    • if none of persons documents has type from PERSON_LEGAL_CAPACITY_DOCUMENT_TYPES config parameter - check that confidant_person is submitted

      • In case of error - return 422 ('Confidant person is mandatory for minor patients.')

    • Else if at least one of submitted person document types exist in PERSON_LEGAL_CAPACITY_DOCUMENT_TYPES config parameter - check that confidant_person is not submitted

      • in case of error - return 422 ('Confidant can not be submitted for person who has document that proves legal capacity.')

Validate confidant person

Confidant person must be validated only if $.person.confidant_person block is presented in the request:

  • Check that confidant_person.person_id exists in persons table (MPI DB) with status = active and is_active = true

    • in case of error - return 422 ('Confidant person is not found')

  • Check if confidant person itself shouldn’t be authorized by confidant - so it doesn’t correspond to following rules:

    • confidant persons age < no_self_registration_age global parameter;

    • confidant persons age between no_self_registration_age and person_full_legal_capacity_age global parameters and person does not have document with type from PERSON_LEGAL_CAPACITY_DOCUMENT_TYPES config parameter;

    • confidant persons age > person_full_legal_capacity_age global parameter and exists at least one active and approved confidant person relationship for person (using following process Check confidant person relationship with person_id = $.person.confidant_person.person_id from request - expected :ok, :approved response)

    • confidant person has at least one confidant person in persons.confidant_person array

      • in case of error - return 422 ('Person with incorrect age or with active confidant person relationship can not be submitted as confidant')

  • Check that confidant person cumulative verification status is not in NOT_ALLOWED_CONFIDANT_PERSON_VERIFICATION_STATUSES config parameter

    • in case of error - return 422 ('Person with cumulative verification status <person.verification_status> can not be submitted as confidant')

  • Check that confidant person has active authentication method with type = OTP

    • in case of error - return 422 ('Confidant person must have active authentication method with type "OTP"')

  • Validate confidant persons documents_relationship

    • Validate document issued_at date

      • Check that issued_at <= now()

        • in case of error - return 422 ('Document issued date should be in the past')

      • Check that issued_at => person.birth_date

        • in case of error - return 422 ('Document issued date should greater than person.birth_date')

    • Validate document active_to date

      • Check that active_to > now()

        • in case error - return 422 ('Document active_to should be in future')

    • Validate document type according to DOCUMENT_RELATIONSHIP_TYPE dictionary

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

    • Validate document number according to regexp (as part of JSON Schema validation) 

      • BIRTH_CERTIFICATE - ^((?![ЫЪЭЁыъэё@%&$^#`~:,.*|}{?!])[A-ZА-ЯҐЇІЄ0-9№\\/()-]){2,25}$

        • In case of error - return 422 ('string does not match pattern') with the corresponding regexp

      • other document type numbers should be validated according to format varchar (255)

        • in case of error - return 422 ('expected value to have a maximum length of 255 but was <<document_number_length>>')

Validate person documents

  • Check submitted person document types exist in PERSON_REGISTRATION_DOCUMENT_TYPES config parameter that contains values from DOCUMENT_TYPE dictionary

    • in case of error - return 422 ('Submitted document type is not allowed')

  • Check document types from PERSON_LEGAL_CAPACITY_DOCUMENT_TYPES config parameter (that prove persons legal capacity) are not submitted if persons age is less then no_self_registration_age global parameter or greater then person_full_legal_capacity_age global parameter

    • in case of error - return 422 ('<Document type> can not be submitted for this person') with first found document type

  • If at least one document type from PERSON_LEGAL_CAPACITY_DOCUMENT_TYPES config parameter is submitted, check that at least one document type from PERSON_REGISTRATION_DOCUMENT_TYPES is submitted

    • in case of error - return 422 ('Document that proves personal data must be submitted.')

  • Validate document issued_at date

    • Check that issued_at <= now()

      • in case of error - return 422 ('Document issued date should be in the past')

    • Check that issued_at => person.birth_date

      • in case of error - return 422 ('Document issued date should greater than person.birth_date')

  • Validate document expiration_date

    • if PERSON_DOCUMENTS_USE_SPECIFIC_EXPIRATION_DATE == true:

      • check that "expiration_date" > PERSON_DOCUMENTS_SPECIFIC_EXPIRATION_DATE

        • in case error show 422, "Document expiration_date should be more than <PERSON_DOCUMENTS_SPECIFIC_EXPIRATION_DATE>"

    • else PERSON_DOCUMENTS_USE_SPECIFIC_EXPIRATION_DATE == false:

      • check that "expiration_date" > now()

        • in case error show 422, "Document expiration_date should be in future"

    • Check that expiration_date exists for following document types:

      • 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 document number according to regexp (as part of JSON Schema validation) 

    • PASSPORT - ^((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{6}$

    • NATIONAL_ID - ^[0-9]{9}$

    • BIRTH_CERTIFICATE - ^((?![ЫЪЭЁыъэё@%&$^#`~:,.*|}{?!])[A-ZА-ЯҐЇІЄ0-9№\\/()-]){2,25}$

    • COMPLEMENTARY_PROTECTION_CERTIFICATE - ^((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{6}$

    • REFUGEE_CERTIFICATE - ^((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{6}$

    • TEMPORARY_CERTIFICATE - ^(((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{4,6}|[0-9]{9}|((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{5}\\/[0-9]{5})$

    • TEMPORARY_PASSPORT - ^((?![ЫЪЭЁыъэё@%&$^#`~:,.*|}{?!])[A-ZА-ЯҐЇІЄ0-9№\\/()-]){2,25}$

    • CHILD_BIRTH_CERTIFICATE - ^((?![ЫЪЭЁыъэё@%&$^#`~:,.*|}{?!])[A-ZА-ЯҐЇІЄ0-9№\\/()-]){2,25}$

    • MARRIAGE_CERTIFICATE - ^((?![ЫЪЭЁыъэё@%&$^#`~:,.*|}{?!])[A-ZА-ЯҐЇІЄ0-9№\\/()-]){2,25}$

    • DIVORCE_CERTIFICATE - ^((?![ЫЪЭЁыъэё@%&$^#`~:,.*|}{?!])[A-ZА-ЯҐЇІЄ0-9№\\/()-]){2,25}$

      • in case of error - return 422 ('string does not match pattern') with the corresponding regexp

  • If unzr exists and is not null, check that it matches pattern - ^[0-9]{8}-[0-9]{5}$

    • in case of error - return 422 ('string does not match pattern') with the corresponding regexp

  • If document with type NATIONAL_ID exists in request, check that unzr exists in request

    • in case of error - return 422 ('unzr is mandatory for document type NATIONAL_ID')

  • Check that document types NATIONAL_ID and PASSPORT both do not exist in request

    • in case of error - return 422 ('Person can have only new passport NATIONAL_ID or old PASSPORT.')

  • Check that document types BIRTH_CERTIFICATE or BIRTH_CERTIFICATE_FOREIGN are submitted if persons age < no_self_auth_age global parameter

    • in case of error - return 422 ('Documents should contain one of: BIRTH_CERTIFICATE, BIRTH_CERTIFICATE_FOREIGN.')

  • Check that document number length < 255

    • in case of error - return 422 ('expected value to have a maximum length of 255 but was <<document_number_length>>')

Search pending declaration requests

Search declarations request in IL.declaration_requests to prevent duplication:

  • if $.person.tax_id is not null, search with following parameters:

    • data_person_tax_id = $.person.tax_id

    • status = NEW or APPROVED

  • if $.person.tax_id is null, search with following parameters:

    • data_person_documents.[i].number = $.person.documents.[i].number

    • status = NEW or APPROVED

If found declaration request - return 409 ('This person already has a declaration request')

Search person

We are looking for a person to prevent duplication of a person.

Create pairs of new person with people from clusters (tax_id, phone_number and number of the document) and send to the deduplication model.

Compare score for each pair with PERSON_ONLINE_DEDUPLICATION_MATCH_SCORE config parameter:

  • in case score < PERSON_ONLINE_DEDUPLICATION_MATCH_SCORE - create new person

  • in case score > PERSON_ONLINE_DEDUPLICATION_MATCH_SCORE - return 409 ('Such person exists. Update this person')

Validate person authentication methods

A block with information about authentication methods must be transferred when the person is created.
It is prohibited to transfer authentication methods when the person is updated.
Endpoints (described here https://e-health-ua.atlassian.net/wiki/spaces/EH/pages/620953636) must be used to update persons authentication methods.

  • Check that only one authentication method is submitted for person

    • in case of error - return 422 ('expected a maximum of 1 items but got <<count_authentication_method_objects>>')

  • In case if person.confidant_person block is not empty:

    • Check that submitted authentication_methods record has type = 'THIRD_PERSON'

      • in case of error - return 422 ('Only THIRD_PERSON authentication method can be created for person')

    • Check that THIRD_PERSON is the same person who is submitted as confidant (authentication_methods[0].value = confidant_person[0].person_id)

      • in case of error - return 422 ('Confidant person must be submitted as THIRD_PERSON for authentication method')

    • Check that THIRD_PERSON is found less than third_person_limit global parameter value in the system (in table person_authentication_methods with value = authentication_methods[0].value& ended_at іs empty or > now() & type = THIRD_PERSON)

      • in case of error - return 422 ('This fiduciary person is present more than $.global_parameters.third_person_limit times in the system')

  • Else if person.confidant_person block is empty:

    • Check that submitted authentication_methods block contains record with type = 'OTP' or type = 'OFFLINE'

      • in case of error - return 422 ('Only OTP or OFFLINE authentication method can be created for person')

    • For authentication method with type = ‘OTP’ perform following phone number limit validation only if USE_PHONE_NUMBER_AUTH_LIMIT config parameter is set to true:

      • check that phone number from persons authentication method is found less than phone_number_auth_limit global parameter in the system (in table person_authentication_methods with phone_number = $.person.authentication_methods.[0].phone_number & ended_at іs empty or > now() & type = OTP)

        • in case of error - return 409 ('This phone number is present more then $.global_parameters.phone_number_auth_limit times in the system')

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 (according to SECRETS_TTL config parameter). If it has been expired - new person request should be created.

Each link is generated for one one-page document in jpeg format. Document should be no more than 10MB.

For each type of documents, if couple of rules worked - only one single link is generated.

  1. Validate block confidant person. If $.person.confidant_person is not null:

    • Generate URLs with type confidant_person.{confidant_person.person_id}.documents_relationship.[:].{type}

  2. Validate block of person documents. If one of the documents has document.type = BIRTH_CERTIFICATE_FOREIGN and there is no same document in {$.person_request.person.confidant_person.[:].documents_relationship.[:]}

    and persons age < no_self_auth_age global parameter then

    1. Generate URL with type person.BIRTH_CERTIFICATE_FOREIGN

  3. Validate block of person documents. If one of the documents has document.type = PERMANENT_RESIDENCE_PERMIT and persons age >= no_self_auth_age global parameter then

    1. Generate URL with type person.PERMANENT_RESIDENCE_PERMIT

  4. Validate block of authentication methods. If authentication method type = OFFLINE

    1. Generate URLs with type person.{$.person.documents.[:].type} for each persons document

  5. Validate persons unzr. If $.person.unzr is not empty and first 8 digits of $.person.unzr != $.person.birth_date

    1. Generate URL with type person.unzr

Invoke Media Content Storage to generate upload URL for each document obtained by executing logic above and save documents to DB.

Search pending person requests

Search pending person requests in IL.person_requests to prevent requests duplication based on person request data:

  • if $.person.tax_id is not null, search with following parameters:

    • tax_id = $.person.tax_id

    • documents.[i].number = $.person.documents.[i].number

    • status = NEW or APPROVED

  • if $.person.tax_id is null, search with following parameters:

    • documents.[i].number = $.person.documents.[i].number

    • first_name = $.person.first_name

    • last_name = $.person.last_name

    • status = NEW or APPROVED

Cancel person request

Change status of all found person requests:

  • set status = CANCELLED

  • set updated_at = now()

  • set updated_by = user_id from token

Save person request

Insert record to IL.person_requests, set values:

  • id = autogenerate uuid

  • person_data = $.person from request in json format

  • status = NEW

  • authentication_method_current = type for auth method that is used to authorize request (set phone_number for type OTP or THIRD_PERSON with type OTP)

  • channel = MIS

  • legal_entity_id = client_id from token (id of legal entity where person request is created)

  • tax_id = $.person.tax_id from request (if not null)

  • last_name = $.person.last_name from request

  • first_name = $.person.first_name from request

  • birth_date = $.person.birth_date from request

  • documents = generated links for documents upload (if needed)

  • person_documents = $.person.documents from request in json format

  • inserted_by = user_id from token

  • updated_by = user_id from token

  • inserted_at = now()

  • updated_at = now()

  • patient_signed = $.patient_signed from request

  • process_disclosure_data_consent = $.process_disclosure_data_consent from request

  • version = 2

Generate verification code

In case if person request authentication_method_current.type = OTP, invoke Initialize OTP to generate one time password and send it to persons or confidants number that is stored in authentication_method_current.phone_number. At this stage, the person receives an SMS message to confirm this phone and the consent to create a person.

Update person request

It is necessary to transfer the same json as when creating person, only to transfer the id of an existing person and do not transfer the block with the authentication methods and confidant person.

Validate existing person

If $.person.id is submitted in request then:

  • Check that $.person.id is a valid uuid

    • in case error - return 422 ('string does not match pattern') with uuid regexp

  • Check that person exists in persons table (MPI DB) with status = active and is_active = true 

    • in case error - return 404 ('Person does not exist.’)

  • Check that amount of changes of person data in request is acceptable (person is not updated too much). Compare updated person data with data from person request using existing Deduplication process NEW | Variables calculation for each pair - check that resulted comparison score is greater that PERSON_ONLINE_DEDUPLICATION_UPDATE_SCORE config parameter

    • in case of error - return 409 ('Such person can't be updated. Deduplication update score is lower than system value (less changes should be made)')

Update person’s data with empty value of the second name is possible by setting second_name = null.

Validate request

Validate request using JSON schema

{ "$schema": "http://json-schema.org/person_request/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": "^(?!.*[ЫЪЭЁыъэё@%&$^#])[А-ЯҐЇІЄа-яґїіє\\'\\-]+(\\s(?!.*[ЫЪЭЁыъэё@%&$^#])[А-ЯҐЇІЄа-яґїіє\\'\\-]+)*$", "minLength": 1, "maxLength": 255 }, "unzr": { "type": "string", "pattern": "^[0-9]{8}-[0-9]{5}$" }, "tax_id": { "type": "string", "pattern": "^[0-9]{10}$", "minLength": 10, "maxLength": 255 }, "no_tax_id": { "type": "boolean", "description": "Status person refused tax_id" }, "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}$" }, "inserted_by": { "type": "string" }, "updated_by": { "type": "string" }, "inserted_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": [ "type", "country", "area", "settlement", "settlement_type", "settlement_id", "inserted_by", "updated_by" ], "additionalProperties": false }, "series_number_document": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "PASSPORT", "COMPLEMENTARY_PROTECTION_CERTIFICATE", "REFUGEE_CERTIFICATE", "TEMPORARY_CERTIFICATE" ], "description": "Dictionary: DOCUMENT_TYPE" }, "number": { "type": "string", "pattern": "^((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{6}$" }, "issued_by": { "type": "string", "minLength": 1 }, "issued_at": { "type": "string", "format": "date" } }, "required": [ "type", "number" ], "additionalProperties": false }, "number_document": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "BIRTH_CERTIFICATE", "TEMPORARY_PASSPORT" ], "description": "Dictionary: DOCUMENT_TYPE" }, "number": { "type": "string", "pattern": "^(?![ЫЪЭЁыъэё@%&$^#`~:,.*|}{?!])[A-ZА-ЯҐЇІЄ0-9№\\/()-]+$", "minLength": 1, "maxLength": 255 }, "issued_by": { "type": "string", "minLength": 1 }, "issued_at": { "type": "string", "format": "date" } }, "required": [ "type", "number" ], "additionalProperties": false }, "id_card": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "NATIONAL_ID" ], "description": "Dictionary: DOCUMENT_TYPE" }, "number": { "type": "string", "pattern": "^[0-9]{9}$" }, "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 } }, "type": "object", "properties": { "person": { "type": "object", "properties": { "id": { "type": "string" }, "first_name": { "type": "string" }, "last_name": { "type": "string" }, "second_name": { "type": "string" }, "birth_date": { "type": "string" }, "birth_country": { "type": "string" }, "birth_settlement": { "type": "string" }, "gender": { "enum": [ "MALE", "FEMALE" ] }, "email": { "type": "string" }, "no_tax_id": { "type": "boolean" }, "tax_id": { "type": "string" }, "secret": { "type": "string" }, "documents": { "type": "array" }, "addresses": { "type": "array" }, "phones": { "type": "array" }, "unzr": { "type": "string" }, "emergency_contact": { "type": "object", "properties": { "first_name": { "type": "string" }, "last_name": { "type": "string" }, "second_name": { "type": "string" }, "phones": { "type": "array" } }, "required": [ "first_name", "last_name", "phones" ] }, "confidant_person": { "type": "array" }, "preferred_way_communication": { "enum": [ "email", "phone" ] } }, "required": [ "first_name", "last_name", "birth_date", "birth_country", "birth_settlement", "gender", "no_tax_id", "tax_id", "secret", "documents", "addresses", "emergency_contact" ] }, "patient_signed": { "type": "boolean" }, "process_disclosure_data_consent": { "type": "boolean" } }, "required": [ "person", "patient_signed", "process_disclosure_data_consent" ] }

Validate client

Validate as on Create person request process

Validate tax id

  • If updated persons tax_id is not null - check that $.person.tax_id equals to updated persons tax_id

    • in case of error - return 422 ('tax_id can't be updated')

  • Validate as on Create person request process

Validate no_tax_id flag

Validate as on Create person request process

Validate patient_signed flag

Validate as on Create person request process

Validate process_disclosure_data_consent flag

Validate as on Create person request process

Validate person addresses

Validate as on Create person request process

Validate person documents

Validate as on Create person request process

Validate authorize_with

The person can pass the id of his auth method which he wants to use to confirm the update person request. The necessary auth method can be found by making Get person's auth methods.

  • Check that $.authorize_with with auth_method.type = 'THIRD_PERSON' is submitted for person that must be authorized by confidant person using following logic:

    1. persons age < no_self_registration_age global parameter;

    2. persons age between no_self_registration_age and person_full_legal_capacity_age global parameters and person does not have document with type from PERSON_LEGAL_CAPACITY_DOCUMENT_TYPES config parameter;

    3. persons age > person_full_legal_capacity_age global parameter and exists at least one active and approved confidant person relationship for person (using following process Check confidant person relationship with person_id = person from request - expected :ok, :approved response)

      1. in case of error - return 422 ('Authentication method with type THIRD_PERSON must be submitted for this person')

  • Check that $.authorize_with is a valid uuid

    1. in case error - return 422 ('string does not match pattern') with uuid regexp

  • Check that auth method exists in MPI database, person_authentication_methods table, belongs to person from request, stored in $.person.id, is active (ended_at > now() or ended_at is null and is_active = true), and type != NA, additionally for auth method with type = ‘THIRD_PERSON’ - check that person from value is an approved confidant for a $.person.id from request – exists active and approved confidant person relationship between person from request and person_id from authentication method value (using following logic: Check confidant person relationship with person_id = person from request and confidant_person_id = value from auth method - expected :ok, :approved response)

    1. in case error - return 409 ('Authentication method doesn't belong to person.')

This field is optional and set in authentication_method_current field of person request.

If person request doesn't have this field, then choose that method which is returned from mpi as using Determination of a default authentication method and return person's active auth_methods .

Determine authentication method current for request

  • If $.authorize_with is not null - set its value as authentication method current for request

  • If $.authorize_with is null - set default auth method as authentication method current for request - use function in mpi that return default auth method

    • Check that persons default auth method != NA

      • in case of error - return 409 ('Person does not have active auth methods.')

Search pending declaration requests

Search as on Create person request process

Generate upload URL

Generate upload URL as on Create person request process

Search pending person requests

Search as on Create person request process

Cancel person request

Change status of all found person requests:

  • set status = CANCELLED

  • set updated_at = now()

  • set updated_by = user_id from token

Save person request

Insert record to IL.person_requests, set values:

  • id = autogenerate uuid

  • person_data = $.person from request in json format

  • status = NEW

  • authentication_method_current = calculated authentication method current for request (set phone_number for type OTP or THIRD_PERSON with type OTP)

  • channel = MIS

  • legal_entity_id = client_id from token (id of legal entity where person request is created)

  • tax_id = $.person.tax_id from request (if not null)

  • last_name = $.person.last_name from request

  • first_name = $.person.first_name from request

  • birth_date = $.person.birth_date from request

  • documents = generated links for documents upload (if needed)

  • person_documents = $.person.documents from request in json format

  • inserted_by = user_id from token

  • updated_by = user_id from token

  • inserted_at = now()

  • updated_at = now()

  • patient_signed = $.patient_signed from request

  • process_disclosure_data_consent = $.process_disclosure_data_consent from request

  • person_data_id = $.person.id from request

  • authorize_with = $.authorize_with from request (if not null)

  • version = 2

Generate verification code

In case if person request authentication_method_current.type = OTP, invoke Initialize OTP to generate one time password and send it to persons or confidants number that is stored in authentication_method_current.phone_number. At this stage, the person receives an SMS message to confirm this phone and the consent to create a person.

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