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

(GraphQL, NHS) Update Person

Purpose

To allow NHS Admin/Data Stuart (NHS employee with assigned appropriate scopes) to SAVE updates to personal data of a Person, based on Person’s official request to NHS, which is actually a legal authorisation for changes in his personal data.

Scheme

Design

Start of editing by pressing 'Редагування'

Entered changes

Comparison of changes before signature

Specification

"Creates a person_request record with the status SIGNED (in il.person_request) with following update of a person record (in mpi.persons)." createPersonRequest( input: CreatePersonRequestInput! ): CreatePersonRequestPayload

 

 

""" Input for `createPersonRequest` mutation. User must have a scope **person_request:write_nhs** """ input CreatePersonRequestInput { "Signed data to create Person_Request for update of a person record in mpi.persons" signedContent: SignedContent! "This parameters is MPI.person.(id of edited person).inserted_at, saved in FE at the beginning of editing process and should be transferred to BE for validation of parallel editing" updatedAtForValidation: DateTime! } """ Return type for `createPersonRequest` mutation. """ type CreatePersonRequestPayload { "Updated data of a Person - from mpi.persons" person: Person! }

 

Key points

The process is initiated by any NHS employee (only within NHS Admin Panel) with necessary scopes and involves the transfer (by graphQL mutation) of a signed_content. It includes JSON with Person data, where are id of an existing person and no keys and parameters of the authentication methods.

It has similarities to update part of IL.Update-person-request (w/o declaration) process, but there are some main differences:

  1. Person_request record is created in BE directly in status SIGNED based on obtained signed_content(which is signed with digital signrature) from FE. Without interim records to DB with such statuses as NEW, APPROVED.

  2. During update process of Person’s personal data in MPI.person table, there is no need in ONLINE/OFFLINE approve from Person.

  3. There are two new parameters for controlling level of changes and avoid risks of unnecessary automatic deduplication:

    1. PERSON_ONLINE_DEDUPLICATION_UPDATE_SCORE_NHS_ADMIN

    2. PERSON_ONLINE_DEDUPLICATION_MATCH_SCORE_NHS_ADMIN
      This parameters might be turned on/off by

      1. PERSON_ONLINE_DEDUPLICATION_UPDATE_SCORE_NHS_ACTIVE = true

      2. PERSON_ONLINE_DEDUPLICATION_MATCH_SCORE_NHS_ACTIVE = true

  4. There are additional mandatory fields in the message:

    1. nhs_request_number nhs_request_comment
  5. And there are other differences in fields, values and controls:

    1. $.patient_signed and $.process_disclosure_data_consent should be absent in Message and therefore null value should be set in IL.person_requests. And finally in MPI.persons table those values should not be overwritten.

    2. print-form is not necessary

    3. IL.person_requests.(new record).channel = 'NHS'

  6. One more additional parameter is transferred from FE to BE updatedAtForValidation

  7. second_name and unzr can be set to null. no_tax_id and tax_id can be transferred in the message as null, if they are set both to null.

 

Process is synchronous. If all validations are successfully completed, the synchronous process of update a person starts by processing the message. 

Scope and roles

Scope name

Roles

Description

Scope name

Roles

Description

New

person_request:write_nhs

  1. ADMIN

  2. NHS ADMIN VERIFIER

Scope for creation ofperson_request record with following update of a person record. Without online/offline approve by Person. As Person’s paper request to NHS - is actually a legal authorisation for changes in Person’s personal data.

Related articles

#

Path

Link and Article

#

Path

Link and Article

1

E-Health > Persons > Ідентифіковані персони > Person Requests Technical Requirements

IL.Create/Update person request (w/o declaration)

https://e-health-ua.atlassian.net/wiki/spaces/EH/pages/589266986

https://e-health-ua.atlassian.net/wiki/spaces/EH/pages/589266986

2

Public. Medical Service Provider Integration Layer > Person Requests

https://uaehealthapi.docs.apiary.io/#reference/public.-medical-service-provider-integration-layer/person-requests

https://uaehealthapi.docs.apiary.io/#reference/public.-medical-service-provider-integration-layer/person-requests

Authorize

  1. Verify the validity of access token

    1. Return 401 in case validation fails

  2. Check user scopes person_request:write_nhs

    1. Return 403 in case invalid scope(s)

Digital signature

Decode content that is encrypted in an electronic digital signature.
Use Digital signature WS. Method checks digital signature and returns result.
See service specification

Validate DRFO

  1. Check that DRFO in Certificate details exists and not empty

  2. Check that DRFO in Certificate details is equal to DRFO in Party

    1. Get party.tax_id using employee_id in person payload

    2. Compare DRFO in Certificate with party.tax_id

      1. Convert DRFO and TAX_ID to uppercase

      2. Compare DRFO and TAX_ID as Cyrillic letters

      3. Convert DRFO to Cyrillic and compare as Cyrillic letters

    3. In case validation fails - generate 422 error

