rez_core 2.2.227 → 2.2.228

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/app.module.js +0 -2
  2. package/dist/app.module.js.map +1 -1
  3. package/dist/constant/global.constant.d.ts +1 -0
  4. package/dist/constant/global.constant.js +2 -1
  5. package/dist/constant/global.constant.js.map +1 -1
  6. package/dist/core.module.js +3 -0
  7. package/dist/core.module.js.map +1 -1
  8. package/dist/module/enterprise/enterprise.module.js +1 -1
  9. package/dist/module/filter/filter.module.js +3 -1
  10. package/dist/module/filter/filter.module.js.map +1 -1
  11. package/dist/module/filter/service/filter-evaluator.service.d.ts +9 -0
  12. package/dist/module/filter/service/filter-evaluator.service.js +61 -0
  13. package/dist/module/filter/service/filter-evaluator.service.js.map +1 -0
  14. package/dist/module/filter/service/saved-filter.service.d.ts +1 -1
  15. package/dist/module/filter/service/saved-filter.service.js.map +1 -1
  16. package/dist/module/meta/controller/entity.controller.d.ts +3 -1
  17. package/dist/module/meta/controller/entity.controller.js +11 -4
  18. package/dist/module/meta/controller/entity.controller.js.map +1 -1
  19. package/dist/module/meta/entity.module.js +2 -0
  20. package/dist/module/meta/entity.module.js.map +1 -1
  21. package/dist/module/meta/service/entity-service-impl.service.js +2 -1
  22. package/dist/module/meta/service/entity-service-impl.service.js.map +1 -1
  23. package/dist/module/user/service/user.service.d.ts +2 -0
  24. package/dist/module/user/service/user.service.js +4 -0
  25. package/dist/module/user/service/user.service.js.map +1 -1
  26. package/dist/module/workflow-automation/entity/workflow-automation-action.entity.d.ts +9 -0
  27. package/dist/module/workflow-automation/entity/workflow-automation-action.entity.js +47 -0
  28. package/dist/module/workflow-automation/entity/workflow-automation-action.entity.js.map +1 -0
  29. package/dist/module/workflow-automation/entity/workflow-automation.entity.d.ts +0 -1
  30. package/dist/module/workflow-automation/entity/workflow-automation.entity.js +0 -4
  31. package/dist/module/workflow-automation/entity/workflow-automation.entity.js.map +1 -1
  32. package/dist/module/workflow-automation/interface/action.decorator.d.ts +2 -0
  33. package/dist/module/workflow-automation/interface/action.decorator.js +8 -0
  34. package/dist/module/workflow-automation/interface/action.decorator.js.map +1 -0
  35. package/dist/module/workflow-automation/interface/action.interface.d.ts +4 -0
  36. package/dist/module/workflow-automation/interface/action.interface.js +3 -0
  37. package/dist/module/workflow-automation/interface/action.interface.js.map +1 -0
  38. package/dist/module/workflow-automation/service/action-registery.service.d.ts +11 -0
  39. package/dist/module/workflow-automation/service/action-registery.service.js +46 -0
  40. package/dist/module/workflow-automation/service/action-registery.service.js.map +1 -0
  41. package/dist/module/workflow-automation/service/workflow-automation-engine.service.d.ts +12 -0
  42. package/dist/module/workflow-automation/service/workflow-automation-engine.service.js +60 -0
  43. package/dist/module/workflow-automation/service/workflow-automation-engine.service.js.map +1 -0
  44. package/dist/module/workflow-automation/service/workflow-automation.service.d.ts +13 -5
  45. package/dist/module/workflow-automation/service/workflow-automation.service.js +42 -7
  46. package/dist/module/workflow-automation/service/workflow-automation.service.js.map +1 -1
  47. package/dist/module/workflow-automation/workflow-automation.module.js +16 -3
  48. package/dist/module/workflow-automation/workflow-automation.module.js.map +1 -1
  49. package/dist/tsconfig.build.tsbuildinfo +1 -1
  50. package/package.json +1 -1
  51. package/src/app.module.ts +0 -1
  52. package/src/constant/global.constant.ts +1 -0
  53. package/src/core.module.ts +3 -0
  54. package/src/module/enterprise/enterprise.module.ts +1 -1
  55. package/src/module/filter/filter.module.ts +4 -1
  56. package/src/module/filter/service/filter-evaluator.service.ts +86 -0
  57. package/src/module/filter/service/saved-filter.service.ts +4 -3
  58. package/src/module/meta/controller/entity.controller.ts +23 -2
  59. package/src/module/meta/entity.module.ts +2 -0
  60. package/src/module/meta/service/entity-service-impl.service.ts +5 -1
  61. package/src/module/user/service/user.service.ts +7 -0
  62. package/src/module/workflow-automation/entity/workflow-automation-action.entity.ts +26 -0
  63. package/src/module/workflow-automation/entity/workflow-automation.entity.ts +0 -3
  64. package/src/module/workflow-automation/interface/action.decorator.ts +7 -0
  65. package/src/module/workflow-automation/interface/action.interface.ts +5 -0
  66. package/src/module/workflow-automation/service/action-registery.service.ts +35 -0
  67. package/src/module/workflow-automation/service/workflow-automation-engine.service.ts +76 -0
  68. package/src/module/workflow-automation/service/workflow-automation.service.ts +53 -5
  69. package/src/module/workflow-automation/workflow-automation.module.ts +16 -3
  70. package/src/module/user/test/user.controller.spec.ts +0 -61
  71. package/src/module/user/test/user.service.spec.ts +0 -62
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rez_core",
3
- "version": "2.2.227",
3
+ "version": "2.2.228",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
package/src/app.module.ts CHANGED
@@ -42,7 +42,6 @@ import { WorkflowAutomationModule } from './module/workflow-automation/workflow-
42
42
  DashboardModule,
