Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Note: methods logic is unchanged, only response must be modified according to specification.

Table of Contents
minLevel1
maxLevel6
outlinefalse
styledefault
typelist
printablefalse

Purpose

This WS is designed to allow NHS employee with assigned appropriate scopes to get person’s data.

Key points 

  1. This is a graphQl query method used in Administration panel only.

  2. Only authenticated and authorized NHS employee with appropriate scope can get person’s data details.

Specification

Expand
titlepersons.graphql
Code Block
languagegraphql
"""
This is Person (MPI) details. In order to obtain details user must have a scope **person:read**
"""
type Person implements Node {
  "The ID of an object"
  id: ID!
  "Primary key identifier from the database"
  databaseId: UUID!
  "Patient first name."
  firstName: String! @fake(locale: "uk", method: "name.firstName", args: [1])
  "Patient last name."
  lastName: String! @fake(locale: "uk", method: "name.lastName", args: [1])
  "Patient second name, is exists."
  secondName: String @fake(locale: "uk", method: "name.firstName", args: [0])
  "Patient birth date."
  birthDate: Date! @fake(locale: "uk", method: "date.past", args: [100])
  "Patient birth country."
  birthCountry: String! @fake(locale: "uk", format: "Україна")
  "Person's death date."
  deathDate: Date @fake(locale: "uk", method: "date.past", args: [100])
  "Patient gender. The value should be present in the `GENDER` dictionary."
  gender: String!
  "Patient's email"
  email: String
  "Patient status in the system, is set automatically."
  status: PersonStatus!
  "Patient birth settlement."
  birthSettlement: String! @fake(locale: "uk", method: "address.city")
  "the unique number in Unified State Register"
  unzr: String @fake(randexp: "^[0-9]{8}-[0-9]{5}$")
  "National person identifier."
  taxId: String
    @fake(
      locale: "uk"
      method: "random.number"
      args: [{ min: 1000000000, max: 9999999999 }]
    )
  "Flag to show whether person rejected to have taxId"
  noTaxId: Boolean
  "Preferred way to communicate with the patient."
  preferredWayCommunication: PersonPreferredWayCommunication
  "Technical information when the patient was inserted into the DB."
  insertedAt: DateTime!
  "Technical information when the patient was updated in the DB."
  updatedAt: DateTime!
  "The method to verify changes of patient by patient."
  authenticationMethods(
    "The method to use when ordering collection items."
    filter: PersonAuthenticationMethodFilter
    "The method to use when ordering collection items."
    orderBy: PersonAuthenticationMethodOrderBy
    "Read all values in the set after (below) this cursor."
    after: String
    "Read all values in the set before (above) this cursor."
    before: String
    "Only read the first _n_ values of the set."
    first: Int
    "Only read the last _n_ values of the set."
    last: Int
  ): PersonAuthenticationMethodConnection!
  "Information of patients confidant person relationships."
  confidantPersonRelationships(
    "The method to use when ordering collection items."
    filter: ConfidantPersonRelationshipsFilter
    "The method to use when ordering collection items."
    orderBy: ConfidantPersonRelationshipsOrderBy
    "Read all values in the set after (below) this cursor."
    after: String
    "Read all values in the set before (above) this cursor."
    before: String
    "Only read the first _n_ values of the set."
    first: Int
    "Only read the last _n_ values of the set."
    last: Int
  ): ConfidantPersonRelationshipsConnection!
  "Patient identification documents."
  documents: [PersonDocument]
  "Patient addresses."
  addresses: [Address]!
  "The way how a patient wants to be reached."
  phones: [Phone]
  "Patient's contract person in case of emergency"
  emergencyContact: EmergencyContact!
  "The person(s) who is(are) responsible for the patient"
  confidantPersons: [ConfidantPerson]
  "Person's declarations."
  declarations(
    "The method to use when ordering collection items."
    orderBy: DeclarationOrderBy
    "Read all values in the set after (below) this cursor."
    after: String
    "Read all values in the set before (above) this cursor."
    before: String
    "Only read the first _n_ values of the set."
    first: Int
    "Only read the last _n_ values of the set."
    last: Int
  ): DeclarationConnection!
  "Person's secret word for voice authentification"
  secret: String
  "internal NHS number of Requests written by Person. 15-20 symbols"
  nhsRequestNumber: String!
  "Description of request - either title of paper Request or description of requested changes. Up to 300 symbols"
  nhsRequestComment: String!
  "Scan files of Person's documents, located in Bucket, where name = latest Person_request.ID identifier. person_documents:read scope is needed to get this parameter"
  personRequestAttachedDocuments: PersonRequestAttachedDocuments
  "Scan files of Confidant person relationships documents"
  confidantPersonRelationshipAttachedDocuments: ConfidantPersonRelationshipAttachedDocuments  
  "Cummulative verification status of the person"
  verificationStatus: PersonVerificationStatus!
  "Details about cummulative verification status of the person"
  verificationDetails: PersonVerificationDetail
}