Latin to Cyrillic mapping

Validation of Signed Content

Get global parameters

For futher validation, Invoke Global parameters to get following parameter:

  • no_self_auth_age 

cURL example

 

Validation

Validation

1

Validate parallel editings (new)

Whether Person data were not changed by other users (MSP, NHS) of NHS system. By preliminary keeping value updated_at (saved out of initial query of personal data during start of editing process) and checking at the moment of saving data:

  • If MPI.person.(id = $.id).updated_at = $.updatedAtForValidation then Ok

    • in case of error return 422, 'Person's data were changed while you were editing. Please repeat your steps for update'

2

Validate Person’s status id in DB and deduplication controls

  • If person.id is in request then 

    • if $.person.id is UUID and UUID_version($.person.id is UUID) = 4 then ok

      • in case of error, return 422, “person.id is not UUID type or UUID version is not appropriate“

    • search person by person.id in MPI 

      • in case of error return 404, "not found"

    • If MPI.persons.($.id).status = “active” then ok

      • in case of error return 422 - msg "The Person is not active, therefore any updates of personal data are prohibited”

    • Scoring of level of updates

      Check decoded signed content within system’s deduplication controls within two validations . I.e.

      • Deduplication validation 1 check whether level of changes is “so high” that it is necessary to prohibit (forbid) saving changes.

        • if calculated_score (current data, updates_of_Person) >  PERSON_ONLINE_DEDUPLICATION_UPDATE_SCORE_NHS_ADMIN
          then Validation 1 passed, check other validations

          • else return error 409, "Level of conducted changes is higher than permitted. Updates can't be saved. Please check whether you have selected appropriate Person for changes. Calculated score: <calculated_score>. Permitted score: PERSON_ONLINE_DEDUPLICATION_UPDATE_SCORE_NHS_ADMIN) "

      • Deduplication validation 2 - whether there are no other Persons, which highly similar to current updates of a Person

        • if calculated_score (updates_of_Person, other_similar_Persons) <  PERSON_ONLINE_DEDUPLICATION_MATCH_SCORE_NHS_ADMIN
          then Validation 2 passed, check other validations

          • else return error 409, "We have found Person(s) with high similarity in DB. Calculated score is equal or greater than permitted PERSON_ONLINE_DEDUPLICATION_MATCH_SCORE_NHS_ADMIN. Please check whether you have selected appropriate Person for changes and investigate possible duplicates of the Person."

    • Deduplication validation 1 and 2 might be turned off by setting independently any of the following parameters

      • PERSON_ONLINE_DEDUPLICATION_UPDATE_SCORE_NHS_ACTIVE = true

      • PERSON_ONLINE_DEDUPLICATION_MATCH_SCORE_NHS_ACTIVE = true

3

Check “patient_signed” flag.

This field should not be transferred. And therefore BE should not overwrite this field in DB

4

Check “process_disclosure_data_consent” flag.

This field should not be transferred. And therefore BE should not overwrite this field in DB

5

Validate confidant person

If person age < prm.global_parameters.no_self_auth_age then

check existence of confidant_person

  • in case of error return 422 - msg "Confidant person is mandatory for children"

Validate confidant person age >= prm.global_parameters.no_self_auth_age:

  • in case of error return 422 - msg "Third person must be adult"

validate presence of a secret word:

  • in case of error return 422,

6

