Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(message-queue): allow confirming and rejecting record externally #7674

Merged
merged 24 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
39a0f53
feat: allow confirming and rejecting record externally
naftis Sep 26, 2024
420ec4d
revert: no 'patch' needed after all
naftis Sep 26, 2024
39b857b
fix: remove dummy definitions
naftis Sep 30, 2024
d9a9646
refactor: improve typing on graphql gateway supported patient identif…
naftis Sep 30, 2024
c2db318
refactor: use defined rejection types
naftis Sep 30, 2024
af52157
refactor(tests): use defined rejection types
naftis Oct 1, 2024
d09c8a4
Merge branch 'ocrvs-6208' into ocrvs-6208-reject-registration
rikukissa Oct 2, 2024
522f2cd
fix: add some missing rejection reasons
naftis Oct 8, 2024
eb9c240
fix: linter issues
naftis Oct 8, 2024
04eaf60
fix: named types not being included in the generated graphql query
naftis Oct 8, 2024
529d702
fix: REVERT THIS? remove trivy from build
naftis Oct 8, 2024
cac78c3
revert: typing work related to reasons
naftis Oct 9, 2024
201cec7
refactor: stop using global interception in workflow tests
naftis Oct 9, 2024
edb08fb
chore: allow specifying the port to the queue
naftis Oct 9, 2024
767169f
feat: add testcontainers
naftis Oct 9, 2024
5fca7b0
chore: add host&port to missing places
naftis Oct 9, 2024
ed761f9
refactor: add port and host to redis call
naftis Oct 9, 2024
b72601b
chore: clean up testcontainers
naftis Oct 9, 2024
24430af
fix: use defined redis port in gateway
naftis Oct 9, 2024
c0fd996
Revert "refactor: stop using global interception in workflow tests"
naftis Oct 9, 2024
bc318fc
revert: yarn.lock changes
naftis Oct 9, 2024
5387247
revert: typing efforts in client - add a todo comment to look into this
naftis Oct 9, 2024
cef4bb3
Revert "fix: REVERT THIS? remove trivy from build"
naftis Oct 10, 2024
1d9a688
Merge branch 'ocrvs-6208' of https://github.com/opencrvs/opencrvs-cor…
naftis Oct 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ services:
- NODE_ENV=development
- FHIR_URL=http://hearth:3447/fhir
- AUTH_URL=http://auth:4040
- CONFIRM_REGISTRATION_URL=http://workflow:5050/confirm/registration
- CHECK_INVALID_TOKEN=true
ports:
- '3040:3040'
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/declarations/submissionMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@
import { updateRegistrarWorkqueue } from '@client/workqueue'
import { Action, Middleware, createAction } from '@reduxjs/toolkit'
import { Dispatch } from 'redux'
// eslint-disable-next-line no-restricted-imports
import { getReviewForm } from '@client/forms/register/review-selectors'
import { IOfflineData } from '@client/offline/reducer'
import { getOfflineData } from '@client/offline/selectors'
import type { MutationToRequestRegistrationCorrectionArgs } from '@client/utils/gateway-deprecated-do-not-use'
import { UserDetails } from '@client/utils/userUtils'
// eslint-disable-next-line no-restricted-imports
import { captureException } from '@sentry/browser'
import { submitAndWaitUntilRecordInWorkqueue } from './createRecord'

Expand Down Expand Up @@ -352,7 +352,7 @@
captureException(error)
return
}
console.log(error)

Check warning on line 355 in packages/client/src/declarations/submissionMiddleware.ts

View workflow job for this annotation

GitHub Actions / test (packages/client)

Unexpected console statement

updateDeclaration(dispatch, {
...declaration,
Expand Down
15 changes: 15 additions & 0 deletions packages/gateway/src/features/registration/root-resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
import {
archiveRegistration,
certifyRegistration,
confirmRegistration,
createRegistration,
duplicateRegistration,
fetchRegistrationForDownloading,
Expand Down Expand Up @@ -634,6 +635,20 @@ export const resolvers: GQLResolver = {
)

return taskEntry.resource.id
},
async confirmRegistration(_, { id, details }, { headers: authHeader }) {
if (!inScope(authHeader, ['register', 'validate'])) {
throw new Error('User does not have a register or validate scope')
}

return confirmRegistration(id, authHeader, details as any) // Type 'string' is not assignable to type '"PASSPORT" | "NATIONAL_ID" | "MOSIP_PSUT_TOKEN_ID" | "DECEASED_PATIENT_ENTRY" | "BIRTH_PA...
naftis marked this conversation as resolved.
Show resolved Hide resolved
},
async rejectRegistration(_, { id, details }, { headers: authHeader }) {
if (!inScope(authHeader, ['register', 'validate'])) {
throw new Error('User does not have a register or validate scope')
}

return rejectDeclaration(id, authHeader, details.comment, details.reason)
}
}
}
Expand Down
22 changes: 22 additions & 0 deletions packages/gateway/src/features/registration/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,26 @@ input CorrectionRejectionInput {
timeLoggedMS: Int!
}

