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

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

Мета

Даний веб-сервіс (WS) використовується для завершення запиту на персону для оновлення даних персони у відповідності до його id, який було знайдено перед цим, використовуючи person_id з токену доступу.

Специфікація

Apiary

Основні положення

  1. Даний веб-сервіс (WS) має використовуватись тільки для завершення запиту на персону при оновленні існуючої персони в системі.

  2. Тільки запит на персону, створений через PIS має завершуватись даним веб-сервісом (WS).

  3. Перед завершенням - скан-копії документів персони можуть бути завантажені до сховища даних.

Авторизація

  • Перевірити валідність токену доступу

    • Повернути (401, 'Invalid access token') в разі неуспішних перевірок

  • Перевірити, що токен дійсний

    • в разі помилки - повернути (401, 'Invalid access token')

  • Перевірити скоупи користувача на можливість виконання даної дії (scope = 'person_request:write_pis')

    • Повернути (403, 'Your scope does not allow to access this resource. Missing allowances: person_request:write_pis') в разі невалідних скоупів

  • Перевірити, що токен містисть person_id

    • в разі помилки - повернути (401, 'Invalid access token')

Перевірити персону

  • Отримати person_id з токену (x-person-id header)

  • Перевірити, що статус персони активний (status = ‘active' & is_active = 'true’)

    • в разі помилки - повернути 404 ('Person is not found')

Перевірити довірену особу та взаємозв'язок

Якщо персона юридично не дієздатна - система має переконатись, що її дані оновлюються довіреною особою та є зареєстрований та верифікований взаємозв'язок.

Отримати applicant_person_id з токену, порівняти цого до person_id з токену:

  • якщо рівний - перевірити, що персона має бути не авторизована як довірена особа, що вона не відповідає наступним правилам:

    • вік персони < no_self_registration_age глобальному параметру;

    • що вік персони між значенням no_self_registration_age та person_full_legal_capacity_age глобальних параметрів та персона не має документу з типом з конфігураційного параметру PIS_PERSON_LEGAL_CAPACITY_DOCUMENT_TYPES;

    • вік персони > person_full_legal_capacity_age глобального параметру та існує хоча б один взаємозв'язок активний та погоджений з довіреною особою з персоною (викорисовуючи наступний процес /wiki/spaces/PCAB/pages/17415995422 з person_id = person з запиту - очікується відповідь :ok, :approved)

      • в разі помилки - повернути 409 (‘Request must be authorized by confidant person’)

  • Якщо не рівний - перевірити взаємозв'язок по наступним крокам:

    • Перевірити, що зареєстрований взаємозв'язок між person_id та applicant_person_id(MPI.confidant_person_relationships)

    • Перевірити, що взаємозв'язок є VERIFIED

      • в разі помилки - повернути 409 (‘Can’t confirm relationship’)

    • Перевірити, що існує applicant_person_id (status = 'active' & is_active = 'true') та має будь-який verification_status але не NOT_VERIFIED

      • в разі помилки - повернути 409 (‘Confidant person not found or is not verified’)

Перевірити запит

Перевірити закодований та декодований запит у відповідності до схеми JSON

 JSON Schema (encoded)
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "signed_content": {
      "type": "string"
    },
    "signed_content_encoding": {
      "type": "string",
      "enum": [
        "base64"
      ]
    }
  },
  "required": [
    "signed_content",
    "signed_content_encoding"
  ],
  "additionalProperties": false
}
 JSON Schema (decoded)
{
  "$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
    },
    "channel": {
      "type": "string",
      "enum": [
        "PIS"
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "NEW"
      ]
    },
    "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}$"
    },
    "content": {
      "type": "string"
    },
    "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
    }
  },
  "type": "object",
  "properties": {
    "person": {
      "type": "object",
      "properties": {
        "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}$"
        },
        "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"
          ]
        },
        "preferred_way_communication": {
          "enum": [
            "email",
            "phone"
          ]
        }
      },
      "required": [
        "first_name",
        "last_name",
        "birth_date",
        "birth_country",
        "birth_settlement",
        "gender",
        "secret",
        "documents",
        "addresses",
        "emergency_contact"
      ]
    },
    "patient_signed": {
      "type": "boolean"
    },
    "process_disclosure_data_consent": {
      "type": "boolean"
    }
  },
  "required": [
    "id",
    "person",
    "patient_signed",
    "process_disclosure_data_consent",
    "channel",
    "content",
    "status"
  ]
}
  • в разі, якщо значення поля не відповідає схемі - повернути 422 з повідомленням у відповідності до поля

  • в разі, якщо додаткові поля присутні в запиті - повернути 422 ('schema does not allow additional properties')

  • в разі, якщо потрібні параметри не присутні в запиті - повернути 422 ('required property %{property} was not present')

  • в разі, якщо необхідний набір параметрів не присутній в запиті - повернути 422 ('expected a minimum of %{min} items but got %{actual}')

