From bed09afcebe8725be0ed19d75ea72f6dc485fda9 Mon Sep 17 00:00:00 2001 From: Siyasanga Date: Thu, 23 Oct 2025 12:03:11 +0200 Subject: [PATCH 1/4] feat: Add registration number field to advanced search configuration https://github.com/opencrvs/opencrvs-core/issues/10760 --- CHANGELOG.md | 3 +++ .../client/src/v2-events/features/events/Search/utils.ts | 9 +++++++++ packages/commons/src/events/AdvancedSearchConfig.ts | 2 ++ 3 files changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4660e038a2d..1448c6f9954 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ HTTP input now accepts `field('..')` references in the HTTP body definition. - **Searchable Select**: A new select component that allows searching through options. Useful for selects with a large number of options. Currently being used in address fields. [#10749](https://github.com/opencrvs/opencrvs-core/issues/10749) ### Bug fixes + - During user password reset, email address lookup is now case insensitive [#9869](https://github.com/opencrvs/opencrvs-core/issues/9869) - Users cannot activate or reactivate users with roles not specified in the `user.edit` scope [#9933](https://github.com/opencrvs/opencrvs-core/issues/9933) - Login page no longer show "Farajaland CRVS" before showing the correct title [#10958](https://github.com/opencrvs/opencrvs-core/issues/10958) @@ -332,6 +333,8 @@ To see Events V2 in action, check out the example configurations in the **countr - Add Import/Export system client and `record.export` scope to enable data migrations [#10415](https://github.com/opencrvs/opencrvs-core/issues/10415) - Add an Alpha version of configurable "Print" button that will be refactored in a later release - this button can be used to print certificates during declaration/correction flow. [#10039](https://github.com/opencrvs/opencrvs-core/issues/10039) - Add bulk import endpoint [#10590](https://github.com/opencrvs/opencrvs-core/pull/10590) +- Add multi-field search with a single component [#10617](https://github.com/opencrvs/opencrvs-core/issues/10617) +- Add registration number field to advanced search configuration so that documents can be searched by their `Registration Number`. [#10760](https://github.com/opencrvs/opencrvs-core/issues/10760) ### Improvements diff --git a/packages/client/src/v2-events/features/events/Search/utils.ts b/packages/client/src/v2-events/features/events/Search/utils.ts index 1b15656f92f..6955602f728 100644 --- a/packages/client/src/v2-events/features/events/Search/utils.ts +++ b/packages/client/src/v2-events/features/events/Search/utils.ts @@ -138,6 +138,15 @@ const defaultSearchFieldGenerator: Record< id: 'advancedSearch.status' }, options: statusOptions + }), + 'event.legalStatuses.REGISTERED.registrationNumber': (_) => ({ + id: 'event.legalStatuses.REGISTERED.registrationNumber', + type: FieldType.TEXT, + label: { + defaultMessage: 'Registration number', + description: 'Label for registration number field', + id: 'advancedSearch.registrationNumber' + } }) } satisfies Record FieldConfig> diff --git a/packages/commons/src/events/AdvancedSearchConfig.ts b/packages/commons/src/events/AdvancedSearchConfig.ts index 06547785f24..47703d01c76 100644 --- a/packages/commons/src/events/AdvancedSearchConfig.ts +++ b/packages/commons/src/events/AdvancedSearchConfig.ts @@ -124,6 +124,7 @@ export const EventFieldIdInput = z.enum([ 'status', 'legalStatuses.REGISTERED.acceptedAt', 'legalStatuses.REGISTERED.createdAtLocation', + 'legalStatuses.REGISTERED.registrationNumber', 'updatedAt' ]) @@ -142,6 +143,7 @@ export const EventFieldId = z.enum([ `${METADATA_FIELD_PREFIX}status`, `${METADATA_FIELD_PREFIX}legalStatuses.REGISTERED.acceptedAt`, `${METADATA_FIELD_PREFIX}legalStatuses.REGISTERED.createdAtLocation`, + `${METADATA_FIELD_PREFIX}legalStatuses.REGISTERED.registrationNumber`, `${METADATA_FIELD_PREFIX}updatedAt` ]) From d1f6df861d731de0bd97046d5c861a34e345fb1f Mon Sep 17 00:00:00 2001 From: Siyasanga Date: Mon, 8 Dec 2025 16:26:15 +0200 Subject: [PATCH 2/4] fix: remove .shape from ActionConfig extends to properly override conditionals The .extend(z.object({...}).shape) pattern was preventing proper field overrides. Specifically, ReadActionConfig's conditionals: z.never() override wasn't working, causing validation errors when READ actions inherited the array conditionals from ActionConfigBase. This fixes Zod validation errors: - 'expected never, received array' for READ action conditionals - Proper discriminated union validation for all action types --- packages/commons/src/events/ActionConfig.ts | 83 +++++++++------------ 1 file changed, 35 insertions(+), 48 deletions(-) diff --git a/packages/commons/src/events/ActionConfig.ts b/packages/commons/src/events/ActionConfig.ts index 33542b126e9..d2d2a240cb8 100644 --- a/packages/commons/src/events/ActionConfig.ts +++ b/packages/commons/src/events/ActionConfig.ts @@ -53,59 +53,45 @@ const DeclarationActionBase = ActionConfigBase.extend({ deduplication: DeduplicationConfig.optional() }) -const ReadActionConfig = ActionConfigBase.extend( - z.object({ - type: z.literal(ActionType.READ), - review: DeclarationReviewConfig.describe( - 'Configuration of the review page for read-only view.' - ), - conditionals: z - .never() - .optional() - .describe('Read-action can not be disabled or hidden with conditionals.') - }).shape -) +const ReadActionConfig = ActionConfigBase.extend({ + type: z.literal(ActionType.READ), + review: DeclarationReviewConfig.describe( + 'Configuration of the review page for read-only view.' + ), + conditionals: z + .never() + .optional() + .describe('Read-action can not be disabled or hidden with conditionals.') +}) -const DeclareConfig = DeclarationActionBase.extend( - z.object({ - type: z.literal(ActionType.DECLARE), - review: DeclarationReviewConfig.describe( - 'Configuration of the review page fields.' - ) - }).shape -) +const DeclareConfig = DeclarationActionBase.extend({ + type: z.literal(ActionType.DECLARE), + review: DeclarationReviewConfig.describe( + 'Configuration of the review page fields.' + ) +}) -const RejectConfig = ActionConfigBase.extend( - z.object({ - type: z.literal(ActionType.REJECT) - }).shape -) +const RejectConfig = ActionConfigBase.extend({ + type: z.literal(ActionType.REJECT) +}) -const ValidateConfig = DeclarationActionBase.extend( - z.object({ - type: z.literal(ActionType.VALIDATE) - }).shape -) +const ValidateConfig = DeclarationActionBase.extend({ + type: z.literal(ActionType.VALIDATE) +}) -const RegisterConfig = DeclarationActionBase.extend( - z.object({ - type: z.literal(ActionType.REGISTER) - }).shape -) +const RegisterConfig = DeclarationActionBase.extend({ + type: z.literal(ActionType.REGISTER) +}) -const PrintCertificateActionConfig = ActionConfigBase.extend( - z.object({ - type: z.literal(ActionType.PRINT_CERTIFICATE), - printForm: ActionFormConfig - }).shape -) +const PrintCertificateActionConfig = ActionConfigBase.extend({ + type: z.literal(ActionType.PRINT_CERTIFICATE), + printForm: ActionFormConfig +}) -const RequestCorrectionConfig = ActionConfigBase.extend( - z.object({ - type: z.literal(ActionType.REQUEST_CORRECTION), - correctionForm: ActionFormConfig - }).shape -) +const RequestCorrectionConfig = ActionConfigBase.extend({ + type: z.literal(ActionType.REQUEST_CORRECTION), + correctionForm: ActionFormConfig +}) const CustomActionConfig = ActionConfigBase.merge( z.object({ @@ -149,7 +135,8 @@ export type ActionConfig = z.infer // Build a runtime set directly from the schema export const actionConfigTypes: Set = new Set( - ActionConfig.options.map((opt) => opt.shape.type.value) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ActionConfig.options.map((opt: z.ZodObject) => opt.shape.type.value) ) /** * Action types that come specifically from the country configuration. From 3091763abd17e28a63f800ddd8fa20faaf7f5b39 Mon Sep 17 00:00:00 2001 From: Siyasanga Date: Tue, 9 Dec 2025 12:37:11 +0200 Subject: [PATCH 3/4] fix: use omit() to properly remove conditionals from ReadActionConfig The .extend() method in Zod merges fields rather than replacing them. When ActionConfigBase has conditionals defined, extending with conditionals: z.never() creates a conflict. Using .omit({conditionals: true}) first removes the field completely, then .extend() adds only the fields we want without the conditionals field. This ensures READ actions truly cannot have conditionals, fixing the validation error: 'expected never, received array' at path actions[0].conditionals --- packages/commons/src/conditionals/validate.ts | 2 +- packages/commons/src/events/ActionConfig.ts | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/commons/src/conditionals/validate.ts b/packages/commons/src/conditionals/validate.ts index 83e706dd2e9..cadeb4ed712 100644 --- a/packages/commons/src/conditionals/validate.ts +++ b/packages/commons/src/conditionals/validate.ts @@ -287,7 +287,7 @@ function isActionConditionMet( context: ValidatorContext, conditionalType: ConditionalType ) { - if (!actionConfig.conditionals) { + if (!('conditionals' in actionConfig) || !actionConfig.conditionals) { return true } diff --git a/packages/commons/src/events/ActionConfig.ts b/packages/commons/src/events/ActionConfig.ts index d2d2a240cb8..6c9f3023973 100644 --- a/packages/commons/src/events/ActionConfig.ts +++ b/packages/commons/src/events/ActionConfig.ts @@ -53,15 +53,11 @@ const DeclarationActionBase = ActionConfigBase.extend({ deduplication: DeduplicationConfig.optional() }) -const ReadActionConfig = ActionConfigBase.extend({ +const ReadActionConfig = ActionConfigBase.omit({ conditionals: true }).extend({ type: z.literal(ActionType.READ), review: DeclarationReviewConfig.describe( 'Configuration of the review page for read-only view.' - ), - conditionals: z - .never() - .optional() - .describe('Read-action can not be disabled or hidden with conditionals.') + ) }) const DeclareConfig = DeclarationActionBase.extend({ From f134e09330127c5bb5c5fe2ac6e8db927a852e7b Mon Sep 17 00:00:00 2001 From: Siyasanga Date: Tue, 9 Dec 2025 12:50:55 +0200 Subject: [PATCH 4/4] fix: add type guard for conditionals property in client Use 'in' operator to properly narrow ActionConfig type before accessing conditionals property. Some action types (like READ) don't have conditionals, so we need a type guard to satisfy TypeScript's stricter checking. --- .../components/useAllowedActionConfigurations.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/client/src/v2-events/features/workqueues/EventOverview/components/useAllowedActionConfigurations.tsx b/packages/client/src/v2-events/features/workqueues/EventOverview/components/useAllowedActionConfigurations.tsx index 3e97ea41c8d..389a2228173 100644 --- a/packages/client/src/v2-events/features/workqueues/EventOverview/components/useAllowedActionConfigurations.tsx +++ b/packages/client/src/v2-events/features/workqueues/EventOverview/components/useAllowedActionConfigurations.tsx @@ -640,7 +640,11 @@ function applyActionConditionalEffects({ 'customActionType' in action ? action.customActionType : undefined }) - if (!actionConfig || !actionConfig.conditionals) { + if ( + !actionConfig || + !('conditionals' in actionConfig) || + !actionConfig.conditionals + ) { return action }