43
43
  CommunicationModule,
44
44
  AuthModule,
45
- WorkflowAutomationModule,
46
45
  ScheduleModule.forRoot(),
47
46
  ],
48
47
  })
@@ -48,6 +48,7 @@ export const STAGE = 'WFS';
48
48
  export const STAGE_GROUP = 'WFSG';
49
49
  export const ACTION_CATEGORY = 'WFAC';
50
50
  export const WORKFLOW_AUTOMATION = 'WFAM';
51
+ export const WORKFLOW_AUTOMATION_ACTION = 'WFAA';
51
52
  export const STAGE_ACTION_MAPPING = 'WFSA';
52
53
  export const COMM_TEMPLATE = 'TEM';
53
54
  export const ACTION_TEMPLATE_MAPPING = 'WFAT';
@@ -14,6 +14,7 @@ import { AuthModule } from './module/auth/auth.module';
14
14
  import { LeadModule } from './module/lead/lead.module';
15
15
  import { LayoutPreferenceModule } from './module/layout_preference/layout_preference.module';
16
16
  import { WorkflowModule } from './module/workflow/workflow.module';
17
+ import { WorkflowAutomationModule } from './module/workflow-automation/workflow-automation.module';
17
18
 
18
19
  @Global()
19
20
  @Module({})
@@ -35,6 +36,7 @@ export class CoreModule {
35
36
  LeadModule,
36
37
  LayoutPreferenceModule,
37
38
  WorkflowModule,
39
+ WorkflowAutomationModule
38
40
  ];
39
41
 