Перевірити, що запит на персону з URL вказані в базі даних IL, таблиця person_requests, з person_data_id = person_id з токену

  • в разі помилки - повернути 404 ('Person request not found')

Перевірити статус зміни

Тільки запити на персону в статусі NEW та PIS може бути завершений.

  • Перевірити, що запит на персону для URL має статус = NEW та канал = PiS

    • в разі помилки - повернути 409 ('Invalid transition')

Перевірити підписний контент

  • Перевірити, що поле $.signed_content це валідний рядок base64

    • в разі помилки - повернути 422 ('Not a base64 string')

  • Перевірити, що значення поля $.signed_content_encoding рівний 'base64'

    • в разі помилки - повернути 422 ('value is not allowed in enum')

  • Перевірити, що поле $.signed_content містить цифровий підпис

    • в разі помилки - повернути 400 ('Invalid signature')

  • Перевірити цифровий підпис для $.signed_content валідний

    • в разі помилки - повернути 400 з помилкою валідації цифрового підпису

  • Перевірити, що декодований підписний контент відповідає з попереднього збереженим в таблиці person_requests для запиту на персону (окрім поля $.patient_signed)

    • в разі помилки - повернути 422 ('Signed content does not match the previously created content')

  • Перевірити, що поле drfo в цифровому підписі рівний персоні, що завершує запит, на основі поля applicant_person_id з токену

    • якщо applicant_person_id = person_id з токену - порівняти з персоною з запиту

      • якщо значення рівне tax_id regexp (^[0-9]{10}$), полу містить tax_id, використати поле tax_id з запиту на персону для порівняння;

      • якщо значення рівне номеру national_id regexp (^[0-9]{9}$), поле містить номер national_id, використовувати поле documents.number з documents.type = 'NATIONAL_ID' для порівняння;

      • якщо значення містить хоча б одну літеру, виконати зворотню транслітерацію поля, використовуючи існуючий алгоритм (описаний тут), тоді перевірити, що значення рівне номеру паспорту regexp (^((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{6}$), в разі рівності, поле містить номер паспорту, використати поле documents.number з documents.type = 'PASSPORT' для порівняння;

    • якщо applicant_person_id != person_id з токену - порівняти з довіреною особою в базі даних MPI

      • якщо значення drfo рівне tax_id regexp (^[0-9]{10}$), полу містить tax_id, порівняти з persons.tax_id;

      • якщо значення drfo рівне номеру national_id regexp (^[0-9]{9}$), поле містить номер national_id, порівняти document.number з типом = 'NATIONAL_ID'

      • якщо значення drfo містить хоча б одну літеру, виконати зворотню транслітерацію поля, використовуючи існуючий алгоритм (описаний тут), тоді перевірити, що значення рівне номеру паспорту regexp (^((?![ЫЪЭЁ])([А-ЯҐЇІЄ])){2}[0-9]{6}$), в разі рівності, поле містить номер паспорту, порівняти documents.number з типом 'PASSPORT'

        • в разі помилки - повернути 409 ('Unable to authenticate signer.')

Перевірити признак patient_signed

Запит на персону має бути підписаний тільки після того, як персона переглянула друковану форму.

Після того, як персона переглянула друковану форму, для поля patient_signed має бути встановлено значення true та передане в $.signed_content.

  • Перевірити, що поле patient_signed міститься в декодованому запиті на персону

    • в разі помилки - повернути 422 ('required property patient_signed was not present')

  • Перевірити, що patient_signed = true в декодованому запиті на персону

    • в разі помилки - повернути 422 ('value is not allowed in enum')

Перевірити завантажені документи

Отримати перелік типів документів, що мають бути завантажені до сховища даних в полі documents для запиту на персону.

  • якщо перелік пустий - пропустити перевірки

  • якщо перелік не пустий - перевірити, що документи були завантажені, використовуючи Media Content Storage

    • в разі помилки - повернути 409 ('Documents <<document_types_to_upload>> is not uploaded') with types of documents that must be uploaded to media content storage

Сервісна логіка

Зберегти підписаний запит на персону до сховища даних

Після того, як запит на персону було успішно підписано, зберегти підписаний запит на персону до сховища даних.

Отримати назву бакету з конфігураційного параметру MEDIA_STORAGE_PERSON_REQUEST_BUCKET, зберегти запит на персону до папки /person_requests/person_request_id з назвою файлу signed_content .

Оновити запит на персону

Оновити запит на персону, встановити значення:

  • status = SIGNED

  • updated_by = user_id з токену

  • updated_at = now()

  • patient_signed = true

  • person_id = person_id з токену

Оновити запити на декларацію зі статусом

Знайти активні запити на декларацію в таблиці IL.declaration_requests з наступними пошуковими параметрами:

  • mpi_id = person_id з токену

  • status = NEW або APRROVED

Якщо знайдено - відмінити запити на декларацію, встановити значення:

  • status = CANCELLED

  • status_reason = request_cancelled

  • updated_at = now()

  • updated_by = user_id з токену

Оновити персону

Оновити існуючу персону (з person_id з токену) в базі даних MPI.

Встановити значення у наступних таблицях для запиту на персону:

  1. таблиця persons

  2. таблиця person_phones

  3. таблиця person_addresses

  4. таблиця person_documents

Вказати персону для верифікації

Оновити існуючий запис в таблиці person_verifications для персони у відповідност і до логічного блоку нижче. Також, встановити:

  • updated_at = now()

  • updated_by = user uuid

Ручна верифікація NHS

Вказати персону для ручної верифікації НСЗУ у відповідності до наступної логіки: https://e-health-ua.atlassian.net/wiki/spaces/EH/pages/589430849/Sign+person+request#Manual-NHS-verification

Верифікація по реєстру DRFO

Вказати персону для верифікації по реєстру DRFO у відповідності до наступної логіки: https://e-health-ua.atlassian.net/wiki/spaces/EH/pages/589430849/Sign+person+request#DRFO-registry-verification

Верифікація по реєстру актів смерті DRACS

Вказати персону для верифікації по реєстру актів смерті DRACS у відповідності до наступної логіки: https://e-health-ua.atlassian.net/wiki/spaces/EH/pages/589430849/Sign+person+request#DRACS-death-acts-registry-verification

Розрахувати комулятивний статус верифікації

Розрахувати комулятивний статус верифікації персони у відповідності до наступної логіки: https://e-health-ua.atlassian.net/wiki/spaces/EH/pages/589430849/Sign+person+request#Calculate-cumulative-verification-status

Оновити взаємозв'язок між довіреною персоною та оновленою персоною

В разі, якщо хоча б один тип документу по вказаній персоні вказано в конфігураційному параметрі PERSON_LEGAL_CAPACITY_DOCUMENT_TYPES - деактивувати всі існуючі взаємозв'язки з довіреною особою для персони:

  • Деактивувати всі записи в таблиці IL.confidant_person_relationship_requests, де person_id = person.id та статус = NEW, встановити значення:

    • status = CANCELLED

    • updated_at = now()

    • updated_by = user_id (з токену)

  • Деактивувати всі записи в таблиці MPI.confidant_person_relationship, де person_id = person.id та is_active = true, встановити значення:

    • is_active = false

    • updated_at = now()

    • updated_by = user_id (з токену)

  • Для всіх взаємозв'язків з попереднього кроку - деактивувати методи автентифікації в таблиці https://e-health-ua.atlassian.net/wiki/spaces/EH/pages/724729917/MPI#person_authentication_methods з типом = THIRD_PERSON та значення = confidant_person_relationships.confidant_person_id, встановити значення:

    • is_active = false

    • ended_at = now()

    • updated_at = now()

    • updated_by = user_id (з токену)

Відобразити відповідь

Відобразити відповідь у відповідності до специфікації.

  • No labels