"""
     Scan files of documents, located in Bucket
"""
type PersonRequestAttachedDocuments {
  "List of scan copies of documents, related to Confidant persons"
  confidantPersons: [ConfidantPersonAttachedDocuments] 
  "List of scan copies of Person's documents"
  documents: [PersonRequestAttachedDocument]
  "List of scan copies of Confidant person relationships documents"
  confidantPersonRelationships: [ConfidantPersonRelationshipAttachedDocuments]
  "Channel, which was used for creation of a latest Person Request"
  lastPersonRequestChannel: String
  "Date and time of creation of a latest Person Request"
  lastPersonRequestInsertedAt: DateTime
}

 """
     Scan file of document, located in Bucket
 """
 type PersonRequestAttachedDocument {
  "The type of document."
  type: String!
  "Person's scan files of documents, located in Bucket, in latest Person_request.id folder."
  url: String!
 }

"""
List of person statuses.
"""
enum PersonStatus {
  "Status `ACTIVE` for a person"
  ACTIVE
  "Status `INACTIVE` for a person"
  INACTIVE
}

"""
List of person preferred way communication.
"""
enum PersonPreferredWayCommunication {
  "`EMAIL` as a preferred way of the communication."
  EMAIL
  "`PHONE` as a preferred way of the communication."
  PHONE
}

"""
Person identifier documents.
"""
type PersonDocument {
  "Dictionary DOCUMENT_TYPE"
  type: String
  "document issue number"
  number: String
  "authority which issued the document"
  issuedBy: String @fake(locale: "uk", method: "company.companyName")
  "the date when document was issued"
  issuedAt: Date
  "document expiration date"
  expirationDate: Date
}

"""
Patient's contract person in case of emergency.
"""
type EmergencyContact {
  "Person first name."
  firstName: String! @fake(locale: "uk", method: "name.firstName", args: [1])
  "Person last name."
  lastName: String! @fake(locale: "uk", method: "name.lastName", args: [1])
  "Person second name, if exists."
  secondName: String @fake(locale: "uk", method: "name.firstName", args: [0])
  "The way how a perons wants to be reached."
  phones: [Phone]!
}

"""
The person who is responsible for the patient.
"""
type ConfidantPerson {
  "Priority of persons. The value should be present in the `CONFIDANT_PERSON_TYPE` dictionary."
  relationType: String!
  "Person first name."
  firstName: String! @fake(locale: "uk", method: "name.firstName", args: [1])
  "Person last name."
  lastName: String! @fake(locale: "uk", method: "name.lastName", args: [1])
  "Person second name, is exists."
  secondName: String @fake(locale: "uk", method: "name.firstName", args: [0])
  "Person birth date."
  birthDate: Date @fake(locale: "uk", method: "date.past", args: [100])
  "Person birth country."
  birthCountry: String! @fake(locale: "uk", format: "Україна")
  "Person birth settlement."
  birthSettlement: String! @fake(locale: "uk", method: "address.city")
  "Patient gender. The value should be present in the `GENDER` dictionary."
  gender: String!
  "the unique number in Unified State Register"
  unzr: String @fake(randexp: "^[0-9]{8}-[0-9]{5}$")
  "National person identifier."
  taxId: String
    @fake(
      locale: "uk"
      method: "random.number"
      args: [{ min: 1000000000, max: 9999999999 }]
    )
  "Person's email"
  email: String
  "ConfidantPerson identification documents."
  documents: [PersonDocument]!
  "Documents which prove relationship with the patient"
  relationshipDocuments: [PersonDocument]!
  "The way how a perons wants to be reached."
  phones: [Phone]
  "Preferred way to communicate with the confident person."
  preferredWayCommunication: PersonPreferredWayCommunication
}

type PersonVerificationDetail {
  drfo: PersonDrfoVerification!
  dracsDeath: PersonDracsDeathVerification!
  manualRules: PersonManualRulesVerification!
  dracsBirth: PersonDracsBirthVerification!
  dracsNameChange: PersonDracsNameChangeVerification!
  legalCapacity: PersonLegalCapacityVerification!
}

type PersonDracsBirthVerification {
  dracsBirthActId: ID
  verificationStatus: PersonVerificationStatus!
  verificationReason: PersonVerificationReason!
  verificationComment: String
  syncedAt: DateTime
  unverifiedAt: DateTime
}

type PersonDracsNameChangeVerification {
  verificationStatus: PersonVerificationStatus
  verificationReason: PersonVerificationReason
  verificationComment: String
}

type PersonLegalCapacityVerification {
  verificationStatus: PersonVerificationStatus
  verificationReason: PersonVerificationReason
  unverifiedAt: DateTime
}

Authorize

  • 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:read')

    • Return (403, 'Your scope does not allow to access this resource. Missing allowances: person:read') in case of invalid scope(s)

Validate legal entity

  • Extract client_id from token.

  • Check legal entity status (status = ACTIVE)

    • In case of error - return 409 ('client_id refers to legal entity that is not active')

Validate request

Validate $.personId

Check $.personId is ID from MPI.person.id

  • validate $.personId is UUID and UUID is version 4

    • in case of error, return 422

  • search person $.personId in MPI.person.(id = $.personId) andMPI.person.(id = $.personId).is_active = true then ok

    • in case of error, return 404, "Such person doesn't exist"

Service logic

  1. Get data from mpi DB:

    1. persons by id

  2. Render a response according to specification.