40
42
  const exportsArray = [
@@ -49,6 +51,7 @@ export class CoreModule {
49
51
  LeadModule,
50
52
  LayoutPreferenceModule,
51
53
  WorkflowModule,
54
+ WorkflowAutomationModule
52
55
  ];
53
56
 
54
57
  if (isSso) {
@@ -16,7 +16,7 @@ import { SchoolRepository } from './repository/school.repository';
16
16
  TypeOrmModule.forFeature([OrganizationData, OrganizationAppMapping]),
17
17
  forwardRef(() => UserModule),
18
18
  UtilsModule,
19
- EntityModule,
19
+ EntityModule
20
20
  ],
21
21
  controllers: [OrganizationController],
22
22
  providers: [
@@ -7,18 +7,21 @@ import { SavedFilterRepositoryService } from './repository/saved-filter.reposito
7
7
  import { EntityModule } from '../meta/entity.module';
8
8
  import { FilterService } from './service/filter.service';
9
9
  import { FilterController } from './controller/filter.controller';
10
+ import { FilterEvaluatorService } from './service/filter-evaluator.service';
10
11
 
11
12
  @Module({
12
13
  imports: [
13
14
  TypeOrmModule.forFeature([SavedFilterDetail, SavedFilterMaster]),
14
15
  forwardRef(() => EntityModule),
16
+
15
17
  ],
16
18
  controllers: [FilterController],
17
19
  providers: [
18
20
  { provide: 'SavedFilterService', useClass: SavedFilterService },
19
21
  SavedFilterRepositoryService,
20
22
  FilterService,
23
+ FilterEvaluatorService
21
24
  ],
22
- exports: ['SavedFilterService', SavedFilterRepositoryService, FilterService],
25
+ exports: ['SavedFilterService', SavedFilterRepositoryService, FilterService,FilterEvaluatorService],
23
26
  })
24
27
  export class FilterModule {}
@@ -0,0 +1,86 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { DataSource } from 'typeorm';
3
+ import { SavedFilterDetail } from 'src/module/filter/entity/saved-filter-detail.entity';
4
+ import { FilterService } from './filter.service';
5
+
6
+ @Injectable()
7
+ export class FilterEvaluatorService {
8
+ constructor(
9
+ private readonly dataSource: DataSource,
10
+ private readonly filterService: FilterService,
11
+ ) {}
12
+
13
+ /**
14
+ * Check if any of the trigger attributes are modified in this event.
15
+ * @param oldEntity previous state
16
+ * @param newEntity new state
17
+ * @param savedFilterCode code of saved filter that contains trigger attributes
18
+ * @returns true if at least one trigger attribute changed (and optionally matches value)
19
+ */
20
+ async evaluateTriggerAttributes(
21
+ oldEntity: Record<string, any> | null,
22
+ newEntity: Record<string, any>,
23
+ savedFilterCode: string,
24
+ ): Promise<boolean> {
25
+ // Fetch trigger filter details
26
+ const triggerFilters: SavedFilterDetail[] = await this.dataSource.query(
27
+ `SELECT *
28
+ FROM cr_saved_filter_detail
29
+ WHERE mapped_filter_code = ?`,
30
+ [savedFilterCode],
31
+ );
32
+
33
+ // If no trigger filters defined, just return true (so criteria can run)
34
+ if (!triggerFilters || triggerFilters.length === 0) {
35
+ return true;
36
+ }
37
+
38
+ const oldState = oldEntity || {};
39
+
40
+ // Check each trigger attribute
41
+ for (const filter of triggerFilters) {
42
+ const attr = filter.filter_attribute;
43
+ const expectedValue = filter.filter_value;
44
+
45
+ const oldVal = oldState[attr];
46
+ const newVal = newEntity[attr];
47
+
48
+ // If value changed and (no expected value defined OR matches expected)
49
+ if (oldVal !== newVal && (!expectedValue || newVal == expectedValue)) {
50
+ return true;
51
+ }
52
+ }
53
+
54
+ // No trigger attribute matched
55
+ return false;
56
+ }
57
+
58
+ /**
59
+ * Evaluate the criteria for an entity using the filter service
60
+ * @param entityType type of entity
61
+ * @param entityId id of entity to evaluate
62
+ * @param criteriaFilterCode saved filter code for criteria
63
+ * @param filterService instance of your FilterService
64
+ */
65
+ async evaluateCriteria(
66
+ entityType: string,
67
+ criteriaFilterCode: string,
68
+ entityId: number,
69
+ loggedInUser: any,
70
+ ): Promise<boolean> {
71
+ if (!criteriaFilterCode) return true; // no criteria = always true
72
+
73
+ const filterRequest = {
74
+ entity_type: entityType,
75
+ savedFilterCode: criteriaFilterCode,
76
+ queryParams: { id: entityId },
77
+ page: 1,
78
+ size: 1,
79
+ loggedInUser: loggedInUser || { organization_id: null },
80
+ } as any;
81
+
82
+ const result = await this.filterService.applyFilter(filterRequest);
83
+
84
+ return result?.data?.entity_list?.length > 0;
85
+ }
86
+ }
@@ -1,5 +1,5 @@
1
- import { BadRequestException, Injectable } from '@nestjs/common';
2
- import { EntityServiceImpl } from '../../meta/service/entity-service-impl.service';
1
+ import { BadRequestException, forwardRef, Inject, Injectable } from '@nestjs/common';
2
+ import { EntityServiceImpl } from 'src/module/meta/service/entity-service-impl.service';
3
3
  import { BaseEntity } from '../../meta/entity/base-entity.entity';
4
4
  import { UserData } from '../../user/entity/user.entity';
5
5
  import { SavedFilterMaster } from '../entity/saved-filter-master.entity';
@@ -9,7 +9,8 @@ import { SavedFilterRepositoryService } from '../repository/saved-filter.reposit
9
9
 
10
10
  @Injectable()
11
11
  export class SavedFilterService extends EntityServiceImpl {
12
- constructor(private readonly savedFilterRepo: SavedFilterRepositoryService) {
12
+ constructor(private readonly savedFilterRepo: SavedFilterRepositoryService
13
+ ) {
13
14
  super();
14
15
  }
15
16
 
@@ -27,6 +27,7 @@ import * as path from 'path';
27
27
  import { UserService } from '../../user/service/user.service';
28
28
  import { ENTITYTYPE_USER } from '../../../constant/global.constant';
29
29
  import { UserData } from '../../user/entity/user.entity';
30
+ import { WorkflowAutomationEngineService } from 'src/module/workflow-automation/service/workflow-automation-engine.service';
30
31
 
31
32
  @UseGuards(JwtAuthGuard)
32
33
  @Controller('entity')
@@ -35,6 +36,7 @@ export class EntityController {
35
36
  private entityService: EntityServiceImpl,
36
37
  private reflectionHelper: ReflectionHelper,
37
38
  private entityMasterService: EntityMasterService,
39
+ private readonly workflowAutomationEngineService: WorkflowAutomationEngineService,
38
40
  ) {}
39
41
 
40
42
  @Get('getById/:id')
@@ -163,12 +165,22 @@ export class EntityController {
163
165
  );
164
166
  }
165
167
 
166
- return entityService.createEntity(
168
+ let savedData = await entityService.createEntity(
167
169
  entityData,
168
170
  loggedInUser as UserData,
169
171
  null,
170
172
  appcode,
171
173
  );
174
+
175
+ await this.workflowAutomationEngineService.handleEntityEvent(
176
+ entityData.entity_type,
177
+ 'CREATE',
178
+ entityData,
179
+ null,
180
+ loggedInUser,
181
+ );
182
+
183
+ return savedData;
172
184
  }
173
185
 
174
186
  @Post('update/:id')
@@ -213,11 +225,20 @@ export class EntityController {
213
225
  throw new NotFoundException(`No entity found for id "${id}"`);
214
226
  }
215
227
 
216
- return await entityService.updateEntity(
228
+ let updatedData = await entityService.updateEntity(
217
229
  entityData,
218
230
  loggedInUser as UserData,
219
231
  );
220
232
 
233
+ await this.workflowAutomationEngineService.handleEntityEvent(
234
+ entityData.entity_type,
235
+ 'UPDATE',
236
+ entityData,
237
+ existingEntity,
238
+ loggedInUser,
239
+ );
240
+
241
+ return updatedData;
221
242
  // return {
222
243
  // success: true,
223
244
  // data: updatedEntity,
@@ -58,6 +58,7 @@ import { EntityRelationController } from './controller/entity-relation.controlle
58
58
  import { CommonService } from './service/common.service';
59
59
  import { EntityMasterRepository } from './repository/entity-master.repository';
60
60
  import { EntityMasterController } from './controller/entity-master.controller';
61
+ import { WorkflowAutomationModule } from '../workflow-automation/workflow-automation.module';
61
62
 
62
63
  @Module({
63
64
  imports: [
@@ -77,6 +78,7 @@ import { EntityMasterController } from './controller/entity-master.controller';
77
78
  forwardRef(() => ListMasterModule),
78
79
  forwardRef(() => FilterModule),
79
80
  UtilsModule,
81
+ WorkflowAutomationModule
80
82
  ],
81
83
  providers: [
82
84
  EntityMasterService,
@@ -1,6 +1,7 @@
1
1
  import { EntityService } from './entity.service';
2
2
  import {
3
3
  BadRequestException,
4
+ forwardRef,
4
5
  Inject,
5
6
  Injectable,
6
7
  NotFoundException,
@@ -30,6 +31,7 @@ import { ListMasterItemService } from 'src/module/listmaster/service/list-master
30
31
  import { AttributeMasterService } from './attribute-master.service';
31
32
  import { ResolverService } from './resolver.service';
32
33
  import { NotFound } from '@aws-sdk/client-s3';
34
+ import { WorkflowAutomationEngineService } from 'src/module/workflow-automation/service/workflow-automation-engine.service';
33
35
 
34
36
  @Injectable()
35
37
  export class EntityServiceImpl implements EntityService<BaseEntity> {
@@ -124,7 +126,9 @@ export class EntityServiceImpl implements EntityService<BaseEntity> {
124
126
  if (!entityData.status) entityData.status = statusList[0].id;
125
127
  }
126
128
 
127
- return repo.save(entityData);
129
+ let savedData = repo.save(entityData);
130
+
131
+ return savedData;
128
132
  }
129
133
 
130
134
  async deleteEntity(entityType: string, entityId: number, loggedInUser) {
@@ -27,6 +27,8 @@ import { ServiceResult } from 'src/dtos/response.dto';
27
27
  import { ListMasterService } from 'src/module/listmaster/service/list-master.service';
28
28
  import { OrganizationRepository } from 'src/module/enterprise/repository/organization.repository';
29
29
  import { InjectRepository } from '@nestjs/typeorm';
30
+ import { Action } from 'src/module/workflow-automation/interface/action.interface';
31
+ import { ActionHandler } from 'src/module/workflow-automation/interface/action.decorator';
30
32
 
31
33
  @Injectable()
32
34
  export class UserService extends EntityServiceImpl {
@@ -135,6 +137,11 @@ export class UserService extends EntityServiceImpl {
135
137
  return { success: true, data: savedData };
136
138
  }
137
139
 
140
+ name : string = 'UserService';
141
+ async execute(payload: any): Promise<any> {
142
+ console.log('payload', payload);
143
+ }
144
+
138
145
  async getEntityData(
139
146
  entityType: string,
140
147
  id: number,
@@ -0,0 +1,26 @@
1
+ import { WORKFLOW_AUTOMATION_ACTION } from 'src/constant/global.constant';
2
+ import { BaseEntity } from 'src/module/meta/entity/base-entity.entity';
3
+ import { Column, Entity } from 'typeorm';
4
+
5
+ @Entity({ name: 'cr_workflow_automation_action' })
6
+ export class WorkflowAutomationActionEntity extends BaseEntity {
7
+ constructor() {
8
+ super();
9
+ this.entity_type = WORKFLOW_AUTOMATION_ACTION;
10
+ }
11
+
12
+ @Column({ type: 'int', nullable: true })
13
+ workflow_automation_id: number;
14
+
15
+ @Column({ type: 'int', nullable: true })
16
+ action_category_id: number;
17
+
18
+ @Column({ type: 'varchar', nullable: true })
19
+ payload: string;
20
+
21
+ @Column({ type: 'varchar', nullable: true })
22
+ action_decorator: string;
23
+
24
+ @Column({ type: 'varchar', nullable: true })
25
+ entity_method: string;
26
+ }
@@ -23,7 +23,4 @@ export class WorkflowAutomation extends BaseEntity {
23
23
 
24
24
  @Column({ type: 'varchar', nullable: true })
25
25
  criteria_filter_code: string;
26
-
27
- @Column({ nullable: true })
28
- is_active: boolean;
29
26
  }
@@ -0,0 +1,7 @@
1
+ // src/module/workflow-automation/interface/action.decorator.ts
2
+ import { SetMetadata } from '@nestjs/common';
3
+
4
+ export const ACTION_HANDLER = 'ACTION_HANDLER';
5
+
6
+ export const ActionHandler = (actionName: string) =>
7
+ SetMetadata(ACTION_HANDLER, actionName);
@@ -0,0 +1,5 @@
1
+ // package/src/interfaces/action.interface.ts
2
+ export interface Action {
3
+ name: string; // unique identifier of the action
4
+ execute(payload: any): Promise<any>; // execution logic
5
+ }
@@ -0,0 +1,35 @@
1
+ // src/module/workflow-automation/service/action-registry.service.ts
2
+ import { Injectable, OnModuleInit } from '@nestjs/common';
3
+ import { DiscoveryService, ModuleRef, Reflector } from '@nestjs/core';
4
+ import { WorkflowAutomationEngineService } from './workflow-automation-engine.service';
5
+ import { Action } from '../interface/action.interface';
6
+ import { ACTION_HANDLER } from '../interface/action.decorator';
7
+
8
+ @Injectable()
9
+ export class ActionRegistryService implements OnModuleInit {
10
+ constructor(
11
+ private readonly discoveryService: DiscoveryService,
12
+ private readonly moduleRef: ModuleRef,
13
+ private readonly reflector: Reflector,
14
+ private readonly engine: WorkflowAutomationEngineService,
15
+ ) {}
16
+
17
+ onModuleInit() {
18
+ const providers = this.discoveryService.getProviders();
19
+
20
+ for (const wrapper of providers) {
21
+ const { instance } = wrapper;
22
+ if (!instance) continue;
23
+
24
+ const actionName = this.reflector.get<string>(
25
+ ACTION_HANDLER,
26
+ instance.constructor,
27
+ );
28
+
29
+ if (actionName) {
30
+ this.engine.registerAction(actionName, instance as Action);
31
+ console.log(`✅ Registered action handler: ${actionName}`);
32
+ }
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,76 @@
1
+ // package/src/services/workflow-automation-engine.service.ts
2
+ import { Injectable, Inject } from '@nestjs/common';
3
+ import { WorkflowAutomationService } from './workflow-automation.service';
4
+ import { FilterEvaluatorService } from '../../filter/service/filter-evaluator.service';
5
+ import { Action } from '../interface/action.interface';
6
+
7
+ @Injectable()
8
+ export class WorkflowAutomationEngineService {
9
+ private readonly actions = new Map<string, Action>();
10
+
11
+ constructor(
12
+ @Inject('WorkflowAutomationService')
13
+ private readonly wfService: WorkflowAutomationService,
14
+ private readonly filterEvaluator: FilterEvaluatorService,
15
+ ) {}
16
+
17
+ registerAction(actionName: string, actionInstance: Action) {
18
+ this.actions.set(actionName, actionInstance);
19
+ }
20
+
21
+ /**
22
+ * Called from entity hooks (CREATE / UPDATE / DELETE)
23
+ */
24
+ async handleEntityEvent(entityType, eventType, newEntity, oldEntity, user) {
25
+ const workflows = await this.wfService.getActiveRules(
26
+ entityType,
27
+ eventType,
28
+ );
29
+
30
+ for (const wf of workflows) {
31
+ const eventMatched = await this.filterEvaluator.evaluateTriggerAttributes(
32
+ oldEntity,
33
+ newEntity,
34
+ wf.condition_filter_code,
35
+ );
36
+ if (!eventMatched) continue;
37
+
38
+ const criteriaMatched = await this.filterEvaluator.evaluateCriteria(
39
+ entityType,
40
+ wf.criteria_filter_code,
41
+ newEntity.id,
42
+ user,
43
+ );
44
+ if (!criteriaMatched) continue;
45
+
46
+ await this.executeActions(wf.id, newEntity, user);
47
+ }
48
+ }
49
+
50
+ private async executeActions(
51
+ workflow_automation_id: number,
52
+ entity: any,
53
+ user: any,
54
+ ) {
55
+ // 1. Load actions for this rule from DB
56
+ const actions = await this.wfService.getActionsForRule(
57
+ workflow_automation_id,
58
+ );
59
+ // (this should fetch from cr_workflow_automation_action)
60
+
61
+ for (const action of actions) {
62
+ const impl = this.actions.get(String(action.action_decorator)); // action_code = registered name
63
+ if (!impl) {
64
+ console.warn(
65
+ `⚠️ No implementation found for action: ${action.action_decorator}`,
66
+ );
67
+ continue;
68
+ }
69
+
70
+ console.log(
71
+ `🚀 Executing action ${action.action_decorator} for entity ${entity.id}`,
72
+ );
73
+ await impl.execute({ entity, user, config: action.payload });
74
+ }
75
+ }
76
+ }
@@ -1,10 +1,58 @@
1
1
  import { Injectable } from '@nestjs/common';
2
- import { EntityServiceImpl } from 'src/module/meta/service/entity-service-impl.service';
3
- import { DataSource } from 'typeorm';
2
+ import { InjectRepository } from '@nestjs/typeorm';
3
+ import { Repository } from 'typeorm';
4
+ import { WorkflowAutomation } from '../entity/workflow-automation.entity';
5
+ import { WorkflowAutomationActionEntity } from '../entity/workflow-automation-action.entity';
4
6
 
5
7
  @Injectable()
6
- export class WorkflowAutomationService extends EntityServiceImpl {
7
- constructor(private readonly dataSource: DataSource) {
8
- super();
8
+ export class WorkflowAutomationService {
9
+ constructor(
10
+ @InjectRepository(WorkflowAutomation)
11
+ private readonly wfRepo: Repository<WorkflowAutomation>,
12
+ @InjectRepository(WorkflowAutomationActionEntity)
13
+ private readonly actionRepo: Repository<WorkflowAutomationActionEntity>,
14
+ ) {}
15
+
16
+ async createRule(
17
+ data: Partial<WorkflowAutomation>,
18
+ ): Promise<WorkflowAutomation> {
19
+ const rule = this.wfRepo.create(data);
20
+ return this.wfRepo.save(rule);
21
+ }
22
+
23
+ async updateRule(
24
+ id: number,
25
+ data: Partial<WorkflowAutomation>,
26
+ ): Promise<WorkflowAutomation | null> {
27
+ await this.wfRepo.update(id, data);
28
+ return this.wfRepo.findOneBy({ id });
29
+ }
30
+
31
+ async deleteRule(id: number): Promise<void> {
32
+ await this.wfRepo.delete(id);
33
+ }
34
+
35
+ async getRule(id: number): Promise<WorkflowAutomation | null> {
36
+ return this.wfRepo.findOneBy({ id });
37
+ }
38
+
39
+ async getActiveRules(
40
+ entityType: string,
41
+ event: string,
42
+ ): Promise<WorkflowAutomation[]> {
43
+ return this.wfRepo.find({
44
+ where: {
45
+ mapped_entity_type: entityType,
46
+ trigger_event: event,
47
+ },
48
+ });
49
+ }
50
+
51
+ async getActionsForRule(
52
+ workflow_automation_id: number,
53
+ ): Promise<WorkflowAutomationActionEntity[]> {
54
+ return this.actionRepo.find({
55
+ where: { workflow_automation_id },
56
+ });
9
57
  }
10
58
  }
@@ -1,19 +1,32 @@
1
1
  import { Module } from '@nestjs/common';
2
2
  import { TypeOrmModule } from '@nestjs/typeorm';
3
+ import { DiscoveryModule } from '@nestjs/core';
3
4
  import { WorkflowAutomation } from './entity/workflow-automation.entity';
4
5
  import { WorkflowAutomationController } from './controller/workflow-automation.controller';
6
+ import { WorkflowAutomationEngineService } from './service/workflow-automation-engine.service';
7
+ import { FilterModule } from '../filter/filter.module';
5
8
  import { WorkflowAutomationService } from './service/workflow-automation.service';
6
- import { EntityModule } from '../meta/entity.module';
9
+ import { WorkflowAutomationActionEntity } from './entity/workflow-automation-action.entity';
10
+ import { ActionRegistryService } from './service/action-registery.service';
7
11
 
8
12
  @Module({
9
- imports: [TypeOrmModule.forFeature([WorkflowAutomation]), EntityModule],
13
+ imports: [
14
+ TypeOrmModule.forFeature([
15
+ WorkflowAutomation,
16
+ WorkflowAutomationActionEntity,
17
+ ]),
18
+ FilterModule,
19
+ DiscoveryModule, // 👈 enables provider scanning
20
+ ],
10
21
  providers: [
22
+ WorkflowAutomationEngineService,
11
23
  {
12
24
  provide: 'WorkflowAutomationService',
13
25
  useClass: WorkflowAutomationService,
14
26
  },
27
+ ActionRegistryService, // 👈 auto-registers actions
15
28
  ],
16
- exports: [],
29
+ exports: [WorkflowAutomationEngineService, 'WorkflowAutomationService'],
17
30
  controllers: [WorkflowAutomationController],
18
31
  })
19
32
  export class WorkflowAutomationModule {}
@@ -1,61 +0,0 @@
1
- import { Test, TestingModule } from '@nestjs/testing';
2
- import { UserService } from '../service/user.service';
3
- import { ForbiddenException } from '@nestjs/common';
4
- import { UserController } from '../controller/user.controller';
5
-
6
- describe('UserController', () => {
7
- let userController: UserController;
8
- let userService: UserService;
9
-
10
- beforeEach(async () => {
11
- const module: TestingModule = await Test.createTestingModule({
12
- controllers: [UserController],
13
- providers: [
14
- {
15
- provide: 'UserService',
16
- useValue: {
17
- checkEmailExists: jest.fn(),
18
- },
19
- },
20
- ],
21
- }).compile();
22
-
23
- userController = module.get<UserController>(UserController);
24
- userService = module.get<UserService>('UserService');
25
- });
26
-
27
- describe('checkEmail', () => {
28
- it('✅ should return success response when email exists', async () => {
29
- const mockResponse = {
30
- success: true,
31
- message:
32
- 'An account already exists for this email address. Login or use a different email address to sign up.',
33
- userId: 101,
34
- };
35
-
36
- (userService.checkEmailExists as jest.Mock).mockResolvedValue(
37
- mockResponse,
38
- );
39
-
40
- const result = await userController.checkEmail('test@example.com');
41
-
42
- expect(result).toEqual(mockResponse);
43
- expect(userService.checkEmailExists).toHaveBeenCalledWith(
44
- 'test@example.com',
45
- );
46
- });
47
-
48
- it('❌ should throw ForbiddenException when email does not exist', async () => {
49
- (userService.checkEmailExists as jest.Mock).mockRejectedValue(
50
- new ForbiddenException('No account found with this email address.'),
51
- );
52
-
53
- await expect(
54
- userController.checkEmail('notfound@example.com'),
55
- ).rejects.toThrow(ForbiddenException);
56
- expect(userService.checkEmailExists).toHaveBeenCalledWith(
57
- 'notfound@example.com',
58
- );
59
- });
60
- });
61
- });