diff --git a/packages/common/src/rule-engine/operators/helpers.ts b/packages/common/src/rule-engine/operators/helpers.ts index 14bf0258d7..d42a2b311d 100644 --- a/packages/common/src/rule-engine/operators/helpers.ts +++ b/packages/common/src/rule-engine/operators/helpers.ts @@ -255,6 +255,7 @@ class LastYear extends BaseOperator { const yearsAgo = new Date(); yearsAgo.setFullYear(yearsAgo.getFullYear() - conditionValue.years); + yearsAgo.setHours(0, 0, 0, 0); return date >= yearsAgo; } diff --git a/services/workflows-service/src/workflow/dtos/workflow-where-unique-input.ts b/services/workflows-service/src/workflow/dtos/workflow-where-unique-input.ts index 8e803533ef..f3b44dc856 100644 --- a/services/workflows-service/src/workflow/dtos/workflow-where-unique-input.ts +++ b/services/workflows-service/src/workflow/dtos/workflow-where-unique-input.ts @@ -12,5 +12,5 @@ export class WorkflowDefinitionWhereUniqueInput { } export const WorkflowDefinitionWhereUniqueInputSchema = Type.String({ - description: "The workflow's id", + description: "The workflow's definition id", }); diff --git a/services/workflows-service/src/workflow/schemas/extensions.schemas.ts b/services/workflows-service/src/workflow/schemas/extensions.schemas.ts index bfe4af85b4..00ef959607 100644 --- a/services/workflows-service/src/workflow/schemas/extensions.schemas.ts +++ b/services/workflows-service/src/workflow/schemas/extensions.schemas.ts @@ -73,11 +73,18 @@ const DispatchEventPluginSchema = Type.Object({ successAction: Type.String(), }); -export const WorkflowExtensionSchema = Type.Object({ - apiPlugins: Type.Optional(Type.Array(ApiPluginSchema)), - commonPlugins: Type.Optional(Type.Array(CommonPluginSchema)), - childWorkflowPlugins: Type.Optional(Type.Array(ChildWorkflowPluginSchema)), - dispatchEventPlugins: Type.Optional(Type.Array(DispatchEventPluginSchema)), -}); +const getWorkflowExtensionSchema = ({ forUpdate }: { forUpdate: boolean }) => { + const options = forUpdate ? { minItems: 1 } : undefined; + + return Type.Object({ + apiPlugins: Type.Optional(Type.Array(ApiPluginSchema, options)), + commonPlugins: Type.Optional(Type.Array(CommonPluginSchema, options)), + childWorkflowPlugins: Type.Optional(Type.Array(ChildWorkflowPluginSchema, options)), + dispatchEventPlugins: Type.Optional(Type.Array(DispatchEventPluginSchema, options)), + }); +}; +export const WorkflowExtensionSchema = getWorkflowExtensionSchema({ forUpdate: false }); + +export const PutWorkflowExtensionSchema = getWorkflowExtensionSchema({ forUpdate: true }); export type TWorkflowExtension = Static; diff --git a/services/workflows-service/src/workflow/workflow-controller-examples.ts b/services/workflows-service/src/workflow/workflow-controller-examples.ts new file mode 100644 index 0000000000..06bf7c4a74 --- /dev/null +++ b/services/workflows-service/src/workflow/workflow-controller-examples.ts @@ -0,0 +1,60 @@ +export const putPluginsExampleResponse = { + apiPlugins: [ + { + name: 'company-sanctions', + vendor: 'asia-verify', + pluginKind: 'company-sanctions', + stateNames: ['run_vendor_data'], + displayName: 'Company Sanctions', + errorAction: 'VENDOR_FAILED', + successAction: 'VENDOR_DONE', + }, + { + name: 'kyb', + vendor: 'asia-verify', + pluginKind: 'registry-information', + stateNames: ['get_vendor_data'], + displayName: 'Registry Information', + errorAction: 'VENDOR_FAILED', + successAction: 'VENDOR_DONE', + }, + { + name: 'company-sanctions', + vendor: 'asia-verify', + pluginKind: 'company-sanctions', + stateNames: ['get_vendor_data'], + displayName: 'Company Sanctions', + errorAction: 'VENDOR_FAILED', + successAction: 'VENDOR_DONE', + }, + { + name: 'ubo', + vendor: 'asia-verify', + pluginKind: 'ubo', + stateNames: ['get_vendor_data'], + displayName: 'UBO Check', + errorAction: 'VENDOR_FAILED', + successAction: 'VENDOR_DONE', + }, + { + name: 'resubmission-email', + pluginKind: 'resubmission-email', + stateNames: ['pending_resubmission'], + errorAction: 'EMAIL_FAILURE', + successAction: 'EMAIL_SENT', + }, + ], + commonPlugins: [ + { + name: 'risk_evaluation', + pluginKind: 'riskRules', + stateNames: ['manual_review'], + rulesSource: { + source: 'notion', + databaseId: 'aaaaaaaaaaaaaa', + }, + }, + ], + childWorkflowPlugins: [], + dispatchEventPlugins: [], +}; diff --git a/services/workflows-service/src/workflow/workflow.controller.external.ts b/services/workflows-service/src/workflow/workflow.controller.external.ts index 54ad806ef3..c5abe40be1 100644 --- a/services/workflows-service/src/workflow/workflow.controller.external.ts +++ b/services/workflows-service/src/workflow/workflow.controller.external.ts @@ -2,12 +2,13 @@ import { defaultPrismaTransactionOptions, isRecordNotFoundError } from '@/prisma import { UserData } from '@/user/user-data.decorator'; import { UserInfo } from '@/user/user-info'; import * as common from '@nestjs/common'; -import { NotFoundException, Query, Res } from '@nestjs/common'; +import { HttpStatus, NotFoundException, Query, Res } from '@nestjs/common'; import * as swagger from '@nestjs/swagger'; import { ApiOkResponse, ApiResponse } from '@nestjs/swagger'; import { WorkflowRuntimeData } from '@prisma/client'; // import * as nestAccessControl from 'nest-access-control'; import { WorkflowTokenService } from '@/auth/workflow-token/workflow-token.service'; +import { putPluginsExampleResponse } from '@/workflow/workflow-controller-examples'; import { CurrentProject } from '@/common/decorators/current-project.decorator'; import { ProjectIds } from '@/common/decorators/project-ids.decorator'; import { Public } from '@/common/decorators/public.decorator'; @@ -39,7 +40,8 @@ import { RunnableWorkflowData } from './types'; import { WorkflowDefinitionModel } from './workflow-definition.model'; import { WorkflowService } from './workflow.service'; import { Validate } from 'ballerine-nestjs-typebox'; -import { WorkflowExtensionSchema } from './schemas/extensions.schemas'; +import { PutWorkflowExtensionSchema, WorkflowExtensionSchema } from './schemas/extensions.schemas'; +import type { TWorkflowExtension } from './schemas/extensions.schemas'; import { type Static, Type } from '@sinclair/typebox'; export const WORKFLOW_TAG = 'Workflows'; @@ -103,6 +105,7 @@ export class WorkflowControllerExternal { @ApiResponse({ status: 200, schema: WorkflowExtensionSchema, + example: putPluginsExampleResponse, }) @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException }) async listWorkflowPlugins( @@ -115,40 +118,63 @@ export class WorkflowControllerExternal { } @swagger.ApiTags(WORKFLOW_DEFINITION_TAG, WORKFLOW_TAG) - @common.Put('/workflow-definition/:id/plugins') + @common.Put('/workflow-definition/:workflow_definition_id/plugins') + @swagger.ApiBody({ + schema: PutWorkflowExtensionSchema, + examples: { + 1: { + value: putPluginsExampleResponse, + summary: 'The plugins for the workflow', + description: 'The plugins for the workflow', + }, + }, + }) @Validate({ request: [ { type: 'param', - name: 'id', + name: 'workflow_definition_id', + description: `The workflow's definition id`, schema: WorkflowDefinitionWhereUniqueInputSchema, + example: { + value: putPluginsExampleResponse, + summary: 'The plugins for the workflow', + description: 'The plugins for the workflow', + }, }, { type: 'body', + schema: WorkflowExtensionSchema, }, ], response: Type.Any(), }) @ApiResponse({ - status: 200, + description: 'The user records', schema: WorkflowExtensionSchema, + example: putPluginsExampleResponse, }) @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException }) async addPlugins( - @common.Param('id') id: Static, + @common.Param('workflow_definition_id') + workflowDefinitionId: Static, @common.Body() body: Static, @CurrentProject() projectId: TProjectId, + @common.Response() res: Response, ) { - const result = await this.workflowDefinitionService.upgradeDefinitionVersion( - id, + const upgradedWorkflowDef = await this.workflowDefinitionService.upgradeDefinitionVersion( + workflowDefinitionId, { extensions: body as InputJsonValue, }, projectId, ); - return result; + if (upgradedWorkflowDef?.extensions) { + return res.json(upgradedWorkflowDef.extensions); + } + return res.status(HttpStatus.NOT_FOUND).send(); } @common.Get('/:id')