input IdentifierInput {
type: String!
value: String!
}
input ConfirmRegistrationInput {
childIdentifiers: [IdentifierInput!]
registrationNumber: String
trackingId: String
}

enum RejectionReason {
other
duplicate
}

input RejectRegistrationInput {
reason: RejectionReason!
comment: String!
}

type Mutation {
# Generic correction handlers for all event types
# Applying a correction request is made on a event level as payload is dependant on event type
Expand Down Expand Up @@ -639,4 +659,6 @@ type Mutation {
comment: String
duplicateTrackingId: String
): ID!
confirmRegistration(id: ID!, details: ConfirmRegistrationInput!): ID!
rejectRegistration(id: ID!, details: RejectRegistrationInput!): ID!
}
57 changes: 57 additions & 0 deletions packages/gateway/src/graphql/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ export interface GQLMutation {
markMarriageAsCertified: string
markMarriageAsIssued: string
markEventAsDuplicate: string
confirmRegistration: string
rejectRegistration: string
createOrUpdateUser: GQLUser
activateUser?: string
changePassword?: string
Expand Down Expand Up @@ -613,6 +615,17 @@ export interface GQLReinstated {
registrationStatus?: GQLRegStatus
}

export interface GQLConfirmRegistrationInput {
childIdentifiers?: Array<GQLIdentifierInput>
registrationNumber?: string
trackingId?: string
}

export interface GQLRejectRegistrationInput {
reason: GQLRejectionReason
comment: string
}

export interface GQLUserInput {
id?: string
name: Array<GQLHumanNameInput>
Expand Down Expand Up @@ -1221,6 +1234,16 @@ export const enum GQLRegStatus {
ISSUED = 'ISSUED'
}

export interface GQLIdentifierInput {
type: string
value: string
}

export const enum GQLRejectionReason {
other = 'other',
duplicate = 'duplicate'
}
naftis marked this conversation as resolved.
Show resolved Hide resolved

export interface GQLHumanNameInput {
use?: string
firstNames?: string
Expand Down Expand Up @@ -2551,6 +2574,8 @@ export interface GQLMutationTypeResolver<TParent = any> {
markMarriageAsCertified?: MutationToMarkMarriageAsCertifiedResolver<TParent>
markMarriageAsIssued?: MutationToMarkMarriageAsIssuedResolver<TParent>
markEventAsDuplicate?: MutationToMarkEventAsDuplicateResolver<TParent>
confirmRegistration?: MutationToConfirmRegistrationResolver<TParent>
rejectRegistration?: MutationToRejectRegistrationResolver<TParent>
createOrUpdateUser?: MutationToCreateOrUpdateUserResolver<TParent>
activateUser?: MutationToActivateUserResolver<TParent>
changePassword?: MutationToChangePasswordResolver<TParent>
Expand Down Expand Up @@ -3083,6 +3108,38 @@ export interface MutationToMarkEventAsDuplicateResolver<
): TResult
}

export interface MutationToConfirmRegistrationArgs {
id: string
details: GQLConfirmRegistrationInput
}
export interface MutationToConfirmRegistrationResolver<
TParent = any,
TResult = any
> {
(
parent: TParent,
args: MutationToConfirmRegistrationArgs,
context: Context,
info: GraphQLResolveInfo
): TResult
}

export interface MutationToRejectRegistrationArgs {
id: string
details: GQLRejectRegistrationInput
}
export interface MutationToRejectRegistrationResolver<
TParent = any,
TResult = any
> {
(
parent: TParent,
args: MutationToRejectRegistrationArgs,
context: Context,
info: GraphQLResolveInfo
): TResult
}

export interface MutationToCreateOrUpdateUserArgs {
user: GQLUserInput
}
Expand Down
23 changes: 23 additions & 0 deletions packages/gateway/src/graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ type Mutation {
comment: String
duplicateTrackingId: String
): ID!
confirmRegistration(id: ID!, details: ConfirmRegistrationInput!): ID!
rejectRegistration(id: ID!, details: RejectRegistrationInput!): ID!
createOrUpdateUser(user: UserInput!): User!
activateUser(
userId: String!
Expand Down Expand Up @@ -728,6 +730,17 @@ type Reinstated {
registrationStatus: RegStatus
}

input ConfirmRegistrationInput {
childIdentifiers: [IdentifierInput!]
registrationNumber: String
trackingId: String
}

input RejectRegistrationInput {
reason: RejectionReason!
comment: String!
}

input UserInput {
id: ID
name: [HumanNameInput!]!
Expand Down Expand Up @@ -1312,6 +1325,16 @@ enum RegStatus {
ISSUED
}

input IdentifierInput {
type: String!
value: String!
}

enum RejectionReason {
other
duplicate
}

input HumanNameInput {
use: String
firstNames: String
Expand Down
38 changes: 37 additions & 1 deletion packages/gateway/src/workflow/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ import {
RejectedRecord,
Resource,
SavedBundle,
SupportedPatientIdentifierCode,
ValidRecord
} from '@opencrvs/commons/types'

const createRequest = async <T = any>(
method: 'POST' | 'GET' | 'PUT' | 'DELETE',
method: 'POST' | 'GET' | 'PUT' | 'PATCH' | 'DELETE',
path: string,
authHeader: IAuthHeader,
body?: Record<string, any>
Expand Down Expand Up @@ -393,3 +394,38 @@ export async function createHospitalNotification(
bundle
)
}

type ConfirmRegistrationDetails = {
childIdentifiers?: {
type: SupportedPatientIdentifierCode
value: string
}[]
}
export async function confirmRegistration(
id: string,
authHeader: IAuthHeader,
details: ConfirmRegistrationDetails
) {
return createRequest<undefined>(
'POST',
`/records/${id}/confirm`,
authHeader,
details
)
}

type RejectRegistrationDetails = {
error: string
}
export async function rejectRegistration(
id: string,
authHeader: IAuthHeader,
details: RejectRegistrationDetails
) {
return createRequest<undefined>(
'POST',
`/records/${id}/reject`,
authHeader,
details
)
}
9 changes: 4 additions & 5 deletions packages/workflow/src/config/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
*
* Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
*/
import { markEventAsRegisteredCallbackHandler } from '@workflow/features/registration/handler'
import { archiveRoute } from '@workflow/records/handler/archive'
import { certifyRoute } from '@workflow/records/handler/certify'
import { confirmRegistrationHandler } from '@workflow/records/handler/confirm'
import { approveCorrectionRoute } from '@workflow/records/handler/correction/approve'
import { makeCorrectionRoute } from '@workflow/records/handler/correction/make-correction'
import { rejectCorrectionRoute } from '@workflow/records/handler/correction/reject'
Expand Down Expand Up @@ -60,12 +60,11 @@ export const getRoutes = () => {
},
{
method: 'POST',
path: '/confirm/registration',
handler: markEventAsRegisteredCallbackHandler,
path: '/records/{id}/confirm',
handler: confirmRegistrationHandler,
config: {
tags: ['api'],
description:
'Register event based on tracking id and registration number.'
description: 'Confirm registration after external validation'
}
},
{
Expand Down
41 changes: 2 additions & 39 deletions packages/workflow/src/features/registration/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,9 @@
*
* Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
*/
import * as Hapi from '@hapi/hapi'
import { toTokenWithBearer } from '@opencrvs/commons'
import {
RecordValidatedPayload,
useExternalValidationQueue
} from '@opencrvs/commons/message-queue'
import {
isWaitingExternalValidation,
SupportedPatientIdentifierCode
} from '@opencrvs/commons/types'
import { REDIS_HOST } from '@workflow/constants'
import { RecordValidatedPayload } from '@opencrvs/commons/message-queue'
import { isWaitingExternalValidation } from '@opencrvs/commons/types'
import { writeMetricsEvent } from '@workflow/records/audit'
import { getRecordById } from '@workflow/records/index'
import {
Expand All @@ -28,7 +20,6 @@ import {
import { indexBundleWithTransaction } from '@workflow/records/search'
import { toRegistered } from '@workflow/records/state-transitions'
import { invokeWebhooks } from '@workflow/records/webhooks'
import { getToken } from '@workflow/utils/auth-utils'
import { getEventType } from './utils'

export async function markEventAsRegistered({
Expand Down Expand Up @@ -73,31 +64,3 @@ export async function markEventAsRegistered({

return
}

const { recordValidated } = useExternalValidationQueue(REDIS_HOST)

type RecordValidatedHTTPPayload = {
registrationNumber: string
childIdentifiers: { type: SupportedPatientIdentifierCode; value: string }[]
compositionId: string
trackingId: string
}

export async function markEventAsRegisteredCallbackHandler(
request: Hapi.Request,
h: Hapi.ResponseToolkit
) {
const token = getToken(request)
const { registrationNumber, childIdentifiers, compositionId, trackingId } =
request.payload as RecordValidatedHTTPPayload

await recordValidated({
recordId: compositionId,
identifiers: childIdentifiers || [],
registrationNumber,
trackingId,
token
})

return h.response().code(200)
}
Loading
Loading