Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Table of Contents

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

Expand
titleEditing

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

Entered changes

Comparison of changes before signature

Specification

Expand
titleindex.graphql
Code Block
"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

...

Expand
titlepersons.graphql
Code Block
"""
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.

...

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

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.

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

...

Code Block
%{"A" => "А", "B" => "В", "C" => "С", "E" => "Е", "H" => "Н", "I" => "І", "K" => "К", "M" => "М", "O" => "О", "P" => "Р", "T" => "Т", "X" => "Х"}

Validation of Signed Content

Get global parameters

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

  • no_self_auth_age 

cURL example
Code Block
curl -X GET \
  {:host}/api/global_parameters

 

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:

...

Expand
titlevalidation of nhsComment and updatedAtForValidation
Code Block
  "nhs_request_number": {
  "type": "string",
  "description": "NHS internal Docflow's number of Person's official request to NHS",
  "maxLength": 50
  },
  "nhs_request_comment":{
  "type": "string",
  "description": "Title of an official Person's request to NHS or a description of that official request to NHS"},
  "maxLength": 3000
  }

Code Block
    "updatedAtForValidation": {
      "type": "string",
      "format": "date-time"
    }

Execution

Search pending person_requests in IL.person_requests

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

Code Block
WHERE IL.person_requests.person_id = :($.person.id)
  AND IL.person_requests.status IN ('NEW', 'APPROVED')

Cancel person_requests records in IL.person_requests

Change status of all found person requests:

Code Block
SET   IL.person_requests.status = 'CANCELED'
WHERE IL.person_requests.id IN (:LIST of Search results)

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