Validate "tax_id"

  • tax_id has validation pattern - `^[0-9]{10}$`

    • if doesn't match, return error 422 "string does not match pattern ..."

  • NHS employee can update birth_date, but

  • (If VALIDATE_TAX_ID_WITH_BIRTH_DATE_GENDER_AND_CHECK_SUM is false then ok

    • If (GetBirthDateFromTaxId($.tax_id) != $.birth_date) or (GetGenderFromTaxId($.tax_id) != $.gender) then

      • in case of error, return 422 “Person's tax ID is not valid.“)

    • else ok

  • NHS employee can update tax_id:

    • from null to tax_id2, in case that there is no any person with tax_id2
      if tax_check_cnt_1 = 0 then ok
      How to get tax_check_cnt_1: select count(*) tax_check_cnt_1 select * from persons where tax_id = $.person.tax_id and status = 'active' and id <> $.person.id and is_active = true

      • in case of error, return 422 “There is another active person in DB with the same Tax_id. Updates to Personal data were not saved. “

    • And from tax_id1 to tax_id2, in case that there is no any person with tax_id2
      if tax_check_cnt_1 = 0 then ok
      How to get tax_check_cnt_1: select count(*) tax_check_cnt_1 select * from persons where tax_id = $.person.tax_id and is_active = 'active' and id <> $.person.id

      • in case of error, return 422 “There is another active person in DB with the same Tax_id. Updates to Personal data were not saved. “

    • from tax_id1 to null

    • from null to null

7

Check "no_tax_id" flag

  • "no_tax_id" can be null in the message, if tax_id is null also.

  • If "no_tax_id"= true, tax_id field should be empty

    • in case of error return 422

  • If "no_tax_id"=false and age>14, tax_id should be present

    • in case of error return 422

8

Validate person documents

  1. issued_at, issued_by is mandatory for documents

  2. Validate dates

    1. issued_at <= now() and issued_at => birth_date

      1.  in case `issued_at > now()` show error 422, "Document issued date should be in the past"

      2.  in case `issued_at < person.birth_date` show error 422, "Document issued date should greater than person.birth_date "

    2. expiration_date > now()

      1.  in case error show 422, "Document expiration_date should be in the future"

      2. expiration_date is mandatory for document_type

        • NATIONAL_ID

        • COMPLEMENTARY_PROTECTION_CERTIFICATE

        • PERMANENT_RESIDENCE_PERMIT

        • REFUGEE_CERTIFICATE

        • TEMPORARY_CERTIFICATE

        • TEMPORARY_PASSPORT

      3. in case of error return 422, "expiration_date is mandatory for document_type $.documents.type"

  3. Validate documents_type.number according to json schema 

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

    2. NATIONAL_ID - `^[0-9]{9}$`

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

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

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

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

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

  4. 'unzr' can be with null value in the message.

  5. if `unzr` exists and is not null and matches "^[0-9]{8}-[0-9]{5}$" check if first 8 symbols = birth_date

    1. in case of error return 422, msg "Birthdate or unzr is not correct"

  6. if documents.type=NATIONAL_ID

    1. check if unzr exists in request, in case of error return 422, msg "unzr is mandatory for document type NATIONAL_ID"

  7. Document numbersmaxLength < 25 

9

Validate NHS request fields

  • nhs_request_number, nhs_request_comment are mandatory

  • Validate them according to json schema 

    • if doesn't match, return error 422 “ required property %{property} was not present"

 

JSON validation schema

What should be other for NHS Admin Panel

As a basis this JSON Schema validator (https://e-health-ua.atlassian.net/wiki/spaces/EH/pages/589266986#Update-person-request ) is used. Except:

  1. patient_signed" and "process_disclosure_data_consent" are not required and should not be present.

  2. allow null value in second_name field of the Person object.

    1. "second_name": { "type": [ "string", "null" ] }

  3. allow null value in unzr field of the Person object

    1. "unzr": { "type": [ "string", "null" ], "pattern": "^[0-9]{8}-[0-9]{5}$" }

  4. allow in message both tax_id, no_tax_id with null values if they are both set to null

  5. updatedAtForValidation key and grouping key nhs_request_number, nhs_request_comment are validated with the following validation Schema:

 

 

Execution

Search pending person_requests in IL.person_requests

Search persons request  in IL.person_requests to prevent inconsistent parallel updates:

Cancel person_requests records in IL.person_requests

Change status of all found person requests:

Create new record in IL.person_requests

  1. Insert [new record] to IL.person_requests:

    1. Set status = 'SIGNED'. 

    2. Set Person’s id, person_id = $.person.id

    3. Set inserted_at= now() (Get current date-time)

    4. Set inserted_by - user_id (Extract user from token)

    5. Set channel, IL.person_request.(newrecord).channel = 'NHS'

    6. Set printout_form = null

Store signed_content in appropriate Person_request Bucket.

Update Person in MPI.persons

  1. Update Person’s data in MPI.persons.(id = $.person.id) with submitted new data $ (including two $.nhs_request_number and$.nhs_request_comment).

  2. Set updated_at - now() (Get current date-time)

  3. Set updated_by - user_id (Extract user from token)

  4. Create appropriate records based on submitted new data $ (including two $.nhs_request_numberand$.nhs_request_comment) in:

    1. MPI.person_documents

    2. MPI.person_phones

    3. MPI.person_addresses

Submit person on verification

Create or update existing record in person_verifications table for a person according to logic in sections below. Also, set:

  • updated_at = now()

  • updated_by = user uuid

  • inserted_at = now() (for new records)

  • inserted_by = user uuid (for new records)

Manual NHS verification

Set person verification according to logic https://e-health-ua.atlassian.net/wiki/spaces/EH/pages/589430849/Sign+person+request#Manual-NHS-verification

DRFO registry verification

Set person verification according to logic https://e-health-ua.atlassian.net/wiki/spaces/EH/pages/589430849/Sign+person+request#DRFO-registry-verification

DRACS death acts registry verification

Set person verification according to logic https://e-health-ua.atlassian.net/wiki/spaces/EH/pages/589430849/Sign+person+request#DRACS-death-acts-registry-verification

Calculate cumulative verification status

Calculate persons cumulative verification status according to logic https://e-health-ua.atlassian.net/wiki/spaces/EH/pages/589430849/Sign+person+request#Calculate-cumulative-verification-status

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