From 595621ccb6ca76c1a6eb3da93900c36b89e7a6ae Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Mon, 23 Sep 2024 18:15:33 +0600 Subject: [PATCH 01/18] chore!: amend migration to update role in related person entry --- ...ioner-role-collection-for-new-userroles.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts b/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts index 023664dc1f..172cb42f42 100644 --- a/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts +++ b/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts @@ -11,7 +11,13 @@ import { Db, MongoClient } from 'mongodb' +const USER_MGNT_MONGO_URL = + process.env.USER_MGNT_MONGO_URL || 'mongodb://localhost/user-mgnt' + export const up = async (db: Db, client: MongoClient) => { + const userManagementClient = new MongoClient(USER_MGNT_MONGO_URL) + const userMgntDb = (await userManagementClient.connect()).db() + const documents = await db .collection('PractitionerRole') .find({ 'code.coding.system': 'http://opencrvs.org/specs/types' }) @@ -29,6 +35,27 @@ export const up = async (db: Db, client: MongoClient) => { .updateOne({ _id: doc._id }, { $set: { code: filteredCode } }) } console.log('Documents updated.') + + const relatedPersons = await db.collection('RelatedPerson').find().toArray() + + for (const person of relatedPersons) { + const relationship = person.relationship.coding[0].code + if (relationship === 'PRINT_IN_ADVANCE') { + const userRole = person.relationship.text + const formattedUserRole = userRole.toUpperCase().replace(' ', '_') + + const userRoleId = userMgntDb.collection('users').find({ + role: formattedUserRole + }) + + await db + .collection('RelatedPerson') + .updateOne( + { _id: person._id }, + { $set: { 'resource.relationship.text': userRoleId } } + ) + } + } } export const down = async (db: Db, client: MongoClient) => {} From cd724672d0867d87bbe1199e46421f134ff43783 Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Tue, 24 Sep 2024 18:16:04 +0600 Subject: [PATCH 02/18] Revert "chore!: amend migration to update role in related person entry" This reverts commit 595621ccb6ca76c1a6eb3da93900c36b89e7a6ae. --- ...ioner-role-collection-for-new-userroles.ts | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts b/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts index 172cb42f42..023664dc1f 100644 --- a/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts +++ b/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts @@ -11,13 +11,7 @@ import { Db, MongoClient } from 'mongodb' -const USER_MGNT_MONGO_URL = - process.env.USER_MGNT_MONGO_URL || 'mongodb://localhost/user-mgnt' - export const up = async (db: Db, client: MongoClient) => { - const userManagementClient = new MongoClient(USER_MGNT_MONGO_URL) - const userMgntDb = (await userManagementClient.connect()).db() - const documents = await db .collection('PractitionerRole') .find({ 'code.coding.system': 'http://opencrvs.org/specs/types' }) @@ -35,27 +29,6 @@ export const up = async (db: Db, client: MongoClient) => { .updateOne({ _id: doc._id }, { $set: { code: filteredCode } }) } console.log('Documents updated.') - - const relatedPersons = await db.collection('RelatedPerson').find().toArray() - - for (const person of relatedPersons) { - const relationship = person.relationship.coding[0].code - if (relationship === 'PRINT_IN_ADVANCE') { - const userRole = person.relationship.text - const formattedUserRole = userRole.toUpperCase().replace(' ', '_') - - const userRoleId = userMgntDb.collection('users').find({ - role: formattedUserRole - }) - - await db - .collection('RelatedPerson') - .updateOne( - { _id: person._id }, - { $set: { 'resource.relationship.text': userRoleId } } - ) - } - } } export const down = async (db: Db, client: MongoClient) => {} From 8ee4a3631572eccf224774d6c8fc853f9670dd46 Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Wed, 25 Sep 2024 15:01:09 +0600 Subject: [PATCH 03/18] chore: add certifier field for querying certificate property --- packages/client/graphql.schema.json | 167 ++++++++++++++++++ packages/client/src/utils/gateway.ts | 16 ++ .../src/views/DataProvider/birth/queries.ts | 24 +++ .../src/views/DataProvider/death/queries.ts | 26 +++ .../views/DataProvider/marriage/queries.ts | 26 ++- .../src/features/registration/schema.graphql | 1 + .../features/registration/type-resolvers.ts | 36 +++- packages/gateway/src/graphql/common.graphql | 58 ++++++ packages/gateway/src/graphql/schema.d.ts | 134 ++++++++++++++ packages/gateway/src/graphql/schema.graphql | 14 ++ 10 files changed, 500 insertions(+), 2 deletions(-) diff --git a/packages/client/graphql.schema.json b/packages/client/graphql.schema.json index 46141f25b5..64a2141139 100644 --- a/packages/client/graphql.schema.json +++ b/packages/client/graphql.schema.json @@ -4139,6 +4139,18 @@ "name": "Certificate", "description": null, "fields": [ + { + "name": "certifier", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Practitioner", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "collector", "description": null, @@ -14460,6 +14472,161 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "Practitioner", + "description": null, + "fields": [ + { + "name": "active", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "address", + "description": null, + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Address", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "birthDate", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "gender", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "identifier", + "description": null, + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Identifier", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "HumanName", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "photo", + "description": null, + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Attachment", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "resourceType", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "telecom", + "description": null, + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ContactPoint", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "Query", diff --git a/packages/client/src/utils/gateway.ts b/packages/client/src/utils/gateway.ts index 00c6440b67..eb12b5705f 100644 --- a/packages/client/src/utils/gateway.ts +++ b/packages/client/src/utils/gateway.ts @@ -521,6 +521,7 @@ export type BookmarkedSeachItem = { export type Certificate = { __typename?: 'Certificate' + certifier?: Maybe collector?: Maybe data?: Maybe hasShowedVerifiedDocument?: Maybe @@ -1693,6 +1694,20 @@ export type PersonInput = { telecom?: InputMaybe>> } +export type Practitioner = { + __typename?: 'Practitioner' + active?: Maybe + address?: Maybe>> + birthDate?: Maybe + gender?: Maybe + id: Scalars['ID'] + identifier?: Maybe>> + name?: Maybe>> + photo?: Maybe>> + resourceType?: Maybe + telecom?: Maybe>> +} + export type Query = { __typename?: 'Query' fetchBirthRegistration?: Maybe @@ -2677,6 +2692,7 @@ export type GetUserRolesQuery = { getUserRoles: Array<{ __typename?: 'UserRole' id: string + scopes: Array label: { __typename?: 'I18nMessage' id: string diff --git a/packages/client/src/views/DataProvider/birth/queries.ts b/packages/client/src/views/DataProvider/birth/queries.ts index dbef098131..d31d4f880a 100644 --- a/packages/client/src/views/DataProvider/birth/queries.ts +++ b/packages/client/src/views/DataProvider/birth/queries.ts @@ -309,6 +309,18 @@ export const GET_BIRTH_REGISTRATION_FOR_REVIEW = gql` use } } + certifier { + name { + use + firstNames + familyName + } + telecom { + system + value + use + } + } } duplicateOf potentialDuplicates @@ -585,6 +597,18 @@ export const GET_BIRTH_REGISTRATION_FOR_CERTIFICATE = gql` use } } + certifier { + name { + use + firstNames + familyName + } + telecom { + system + value + use + } + } } duplicateOf potentialDuplicates diff --git a/packages/client/src/views/DataProvider/death/queries.ts b/packages/client/src/views/DataProvider/death/queries.ts index b517e474a1..495e0737e1 100644 --- a/packages/client/src/views/DataProvider/death/queries.ts +++ b/packages/client/src/views/DataProvider/death/queries.ts @@ -378,6 +378,18 @@ export const GET_DEATH_REGISTRATION_FOR_REVIEW = gql` use } } + certifier { + name { + use + firstNames + familyName + } + telecom { + system + value + use + } + } } duplicateOf potentialDuplicates @@ -643,6 +655,20 @@ export const GET_DEATH_REGISTRATION_FOR_CERTIFICATION = gql` use } } + certifier { + identifier + name { + use + firstNames + familyName + } + address + telecom { + system + value + use + } + } } duplicateOf potentialDuplicates diff --git a/packages/client/src/views/DataProvider/marriage/queries.ts b/packages/client/src/views/DataProvider/marriage/queries.ts index a30e62f3e4..c9336234ba 100644 --- a/packages/client/src/views/DataProvider/marriage/queries.ts +++ b/packages/client/src/views/DataProvider/marriage/queries.ts @@ -312,6 +312,18 @@ const GET_MARRIAGE_REGISTRATION_FOR_REVIEW = gql` use } } + certifier { + name { + use + firstNames + familyName + } + telecom { + system + value + use + } + } } } } @@ -593,7 +605,19 @@ const GET_MARRIAGE_REGISTRATION_FOR_CERTIFICATE = gql` collector { relationship otherRelationship - + name { + use + firstNames + familyName + } + telecom { + system + value + use + } + } + certifier { + identifier name { use firstNames diff --git a/packages/gateway/src/features/registration/schema.graphql b/packages/gateway/src/features/registration/schema.graphql index 2d24236417..58fa790107 100644 --- a/packages/gateway/src/features/registration/schema.graphql +++ b/packages/gateway/src/features/registration/schema.graphql @@ -427,6 +427,7 @@ input CertificateInput { type Certificate { # -> Document Reference collector: RelatedPerson # -> .extension + certifier: Practitioner # -> .extension hasShowedVerifiedDocument: Boolean # -> .extension payments: [Payment] # -> .extension data: String # -> .content.attachment.data base64 diff --git a/packages/gateway/src/features/registration/type-resolvers.ts b/packages/gateway/src/features/registration/type-resolvers.ts index 3edf945189..dced10a1a3 100644 --- a/packages/gateway/src/features/registration/type-resolvers.ts +++ b/packages/gateway/src/features/registration/type-resolvers.ts @@ -663,6 +663,39 @@ export const typeResolvers: GQLResolver = { return person?.address } }, + // incomplete + Practitioner: { + id: (practitioner: Saved) => { + return practitioner.id + }, + active: (practitioner: Saved) => { + return practitioner.id + }, + address: (practitioner: Saved) => { + return practitioner.id + }, + birthDate: (practitioner: Saved) => { + return practitioner.id + }, + gender: (practitioner: Saved) => { + return practitioner.id + }, + identifier: (practitioner: Saved) => { + return practitioner.id + }, + name: (practitioner: Saved) => { + return practitioner.id + }, + photo: (practitioner: Saved) => { + return practitioner.id + }, + telecom: (practitioner: Saved) => { + return practitioner.id + }, + resourceType: (practitioner: Saved) => { + return practitioner.id + } + }, Deceased: { deceased: (person) => { return person && person.deceasedBoolean @@ -1244,7 +1277,8 @@ export const typeResolvers: GQLResolver = { } return false - } + }, + async certifier(docRef: any, _, context) {} }, Identifier: { system: (identifier) => identifier.system, diff --git a/packages/gateway/src/graphql/common.graphql b/packages/gateway/src/graphql/common.graphql index 7b8c4810f2..7373f5cdf2 100644 --- a/packages/gateway/src/graphql/common.graphql +++ b/packages/gateway/src/graphql/common.graphql @@ -80,6 +80,64 @@ input RelatedPersonInput { ageOfIndividualInYears: Int } +type Practitioner { + id: ID! + resourceType: String + identifier: [IdentityType] + active: Boolean + name: [HumanName] + telecom: [ContactPoint] + address: [Address] + gender: String + birthDate: String + photo: [Attachment] + # qualification: [Qualification] + # communication: [CodeableConcept] +} + +# type Attachment { +# contentType: String +# language: String +# data: String +# url: String +# size: Int +# hash: String +# title: String +# creation: String +# } + +# type Qualification { +# identifier: [Identifier] +# code: CodeableConcept +# period: Period +# issuer: Reference +# } + +# type CodeableConcept { +# coding: [Coding] +# text: String +# } + +# type Coding { +# system: String +# version: String +# code: String +# display: String +# userSelected: Boolean +# } + +# type Period { +# start: String +# end: String +# } + +# type Reference { +# reference: String +# type: String +# identifier: Identifier +# display: String +# } + type RelatedPerson { # -> Related Person id: ID _fhirID: ID # -> .id relatedPerson ID diff --git a/packages/gateway/src/graphql/schema.d.ts b/packages/gateway/src/graphql/schema.d.ts index 9694848de0..3dc7a09c52 100644 --- a/packages/gateway/src/graphql/schema.d.ts +++ b/packages/gateway/src/graphql/schema.d.ts @@ -1414,6 +1414,7 @@ export const enum GQLRegistrationType { export interface GQLCertificate { collector?: GQLRelatedPerson + certifier?: GQLPractitioner hasShowedVerifiedDocument?: boolean payments?: Array data?: string @@ -1811,6 +1812,19 @@ export interface GQLMarriageFeeInput { DELAYED?: number } +export interface GQLPractitioner { + id: string + resourceType?: string + identifier?: Array + active?: boolean + name?: Array + telecom?: Array + address?: Array + gender?: string + birthDate?: string + photo?: Array +} + export interface GQLAuditLogItemBase { time: string ipAddress: string @@ -2017,6 +2031,7 @@ export interface GQLResolver { BirthFee?: GQLBirthFeeTypeResolver DeathFee?: GQLDeathFeeTypeResolver MarriageFee?: GQLMarriageFeeTypeResolver + Practitioner?: GQLPractitionerTypeResolver AuditLogItemBase?: { __resolveType: GQLAuditLogItemBaseTypeResolver } @@ -9279,6 +9294,7 @@ export interface RegWorkflowToTimeLoggedResolver { export interface GQLCertificateTypeResolver { collector?: CertificateToCollectorResolver + certifier?: CertificateToCertifierResolver hasShowedVerifiedDocument?: CertificateToHasShowedVerifiedDocumentResolver payments?: CertificateToPaymentsResolver data?: CertificateToDataResolver @@ -9293,6 +9309,15 @@ export interface CertificateToCollectorResolver { ): TResult } +export interface CertificateToCertifierResolver { + ( + parent: TParent, + args: {}, + context: Context, + info: GraphQLResolveInfo + ): TResult +} + export interface CertificateToHasShowedVerifiedDocumentResolver< TParent = any, TResult = any @@ -11687,6 +11712,115 @@ export interface MarriageFeeToDELAYEDResolver { ): TResult } +export interface GQLPractitionerTypeResolver { + id?: PractitionerToIdResolver + resourceType?: PractitionerToResourceTypeResolver + identifier?: PractitionerToIdentifierResolver + active?: PractitionerToActiveResolver + name?: PractitionerToNameResolver + telecom?: PractitionerToTelecomResolver + address?: PractitionerToAddressResolver + gender?: PractitionerToGenderResolver + birthDate?: PractitionerToBirthDateResolver + photo?: PractitionerToPhotoResolver +} + +export interface PractitionerToIdResolver { + ( + parent: TParent, + args: {}, + context: Context, + info: GraphQLResolveInfo + ): TResult +} + +export interface PractitionerToResourceTypeResolver< + TParent = any, + TResult = any +> { + ( + parent: TParent, + args: {}, + context: Context, + info: GraphQLResolveInfo + ): TResult +} + +export interface PractitionerToIdentifierResolver< + TParent = any, + TResult = any +> { + ( + parent: TParent, + args: {}, + context: Context, + info: GraphQLResolveInfo + ): TResult +} + +export interface PractitionerToActiveResolver { + ( + parent: TParent, + args: {}, + context: Context, + info: GraphQLResolveInfo + ): TResult +} + +export interface PractitionerToNameResolver { + ( + parent: TParent, + args: {}, + context: Context, + info: GraphQLResolveInfo + ): TResult +} + +export interface PractitionerToTelecomResolver { + ( + parent: TParent, + args: {}, + context: Context, + info: GraphQLResolveInfo + ): TResult +} + +export interface PractitionerToAddressResolver { + ( + parent: TParent, + args: {}, + context: Context, + info: GraphQLResolveInfo + ): TResult +} + +export interface PractitionerToGenderResolver { + ( + parent: TParent, + args: {}, + context: Context, + info: GraphQLResolveInfo + ): TResult +} + +export interface PractitionerToBirthDateResolver { + ( + parent: TParent, + args: {}, + context: Context, + info: GraphQLResolveInfo + ): TResult +} + +export interface PractitionerToPhotoResolver { + ( + parent: TParent, + args: {}, + context: Context, + info: GraphQLResolveInfo + ): TResult +} + export interface GQLAuditLogItemBaseTypeResolver { (parent: TParent, context: Context, info: GraphQLResolveInfo): | 'UserAuditLogItemWithComposition' diff --git a/packages/gateway/src/graphql/schema.graphql b/packages/gateway/src/graphql/schema.graphql index 721b3cf4c2..158fe10bf2 100644 --- a/packages/gateway/src/graphql/schema.graphql +++ b/packages/gateway/src/graphql/schema.graphql @@ -1520,6 +1520,7 @@ enum RegistrationType { type Certificate { collector: RelatedPerson + certifier: Practitioner hasShowedVerifiedDocument: Boolean payments: [Payment] data: String @@ -1916,6 +1917,19 @@ input MarriageFeeInput { DELAYED: Float } +type Practitioner { + id: ID! + resourceType: String + identifier: [IdentityType] + active: Boolean + name: [HumanName] + telecom: [ContactPoint] + address: [Address] + gender: String + birthDate: String + photo: [Attachment] +} + interface AuditLogItemBase { time: String! ipAddress: String! From e29f3c88ff32911030cf4bcdc9ff16916e9ad54b Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Wed, 25 Sep 2024 19:37:59 +0600 Subject: [PATCH 04/18] chore: save and get practitioner info for certified records --- .../features/registration/type-resolvers.ts | 53 +++++++++---------- packages/workflow/src/records/fhir.ts | 20 +++++-- .../workflow/src/records/state-transitions.ts | 4 ++ 3 files changed, 46 insertions(+), 31 deletions(-) diff --git a/packages/gateway/src/features/registration/type-resolvers.ts b/packages/gateway/src/features/registration/type-resolvers.ts index dced10a1a3..c61ab7d28c 100644 --- a/packages/gateway/src/features/registration/type-resolvers.ts +++ b/packages/gateway/src/features/registration/type-resolvers.ts @@ -663,37 +663,12 @@ export const typeResolvers: GQLResolver = { return person?.address } }, - // incomplete Practitioner: { - id: (practitioner: Saved) => { - return practitioner.id - }, - active: (practitioner: Saved) => { - return practitioner.id - }, - address: (practitioner: Saved) => { - return practitioner.id - }, - birthDate: (practitioner: Saved) => { - return practitioner.id - }, - gender: (practitioner: Saved) => { - return practitioner.id - }, - identifier: (practitioner: Saved) => { - return practitioner.id - }, name: (practitioner: Saved) => { - return practitioner.id - }, - photo: (practitioner: Saved) => { - return practitioner.id + return practitioner.name }, telecom: (practitioner: Saved) => { - return practitioner.id - }, - resourceType: (practitioner: Saved) => { - return practitioner.id + return practitioner.telecom } }, Deceased: { @@ -1278,7 +1253,29 @@ export const typeResolvers: GQLResolver = { return false }, - async certifier(docRef: any, _, context) {} + async certifier(docRef: DocumentReference, _, context) { + const practitionerRef = + docRef.extension && + findExtension( + `${OPENCRVS_SPECIFICATION_URL}extension/collector`, + docRef.extension + ) + + if ( + practitionerRef && + practitionerRef.valueReference && + practitionerRef.valueReference.reference && + practitionerRef.valueReference.reference.startsWith('Practitioner') + ) { + return getResourceFromBundleById( + context.record!, + resourceIdentifierToUUID( + practitionerRef.valueReference.reference as ResourceIdentifier + ) + ) + } + return null + } }, Identifier: { system: (identifier) => identifier.system, diff --git a/packages/workflow/src/records/fhir.ts b/packages/workflow/src/records/fhir.ts index ac64c25413..0451db028e 100644 --- a/packages/workflow/src/records/fhir.ts +++ b/packages/workflow/src/records/fhir.ts @@ -50,7 +50,8 @@ import { urlReferenceToResourceIdentifier, RegistrationStatus, getResourceFromBundleById, - TransactionResponse + TransactionResponse, + findExtension } from '@opencrvs/commons/types' import { FHIR_URL } from '@workflow/constants' import fetch from 'node-fetch' @@ -216,9 +217,21 @@ export function createDocumentReferenceEntryForCertificate( temporaryRelatedPersonId: UUID, eventType: EVENT_TYPE, hasShowedVerifiedDocument: boolean, + collectorDetails: CertifyInput['collector'], + currentTask: SavedTask, attachmentUrl?: string, paymentUrl?: URNReference | ResourceIdentifier ): BundleEntry { + /* For 'PRINT_IN_ADVANCE' records, there will be no related person entry to add. Thus the + related person id should not be referenced rather the regLastUser Practitioner is referenced.*/ + const collectorReference = + collectorDetails.relationship !== 'PRINT_IN_ADVANCE' + ? (`urn:uuid:${temporaryRelatedPersonId}` as const) + : findExtension( + 'http://opencrvs.org/specs/extension/regLastUser', + currentTask.extension + )!.valueReference.reference + return { fullUrl: `urn:uuid:${temporaryDocumentReferenceId}`, resource: { @@ -231,7 +244,7 @@ export function createDocumentReferenceEntryForCertificate( { url: 'http://opencrvs.org/specs/extension/collector', valueReference: { - reference: `urn:uuid:${temporaryRelatedPersonId}` + reference: collectorReference } }, { @@ -286,7 +299,7 @@ export function createRelatedPersonEntries( collectorDetails: CertifyInput['collector'], temporaryRelatedPersonId: UUID, record: RegisteredRecord | CertifiedRecord -): [BundleEntry, ...BundleEntry[]] { +): [BundleEntry, ...BundleEntry[]] | [] { const knownRelationships = z.enum([ 'MOTHER', 'FATHER', @@ -301,6 +314,7 @@ export function createRelatedPersonEntries( `${relationship.toLowerCase() as Lowercase}-details` if ('otherRelationship' in collectorDetails) { + if (collectorDetails.relationship === 'PRINT_IN_ADVANCE') return [] const temporaryPatientId = getUUID() return [ { diff --git a/packages/workflow/src/records/state-transitions.ts b/packages/workflow/src/records/state-transitions.ts index ec3f2ed888..10e4dc4f5e 100644 --- a/packages/workflow/src/records/state-transitions.ts +++ b/packages/workflow/src/records/state-transitions.ts @@ -958,6 +958,8 @@ export async function toCertified( temporaryRelatedPersonId, eventType, certificateDetails.hasShowedVerifiedDocument, + certificateDetails.collector, + certifiedTask, certificateDetails.data ) @@ -1040,6 +1042,8 @@ export async function toIssued( temporaryRelatedPersonId, eventType, certificateDetails.hasShowedVerifiedDocument, + certificateDetails.collector, + issuedTask, undefined, paymentEntry.fullUrl ) From 903fbae952ef1e924241602405c873190f17ed0f Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Wed, 25 Sep 2024 19:41:17 +0600 Subject: [PATCH 05/18] chore: clean up schema comments --- packages/gateway/src/graphql/common.graphql | 45 --------------------- 1 file changed, 45 deletions(-) diff --git a/packages/gateway/src/graphql/common.graphql b/packages/gateway/src/graphql/common.graphql index 7373f5cdf2..d395ab3097 100644 --- a/packages/gateway/src/graphql/common.graphql +++ b/packages/gateway/src/graphql/common.graphql @@ -91,53 +91,8 @@ type Practitioner { gender: String birthDate: String photo: [Attachment] - # qualification: [Qualification] - # communication: [CodeableConcept] } -# type Attachment { -# contentType: String -# language: String -# data: String -# url: String -# size: Int -# hash: String -# title: String -# creation: String -# } - -# type Qualification { -# identifier: [Identifier] -# code: CodeableConcept -# period: Period -# issuer: Reference -# } - -# type CodeableConcept { -# coding: [Coding] -# text: String -# } - -# type Coding { -# system: String -# version: String -# code: String -# display: String -# userSelected: Boolean -# } - -# type Period { -# start: String -# end: String -# } - -# type Reference { -# reference: String -# type: String -# identifier: Identifier -# display: String -# } - type RelatedPerson { # -> Related Person id: ID _fhirID: ID # -> .id relatedPerson ID From 5ae400196dba988d3834da4d3a2d21d8eb37a27d Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Wed, 25 Sep 2024 20:15:57 +0600 Subject: [PATCH 06/18] chore: update record audit modal to show print in advance data --- .../src/views/RecordAudit/ActionDetailsModal.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx b/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx index 14a3e59458..ed6d286889 100644 --- a/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx +++ b/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx @@ -393,7 +393,12 @@ const ActionDetailsModalListTable = ({ return {} } - const name = certificate.collector?.name + const name = certificate.certifier?.name + ? getIndividualNameObj( + certificate.certifier.name, + window.config.LANGUAGES + ) + : certificate.collector?.name ? getIndividualNameObj( certificate.collector.name, window.config.LANGUAGES @@ -408,7 +413,7 @@ const ActionDetailsModalListTable = ({ }` if (relation) return `${collectorName} (${intl.formatMessage(relation.label)})` - if (certificate.collector?.relationship === 'PRINT_IN_ADVANCE') { + if (!certificate.collector?.relationship) { return `${collectorName} (${certificate.collector?.otherRelationship})` } return collectorName @@ -432,10 +437,9 @@ const ActionDetailsModalListTable = ({ const certificateCollector = [ { key: 'collector', - label: - collectorData.relationship === 'PRINT_IN_ADVANCE' - ? intl.formatMessage(certificateMessages.printedOnAdvance) - : intl.formatMessage(certificateMessages.printedOnCollection), + label: collectorData.relationship + ? intl.formatMessage(certificateMessages.printedOnCollection) + : intl.formatMessage(certificateMessages.printedOnAdvance), width: 100 } ] From 6772370896e56fb91e9ec5125b8aa80200bf44bd Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Wed, 25 Sep 2024 21:33:45 +0600 Subject: [PATCH 07/18] chore: show user role for certifier in audit --- packages/client/graphql.schema.json | 14 ++- packages/client/src/utils/gateway.ts | 99 ++++++++++++++++++- .../src/views/DataProvider/birth/queries.ts | 2 + .../src/views/DataProvider/death/queries.ts | 4 +- .../views/DataProvider/marriage/queries.ts | 3 +- .../views/RecordAudit/ActionDetailsModal.tsx | 4 +- .../features/registration/type-resolvers.ts | 12 ++- .../src/features/registration/utils.ts | 23 +++++ packages/gateway/src/graphql/common.graphql | 1 + packages/gateway/src/graphql/schema.d.ts | 11 +++ packages/gateway/src/graphql/schema.graphql | 1 + 11 files changed, 166 insertions(+), 8 deletions(-) diff --git a/packages/client/graphql.schema.json b/packages/client/graphql.schema.json index 64a2141139..64e0af2aa3 100644 --- a/packages/client/graphql.schema.json +++ b/packages/client/graphql.schema.json @@ -14554,7 +14554,7 @@ "name": null, "ofType": { "kind": "OBJECT", - "name": "Identifier", + "name": "IdentityType", "ofType": null } }, @@ -14605,6 +14605,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "role", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "telecom", "description": null, diff --git a/packages/client/src/utils/gateway.ts b/packages/client/src/utils/gateway.ts index eb12b5705f..8d86c6b7db 100644 --- a/packages/client/src/utils/gateway.ts +++ b/packages/client/src/utils/gateway.ts @@ -1701,10 +1701,11 @@ export type Practitioner = { birthDate?: Maybe gender?: Maybe id: Scalars['ID'] - identifier?: Maybe>> + identifier?: Maybe>> name?: Maybe>> photo?: Maybe>> resourceType?: Maybe + role?: Maybe telecom?: Maybe>> } @@ -3794,6 +3795,22 @@ export type FetchBirthRegistrationForReviewQuery = { use?: string | null } | null> | null } | null + certifier?: { + __typename?: 'Practitioner' + role?: string | null + name?: Array<{ + __typename?: 'HumanName' + use?: string | null + firstNames?: string | null + familyName?: string | null + } | null> | null + telecom?: Array<{ + __typename?: 'ContactPoint' + system?: string | null + value?: string | null + use?: string | null + } | null> | null + } | null } | null> | null } | null> | null } | null @@ -4113,6 +4130,22 @@ export type FetchBirthRegistrationForCertificateQuery = { use?: string | null } | null> | null } | null + certifier?: { + __typename?: 'Practitioner' + role?: string | null + name?: Array<{ + __typename?: 'HumanName' + use?: string | null + firstNames?: string | null + familyName?: string | null + } | null> | null + telecom?: Array<{ + __typename?: 'ContactPoint' + system?: string | null + value?: string | null + use?: string | null + } | null> | null + } | null } | null> | null } | null> | null } | null @@ -4595,6 +4628,22 @@ export type FetchDeathRegistrationForReviewQuery = { use?: string | null } | null> | null } | null + certifier?: { + __typename?: 'Practitioner' + role?: string | null + name?: Array<{ + __typename?: 'HumanName' + use?: string | null + firstNames?: string | null + familyName?: string | null + } | null> | null + telecom?: Array<{ + __typename?: 'ContactPoint' + system?: string | null + value?: string | null + use?: string | null + } | null> | null + } | null } | null> | null } | null> | null } | null @@ -4903,6 +4952,22 @@ export type FetchDeathRegistrationForCertificationQuery = { use?: string | null } | null> | null } | null + certifier?: { + __typename?: 'Practitioner' + role?: string | null + name?: Array<{ + __typename?: 'HumanName' + use?: string | null + firstNames?: string | null + familyName?: string | null + } | null> | null + telecom?: Array<{ + __typename?: 'ContactPoint' + system?: string | null + value?: string | null + use?: string | null + } | null> | null + } | null } | null> | null } | null> | null } | null @@ -5311,6 +5376,22 @@ export type FetchMarriageRegistrationForReviewQuery = { use?: string | null } | null> | null } | null + certifier?: { + __typename?: 'Practitioner' + role?: string | null + name?: Array<{ + __typename?: 'HumanName' + use?: string | null + firstNames?: string | null + familyName?: string | null + } | null> | null + telecom?: Array<{ + __typename?: 'ContactPoint' + system?: string | null + value?: string | null + use?: string | null + } | null> | null + } | null } | null> | null } | null> | null } | null @@ -5649,6 +5730,22 @@ export type FetchMarriageRegistrationForCertificateQuery = { use?: string | null } | null> | null } | null + certifier?: { + __typename?: 'Practitioner' + role?: string | null + name?: Array<{ + __typename?: 'HumanName' + use?: string | null + firstNames?: string | null + familyName?: string | null + } | null> | null + telecom?: Array<{ + __typename?: 'ContactPoint' + system?: string | null + value?: string | null + use?: string | null + } | null> | null + } | null } | null> | null } | null> | null } | null diff --git a/packages/client/src/views/DataProvider/birth/queries.ts b/packages/client/src/views/DataProvider/birth/queries.ts index d31d4f880a..a605ceaefe 100644 --- a/packages/client/src/views/DataProvider/birth/queries.ts +++ b/packages/client/src/views/DataProvider/birth/queries.ts @@ -320,6 +320,7 @@ export const GET_BIRTH_REGISTRATION_FOR_REVIEW = gql` value use } + role } } duplicateOf @@ -608,6 +609,7 @@ export const GET_BIRTH_REGISTRATION_FOR_CERTIFICATE = gql` value use } + role } } duplicateOf diff --git a/packages/client/src/views/DataProvider/death/queries.ts b/packages/client/src/views/DataProvider/death/queries.ts index 495e0737e1..af9fc25083 100644 --- a/packages/client/src/views/DataProvider/death/queries.ts +++ b/packages/client/src/views/DataProvider/death/queries.ts @@ -389,6 +389,7 @@ export const GET_DEATH_REGISTRATION_FOR_REVIEW = gql` value use } + role } } duplicateOf @@ -656,18 +657,17 @@ export const GET_DEATH_REGISTRATION_FOR_CERTIFICATION = gql` } } certifier { - identifier name { use firstNames familyName } - address telecom { system value use } + role } } duplicateOf diff --git a/packages/client/src/views/DataProvider/marriage/queries.ts b/packages/client/src/views/DataProvider/marriage/queries.ts index c9336234ba..1f86aaa071 100644 --- a/packages/client/src/views/DataProvider/marriage/queries.ts +++ b/packages/client/src/views/DataProvider/marriage/queries.ts @@ -323,6 +323,7 @@ const GET_MARRIAGE_REGISTRATION_FOR_REVIEW = gql` value use } + role } } } @@ -617,7 +618,6 @@ const GET_MARRIAGE_REGISTRATION_FOR_CERTIFICATE = gql` } } certifier { - identifier name { use firstNames @@ -628,6 +628,7 @@ const GET_MARRIAGE_REGISTRATION_FOR_CERTIFICATE = gql` value use } + role } } } diff --git a/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx b/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx index ed6d286889..4c110d6885 100644 --- a/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx +++ b/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx @@ -413,8 +413,8 @@ const ActionDetailsModalListTable = ({ }` if (relation) return `${collectorName} (${intl.formatMessage(relation.label)})` - if (!certificate.collector?.relationship) { - return `${collectorName} (${certificate.collector?.otherRelationship})` + if (certificate.certifier?.role) { + return `${collectorName} (${certificate.certifier?.role})` } return collectorName } diff --git a/packages/gateway/src/features/registration/type-resolvers.ts b/packages/gateway/src/features/registration/type-resolvers.ts index c61ab7d28c..415a5fd926 100644 --- a/packages/gateway/src/features/registration/type-resolvers.ts +++ b/packages/gateway/src/features/registration/type-resolvers.ts @@ -9,7 +9,10 @@ * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ -import { getPresignedUrlFromUri } from '@gateway/features/registration/utils' +import { + getPractitionerRoleFromPractitioner, + getPresignedUrlFromUri +} from '@gateway/features/registration/utils' import { getSignatureExtension } from '@gateway/features/user/type-resolvers' import { @@ -669,6 +672,13 @@ export const typeResolvers: GQLResolver = { }, telecom: (practitioner: Saved) => { return practitioner.telecom + }, + role: async (practitioner: Saved, _, context) => { + const practitionerRole = getPractitionerRoleFromPractitioner( + practitioner, + context.record! + ) + return practitionerRole } }, Deceased: { diff --git a/packages/gateway/src/features/registration/utils.ts b/packages/gateway/src/features/registration/utils.ts index 9c33de2b9d..7af77f79d8 100644 --- a/packages/gateway/src/features/registration/utils.ts +++ b/packages/gateway/src/features/registration/utils.ts @@ -17,6 +17,12 @@ import { GQLDeathRegistrationInput, GQLMarriageRegistrationInput } from '@gateway/graphql/schema' +import { + isPractitionerRole, + Resource, + SavedBundle, + SavedPractitioner +} from '@opencrvs/commons/types' export async function getPresignedUrlFromUri( fileUri: string, @@ -63,3 +69,20 @@ export async function setCollectorForPrintInAdvance( return details } + +export function getPractitionerRoleFromPractitioner( + practitioner: SavedPractitioner, + bundle: SavedBundle +) { + const bundleEntries = bundle.entry + for (const entry of bundleEntries) { + if ( + isPractitionerRole(entry.resource) && + //@ts-ignore + entry.resource.practitioner.reference.includes(practitioner.id) + ) { + return entry.resource.code?.[0]?.coding?.[0].code + } + } + return null +} diff --git a/packages/gateway/src/graphql/common.graphql b/packages/gateway/src/graphql/common.graphql index d395ab3097..df829d9f6b 100644 --- a/packages/gateway/src/graphql/common.graphql +++ b/packages/gateway/src/graphql/common.graphql @@ -91,6 +91,7 @@ type Practitioner { gender: String birthDate: String photo: [Attachment] + role: String } type RelatedPerson { # -> Related Person diff --git a/packages/gateway/src/graphql/schema.d.ts b/packages/gateway/src/graphql/schema.d.ts index 3dc7a09c52..b2eddf6e10 100644 --- a/packages/gateway/src/graphql/schema.d.ts +++ b/packages/gateway/src/graphql/schema.d.ts @@ -1823,6 +1823,7 @@ export interface GQLPractitioner { gender?: string birthDate?: string photo?: Array + role?: string } export interface GQLAuditLogItemBase { @@ -11723,6 +11724,7 @@ export interface GQLPractitionerTypeResolver { gender?: PractitionerToGenderResolver birthDate?: PractitionerToBirthDateResolver photo?: PractitionerToPhotoResolver + role?: PractitionerToRoleResolver } export interface PractitionerToIdResolver { @@ -11821,6 +11823,15 @@ export interface PractitionerToPhotoResolver { ): TResult } +export interface PractitionerToRoleResolver { + ( + parent: TParent, + args: {}, + context: Context, + info: GraphQLResolveInfo + ): TResult +} + export interface GQLAuditLogItemBaseTypeResolver { (parent: TParent, context: Context, info: GraphQLResolveInfo): | 'UserAuditLogItemWithComposition' diff --git a/packages/gateway/src/graphql/schema.graphql b/packages/gateway/src/graphql/schema.graphql index 158fe10bf2..5f4adb0055 100644 --- a/packages/gateway/src/graphql/schema.graphql +++ b/packages/gateway/src/graphql/schema.graphql @@ -1928,6 +1928,7 @@ type Practitioner { gender: String birthDate: String photo: [Attachment] + role: String } interface AuditLogItemBase { From 0bbfbdf24269aff55f359ee05ae0a60fb526b4ee Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Thu, 26 Sep 2024 15:57:35 +0600 Subject: [PATCH 08/18] chore: use User instead of Practitioner for certifier --- packages/client/graphql.schema.json | 169 +----------------- packages/client/src/utils/gateway.ts | 155 ++++++++-------- .../src/views/DataProvider/birth/queries.ts | 24 +-- .../src/views/DataProvider/death/queries.ts | 24 +-- .../views/DataProvider/marriage/queries.ts | 24 +-- .../views/RecordAudit/ActionDetailsModal.tsx | 4 +- .../src/features/registration/schema.graphql | 2 +- .../features/registration/type-resolvers.ts | 61 ++++--- packages/gateway/src/graphql/common.graphql | 14 -- packages/gateway/src/graphql/schema.d.ts | 136 +------------- packages/gateway/src/graphql/schema.graphql | 16 +- 11 files changed, 166 insertions(+), 463 deletions(-) diff --git a/packages/client/graphql.schema.json b/packages/client/graphql.schema.json index 64e0af2aa3..f3e7ec0029 100644 --- a/packages/client/graphql.schema.json +++ b/packages/client/graphql.schema.json @@ -4145,7 +4145,7 @@ "args": [], "type": { "kind": "OBJECT", - "name": "Practitioner", + "name": "User", "ofType": null }, "isDeprecated": false, @@ -14472,173 +14472,6 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "OBJECT", - "name": "Practitioner", - "description": null, - "fields": [ - { - "name": "active", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "address", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Address", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "birthDate", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "gender", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "identifier", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "IdentityType", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "HumanName", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "photo", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Attachment", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "resourceType", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "role", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "telecom", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "ContactPoint", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, { "kind": "OBJECT", "name": "Query", diff --git a/packages/client/src/utils/gateway.ts b/packages/client/src/utils/gateway.ts index 8d86c6b7db..f99cf059da 100644 --- a/packages/client/src/utils/gateway.ts +++ b/packages/client/src/utils/gateway.ts @@ -521,7 +521,7 @@ export type BookmarkedSeachItem = { export type Certificate = { __typename?: 'Certificate' - certifier?: Maybe + certifier?: Maybe collector?: Maybe data?: Maybe hasShowedVerifiedDocument?: Maybe @@ -1694,21 +1694,6 @@ export type PersonInput = { telecom?: InputMaybe>> } -export type Practitioner = { - __typename?: 'Practitioner' - active?: Maybe - address?: Maybe>> - birthDate?: Maybe - gender?: Maybe - id: Scalars['ID'] - identifier?: Maybe>> - name?: Maybe>> - photo?: Maybe>> - resourceType?: Maybe - role?: Maybe - telecom?: Maybe>> -} - export type Query = { __typename?: 'Query' fetchBirthRegistration?: Maybe @@ -3796,20 +3781,23 @@ export type FetchBirthRegistrationForReviewQuery = { } | null> | null } | null certifier?: { - __typename?: 'Practitioner' - role?: string | null - name?: Array<{ + __typename?: 'User' + name: Array<{ __typename?: 'HumanName' use?: string | null firstNames?: string | null familyName?: string | null - } | null> | null - telecom?: Array<{ - __typename?: 'ContactPoint' - system?: string | null - value?: string | null - use?: string | null - } | null> | null + }> + role: { + __typename?: 'UserRole' + id: string + label: { + __typename?: 'I18nMessage' + id: string + defaultMessage: string + description: string + } + } } | null } | null> | null } | null> | null @@ -4131,20 +4119,23 @@ export type FetchBirthRegistrationForCertificateQuery = { } | null> | null } | null certifier?: { - __typename?: 'Practitioner' - role?: string | null - name?: Array<{ + __typename?: 'User' + name: Array<{ __typename?: 'HumanName' use?: string | null firstNames?: string | null familyName?: string | null - } | null> | null - telecom?: Array<{ - __typename?: 'ContactPoint' - system?: string | null - value?: string | null - use?: string | null - } | null> | null + }> + role: { + __typename?: 'UserRole' + id: string + label: { + __typename?: 'I18nMessage' + id: string + defaultMessage: string + description: string + } + } } | null } | null> | null } | null> | null @@ -4629,20 +4620,23 @@ export type FetchDeathRegistrationForReviewQuery = { } | null> | null } | null certifier?: { - __typename?: 'Practitioner' - role?: string | null - name?: Array<{ + __typename?: 'User' + name: Array<{ __typename?: 'HumanName' use?: string | null firstNames?: string | null familyName?: string | null - } | null> | null - telecom?: Array<{ - __typename?: 'ContactPoint' - system?: string | null - value?: string | null - use?: string | null - } | null> | null + }> + role: { + __typename?: 'UserRole' + id: string + label: { + __typename?: 'I18nMessage' + id: string + defaultMessage: string + description: string + } + } } | null } | null> | null } | null> | null @@ -4953,20 +4947,23 @@ export type FetchDeathRegistrationForCertificationQuery = { } | null> | null } | null certifier?: { - __typename?: 'Practitioner' - role?: string | null - name?: Array<{ + __typename?: 'User' + name: Array<{ __typename?: 'HumanName' use?: string | null firstNames?: string | null familyName?: string | null - } | null> | null - telecom?: Array<{ - __typename?: 'ContactPoint' - system?: string | null - value?: string | null - use?: string | null - } | null> | null + }> + role: { + __typename?: 'UserRole' + id: string + label: { + __typename?: 'I18nMessage' + id: string + defaultMessage: string + description: string + } + } } | null } | null> | null } | null> | null @@ -5377,20 +5374,23 @@ export type FetchMarriageRegistrationForReviewQuery = { } | null> | null } | null certifier?: { - __typename?: 'Practitioner' - role?: string | null - name?: Array<{ + __typename?: 'User' + name: Array<{ __typename?: 'HumanName' use?: string | null firstNames?: string | null familyName?: string | null - } | null> | null - telecom?: Array<{ - __typename?: 'ContactPoint' - system?: string | null - value?: string | null - use?: string | null - } | null> | null + }> + role: { + __typename?: 'UserRole' + id: string + label: { + __typename?: 'I18nMessage' + id: string + defaultMessage: string + description: string + } + } } | null } | null> | null } | null> | null @@ -5731,20 +5731,23 @@ export type FetchMarriageRegistrationForCertificateQuery = { } | null> | null } | null certifier?: { - __typename?: 'Practitioner' - role?: string | null - name?: Array<{ + __typename?: 'User' + name: Array<{ __typename?: 'HumanName' use?: string | null firstNames?: string | null familyName?: string | null - } | null> | null - telecom?: Array<{ - __typename?: 'ContactPoint' - system?: string | null - value?: string | null - use?: string | null - } | null> | null + }> + role: { + __typename?: 'UserRole' + id: string + label: { + __typename?: 'I18nMessage' + id: string + defaultMessage: string + description: string + } + } } | null } | null> | null } | null> | null diff --git a/packages/client/src/views/DataProvider/birth/queries.ts b/packages/client/src/views/DataProvider/birth/queries.ts index a605ceaefe..ebad34e354 100644 --- a/packages/client/src/views/DataProvider/birth/queries.ts +++ b/packages/client/src/views/DataProvider/birth/queries.ts @@ -315,12 +315,14 @@ export const GET_BIRTH_REGISTRATION_FOR_REVIEW = gql` firstNames familyName } - telecom { - system - value - use + role { + id + label { + id + defaultMessage + description + } } - role } } duplicateOf @@ -604,12 +606,14 @@ export const GET_BIRTH_REGISTRATION_FOR_CERTIFICATE = gql` firstNames familyName } - telecom { - system - value - use + role { + id + label { + id + defaultMessage + description + } } - role } } duplicateOf diff --git a/packages/client/src/views/DataProvider/death/queries.ts b/packages/client/src/views/DataProvider/death/queries.ts index af9fc25083..6e3dc08857 100644 --- a/packages/client/src/views/DataProvider/death/queries.ts +++ b/packages/client/src/views/DataProvider/death/queries.ts @@ -384,12 +384,14 @@ export const GET_DEATH_REGISTRATION_FOR_REVIEW = gql` firstNames familyName } - telecom { - system - value - use + role { + id + label { + id + defaultMessage + description + } } - role } } duplicateOf @@ -662,12 +664,14 @@ export const GET_DEATH_REGISTRATION_FOR_CERTIFICATION = gql` firstNames familyName } - telecom { - system - value - use + role { + id + label { + id + defaultMessage + description + } } - role } } duplicateOf diff --git a/packages/client/src/views/DataProvider/marriage/queries.ts b/packages/client/src/views/DataProvider/marriage/queries.ts index 1f86aaa071..64f9afd79f 100644 --- a/packages/client/src/views/DataProvider/marriage/queries.ts +++ b/packages/client/src/views/DataProvider/marriage/queries.ts @@ -318,12 +318,14 @@ const GET_MARRIAGE_REGISTRATION_FOR_REVIEW = gql` firstNames familyName } - telecom { - system - value - use + role { + id + label { + id + defaultMessage + description + } } - role } } } @@ -623,12 +625,14 @@ const GET_MARRIAGE_REGISTRATION_FOR_CERTIFICATE = gql` firstNames familyName } - telecom { - system - value - use + role { + id + label { + id + defaultMessage + description + } } - role } } } diff --git a/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx b/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx index 4c110d6885..1c02fb9617 100644 --- a/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx +++ b/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx @@ -414,7 +414,9 @@ const ActionDetailsModalListTable = ({ if (relation) return `${collectorName} (${intl.formatMessage(relation.label)})` if (certificate.certifier?.role) { - return `${collectorName} (${certificate.certifier?.role})` + return `${collectorName} (${intl.formatMessage( + certificate.certifier.role.label + )})` } return collectorName } diff --git a/packages/gateway/src/features/registration/schema.graphql b/packages/gateway/src/features/registration/schema.graphql index 58fa790107..6685033005 100644 --- a/packages/gateway/src/features/registration/schema.graphql +++ b/packages/gateway/src/features/registration/schema.graphql @@ -427,7 +427,7 @@ input CertificateInput { type Certificate { # -> Document Reference collector: RelatedPerson # -> .extension - certifier: Practitioner # -> .extension + certifier: User # -> .extension hasShowedVerifiedDocument: Boolean # -> .extension payments: [Payment] # -> .extension data: String # -> .content.attachment.data base64 diff --git a/packages/gateway/src/features/registration/type-resolvers.ts b/packages/gateway/src/features/registration/type-resolvers.ts index 415a5fd926..41abb4f6c4 100644 --- a/packages/gateway/src/features/registration/type-resolvers.ts +++ b/packages/gateway/src/features/registration/type-resolvers.ts @@ -9,10 +9,7 @@ * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ -import { - getPractitionerRoleFromPractitioner, - getPresignedUrlFromUri -} from '@gateway/features/registration/utils' +import { getPresignedUrlFromUri } from '@gateway/features/registration/utils' import { getSignatureExtension } from '@gateway/features/user/type-resolvers' import { @@ -666,21 +663,6 @@ export const typeResolvers: GQLResolver = { return person?.address } }, - Practitioner: { - name: (practitioner: Saved) => { - return practitioner.name - }, - telecom: (practitioner: Saved) => { - return practitioner.telecom - }, - role: async (practitioner: Saved, _, context) => { - const practitionerRole = getPractitionerRoleFromPractitioner( - practitioner, - context.record! - ) - return practitionerRole - } - }, Deceased: { deceased: (person) => { return person && person.deceasedBoolean @@ -1277,12 +1259,45 @@ export const typeResolvers: GQLResolver = { practitionerRef.valueReference.reference && practitionerRef.valueReference.reference.startsWith('Practitioner') ) { - return getResourceFromBundleById( - context.record!, - resourceIdentifierToUUID( - practitionerRef.valueReference.reference as ResourceIdentifier + const practitionerId = resourceIdentifierToUUID( + practitionerRef.valueReference.reference as ResourceIdentifier + ) + const practitionerRoleBundle = + await context.dataSources.fhirAPI.getPractitionerRoleByPractitionerId( + practitionerId ) + + const practitionerRoleId = + practitionerRoleBundle.entry?.[0].resource?.id + + const practitionerRoleHistory = + await context.dataSources.fhirAPI.getPractionerRoleHistory( + practitionerRoleId + ) + const task = getTaskFromSavedBundle(context.record!) + const result = practitionerRoleHistory.find( + (it) => + it?.meta?.lastUpdated && + task.lastModified && + it?.meta?.lastUpdated <= task.lastModified! ) + + const targetCode = result?.code?.find((element) => { + return ( + element.coding?.[0].system === 'http://opencrvs.org/specs/roles' + ) + }) + + const roleId = targetCode?.coding?.[0].code + const userResponse = + await context.dataSources.usersAPI.getUserByPractitionerId( + practitionerId + ) + + const allRoles = await context.dataSources.countryConfigAPI.getRoles() + const role = allRoles.find((role) => role.id === roleId)?.id + + return { ...userResponse, role } } return null } diff --git a/packages/gateway/src/graphql/common.graphql b/packages/gateway/src/graphql/common.graphql index df829d9f6b..7b8c4810f2 100644 --- a/packages/gateway/src/graphql/common.graphql +++ b/packages/gateway/src/graphql/common.graphql @@ -80,20 +80,6 @@ input RelatedPersonInput { ageOfIndividualInYears: Int } -type Practitioner { - id: ID! - resourceType: String - identifier: [IdentityType] - active: Boolean - name: [HumanName] - telecom: [ContactPoint] - address: [Address] - gender: String - birthDate: String - photo: [Attachment] - role: String -} - type RelatedPerson { # -> Related Person id: ID _fhirID: ID # -> .id relatedPerson ID diff --git a/packages/gateway/src/graphql/schema.d.ts b/packages/gateway/src/graphql/schema.d.ts index b2eddf6e10..7621d84c86 100644 --- a/packages/gateway/src/graphql/schema.d.ts +++ b/packages/gateway/src/graphql/schema.d.ts @@ -1414,7 +1414,7 @@ export const enum GQLRegistrationType { export interface GQLCertificate { collector?: GQLRelatedPerson - certifier?: GQLPractitioner + certifier?: GQLUser hasShowedVerifiedDocument?: boolean payments?: Array data?: string @@ -1812,20 +1812,6 @@ export interface GQLMarriageFeeInput { DELAYED?: number } -export interface GQLPractitioner { - id: string - resourceType?: string - identifier?: Array - active?: boolean - name?: Array - telecom?: Array - address?: Array - gender?: string - birthDate?: string - photo?: Array - role?: string -} - export interface GQLAuditLogItemBase { time: string ipAddress: string @@ -2032,7 +2018,6 @@ export interface GQLResolver { BirthFee?: GQLBirthFeeTypeResolver DeathFee?: GQLDeathFeeTypeResolver MarriageFee?: GQLMarriageFeeTypeResolver - Practitioner?: GQLPractitionerTypeResolver AuditLogItemBase?: { __resolveType: GQLAuditLogItemBaseTypeResolver } @@ -11713,125 +11698,6 @@ export interface MarriageFeeToDELAYEDResolver { ): TResult } -export interface GQLPractitionerTypeResolver { - id?: PractitionerToIdResolver - resourceType?: PractitionerToResourceTypeResolver - identifier?: PractitionerToIdentifierResolver - active?: PractitionerToActiveResolver - name?: PractitionerToNameResolver - telecom?: PractitionerToTelecomResolver - address?: PractitionerToAddressResolver - gender?: PractitionerToGenderResolver - birthDate?: PractitionerToBirthDateResolver - photo?: PractitionerToPhotoResolver - role?: PractitionerToRoleResolver -} - -export interface PractitionerToIdResolver { - ( - parent: TParent, - args: {}, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - -export interface PractitionerToResourceTypeResolver< - TParent = any, - TResult = any -> { - ( - parent: TParent, - args: {}, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - -export interface PractitionerToIdentifierResolver< - TParent = any, - TResult = any -> { - ( - parent: TParent, - args: {}, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - -export interface PractitionerToActiveResolver { - ( - parent: TParent, - args: {}, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - -export interface PractitionerToNameResolver { - ( - parent: TParent, - args: {}, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - -export interface PractitionerToTelecomResolver { - ( - parent: TParent, - args: {}, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - -export interface PractitionerToAddressResolver { - ( - parent: TParent, - args: {}, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - -export interface PractitionerToGenderResolver { - ( - parent: TParent, - args: {}, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - -export interface PractitionerToBirthDateResolver { - ( - parent: TParent, - args: {}, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - -export interface PractitionerToPhotoResolver { - ( - parent: TParent, - args: {}, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - -export interface PractitionerToRoleResolver { - ( - parent: TParent, - args: {}, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - export interface GQLAuditLogItemBaseTypeResolver { (parent: TParent, context: Context, info: GraphQLResolveInfo): | 'UserAuditLogItemWithComposition' diff --git a/packages/gateway/src/graphql/schema.graphql b/packages/gateway/src/graphql/schema.graphql index 5f4adb0055..97326fcd87 100644 --- a/packages/gateway/src/graphql/schema.graphql +++ b/packages/gateway/src/graphql/schema.graphql @@ -1520,7 +1520,7 @@ enum RegistrationType { type Certificate { collector: RelatedPerson - certifier: Practitioner + certifier: User hasShowedVerifiedDocument: Boolean payments: [Payment] data: String @@ -1917,20 +1917,6 @@ input MarriageFeeInput { DELAYED: Float } -type Practitioner { - id: ID! - resourceType: String - identifier: [IdentityType] - active: Boolean - name: [HumanName] - telecom: [ContactPoint] - address: [Address] - gender: String - birthDate: String - photo: [Attachment] - role: String -} - interface AuditLogItemBase { time: String! ipAddress: String! From 9fc9bc3bb6d9020466b87c2fb8b00694cf2be1d0 Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Thu, 26 Sep 2024 16:33:51 +0600 Subject: [PATCH 09/18] fix: amend reading tasks for certifier --- .../features/registration/type-resolvers.ts | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/gateway/src/features/registration/type-resolvers.ts b/packages/gateway/src/features/registration/type-resolvers.ts index 41abb4f6c4..aeafdd5f5a 100644 --- a/packages/gateway/src/features/registration/type-resolvers.ts +++ b/packages/gateway/src/features/registration/type-resolvers.ts @@ -1211,7 +1211,8 @@ export const typeResolvers: GQLResolver = { } }, Certificate: { - async collector(docRef: DocumentReference, _, context) { + async collector(parent: { docRef: DocumentReference }, _, context) { + const { docRef } = parent const relatedPersonRef = docRef.extension && findExtension( @@ -1229,7 +1230,8 @@ export const typeResolvers: GQLResolver = { ) ) }, - async hasShowedVerifiedDocument(docRef: DocumentReference, _) { + async hasShowedVerifiedDocument(parent: { docRef: DocumentReference }, _) { + const { docRef } = parent const hasShowedDocument = findExtension( `${OPENCRVS_SPECIFICATION_URL}extension/hasShowedVerifiedDocument`, docRef.extension as Extension[] @@ -1245,7 +1247,12 @@ export const typeResolvers: GQLResolver = { return false }, - async certifier(docRef: DocumentReference, _, context) { + async certifier( + parent: { docRef: DocumentReference; task: Saved }, + _, + context + ) { + const { docRef, task } = parent const practitionerRef = docRef.extension && findExtension( @@ -1274,7 +1281,6 @@ export const typeResolvers: GQLResolver = { await context.dataSources.fhirAPI.getPractionerRoleHistory( practitionerRoleId ) - const task = getTaskFromSavedBundle(context.record!) const result = practitionerRoleHistory.find( (it) => it?.meta?.lastUpdated && @@ -2174,8 +2180,11 @@ async function resolveCertificates( return null } - return dataSources.fhirAPI.getDocumentReference( - resourceIdentifierToUUID(certSection.entry[0].reference) - ) + return { + task, + docRef: dataSources.fhirAPI.getDocumentReference( + resourceIdentifierToUUID(certSection.entry[0].reference) + ) + } }) } From 399be8b543db09fb30bd471a1b446f439014de83 Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Thu, 26 Sep 2024 19:44:33 +0600 Subject: [PATCH 10/18] chore: add experimental migration for doc ref --- ...ioner-role-collection-for-new-userroles.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts b/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts index 023664dc1f..12511bfe76 100644 --- a/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts +++ b/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts @@ -9,6 +9,7 @@ * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ +import { resourceIdentifierToUUID } from '@opencrvs/commons/types' import { Db, MongoClient } from 'mongodb' export const up = async (db: Db, client: MongoClient) => { @@ -29,6 +30,27 @@ export const up = async (db: Db, client: MongoClient) => { .updateOne({ _id: doc._id }, { $set: { code: filteredCode } }) } console.log('Documents updated.') + + const relatedPersonDocuments = await db + .collection('RelatedPerson') + .find({ 'relationship.coding.code': 'PRINT_IN_ADVANCE' }) + .toArray() + + for (const relatedPerson of relatedPersonDocuments) { + const patientRef = relatedPerson.patient.reference + const patientId = resourceIdentifierToUUID(patientRef) + await db.collection('Patient').deleteOne({ id: patientId }) + + const docResource = db + .collection('DocumentReference') + .find({ 'extension.valueReference.reference': patientRef }) + + await db.collection('DocumentReference').updateOne( + { id: docResource.id }, + // we have to import the practitioner id here for that specific task + { $set: { 'extension.valueReference.reference': '' } } + ) + } } export const down = async (db: Db, client: MongoClient) => {} From 139cee043cb1cba1112859165310c63b76a69d6a Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Wed, 2 Oct 2024 15:21:17 +0600 Subject: [PATCH 11/18] chore: update gateway schema to latest develop changes --- .../gateway/src/features/user/schema.graphql | 12 +- packages/gateway/src/graphql/schema.d.ts | 99 +- packages/gateway/src/graphql/schema.graphql | 1728 +++++++++++++++++ 3 files changed, 1734 insertions(+), 105 deletions(-) diff --git a/packages/gateway/src/features/user/schema.graphql b/packages/gateway/src/features/user/schema.graphql index e594d9d93a..31c333dba4 100644 --- a/packages/gateway/src/features/user/schema.graphql +++ b/packages/gateway/src/features/user/schema.graphql @@ -23,16 +23,6 @@ input SignatureInput { type: String } -enum SystemRoleType { - FIELD_AGENT - REGISTRATION_AGENT - LOCAL_REGISTRAR - LOCAL_SYSTEM_ADMIN - NATIONAL_SYSTEM_ADMIN - PERFORMANCE_MANAGEMENT - NATIONAL_REGISTRAR -} - enum Status { active deactivated @@ -63,7 +53,7 @@ type Signature { type LocalRegistrar { name: [HumanName]! - role: SystemRoleType! + role: UserRole! signature: Signature } diff --git a/packages/gateway/src/graphql/schema.d.ts b/packages/gateway/src/graphql/schema.d.ts index 4cac270db7..948072e451 100644 --- a/packages/gateway/src/graphql/schema.d.ts +++ b/packages/gateway/src/graphql/schema.d.ts @@ -96,7 +96,6 @@ export interface GQLMutation { resendInvite?: string usernameReminder?: string resetPasswordInvite?: string - updateRole: GQLResponse reactivateSystem?: GQLSystem deactivateSystem?: GQLSystem registerSystem?: GQLSystemSecret @@ -480,20 +479,8 @@ export interface GQLEventProgressResultSet { export interface GQLUserRole { id: string - value: GQLSystemRoleType - roles: Array - active: boolean -} - -export interface GQLComparisonInput { - eq?: string - gt?: string - lt?: string - gte?: string - lte?: string - in?: Array - ne?: string - nin?: Array + label: GQLI18nMessage + scopes: Array } export interface GQLSystem { @@ -631,17 +618,6 @@ export interface GQLAvatarInput { data: string } -export interface GQLResponse { - roleIdMap: GQLMap -} - -export interface GQLSystemRoleInput { - id: string - value?: string - active?: boolean - roles?: Array -} - export interface GQLSystemSecret { system: GQLSystem clientSecret: string @@ -854,7 +830,7 @@ export const enum GQLStatus { export interface GQLLocalRegistrar { name: Array - role: GQLSystemRoleType + role: GQLUserRole signature?: GQLSignature } @@ -1207,11 +1183,6 @@ export interface GQLSignatureInput { type?: string } -export interface GQLRoleInput { - _id?: string - labels: Array -} - export interface GQLSystemSettingsInput { dailyQuota?: number webhook?: Array @@ -1309,16 +1280,6 @@ export interface GQLPayment { attachmentURL?: string } -export const enum GQLSystemRoleType { - FIELD_AGENT = 'FIELD_AGENT', - REGISTRATION_AGENT = 'REGISTRATION_AGENT', - LOCAL_REGISTRAR = 'LOCAL_REGISTRAR', - LOCAL_SYSTEM_ADMIN = 'LOCAL_SYSTEM_ADMIN', - NATIONAL_SYSTEM_ADMIN = 'NATIONAL_SYSTEM_ADMIN', - PERFORMANCE_MANAGEMENT = 'PERFORMANCE_MANAGEMENT', - NATIONAL_REGISTRAR = 'NATIONAL_REGISTRAR' -} - export interface GQLAdvancedSeachParameters { event?: GQLEvent name?: string @@ -1612,11 +1573,6 @@ export interface GQLDeceasedInput { deathDate?: GQLPlainDate } -export interface GQLLabelInput { - lang: string - label: string -} - export interface GQLAuditLogItemBase { time: string ipAddress: string @@ -1741,13 +1697,11 @@ export interface GQLResolver { EventSearchResultSet?: GQLEventSearchResultSetTypeResolver EventProgressResultSet?: GQLEventProgressResultSetTypeResolver UserRole?: GQLUserRoleTypeResolver - CertificateSVG?: GQLCertificateSVGTypeResolver System?: GQLSystemTypeResolver UserInfo?: GQLUserInfoTypeResolver CreatedIds?: GQLCreatedIdsTypeResolver Reinstated?: GQLReinstatedTypeResolver Avatar?: GQLAvatarTypeResolver - Response?: GQLResponseTypeResolver SystemSecret?: GQLSystemSecretTypeResolver BookMarkedSearches?: GQLBookMarkedSearchesTypeResolver Map?: GraphQLScalarType @@ -2424,15 +2378,7 @@ export interface QueryToGetEventsWithProgressResolver< ): TResult } -export interface QueryToGetSystemRolesArgs { - title?: string - value?: GQLComparisonInput - role?: string - active?: boolean - sortBy?: string - sortOrder?: string -} -export interface QueryToGetSystemRolesResolver { +export interface QueryToGetUserRolesResolver { ( parent: TParent, args: {}, @@ -2511,7 +2457,6 @@ export interface GQLMutationTypeResolver { resendInvite?: MutationToResendInviteResolver usernameReminder?: MutationToUsernameReminderResolver resetPasswordInvite?: MutationToResetPasswordInviteResolver - updateRole?: MutationToUpdateRoleResolver reactivateSystem?: MutationToReactivateSystemResolver deactivateSystem?: MutationToDeactivateSystemResolver registerSystem?: MutationToRegisterSystemResolver @@ -3179,18 +3124,6 @@ export interface MutationToResetPasswordInviteResolver< ): TResult } -export interface MutationToUpdateRoleArgs { - systemRole?: GQLSystemRoleInput -} -export interface MutationToUpdateRoleResolver { - ( - parent: TParent, - args: MutationToUpdateRoleArgs, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - export interface MutationToReactivateSystemArgs { clientId: string } @@ -5332,16 +5265,7 @@ export interface UserRoleToLabelResolver { ): TResult } -export interface SystemRoleToRolesResolver { - ( - parent: TParent, - args: {}, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - -export interface SystemRoleToActiveResolver { +export interface UserRoleToScopesResolver { ( parent: TParent, args: {}, @@ -5576,19 +5500,6 @@ export interface AvatarToDataResolver { ): TResult } -export interface GQLResponseTypeResolver { - roleIdMap?: ResponseToRoleIdMapResolver -} - -export interface ResponseToRoleIdMapResolver { - ( - parent: TParent, - args: {}, - context: Context, - info: GraphQLResolveInfo - ): TResult -} - export interface GQLSystemSecretTypeResolver { system?: SystemSecretToSystemResolver clientSecret?: SystemSecretToClientSecretResolver diff --git a/packages/gateway/src/graphql/schema.graphql b/packages/gateway/src/graphql/schema.graphql index e69de29bb2..98ee68d206 100644 --- a/packages/gateway/src/graphql/schema.graphql +++ b/packages/gateway/src/graphql/schema.graphql @@ -0,0 +1,1728 @@ +type Query { + sendNotificationToAllUsers( + subject: String! + body: String! + locale: String! + type: NotificationType = EMAIL + ): NotificationResult + fetchBirthRegistration(id: ID!): BirthRegistration + searchBirthRegistrations(fromDate: Date, toDate: Date): [BirthRegistration] + searchDeathRegistrations(fromDate: Date, toDate: Date): [DeathRegistration] + queryRegistrationByIdentifier(identifier: ID!): BirthRegistration + queryPersonByIdentifier(identifier: ID!): Person + listBirthRegistrations( + locationIds: [String] + status: String + userId: String + from: Date + to: Date + count: Int + skip: Int + ): BirthRegResultSet + fetchDeathRegistration(id: ID!): DeathRegistration + fetchEventRegistration(id: ID!): EventRegistration + fetchRegistration(id: ID!): EventRegistration + fetchRegistrationForViewing(id: ID!): EventRegistration + queryPersonByNidIdentifier(dob: String, nid: String, country: String): Person + fetchRegistrationCountByStatus( + status: [String]! + locationId: String + event: String + ): RegistrationCountResult + fetchMarriageRegistration(id: ID!): MarriageRegistration + fetchRecordDetailsForVerification(id: String!): RecordDetails + hasChildLocation(parentId: String!): Location + getUser(userId: String): User + getUserByMobile(mobile: String): User + getUserByEmail(email: String): User + searchUsers( + username: String + mobile: String + email: String + status: String + primaryOfficeId: String + locationId: String + count: Int + skip: Int + sort: String + ): SearchUserResult + searchFieldAgents( + locationId: String + primaryOfficeId: String + status: String + language: String + timeStart: String! + timeEnd: String! + event: String + count: Int + skip: Int + sort: String + ): SearchFieldAgentResult + verifyPasswordById(id: String!, password: String!): VerifyPasswordResult + getTotalMetrics( + timeStart: String! + timeEnd: String! + locationId: String + event: String! + ): TotalMetricsResult + getRegistrationsListByFilter( + timeStart: String! + timeEnd: String! + locationId: String + event: String! + filterBy: String! + skip: Int! + size: Int! + ): MixedTotalMetricsResult + getVSExports: TotalVSExport + getTotalPayments( + timeStart: String! + timeEnd: String! + locationId: String + event: String! + ): [PaymentMetric!] + getTotalCertifications( + timeStart: String! + timeEnd: String! + locationId: String + ): [CertificationMetric!] + getTotalCorrections( + timeStart: String! + timeEnd: String! + locationId: String + event: String! + ): [CorrectionMetric!] + getLocationStatistics( + locationId: String + populationYear: Int! + ): LocationStatisticsResponse + getDeclarationsStartedMetrics( + timeStart: String! + timeEnd: String! + locationId: String! + ): DeclarationsStartedMetrics + fetchMonthWiseEventMetrics( + timeStart: String! + timeEnd: String! + locationId: String + event: String! + ): [MonthWiseEstimationMetric!] + fetchLocationWiseEventMetrics( + timeStart: String! + timeEnd: String! + locationId: String + event: String! + ): [LocationWiseEstimationMetric!] + getUserAuditLog( + practitionerId: String! + skip: Int + count: Int! + timeStart: String + timeEnd: String + ): UserAuditLogResultSet + searchEvents( + userId: String + advancedSearchParameters: AdvancedSearchParametersInput! + count: Int + skip: Int + sort: String + sortColumn: String + sortBy: [SortBy!] + ): EventSearchResultSet + getEventsWithProgress( + declarationJurisdictionId: String + registrationStatuses: [String] + compositionType: [String] + count: Int + skip: Int + sort: String + ): EventProgressResultSet + getUserRoles: [UserRole!]! + fetchSystem(clientId: ID!): System + getOIDPUserInfo( + code: String! + clientId: String! + redirectUri: String! + grantType: String + ): UserInfo +} + +type Mutation { + requestRegistrationCorrection(id: ID!, details: CorrectionInput!): ID! + rejectRegistrationCorrection(id: ID!, details: CorrectionRejectionInput!): ID! + approveBirthRegistrationCorrection( + id: ID! + details: BirthRegistrationInput! + ): ID! + approveDeathRegistrationCorrection( + id: ID! + details: DeathRegistrationInput! + ): ID! + approveMarriageRegistrationCorrection( + id: ID! + details: MarriageRegistrationInput! + ): ID! + createBirthRegistrationCorrection( + id: ID! + details: BirthRegistrationInput! + ): ID! + createDeathRegistrationCorrection( + id: ID! + details: DeathRegistrationInput! + ): ID! + createMarriageRegistrationCorrection( + id: ID! + details: MarriageRegistrationInput! + ): ID! + createBirthRegistration(details: BirthRegistrationInput!): CreatedIds! + markBirthAsVerified( + id: ID! + details: BirthRegistrationInput + ): BirthRegistration + markBirthAsValidated(id: ID!, details: BirthRegistrationInput): ID + markBirthAsRegistered(id: ID!, details: BirthRegistrationInput!): ID! + markBirthAsCertified(id: ID!, details: BirthRegistrationInput!): ID! + markBirthAsIssued(id: ID!, details: BirthRegistrationInput!): ID! + markEventAsVoided(id: String!, reason: String!, comment: String!): ID! + markEventAsReinstated(id: String!): Reinstated + markEventAsNotDuplicate(id: String!): ID! + markEventAsArchived( + id: String! + reason: String + comment: String + duplicateTrackingId: String + ): ID! + createDeathRegistration(details: DeathRegistrationInput!): CreatedIds! + updateDeathRegistration(id: ID!, details: DeathRegistrationInput!): ID! + markDeathAsVerified( + id: ID! + details: DeathRegistrationInput + ): DeathRegistration + markDeathAsValidated(id: ID!, details: DeathRegistrationInput): ID + markDeathAsRegistered(id: ID!, details: DeathRegistrationInput!): ID! + markDeathAsCertified(id: ID!, details: DeathRegistrationInput!): ID! + markDeathAsIssued(id: ID!, details: DeathRegistrationInput!): ID! + markEventAsUnassigned(id: String!): ID! + createMarriageRegistration(details: MarriageRegistrationInput!): CreatedIds! + markMarriageAsValidated(id: ID!, details: MarriageRegistrationInput): ID + markMarriageAsRegistered(id: ID!, details: MarriageRegistrationInput!): ID! + markMarriageAsCertified(id: ID!, details: MarriageRegistrationInput!): ID! + markMarriageAsIssued(id: ID!, details: MarriageRegistrationInput!): ID! + markEventAsDuplicate( + id: String! + reason: String! + comment: String + duplicateTrackingId: String + ): ID! + createOrUpdateUser(user: UserInput!): User! + activateUser( + userId: String! + password: String! + securityQNAs: [SecurityQuestionAnswer]! + ): String + changePassword( + userId: String! + existingPassword: String! + password: String! + ): String + changePhone( + userId: String! + phoneNumber: String! + nonce: String! + verifyCode: String! + ): String + changeEmail( + userId: String! + email: String! + nonce: String! + verifyCode: String! + ): String + changeAvatar(userId: String!, avatar: AvatarInput!): Avatar + auditUser( + userId: String! + action: String! + reason: String! + comment: String + ): String + resendInvite(userId: String!): String + usernameReminder(userId: String!): String + resetPasswordInvite(userId: String!): String + reactivateSystem(clientId: ID!): System + deactivateSystem(clientId: ID!): System + registerSystem(system: SystemInput): SystemSecret + refreshSystemSecret(clientId: String!): SystemSecret + updatePermissions(setting: UpdatePermissionsInput!): System + deleteSystem(clientId: ID!): System + bookmarkAdvancedSearch( + bookmarkSearchInput: BookmarkSearchInput! + ): BookMarkedSearches + removeBookmarkedAdvancedSearch( + removeBookmarkedSearchInput: RemoveBookmarkedSeachInput! + ): BookMarkedSearches +} + +type Dummy { + dummy: String! +} + +type NotificationResult { + success: Boolean! +} + +enum NotificationType { + EMAIL + SMS +} + +type BirthRegistration implements EventRegistration { + id: ID! + _fhirIDMap: Map + registration: Registration + child: Person + mother: Person + father: Person + informant: RelatedPerson + eventLocation: Location + birthType: String + questionnaire: [QuestionnaireQuestion] + weightAtBirth: Float + attendantAtBirth: String + otherAttendantAtBirth: String + childrenBornAliveToMother: Int + foetalDeathsToMother: Int + lastPreviousLiveBirth: Date + createdAt: Date + updatedAt: Date + history: [History] +} + +scalar Date + +type DeathRegistration implements EventRegistration { + id: ID! + _fhirIDMap: Map + registration: Registration + deceased: Person + informant: RelatedPerson + mother: Person + father: Person + spouse: Person + eventLocation: Location + questionnaire: [QuestionnaireQuestion] + mannerOfDeath: String + deathDescription: String + causeOfDeathMethod: String + causeOfDeathEstablished: String + causeOfDeath: String + maleDependentsOfDeceased: Float + femaleDependentsOfDeceased: Float + medicalPractitioner: MedicalPractitioner + createdAt: Date + updatedAt: Date + history: [History] +} + +type Person { + id: ID + _fhirID: ID + identifier: [IdentityType] + name: [HumanName] + telecom: [ContactPoint] + gender: String + birthDate: PlainDate + age: Float + maritalStatus: String + occupation: String + detailsExist: Boolean + reasonNotApplying: String + dateOfMarriage: PlainDate + multipleBirth: Int + address: [Address] + photo: [Attachment] + deceased: Deceased + nationality: [String] + educationalAttainment: String + ageOfIndividualInYears: Int + exactDateOfBirthUnknown: Boolean +} + +type BirthRegResultSet { + results: [BirthRegistration] + totalItems: Int +} + +interface EventRegistration { + id: ID! + registration: Registration + history: [History] + createdAt: Date +} + +type RegistrationCountResult { + results: [StatusWiseRegistrationCount]! + total: Int! +} + +type MarriageRegistration implements EventRegistration { + id: ID! + _fhirIDMap: Map + registration: Registration + informant: RelatedPerson + bride: Person + groom: Person + witnessOne: RelatedPerson + witnessTwo: RelatedPerson + eventLocation: Location + typeOfMarriage: String + questionnaire: [QuestionnaireQuestion] + createdAt: Date + updatedAt: Date + history: [History] +} + +union RecordDetails = BirthRegistration | DeathRegistration + +type Location { + id: ID! + _fhirID: ID + identifier: [Identifier!] + status: String + name: String + alias: [String!] + description: String + partOf: String + type: String + telecom: [ContactPoint] + address: Address + longitude: Float + latitude: Float + altitude: Float + geoData: String + hierarchy: [Location!] +} + +type User { + id: ID! + userMgntUserID: ID! + practitionerId: String! + name: [HumanName!]! + username: String + mobile: String + role: UserRole! + email: String + status: Status! + underInvestigation: Boolean + primaryOffice: Location! + localRegistrar: LocalRegistrar + identifier: Identifier + signature: Signature + creationDate: String! + avatar: Avatar + device: String + searches: [BookmarkedSeachItem!] +} + +type SearchUserResult { + results: [User] + totalItems: Int +} + +type SearchFieldAgentResult { + results: [SearchFieldAgentResponse] + totalItems: Int +} + +type VerifyPasswordResult { + mobile: String + scrope: [String] + status: String + username: String + id: String +} + +type TotalMetricsResult { + estimated: Estimation! + results: [EventMetrics!]! +} + +union MixedTotalMetricsResult = + TotalMetricsByRegistrar + | TotalMetricsByLocation + | TotalMetricsByTime + +type TotalVSExport { + results: [VSExport!] +} + +type PaymentMetric { + total: Float! + paymentType: String! +} + +type CertificationMetric { + total: Float! + eventType: String! +} + +type CorrectionMetric { + total: Float! + reason: String! +} + +type LocationStatisticsResponse { + population: Int + registrars: Int! + offices: Int! +} + +type DeclarationsStartedMetrics { + fieldAgentDeclarations: Int! + hospitalDeclarations: Int! + officeDeclarations: Int! +} + +type MonthWiseEstimationMetric { + total: Float! + withinTarget: Float! + within1Year: Float! + within5Years: Float! + estimated: Float! + month: Float! + year: Float! +} + +type LocationWiseEstimationMetric { + total: Float! + withinTarget: Float! + within1Year: Float! + within5Years: Float! + estimated: Float! + locationId: String! + locationName: String! +} + +type UserAuditLogResultSet { + total: Int! + results: [UserAuditLogResultItem!]! +} + +type EventSearchResultSet { + results: [EventSearchSet] + totalItems: Int +} + +input AdvancedSearchParametersInput { + event: Event + name: String + registrationStatuses: [String] + dateOfEvent: String + dateOfEventStart: String + dateOfEventEnd: String + timePeriodFrom: String + contactNumber: String + contactEmail: String + nationalId: String + registrationNumber: String + trackingId: String + recordId: ID + dateOfRegistration: String + dateOfRegistrationStart: String + dateOfRegistrationEnd: String + declarationLocationId: String + declarationJurisdictionId: String + eventLocationId: String + eventCountry: String + eventLocationLevel1: String + eventLocationLevel2: String + eventLocationLevel3: String + eventLocationLevel4: String + eventLocationLevel5: String + childFirstNames: String + childLastName: String + childDoB: String + childDoBStart: String + childDoBEnd: String + childGender: String + childIdentifier: String + deceasedFirstNames: String + deceasedFamilyName: String + deceasedGender: String + deceasedDoB: String + deceasedDoBStart: String + deceasedDoBEnd: String + deceasedIdentifier: String + groomFirstNames: String + groomFamilyName: String + groomDoB: String + groomDoBStart: String + groomDoBEnd: String + groomIdentifier: String + brideFirstNames: String + brideFamilyName: String + brideDoB: String + brideDoBStart: String + brideDoBEnd: String + brideIdentifier: String + dateOfMarriage: String + motherFirstNames: String + motherFamilyName: String + motherDoB: String + motherDoBStart: String + motherDoBEnd: String + motherIdentifier: String + fatherFirstNames: String + fatherFamilyName: String + fatherDoB: String + fatherDoBStart: String + fatherDoBEnd: String + fatherIdentifier: String + informantFirstNames: String + informantFamilyName: String + informantDoB: String + informantDoBStart: String + informantDoBEnd: String + informantIdentifier: String + compositionType: [String] +} + +input SortBy { + column: String! + order: String! +} + +type EventProgressResultSet { + results: [EventProgressSet] + totalItems: Int +} + +type UserRole { + id: ID! + label: I18nMessage! + scopes: [String!]! +} + +type System { + _id: ID! + clientId: ID! + shaSecret: ID! + status: SystemStatus! + name: String! + type: SystemType! + integratingSystemType: IntegratingSystemType + settings: SystemSettings +} + +type UserInfo { + oidpUserInfo: OIDPUserInfo + districtFhirId: String + stateFhirId: String + locationLevel3FhirId: String +} + +input CorrectionInput { + requester: String! + requesterOther: String + hasShowedVerifiedDocument: Boolean! + noSupportingDocumentationRequired: Boolean! + attachments: [AttachmentInput!]! + payment: CorrectionPaymentInput + values: [CorrectionValueInput!]! + location: LocationInput! + reason: String! + otherReason: String! + note: String! +} + +input CorrectionRejectionInput { + reason: String! + timeLoggedMS: Int! +} + +input BirthRegistrationInput { + _fhirIDMap: FHIRIDMap + registration: RegistrationInput + child: PersonInput + mother: PersonInput + father: PersonInput + informant: RelatedPersonInput + eventLocation: LocationInput + birthType: String + questionnaire: [QuestionnaireQuestionInput] + weightAtBirth: Float + attendantAtBirth: String + otherAttendantAtBirth: String + childrenBornAliveToMother: Int + foetalDeathsToMother: Int + lastPreviousLiveBirth: Date + createdAt: Date + updatedAt: Date +} + +input DeathRegistrationInput { + _fhirIDMap: FHIRIDMap + registration: RegistrationInput + deceased: PersonInput + informant: RelatedPersonInput + mother: PersonInput + father: PersonInput + spouse: PersonInput + eventLocation: LocationInput + questionnaire: [QuestionnaireQuestionInput] + mannerOfDeath: String + deathDescription: String + causeOfDeathMethod: String + causeOfDeathEstablished: String + causeOfDeath: String + maleDependentsOfDeceased: Float + femaleDependentsOfDeceased: Float + medicalPractitioner: MedicalPractitionerInput + createdAt: Date + updatedAt: Date +} + +input MarriageRegistrationInput { + _fhirIDMap: FHIRIDMap + registration: RegistrationInput + informant: RelatedPersonInput + bride: PersonInput + groom: PersonInput + witnessOne: RelatedPersonInput + witnessTwo: RelatedPersonInput + eventLocation: LocationInput + typeOfMarriage: String + questionnaire: [QuestionnaireQuestionInput] + createdAt: Date + updatedAt: Date +} + +type CreatedIds { + compositionId: String + trackingId: String + isPotentiallyDuplicate: Boolean +} + +type Reinstated { + taskEntryResourceID: ID! + registrationStatus: RegStatus +} + +input UserInput { + id: ID + name: [HumanNameInput!]! + identifier: [UserIdentifierInput] + username: String + mobile: String + password: String + status: Status + role: String + email: String + primaryOffice: String + device: String + signature: SignatureInput +} + +input SecurityQuestionAnswer { + questionKey: String + answer: String +} + +type Avatar { + type: String! + data: String! +} + +input AvatarInput { + type: String! + data: String! +} + +type SystemSecret { + system: System! + clientSecret: ID! +} + +input SystemInput { + name: String! + type: SystemType! + settings: SystemSettingsInput + integratingSystemType: IntegratingSystemType +} + +input UpdatePermissionsInput { + clientId: String! + webhook: [WebhookInput!]! +} + +type BookMarkedSearches { + searchList: [BookmarkedSeachItem!] +} + +input BookmarkSearchInput { + userId: String! + name: String! + parameters: AdvancedSearchParametersInput! +} + +input RemoveBookmarkedSeachInput { + userId: String! + searchId: String! +} + +scalar Map + +type Registration { + id: ID + _fhirID: ID + draftId: String + trackingId: String + mosipAid: String + registrationNumber: String + paperFormID: String + page: String + book: String + informantType: String + otherInformantType: String + assignment: AssignmentData + contact: String + contactRelationship: String + informantsSignature: String + groomSignature: String + brideSignature: String + witnessOneSignature: String + witnessTwoSignature: String + contactPhoneNumber: String + contactEmail: String + status: [RegWorkflow] + type: RegistrationType + inCompleteFields: String + attachments: [Attachment] + certificates: [Certificate] + duplicates: [DuplicatesInfo] +} + +type RelatedPerson { + id: ID + _fhirID: ID + _fhirIDPatient: ID + relationship: String + otherRelationship: String + affidavit: [Attachment] + identifier: [IdentityType] + name: [HumanName] + telecom: [ContactPoint] + gender: String + birthDate: String + age: Float + maritalStatus: String + occupation: String + detailsExist: Boolean + reasonNotApplying: String + dateOfMarriage: Date + multipleBirth: Int + address: [Address] + photo: [Attachment] + deceased: Deceased + nationality: [String] + educationalAttainment: String + ageOfIndividualInYears: Int + exactDateOfBirthUnknown: Boolean +} + +type QuestionnaireQuestion { + fieldId: String + value: String +} + +type History { + user: User + date: Date + regStatus: RegStatus + ipAddress: String + action: RegAction + note: String + statusReason: StatusReason + reason: String + requester: String + requesterOther: String + hasShowedVerifiedDocument: Boolean + noSupportingDocumentationRequired: Boolean + otherReason: String + system: IntegratedSystem + location: Location + office: Location + dhis2Notification: Boolean + comments: [Comment] + input: [InputOutput] + output: [InputOutput] + certificates: [Certificate] + signature: Signature + payment: Payment + documents: [Attachment!]! + duplicateOf: String + potentialDuplicates: [String!] +} + +type MedicalPractitioner { + name: String + qualification: String + lastVisitDate: Date +} + +type IdentityType { + id: ID + type: String + otherType: String + fieldsModifiedByIdentity: [String] +} + +type HumanName { + use: String + firstNames: String + middleName: String + familyName: String + marriedLastName: String +} + +type ContactPoint { + system: String + value: String + use: String +} + +scalar PlainDate + +type Address { + use: String + type: String + text: String + line: [String] + lineName: [String] + city: String + district: String + districtName: String + state: String + stateName: String + postalCode: String + country: String + from: Date + to: Date + partOf: String +} + +type Attachment { + id: ID! + _fhirID: ID + contentType: String + data: String + uri: String + status: String + originalFileName: String + systemFileName: String + type: String + description: String + subject: String + createdAt: Date +} + +type Deceased { + deceased: Boolean + deathDate: PlainDate +} + +type StatusWiseRegistrationCount { + status: String! + count: Int! +} + +type Identifier { + system: String + value: String +} + +enum Status { + active + deactivated + pending + disabled +} + +type LocalRegistrar { + name: [HumanName]! + role: UserRole! + signature: Signature +} + +type Signature { + data: String + type: String +} + +type BookmarkedSeachItem { + searchId: String! + name: String! + parameters: AdvancedSeachParameters! +} + +type SearchFieldAgentResponse { + practitionerId: String + fullName: String + role: UserRole + status: Status + avatar: Avatar + primaryOfficeId: String + creationDate: String + totalNumberOfDeclarationStarted: Int + totalNumberOfInProgressAppStarted: Int + totalNumberOfRejectedDeclarations: Int + averageTimeForDeclaredDeclarations: Int +} + +type Estimation { + totalEstimation: Float! + maleEstimation: Float! + femaleEstimation: Float! + locationId: String! + locationLevel: String! +} + +type EventMetrics { + total: Int! + gender: String! + eventLocationType: String! + timeLabel: String! + practitionerRole: String! +} + +type TotalMetricsByRegistrar { + results: [EventMetricsByRegistrar!]! + total: Int +} + +type TotalMetricsByLocation { + results: [EventMetricsByLocation!]! + total: Int +} + +type TotalMetricsByTime { + results: [EventMetricsByTime!]! + total: Int +} + +type VSExport { + event: String! + startDate: Date! + endDate: Date! + fileSize: String! + url: String! + createdOn: Date! +} + +union UserAuditLogResultItem = + UserAuditLogItemWithComposition + | UserAuditLogItem + +interface EventSearchSet { + id: ID! + type: String + registration: RegistrationSearchSet + operationHistories: [OperationHistorySearchSet] +} + +enum Event { + birth + death + marriage +} + +type EventProgressSet { + id: ID! + type: String + name: [HumanName] + dateOfEvent: PlainDate + registration: RegistrationSearchSet + startedBy: User + startedByFacility: String + startedAt: Date + progressReport: EventProgressData +} + +type I18nMessage { + id: String! + defaultMessage: String! + description: String! +} + +enum SystemStatus { + active + deactivated +} + +enum SystemType { + NATIONAL_ID + HEALTH + RECORD_SEARCH + WEBHOOK +} + +enum IntegratingSystemType { + MOSIP + OTHER +} + +type SystemSettings { + dailyQuota: Int + webhook: [WebhookPermission!] + openIdProviderClientId: String + openIdProviderBaseUrl: String + openIdProviderClaims: String +} + +type OIDPUserInfo { + sub: String! + name: String + given_name: String + family_name: String + middle_name: String + nickname: String + preferred_username: String + profile: String + picture: String + website: String + email: String + email_verified: Boolean + gender: String + birthdate: String + zoneinfo: String + locale: String + phone_number: String + phone_number_verified: Boolean + address: OIDPUserAddress + updated_at: Int +} + +input AttachmentInput { + _fhirID: ID + contentType: String + data: String + uri: String + status: AttachmentInputStatus + originalFileName: String + systemFileName: String + type: String + description: String + subject: String + createdAt: Date +} + +input CorrectionPaymentInput { + _fhirID: ID + attachmentData: String + type: PaymentType! + amount: Float! + outcome: PaymentOutcomeType! + date: Date! +} + +input CorrectionValueInput { + section: String! + fieldName: String! + oldValue: FieldValue + newValue: FieldValue! +} + +input LocationInput { + _fhirID: ID + identifier: [ID] + status: String + name: String + alias: [String] + description: String + partOf: String + type: String + telecom: [ContactPointInput] + address: AddressInput + longitude: Float + latitude: Float + altitude: Float + geoData: String +} + +input FHIRIDMap { + composition: String + encounter: String + eventLocation: String + questionnaireResponse: String + observation: ObservationFHIRIDS +} + +input RegistrationInput { + _fhirID: ID + draftId: String + trackingId: String + mosipAid: String + registrationNumber: String + paperFormID: String + page: String + book: String + informantsSignature: String + groomSignature: String + brideSignature: String + witnessOneSignature: String + witnessTwoSignature: String + informantType: String + otherInformantType: String + contactPhoneNumber: String + contactEmail: String + status: [RegWorkflowInput] + type: RegistrationType + inCompleteFields: String + attachments: [AttachmentInput!] + certificates: [CertificateInput] + location: LocationInput + correction: CorrectionInput + changedValues: [CorrectionValueInput!] +} + +input PersonInput { + _fhirID: ID + identifier: [IdentityInput] + name: [HumanNameInput] + telecom: [ContactPointInput] + gender: Gender + birthDate: PlainDate + age: Float + maritalStatus: String + occupation: String + detailsExist: Boolean + reasonNotApplying: String + dateOfMarriage: PlainDate + multipleBirth: Int + address: [AddressInput] + photo: [AttachmentInput!] + deceased: DeceasedInput + nationality: [String] + educationalAttainment: String + ageOfIndividualInYears: Int +} + +input RelatedPersonInput { + id: ID + _fhirID: ID + _fhirIDPatient: ID + relationship: String + otherRelationship: String + affidavit: [AttachmentInput!] + exactDateOfBirthUnknown: Boolean + identifier: [IdentityInput] + name: [HumanNameInput] + telecom: [ContactPointInput] + gender: Gender + birthDate: String + age: Float + maritalStatus: String + occupation: String + detailsExist: Boolean + reasonNotApplying: String + dateOfMarriage: Date + multipleBirth: Int + address: [AddressInput] + photo: [AttachmentInput!] + deceased: DeceasedInput + nationality: [String] + educationalAttainment: String + ageOfIndividualInYears: Int +} + +input QuestionnaireQuestionInput { + fieldId: String + value: String +} + +input MedicalPractitionerInput { + name: String + qualification: String + lastVisitDate: Date +} + +enum RegStatus { + IN_PROGRESS + ARCHIVED + DECLARED + DECLARATION_UPDATED + WAITING_VALIDATION + CORRECTION_REQUESTED + VALIDATED + REGISTERED + CERTIFIED + REJECTED + ISSUED +} + +input HumanNameInput { + use: String + firstNames: String + middleName: String + familyName: String + marriedLastName: String +} + +input UserIdentifierInput { + use: String + system: String + value: String +} + +input SignatureInput { + data: String! + type: String +} + +input SystemSettingsInput { + dailyQuota: Int + webhook: [WebhookInput] +} + +input WebhookInput { + event: String! + permissions: [String]! +} + +type AssignmentData { + practitionerId: String + firstName: String + lastName: String + officeName: String + avatarURL: String! +} + +type RegWorkflow { + id: ID! + type: RegStatus + user: User + timestamp: Date + comments: [Comment] + reason: String + location: Location + office: Location + timeLogged: Int +} + +enum RegistrationType { + BIRTH + DEATH + MARRIAGE +} + +type Certificate { + collector: RelatedPerson + certifier: User + hasShowedVerifiedDocument: Boolean + payments: [Payment] + data: String +} + +type DuplicatesInfo { + compositionId: ID + trackingId: String +} + +enum RegAction { + VERIFIED + ASSIGNED + UNASSIGNED + REINSTATED + REQUESTED_CORRECTION + APPROVED_CORRECTION + REJECTED_CORRECTION + CORRECTED + DOWNLOADED + VIEWED + MARKED_AS_DUPLICATE + MARKED_AS_NOT_DUPLICATE + FLAGGED_AS_POTENTIAL_DUPLICATE +} + +type StatusReason { + text: String +} + +type IntegratedSystem { + name: String + username: String + type: String +} + +type Comment { + id: ID! + user: User + comment: String + createdAt: Date +} + +type InputOutput { + valueCode: String! + valueId: String! + value: FieldValue! +} + +type Payment { + id: ID! + type: PaymentType! + amount: Float! + outcome: PaymentOutcomeType! + date: Date! + attachmentURL: String +} + +type AdvancedSeachParameters { + event: Event + name: String + registrationStatuses: [String] + dateOfEvent: String + dateOfEventStart: String + dateOfEventEnd: String + timePeriodFrom: String + contactNumber: String + contactEmail: String + nationalId: String + registrationNumber: String + trackingId: String + dateOfRegistration: String + dateOfRegistrationStart: String + dateOfRegistrationEnd: String + declarationLocationId: String + declarationJurisdictionId: String + eventLocationId: String + eventCountry: String + eventLocationLevel1: String + eventLocationLevel2: String + eventLocationLevel3: String + eventLocationLevel4: String + eventLocationLevel5: String + childFirstNames: String + childLastName: String + childDoB: String + childDoBStart: String + childDoBEnd: String + childGender: String + childIdentifier: String + deceasedFirstNames: String + deceasedFamilyName: String + deceasedGender: String + deceasedDoB: String + deceasedDoBStart: String + deceasedDoBEnd: String + deceasedIdentifier: String + motherFirstNames: String + motherFamilyName: String + motherDoB: String + motherDoBStart: String + motherDoBEnd: String + motherIdentifier: String + fatherFirstNames: String + fatherFamilyName: String + fatherDoB: String + fatherDoBStart: String + fatherDoBEnd: String + fatherIdentifier: String + informantFirstNames: String + informantFamilyName: String + informantDoB: String + informantDoBStart: String + informantDoBEnd: String + informantIdentifier: String + compositionType: [String] +} + +type EventMetricsByRegistrar { + registrarPractitioner: User + total: Int! + late: Int! + delayed: Int! +} + +type EventMetricsByLocation { + location: Location! + total: Int! + late: Int! + delayed: Int! + home: Int! + healthFacility: Int! +} + +type EventMetricsByTime { + total: Int! + late: Int! + delayed: Int! + home: Int! + healthFacility: Int! + month: String! + time: String! +} + +type UserAuditLogItemWithComposition implements AuditLogItemBase { + time: String! + ipAddress: String! + userAgent: String! + action: String! + practitionerId: String! + data: AdditionalIdWithCompositionId! +} + +type UserAuditLogItem implements AuditLogItemBase { + time: String! + ipAddress: String! + userAgent: String! + action: String! + practitionerId: String! +} + +type RegistrationSearchSet { + status: String + contactNumber: String + contactEmail: String + contactRelationship: String + dateOfDeclaration: Date + trackingId: String + registrationNumber: String + eventLocationId: String + registeredLocationId: String + reason: String + comment: String + duplicates: [ID] + createdAt: String + modifiedAt: String + assignment: AssignmentData +} + +type OperationHistorySearchSet { + operationType: String + operatedOn: Date + operatorRole: String + operatorName: [HumanName] + operatorOfficeName: String + operatorOfficeAlias: [String] + notificationFacilityName: String + notificationFacilityAlias: [String] + rejectReason: String + rejectComment: String +} + +type BirthEventSearchSet implements EventSearchSet { + id: ID! + type: String + childName: [HumanName] + childIdentifier: String + dateOfBirth: PlainDate + registration: RegistrationSearchSet + operationHistories: [OperationHistorySearchSet] + placeOfBirth: String + childGender: String + mothersFirstName: String + mothersLastName: String + fathersFirstName: String + fathersLastName: String + motherDateOfBirth: String + fatherDateOfBirth: String + motherIdentifier: String + fatherIdentifier: String +} + +type DeathEventSearchSet implements EventSearchSet { + id: ID! + type: String + deceasedGender: String + deceasedName: [HumanName] + dateOfDeath: PlainDate + registration: RegistrationSearchSet + operationHistories: [OperationHistorySearchSet] +} + +type MarriageEventSearchSet implements EventSearchSet { + id: ID! + type: String + brideName: [HumanName] + groomName: [HumanName] + brideIdentifier: String + groomIdentifier: String + dateOfMarriage: PlainDate + registration: RegistrationSearchSet + operationHistories: [OperationHistorySearchSet] +} + +type EventProgressData { + timeInProgress: Int + timeInReadyForReview: Int + timeInRequiresUpdates: Int + timeInWaitingForApproval: Int + timeInWaitingForBRIS: Int + timeInReadyToPrint: Int +} + +type WebhookPermission { + event: String! + permissions: [String!]! +} + +type OIDPUserAddress { + formatted: String + street_address: String + locality: String + region: String + postal_code: String + city: String + country: String +} + +enum AttachmentInputStatus { + approved + validated + deleted +} + +enum PaymentType { + MANUAL +} + +enum PaymentOutcomeType { + COMPLETED + ERROR + PARTIAL +} + +scalar FieldValue + +input ContactPointInput { + system: TelecomSystem + value: String + use: TelecomUse +} + +input AddressInput { + use: AddressUse + type: AddressType + text: String + line: [String!] + city: String + district: String + state: String + postalCode: String + country: String + from: Date + to: Date + partOf: String +} + +input ObservationFHIRIDS { + maleDependentsOfDeceased: String + femaleDependentsOfDeceased: String + mannerOfDeath: String + deathDescription: String + causeOfDeathEstablished: String + causeOfDeathMethod: String + causeOfDeath: String + birthType: String + typeOfMarriage: String + weightAtBirth: String + attendantAtBirth: String + childrenBornAliveToMother: String + foetalDeathsToMother: String + lastPreviousLiveBirth: String +} + +input RegWorkflowInput { + type: RegStatus + user: UserInput + timestamp: Date + reason: String + comments: [CommentInput] + location: LocationInput + timeLoggedMS: Int +} + +input CertificateInput { + collector: RelatedPersonInput + hasShowedVerifiedDocument: Boolean + payments: [PaymentInput] + data: String +} + +input IdentityInput { + id: ID + type: String + otherType: String + fieldsModifiedByIdentity: [String] +} + +enum Gender { + male + female + other + unknown +} + +input DeceasedInput { + deceased: Boolean + deathDate: PlainDate +} + +interface AuditLogItemBase { + time: String! + ipAddress: String! + userAgent: String! + action: String! + practitionerId: String! +} + +type AdditionalIdWithCompositionId { + compositionId: String! + trackingId: String! +} + +enum TelecomSystem { + other + phone + fax + email + pager + url + sms +} + +enum TelecomUse { + home + work + temp + old + mobile +} + +enum AddressUse { + home + work + temp + old +} + +enum AddressType { + PRIMARY_ADDRESS + SECONDARY_ADDRESS + postal + physical + both +} + +input CommentInput { + user: UserInput + comment: String + createdAt: Date +} + +input PaymentInput { + paymentId: ID + type: PaymentType + amount: Float + outcome: PaymentOutcomeType + date: Date + data: String +} From dc94aff11fe480ab4468d4ec4e91b01be99a3f9e Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Wed, 2 Oct 2024 16:59:15 +0600 Subject: [PATCH 12/18] chore: update client queries for role --- packages/client/graphql.schema.json | 243 ++----------------------- packages/client/src/profile/queries.ts | 8 +- packages/client/src/utils/gateway.ts | 194 ++++++++------------ 3 files changed, 102 insertions(+), 343 deletions(-) diff --git a/packages/client/graphql.schema.json b/packages/client/graphql.schema.json index 31d2e69697..89c050ff70 100644 --- a/packages/client/graphql.schema.json +++ b/packages/client/graphql.schema.json @@ -7280,8 +7280,8 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "ENUM", - "name": "SystemRoleType", + "kind": "OBJECT", + "name": "UserRole", "ofType": null } }, @@ -16825,174 +16825,6 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "OBJECT", - "name": "Response", - "description": null, - "fields": [ - { - "name": "roleIdMap", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Map", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Role", - "description": null, - "fields": [ - { - "name": "_id", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "labels", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "RoleLabel", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "RoleInput", - "description": null, - "fields": null, - "inputFields": [ - { - "name": "_id", - "description": null, - "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - }, - "defaultValue": null, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "labels", - "description": null, - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "LabelInput", - "ofType": null - } - } - } - }, - "defaultValue": null, - "isDeprecated": false, - "deprecationReason": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "RoleLabel", - "description": null, - "fields": [ - { - "name": "label", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lang", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, { "kind": "OBJECT", "name": "SearchFieldAgentResponse", @@ -17675,59 +17507,6 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "ENUM", - "name": "SystemRoleType", - "description": null, - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "FIELD_AGENT", - "description": null, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "LOCAL_REGISTRAR", - "description": null, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "LOCAL_SYSTEM_ADMIN", - "description": null, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NATIONAL_REGISTRAR", - "description": null, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NATIONAL_SYSTEM_ADMIN", - "description": null, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "PERFORMANCE_MANAGEMENT", - "description": null, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "REGISTRATION_AGENT", - "description": null, - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, { "kind": "OBJECT", "name": "SystemSecret", @@ -20434,7 +20213,11 @@ "name": "include", "description": "Directs the executor to include this field or fragment only when the `if` argument is true.", "isRepeatable": false, - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], + "locations": [ + "FIELD", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" + ], "args": [ { "name": "if", @@ -20458,7 +20241,11 @@ "name": "skip", "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", "isRepeatable": false, - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], + "locations": [ + "FIELD", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" + ], "args": [ { "name": "if", @@ -20482,7 +20269,9 @@ "name": "specifiedBy", "description": "Exposes a URL that specifies the behaviour of this scalar.", "isRepeatable": false, - "locations": ["SCALAR"], + "locations": [ + "SCALAR" + ], "args": [ { "name": "url", @@ -20504,4 +20293,4 @@ } ] } -} +} \ No newline at end of file diff --git a/packages/client/src/profile/queries.ts b/packages/client/src/profile/queries.ts index 3dd2cba3cb..73820ba0f1 100644 --- a/packages/client/src/profile/queries.ts +++ b/packages/client/src/profile/queries.ts @@ -52,7 +52,13 @@ const FETCH_USER = gql` firstNames familyName } - role + role { + label { + id + defaultMessage + description + } + } signature { data type diff --git a/packages/client/src/utils/gateway.ts b/packages/client/src/utils/gateway.ts index 9889f48f42..6accdea6ac 100644 --- a/packages/client/src/utils/gateway.ts +++ b/packages/client/src/utils/gateway.ts @@ -69,11 +69,10 @@ export const scopes = [ 'record.read-audit', 'record.read-comments', 'record.create-comments', - 'profile.electronic-signature', - 'profile.update-name', + 'profile.update-signature', 'profile.update-phone-number', + 'profile.update-name', 'profile.update-profile-image', - 'profile.update-signature', 'performance.read:my-office', 'performance.read', 'performance.read-dashboards', @@ -851,15 +850,10 @@ export enum IntegratingSystemType { Other = 'OTHER' } -export type LabelInput = { - label: Scalars['String'] - lang: Scalars['String'] -} - export type LocalRegistrar = { __typename?: 'LocalRegistrar' name: Array> - role: SystemRoleType + role: UserRole signature?: Maybe } @@ -1937,28 +1931,6 @@ export type RemoveBookmarkedSeachInput = { userId: Scalars['String'] } -export type Response = { - __typename?: 'Response' - roleIdMap: Scalars['Map'] -} - -export type Role = { - __typename?: 'Role' - _id: Scalars['ID'] - labels: Array -} - -export type RoleInput = { - _id?: InputMaybe - labels: Array -} - -export type RoleLabel = { - __typename?: 'RoleLabel' - label: Scalars['String'] - lang: Scalars['String'] -} - export type SearchFieldAgentResponse = { __typename?: 'SearchFieldAgentResponse' avatar?: Maybe @@ -2044,16 +2016,6 @@ export type SystemInput = { type: SystemType } -export enum SystemRoleType { - FieldAgent = 'FIELD_AGENT', - LocalRegistrar = 'LOCAL_REGISTRAR', - LocalSystemAdmin = 'LOCAL_SYSTEM_ADMIN', - NationalRegistrar = 'NATIONAL_REGISTRAR', - NationalSystemAdmin = 'NATIONAL_SYSTEM_ADMIN', - PerformanceManagement = 'PERFORMANCE_MANAGEMENT', - RegistrationAgent = 'REGISTRATION_AGENT' -} - export type SystemSecret = { __typename?: 'SystemSecret' clientSecret: Scalars['ID'] @@ -2662,13 +2624,21 @@ export type FetchUserQuery = { } localRegistrar?: { __typename?: 'LocalRegistrar' - role: SystemRoleType name: Array<{ __typename?: 'HumanName' use?: string | null firstNames?: string | null familyName?: string | null } | null> + role: { + __typename?: 'UserRole' + label: { + __typename?: 'I18nMessage' + id: string + defaultMessage: string + description: string + } + } signature?: { __typename?: 'Signature' data?: string | null @@ -7345,82 +7315,76 @@ export type GetRegistrationsListByFilterQueryVariables = Exact<{ size: Scalars['Int'] }> -export type RegistrationsListByLocationFilter = { - __typename: 'TotalMetricsByLocation' - total?: number | null - results: Array<{ - __typename?: 'EventMetricsByLocation' - total: number - late: number - delayed: number - home: number - healthFacility: number - location: { __typename?: 'Location'; name?: string | null } - }> -} - -export type RegistrationsListByRegistrarFilter = { - __typename: 'TotalMetricsByRegistrar' - total?: number | null - results: Array<{ - __typename?: 'EventMetricsByRegistrar' - total: number - late: number - delayed: number - registrarPractitioner?: { - __typename?: 'User' - id: string - systemRole: SystemRoleType - role: { - __typename?: 'Role' - _id: string - labels: Array<{ - __typename?: 'RoleLabel' - lang: string - label: string - }> - } - primaryOffice?: { - __typename?: 'Location' - name?: string | null - id: string - } | null - name: Array<{ - __typename?: 'HumanName' - firstNames?: string | null - familyName?: string | null - use?: string | null - }> - avatar?: { - __typename?: 'Avatar' - type: string - data: string - } | null - } | null - }> -} - -export type RegistrationsListByTimeFilter = { - __typename: 'TotalMetricsByTime' - total?: number | null - results: Array<{ - __typename?: 'EventMetricsByTime' - total: number - delayed: number - late: number - home: number - healthFacility: number - month: string - time: string - }> -} - export type GetRegistrationsListByFilterQuery = { __typename?: 'Query' getRegistrationsListByFilter?: - | RegistrationsListByLocationFilter - | RegistrationsListByRegistrarFilter - | RegistrationsListByTimeFilter + | { + __typename: 'TotalMetricsByLocation' + total?: number | null + results: Array<{ + __typename?: 'EventMetricsByLocation' + total: number + late: number + delayed: number + home: number + healthFacility: number + location: { __typename?: 'Location'; name?: string | null } + }> + } + | { + __typename: 'TotalMetricsByRegistrar' + total?: number | null + results: Array<{ + __typename?: 'EventMetricsByRegistrar' + total: number + late: number + delayed: number + registrarPractitioner?: { + __typename?: 'User' + id: string + role: { + __typename?: 'UserRole' + id: string + label: { + __typename?: 'I18nMessage' + id: string + defaultMessage: string + description: string + } + } + primaryOffice: { + __typename?: 'Location' + name?: string | null + id: string + } + name: Array<{ + __typename?: 'HumanName' + firstNames?: string | null + familyName?: string | null + use?: string | null + }> + avatar?: { + __typename?: 'Avatar' + type: string + data: string + } | null + } | null + }> + } + | { + __typename: 'TotalMetricsByTime' + total?: number | null + results: Array<{ + __typename?: 'EventMetricsByTime' + total: number + delayed: number + late: number + home: number + healthFacility: number + month: string + time: string + }> + } | null } From 9cd47d479327c80bb7d87cb084dccf71a1b8260c Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Wed, 2 Oct 2024 17:22:58 +0600 Subject: [PATCH 13/18] chore: revert migration changes deleting patient entries --- ...ioner-role-collection-for-new-userroles.ts | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts b/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts index 12511bfe76..023664dc1f 100644 --- a/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts +++ b/packages/migration/src/migrations/hearth/20240812142943-update-practitioner-role-collection-for-new-userroles.ts @@ -9,7 +9,6 @@ * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ -import { resourceIdentifierToUUID } from '@opencrvs/commons/types' import { Db, MongoClient } from 'mongodb' export const up = async (db: Db, client: MongoClient) => { @@ -30,27 +29,6 @@ export const up = async (db: Db, client: MongoClient) => { .updateOne({ _id: doc._id }, { $set: { code: filteredCode } }) } console.log('Documents updated.') - - const relatedPersonDocuments = await db - .collection('RelatedPerson') - .find({ 'relationship.coding.code': 'PRINT_IN_ADVANCE' }) - .toArray() - - for (const relatedPerson of relatedPersonDocuments) { - const patientRef = relatedPerson.patient.reference - const patientId = resourceIdentifierToUUID(patientRef) - await db.collection('Patient').deleteOne({ id: patientId }) - - const docResource = db - .collection('DocumentReference') - .find({ 'extension.valueReference.reference': patientRef }) - - await db.collection('DocumentReference').updateOne( - { id: docResource.id }, - // we have to import the practitioner id here for that specific task - { $set: { 'extension.valueReference.reference': '' } } - ) - } } export const down = async (db: Db, client: MongoClient) => {} From 30947812a8c8d35edb7c96d992efea148949d62a Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Wed, 2 Oct 2024 18:02:39 +0600 Subject: [PATCH 14/18] chore: update audit modal to show previous values of certified records --- .../src/views/RecordAudit/ActionDetailsModal.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx b/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx index 34b1cc7701..2b0816cd79 100644 --- a/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx +++ b/packages/client/src/views/RecordAudit/ActionDetailsModal.tsx @@ -426,11 +426,15 @@ const ActionDetailsModalListTable = ({ }` if (relation) return `${collectorName} (${intl.formatMessage(relation.label)})` - if (certificate.certifier?.role) { + + if (certificate.certifier?.role) return `${collectorName} (${intl.formatMessage( certificate.certifier.role.label )})` - } + + if (certificate.collector?.relationship === 'PRINT_IN_ADVANCE') + return `${collectorName} (${certificate.collector.otherRelationship})` + return collectorName } @@ -452,9 +456,11 @@ const ActionDetailsModalListTable = ({ const certificateCollector = [ { key: 'collector', - label: collectorData.relationship - ? intl.formatMessage(certificateMessages.printedOnCollection) - : intl.formatMessage(certificateMessages.printedOnAdvance), + label: + !collectorData.relationship || // relationship should not be available if certifier is found for certificate + collectorData.relationship === 'PRINT_IN_ADVANCE' + ? intl.formatMessage(certificateMessages.printedOnAdvance) + : intl.formatMessage(certificateMessages.printedOnCollection), width: 100 } ] From f0db8232483c71ec98d37b0a6670a89065d0606f Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Wed, 2 Oct 2024 18:48:47 +0600 Subject: [PATCH 15/18] fix: amend role types --- packages/client/src/declarations/index.test.ts | 13 +++++++++++-- packages/client/src/tests/util.tsx | 18 +++++++++++++++--- .../RegisterForm/RegisterForm.init.test.tsx | 13 +++++++++++-- .../Team/user/UserAuditActionModal.test.tsx | 18 +++++++++++++++--- .../client/src/views/Unlock/ForgotPIN.test.tsx | 10 ++++++++-- 5 files changed, 60 insertions(+), 12 deletions(-) diff --git a/packages/client/src/declarations/index.test.ts b/packages/client/src/declarations/index.test.ts index 171c65bb80..190a4720c3 100644 --- a/packages/client/src/declarations/index.test.ts +++ b/packages/client/src/declarations/index.test.ts @@ -17,7 +17,7 @@ import { filterProcessingDeclarations, filterProcessingDeclarationsFromQuery } from '.' -import { Event, SystemRoleType, Status } from '@client/utils/gateway' +import { Event, Status } from '@client/utils/gateway' import { AppStore, createStore } from '@client/store' import { mockDeclarationData, flushPromises } from '@client/tests/util' import { storage } from '@client/storage' @@ -331,7 +331,16 @@ describe('archiveDeclaration tests', () => { } }, name: [], - localRegistrar: { name: [], role: 'FIELD_AGENT' as SystemRoleType } + localRegistrar: { + name: [], + role: { + label: { + defaultMessage: 'Field Agent', + description: 'Name for user role Field Agent', + id: 'userRole.fieldAgent' + } + } + } } indexedDB = { diff --git a/packages/client/src/tests/util.tsx b/packages/client/src/tests/util.tsx index bb55e6b91a..7acc8f234e 100644 --- a/packages/client/src/tests/util.tsx +++ b/packages/client/src/tests/util.tsx @@ -9,7 +9,7 @@ * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ import { App } from '@client/App' -import { Event, SystemRoleType, Status, Scope } from '@client/utils/gateway' +import { Event, Status, Scope } from '@client/utils/gateway' import { UserDetails } from '@client/utils/userUtils' import { getRegisterForm } from '@client/forms/register/declaration-selectors' import { getReviewForm } from '@client/forms/register/review-selectors' @@ -392,7 +392,13 @@ export const userDetails: UserDetails = { status: 'active' }, localRegistrar: { - role: 'LOCAL_REGISTRAR' as SystemRoleType, + role: { + label: { + defaultMessage: 'Local Registrar', + description: 'Name for user role Field Agent', + id: 'userRole.fieldAgent' + } + }, signature: { data: `data:image/png;base64,${validImageB64String}`, type: 'image/png' @@ -1119,7 +1125,13 @@ export function loginAsFieldAgent(store: AppStore) { familyName: 'Ashraful' } ], - role: SystemRoleType.LocalRegistrar, + role: { + label: { + defaultMessage: 'Local Registrar', + description: 'Name for user role Field Agent', + id: 'userRole.fieldAgent' + } + }, signature: undefined } } diff --git a/packages/client/src/views/RegisterForm/RegisterForm.init.test.tsx b/packages/client/src/views/RegisterForm/RegisterForm.init.test.tsx index 847352fe36..46e6a32076 100644 --- a/packages/client/src/views/RegisterForm/RegisterForm.init.test.tsx +++ b/packages/client/src/views/RegisterForm/RegisterForm.init.test.tsx @@ -27,7 +27,7 @@ import { import { DRAFT_BIRTH_PARENT_FORM_PAGE } from '@opencrvs/client/src/navigation/routes' import { vi } from 'vitest' -import { Event, SystemRoleType, Status } from '@client/utils/gateway' +import { Event, Status } from '@client/utils/gateway' import { storage } from '@client/storage' import { UserDetails } from '@client/utils/userUtils' describe('when user logs in', () => { @@ -68,7 +68,16 @@ describe('when user logs in', () => { } }, status: 'active' as Status, - localRegistrar: { name: [], role: 'FIELD_AGENT' as SystemRoleType } + localRegistrar: { + name: [], + role: { + label: { + defaultMessage: 'Field Agent', + description: 'Name for user role Field Agent', + id: 'userRole.fieldAgent' + } + } + } } const indexedDB = { diff --git a/packages/client/src/views/SysAdmin/Team/user/UserAuditActionModal.test.tsx b/packages/client/src/views/SysAdmin/Team/user/UserAuditActionModal.test.tsx index ef9794b2ef..a17448b8ff 100644 --- a/packages/client/src/views/SysAdmin/Team/user/UserAuditActionModal.test.tsx +++ b/packages/client/src/views/SysAdmin/Team/user/UserAuditActionModal.test.tsx @@ -18,7 +18,7 @@ import { USER_AUDIT_ACTION } from '@client/user/queries' import { GraphQLError } from 'graphql' import { History } from 'history' import { vi, Mock } from 'vitest' -import { SystemRoleType, Status } from '@client/utils/gateway' +import { Status } from '@client/utils/gateway' import { UserDetails } from '@client/utils/userUtils' const users: UserDetails[] = [ @@ -40,7 +40,13 @@ const users: UserDetails[] = [ familyName: 'Huq' } ], - role: SystemRoleType.LocalRegistrar, + role: { + label: { + defaultMessage: 'Local Registrar', + description: 'Name for user role Local Registrar', + id: 'userRole.localRegistrar' + } + }, signature: undefined }, role: { @@ -88,7 +94,13 @@ const users: UserDetails[] = [ familyName: 'Islam' } ], - role: SystemRoleType.LocalRegistrar, + role: { + label: { + defaultMessage: 'Local Registrar', + description: 'Name for user role Local Registrar', + id: 'userRole.localRegistrar' + } + }, signature: undefined }, creationDate: '2022-10-03T10:42:46.920Z', diff --git a/packages/client/src/views/Unlock/ForgotPIN.test.tsx b/packages/client/src/views/Unlock/ForgotPIN.test.tsx index 78121bd584..97c0edfff9 100644 --- a/packages/client/src/views/Unlock/ForgotPIN.test.tsx +++ b/packages/client/src/views/Unlock/ForgotPIN.test.tsx @@ -22,7 +22,7 @@ import { SCREEN_LOCK } from '@client/components/ProtectedPage' import { SECURITY_PIN_EXPIRED_AT } from '@client/utils/constants' import { History } from 'history' import { vi, Mock } from 'vitest' -import { SystemRoleType, Status } from '@client/utils/gateway' +import { Status } from '@client/utils/gateway' describe('ForgotPIN tests', () => { let component: ReactWrapper @@ -75,7 +75,13 @@ describe('ForgotPIN tests', () => { familyName: 'Ashraful' } ], - role: SystemRoleType.LocalRegistrar, + role: { + label: { + defaultMessage: 'Local Registrar', + description: 'Name for user role Local Registrar', + id: 'userRole.localRegistrar' + } + }, signature: undefined } } From 3001099e73d573a5a481494f913773c00a807f42 Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Wed, 2 Oct 2024 18:51:50 +0600 Subject: [PATCH 16/18] fix: clean up console --- packages/search/src/config/routes.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/search/src/config/routes.ts b/packages/search/src/config/routes.ts index 2ae47c06b5..a92c882b64 100644 --- a/packages/search/src/config/routes.ts +++ b/packages/search/src/config/routes.ts @@ -61,8 +61,6 @@ export const getRoutes = () => { method: 'GET', path: '/ping', handler: async (request: any, h: any) => { - console.trace() - try { const res = await client.ping(undefined, { meta: true }) From 0c9cc04acd5e6f38bb7d6c9f4698bed2cbcc8c4b Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Thu, 3 Oct 2024 19:06:02 +0600 Subject: [PATCH 17/18] chore: amend review changes --- .../features/registration/type-resolvers.ts | 72 +++++++++---------- .../src/features/registration/utils.ts | 23 ------ packages/workflow/src/records/fhir.ts | 15 +--- .../workflow/src/records/state-transitions.ts | 20 ++++-- 4 files changed, 48 insertions(+), 82 deletions(-) diff --git a/packages/gateway/src/features/registration/type-resolvers.ts b/packages/gateway/src/features/registration/type-resolvers.ts index b13205b92e..94a4069dc8 100644 --- a/packages/gateway/src/features/registration/type-resolvers.ts +++ b/packages/gateway/src/features/registration/type-resolvers.ts @@ -1258,51 +1258,45 @@ export const typeResolvers: GQLResolver = { ) if ( - practitionerRef && - practitionerRef.valueReference && - practitionerRef.valueReference.reference && - practitionerRef.valueReference.reference.startsWith('Practitioner') - ) { - const practitionerId = resourceIdentifierToUUID( - practitionerRef.valueReference.reference as ResourceIdentifier + !practitionerRef?.valueReference?.reference?.startsWith('Practitioner') + ) + return null + + const practitionerId = resourceIdentifierToUUID( + practitionerRef.valueReference.reference as ResourceIdentifier + ) + const practitionerRoleBundle = + await context.dataSources.fhirAPI.getPractitionerRoleByPractitionerId( + practitionerId ) - const practitionerRoleBundle = - await context.dataSources.fhirAPI.getPractitionerRoleByPractitionerId( - practitionerId - ) - - const practitionerRoleId = - practitionerRoleBundle.entry?.[0].resource?.id - - const practitionerRoleHistory = - await context.dataSources.fhirAPI.getPractionerRoleHistory( - practitionerRoleId - ) - const result = practitionerRoleHistory.find( - (it) => - it?.meta?.lastUpdated && - task.lastModified && - it?.meta?.lastUpdated <= task.lastModified! + + const practitionerRoleId = practitionerRoleBundle.entry?.[0].resource?.id + + const practitionerRoleHistory = + await context.dataSources.fhirAPI.getPractionerRoleHistory( + practitionerRoleId ) + const result = practitionerRoleHistory.find( + (it) => + it?.meta?.lastUpdated && + task.lastModified && + it?.meta?.lastUpdated <= task.lastModified! + ) - const targetCode = result?.code?.find((element) => { - return ( - element.coding?.[0].system === 'http://opencrvs.org/specs/roles' - ) - }) + const targetCode = result?.code?.find((element) => { + return element.coding?.[0].system === 'http://opencrvs.org/specs/roles' + }) - const roleId = targetCode?.coding?.[0].code - const userResponse = - await context.dataSources.usersAPI.getUserByPractitionerId( - practitionerId - ) + const roleId = targetCode?.coding?.[0].code + const userResponse = + await context.dataSources.usersAPI.getUserByPractitionerId( + practitionerId + ) - const allRoles = await context.dataSources.countryConfigAPI.getRoles() - const role = allRoles.find((role) => role.id === roleId)?.id + const allRoles = await context.dataSources.countryConfigAPI.getRoles() + const role = allRoles.find((role) => role.id === roleId)?.id - return { ...userResponse, role } - } - return null + return { ...userResponse, role } } }, Identifier: { diff --git a/packages/gateway/src/features/registration/utils.ts b/packages/gateway/src/features/registration/utils.ts index 7af77f79d8..9c33de2b9d 100644 --- a/packages/gateway/src/features/registration/utils.ts +++ b/packages/gateway/src/features/registration/utils.ts @@ -17,12 +17,6 @@ import { GQLDeathRegistrationInput, GQLMarriageRegistrationInput } from '@gateway/graphql/schema' -import { - isPractitionerRole, - Resource, - SavedBundle, - SavedPractitioner -} from '@opencrvs/commons/types' export async function getPresignedUrlFromUri( fileUri: string, @@ -69,20 +63,3 @@ export async function setCollectorForPrintInAdvance( return details } - -export function getPractitionerRoleFromPractitioner( - practitioner: SavedPractitioner, - bundle: SavedBundle -) { - const bundleEntries = bundle.entry - for (const entry of bundleEntries) { - if ( - isPractitionerRole(entry.resource) && - //@ts-ignore - entry.resource.practitioner.reference.includes(practitioner.id) - ) { - return entry.resource.code?.[0]?.coding?.[0].code - } - } - return null -} diff --git a/packages/workflow/src/records/fhir.ts b/packages/workflow/src/records/fhir.ts index fefaceb930..6d4bd1979d 100644 --- a/packages/workflow/src/records/fhir.ts +++ b/packages/workflow/src/records/fhir.ts @@ -51,7 +51,6 @@ import { RegistrationStatus, getResourceFromBundleById, TransactionResponse, - findExtension, TaskIdentifierSystem, Location } from '@opencrvs/commons/types' @@ -216,24 +215,12 @@ export function createCorrectionProofOfLegalCorrectionDocument( export function createDocumentReferenceEntryForCertificate( temporaryDocumentReferenceId: UUID, - temporaryRelatedPersonId: UUID, eventType: EVENT_TYPE, hasShowedVerifiedDocument: boolean, - collectorDetails: CertifyInput['collector'], - currentTask: SavedTask, + collectorReference: ResourceIdentifier | URNReference, attachmentUrl?: string, paymentUrl?: URNReference | ResourceIdentifier ): BundleEntry { - /* For 'PRINT_IN_ADVANCE' records, there will be no related person entry to add. Thus the - related person id should not be referenced rather the regLastUser Practitioner is referenced.*/ - const collectorReference = - collectorDetails.relationship !== 'PRINT_IN_ADVANCE' - ? (`urn:uuid:${temporaryRelatedPersonId}` as const) - : findExtension( - 'http://opencrvs.org/specs/extension/regLastUser', - currentTask.extension - )!.valueReference.reference - return { fullUrl: `urn:uuid:${temporaryDocumentReferenceId}`, resource: { diff --git a/packages/workflow/src/records/state-transitions.ts b/packages/workflow/src/records/state-transitions.ts index afff6292fa..2ffa8f487a 100644 --- a/packages/workflow/src/records/state-transitions.ts +++ b/packages/workflow/src/records/state-transitions.ts @@ -955,14 +955,23 @@ export async function toCertified( temporaryRelatedPersonId, record ) + const practitionerReference = findExtension( + 'http://opencrvs.org/specs/extension/regLastUser', + certifiedTask.extension + )!.valueReference.reference + + /* For 'PRINT_IN_ADVANCE' records, there will be no related person entry to add. Thus the + related person id should not be referenced rather the regLastUser Practitioner is referenced.*/ + const collectorReference = + certificateDetails.collector.relationship !== 'PRINT_IN_ADVANCE' + ? (`urn:uuid:${temporaryRelatedPersonId}` as const) + : practitionerReference const documentReferenceEntry = createDocumentReferenceEntryForCertificate( temporaryDocumentReferenceId, - temporaryRelatedPersonId, eventType, certificateDetails.hasShowedVerifiedDocument, - certificateDetails.collector, - certifiedTask, + collectorReference, certificateDetails.data ) @@ -1040,13 +1049,12 @@ export async function toIssued( const [paymentEntry] = createPaymentResources(certificateDetails.payment) + const collectorReference = `urn:uuid:${temporaryRelatedPersonId}` as const const documentReferenceEntry = createDocumentReferenceEntryForCertificate( temporaryDocumentReferenceId, - temporaryRelatedPersonId, eventType, certificateDetails.hasShowedVerifiedDocument, - certificateDetails.collector, - issuedTask, + collectorReference, undefined, paymentEntry.fullUrl ) From 1f6e30e3788768eb6a4d4d6e65e574a0ecc8da3a Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Thu, 3 Oct 2024 19:55:19 +0600 Subject: [PATCH 18/18] chore: refactor fetching role --- packages/commons/src/fhir/practitioner.ts | 6 ++---- .../registration/type-resolvers.test.ts | 10 ++-------- .../features/registration/type-resolvers.ts | 19 ++++++------------- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/packages/commons/src/fhir/practitioner.ts b/packages/commons/src/fhir/practitioner.ts index eedc19c89c..313ef98a1d 100644 --- a/packages/commons/src/fhir/practitioner.ts +++ b/packages/commons/src/fhir/practitioner.ts @@ -131,11 +131,9 @@ export const getUserRoleFromHistory = ( ) const targetCode = result?.code?.find((element) => { - return element.coding?.[0].system === 'http://opencrvs.org/specs/types' + return element.coding?.[0].system === 'http://opencrvs.org/specs/roles' }) const role = targetCode?.coding?.[0].code - const systemRole = result?.code?.[0].coding?.[0].code - - return { role, systemRole } + return role } diff --git a/packages/gateway/src/features/registration/type-resolvers.test.ts b/packages/gateway/src/features/registration/type-resolvers.test.ts index cfa45a712f..26841d69d0 100644 --- a/packages/gateway/src/features/registration/type-resolvers.test.ts +++ b/packages/gateway/src/features/registration/type-resolvers.test.ts @@ -519,15 +519,9 @@ test('getting role at a specific time from roleHistory', async () => { */ const lastModified = '2024-08-30T13:14:33.704Z' - const expectedRole = - '[{"lang":"en","label":"National Registrar"},{"lang":"fr","label":"Registraire national"}]' - const expectedSystemRole = 'NATIONAL_REGISTRAR' + const expectedRole = 'NATIONAL_REGISTRAR' - const { role, systemRole } = getUserRoleFromHistory( - practitionerRoleHistory, - lastModified - ) + const role = getUserRoleFromHistory(practitionerRoleHistory, lastModified) expect(role).toEqual(expectedRole) - expect(systemRole).toEqual(expectedSystemRole) }) diff --git a/packages/gateway/src/features/registration/type-resolvers.ts b/packages/gateway/src/features/registration/type-resolvers.ts index 94a4069dc8..9a36c6d1e1 100644 --- a/packages/gateway/src/features/registration/type-resolvers.ts +++ b/packages/gateway/src/features/registration/type-resolvers.ts @@ -87,7 +87,8 @@ import { findLastOfficeFromSavedBundle, findLastOfficeLocationFromSavedBundle, notCorrectedHistory, - findResourceFromBundleById + findResourceFromBundleById, + getUserRoleFromHistory } from '@opencrvs/commons/types' import { GQLQuestionnaireQuestion, GQLResolver } from '@gateway/graphql/schema' @@ -1552,19 +1553,11 @@ export const typeResolvers: GQLResolver = { const practitionerRoleHistory = await dataSources.fhirAPI.getPractionerRoleHistory(practitionerRoleId) - const result = practitionerRoleHistory.find( - (it) => - it?.meta?.lastUpdated && - task.lastModified && - it?.meta?.lastUpdated <= task.lastModified! - ) - - const targetCode = result?.code?.find((element) => { - return element.coding?.[0].system === 'http://opencrvs.org/specs/roles' - }) - - const roleId = targetCode?.coding?.[0].code + const roleId = getUserRoleFromHistory( + practitionerRoleHistory, + task.lastModified + ) const userResponse = await dataSources.usersAPI.getUserByPractitionerId( resourceIdentifierToUUID(user.valueReference.reference) )