rez_core 4.0.184 → 4.0.187

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 (197) hide show
  1. package/dist/app.module.js +11 -0
  2. package/dist/app.module.js.map +1 -1
  3. package/dist/config/bull.config.d.ts +10 -0
  4. package/dist/config/bull.config.js +66 -0
  5. package/dist/config/bull.config.js.map +1 -0
  6. package/dist/config/database.config.js +1 -1
  7. package/dist/config/database.config.js.map +1 -1
  8. package/dist/module/entity_json/controller/entity_json.controller.d.ts +8 -0
  9. package/dist/module/entity_json/controller/entity_json.controller.js +43 -0
  10. package/dist/module/entity_json/controller/entity_json.controller.js.map +1 -0
  11. package/dist/module/entity_json/entity_json.module.d.ts +2 -0
  12. package/dist/module/entity_json/entity_json.module.js +26 -0
  13. package/dist/module/entity_json/entity_json.module.js.map +1 -0
  14. package/dist/module/entity_json/service/entity_json.service.d.ts +7 -0
  15. package/dist/module/entity_json/service/entity_json.service.js +116 -0
  16. package/dist/module/entity_json/service/entity_json.service.js.map +1 -0
  17. package/dist/module/filter/service/filter.service.js.map +1 -1
  18. package/dist/module/integration/service/wrapper.service.d.ts +3 -1
  19. package/dist/module/integration/service/wrapper.service.js +39 -36
  20. package/dist/module/integration/service/wrapper.service.js.map +1 -1
  21. package/dist/module/linked_attributes/controller/linked_attributes.controller.d.ts +5 -0
  22. package/dist/module/linked_attributes/controller/linked_attributes.controller.js +29 -0
  23. package/dist/module/linked_attributes/controller/linked_attributes.controller.js.map +1 -0
  24. package/dist/module/linked_attributes/entity/linked_attribute.entity.d.ts +9 -0
  25. package/dist/module/linked_attributes/entity/linked_attribute.entity.js +70 -0
  26. package/dist/module/linked_attributes/entity/linked_attribute.entity.js.map +1 -0
  27. package/dist/module/linked_attributes/linked_attributes.module.d.ts +2 -0
  28. package/dist/module/linked_attributes/linked_attributes.module.js +29 -0
  29. package/dist/module/linked_attributes/linked_attributes.module.js.map +1 -0
  30. package/dist/module/linked_attributes/repository/linked_attribute.repository.d.ts +6 -0
  31. package/dist/module/linked_attributes/repository/linked_attribute.repository.js +31 -0
  32. package/dist/module/linked_attributes/repository/linked_attribute.repository.js.map +1 -0
  33. package/dist/module/linked_attributes/service/linked_attributes.service.d.ts +5 -0
  34. package/dist/module/linked_attributes/service/linked_attributes.service.js +34 -0
  35. package/dist/module/linked_attributes/service/linked_attributes.service.js.map +1 -0
  36. package/dist/module/mapper/service/field-mapper.service.js +2 -2
  37. package/dist/module/mapper/service/field-mapper.service.js.map +1 -1
  38. package/dist/module/meta/controller/attribute-master.controller.d.ts +10 -1
  39. package/dist/module/meta/controller/attribute-master.controller.js +27 -2
  40. package/dist/module/meta/controller/attribute-master.controller.js.map +1 -1
  41. package/dist/module/meta/controller/entity-master.controller.d.ts +6 -0
  42. package/dist/module/meta/controller/entity-master.controller.js +13 -0
  43. package/dist/module/meta/controller/entity-master.controller.js.map +1 -1
  44. package/dist/module/meta/entity.module.js +7 -0
  45. package/dist/module/meta/entity.module.js.map +1 -1
  46. package/dist/module/meta/repository/attribute-master.repository.d.ts +4 -0
  47. package/dist/module/meta/repository/attribute-master.repository.js +19 -0
  48. package/dist/module/meta/repository/attribute-master.repository.js.map +1 -1
  49. package/dist/module/meta/repository/entity-attribute-update.repository.d.ts +6 -0
  50. package/dist/module/meta/repository/entity-attribute-update.repository.js +44 -0
  51. package/dist/module/meta/repository/entity-attribute-update.repository.js.map +1 -0
  52. package/dist/module/meta/repository/entity-master.repository.d.ts +7 -1
  53. package/dist/module/meta/repository/entity-master.repository.js +24 -2
  54. package/dist/module/meta/repository/entity-master.repository.js.map +1 -1
  55. package/dist/module/meta/service/attribute-master.service.d.ts +4 -0
  56. package/dist/module/meta/service/attribute-master.service.js +3 -0
  57. package/dist/module/meta/service/attribute-master.service.js.map +1 -1
  58. package/dist/module/meta/service/entity-attribute-update.service.d.ts +7 -0
  59. package/dist/module/meta/service/entity-attribute-update.service.js +35 -0
  60. package/dist/module/meta/service/entity-attribute-update.service.js.map +1 -0
  61. package/dist/module/meta/service/entity-master.service.d.ts +4 -0
  62. package/dist/module/meta/service/entity-master.service.js +3 -0
  63. package/dist/module/meta/service/entity-master.service.js.map +1 -1
  64. package/dist/module/meta/service/resolver.service.js +2 -2
  65. package/dist/module/meta/service/resolver.service.js.map +1 -1
  66. package/dist/module/module/service/module-access.service.js +1 -7
  67. package/dist/module/module/service/module-access.service.js.map +1 -1
  68. package/dist/module/workflow/entity/action.entity.d.ts +1 -0
  69. package/dist/module/workflow/entity/action.entity.js +4 -0
  70. package/dist/module/workflow/entity/action.entity.js.map +1 -1
  71. package/dist/module/workflow/repository/action-data.repository.js +1 -0
  72. package/dist/module/workflow/repository/action-data.repository.js.map +1 -1
  73. package/dist/module/workflow/repository/task.repository.d.ts +3 -1
  74. package/dist/module/workflow/repository/task.repository.js +6 -1
  75. package/dist/module/workflow/repository/task.repository.js.map +1 -1
  76. package/dist/module/workflow/service/task.service.js +41 -27
  77. package/dist/module/workflow/service/task.service.js.map +1 -1
  78. package/dist/module/workflow/service/workflow-meta.service.js +23 -21
  79. package/dist/module/workflow/service/workflow-meta.service.js.map +1 -1
  80. package/dist/module/workflow-automation/controller/workflow-automation.controller.d.ts +6 -0
  81. package/dist/module/workflow-automation/controller/workflow-automation.controller.js +16 -0
  82. package/dist/module/workflow-automation/controller/workflow-automation.controller.js.map +1 -1
  83. package/dist/module/workflow-automation/entity/workflow-automation.entity.d.ts +2 -0
  84. package/dist/module/workflow-automation/entity/workflow-automation.entity.js +8 -0
  85. package/dist/module/workflow-automation/entity/workflow-automation.entity.js.map +1 -1
  86. package/dist/module/workflow-automation/service/schedule-handler.service.d.ts +16 -0
  87. package/dist/module/workflow-automation/service/schedule-handler.service.js +109 -0
  88. package/dist/module/workflow-automation/service/schedule-handler.service.js.map +1 -0
  89. package/dist/module/workflow-automation/service/workflow-automation-engine.service.d.ts +1 -1
  90. package/dist/module/workflow-automation/service/workflow-automation-engine.service.js.map +1 -1
  91. package/dist/module/workflow-automation/service/workflow-automation.service.d.ts +13 -1
  92. package/dist/module/workflow-automation/service/workflow-automation.service.js +111 -2
  93. package/dist/module/workflow-automation/service/workflow-automation.service.js.map +1 -1
  94. package/dist/module/workflow-automation/workflow-automation.module.js +14 -1
  95. package/dist/module/workflow-automation/workflow-automation.module.js.map +1 -1
  96. package/dist/module/workflow-schedule/constants/schedule.constants.d.ts +27 -0
  97. package/dist/module/workflow-schedule/constants/schedule.constants.js +31 -0
  98. package/dist/module/workflow-schedule/constants/schedule.constants.js.map +1 -0
  99. package/dist/module/workflow-schedule/controller/workflow-schedule.controller.d.ts +83 -0
  100. package/dist/module/workflow-schedule/controller/workflow-schedule.controller.js +220 -0
  101. package/dist/module/workflow-schedule/controller/workflow-schedule.controller.js.map +1 -0
  102. package/dist/module/workflow-schedule/dto/create-schedule.dto.d.ts +32 -0
  103. package/dist/module/workflow-schedule/dto/create-schedule.dto.js +163 -0
  104. package/dist/module/workflow-schedule/dto/create-schedule.dto.js.map +1 -0
  105. package/dist/module/workflow-schedule/dto/get-execution-logs.dto.d.ts +35 -0
  106. package/dist/module/workflow-schedule/dto/get-execution-logs.dto.js +124 -0
  107. package/dist/module/workflow-schedule/dto/get-execution-logs.dto.js.map +1 -0
  108. package/dist/module/workflow-schedule/dto/update-schedule.dto.d.ts +19 -0
  109. package/dist/module/workflow-schedule/dto/update-schedule.dto.js +106 -0
  110. package/dist/module/workflow-schedule/dto/update-schedule.dto.js.map +1 -0
  111. package/dist/module/workflow-schedule/entities/scheduled-workflow.entity.d.ts +30 -0
  112. package/dist/module/workflow-schedule/entities/scheduled-workflow.entity.js +113 -0
  113. package/dist/module/workflow-schedule/entities/scheduled-workflow.entity.js.map +1 -0
  114. package/dist/module/workflow-schedule/entities/workflow-execution-log.entity.d.ts +34 -0
  115. package/dist/module/workflow-schedule/entities/workflow-execution-log.entity.js +118 -0
  116. package/dist/module/workflow-schedule/entities/workflow-execution-log.entity.js.map +1 -0
  117. package/dist/module/workflow-schedule/interfaces/schedule-job-data.interface.d.ts +44 -0
  118. package/dist/module/workflow-schedule/interfaces/schedule-job-data.interface.js +3 -0
  119. package/dist/module/workflow-schedule/interfaces/schedule-job-data.interface.js.map +1 -0
  120. package/dist/module/workflow-schedule/interfaces/workflow-schedule-options.interface.d.ts +3 -0
  121. package/dist/module/workflow-schedule/interfaces/workflow-schedule-options.interface.js +3 -0
  122. package/dist/module/workflow-schedule/interfaces/workflow-schedule-options.interface.js.map +1 -0
  123. package/dist/module/workflow-schedule/processors/schedule.processor.d.ts +31 -0
  124. package/dist/module/workflow-schedule/processors/schedule.processor.js +409 -0
  125. package/dist/module/workflow-schedule/processors/schedule.processor.js.map +1 -0
  126. package/dist/module/workflow-schedule/service/workflow-schedule.service.d.ts +44 -0
  127. package/dist/module/workflow-schedule/service/workflow-schedule.service.js +434 -0
  128. package/dist/module/workflow-schedule/service/workflow-schedule.service.js.map +1 -0
  129. package/dist/module/workflow-schedule/workflow-schedule.module.d.ts +5 -0
  130. package/dist/module/workflow-schedule/workflow-schedule.module.js +52 -0
  131. package/dist/module/workflow-schedule/workflow-schedule.module.js.map +1 -0
  132. package/dist/table.config.d.ts +1 -1
  133. package/dist/tsconfig.build.tsbuildinfo +1 -1
  134. package/dist/utils/service/loggingUtil.service.d.ts +9 -2
  135. package/dist/utils/service/loggingUtil.service.js +65 -14
  136. package/dist/utils/service/loggingUtil.service.js.map +1 -1
  137. package/dist/utils/utils.module.js +2 -0
  138. package/dist/utils/utils.module.js.map +1 -1
  139. package/package.json +9 -4
  140. package/src/app.module.ts +16 -2
  141. package/src/config/bull.config.ts +69 -0
  142. package/src/config/database.config.ts +1 -1
  143. package/src/module/entity_json/controller/entity_json.controller.ts +47 -0
  144. package/src/module/entity_json/entity_json.module.ts +13 -0
  145. package/src/module/entity_json/service/entity_json.service.ts +162 -0
  146. package/src/module/filter/service/filter.service.ts +0 -2
  147. package/src/module/integration/service/wrapper.service.ts +248 -41
  148. package/src/module/linked_attributes/controller/linked_attributes.controller.ts +10 -0
  149. package/src/module/linked_attributes/entity/linked_attribute.entity.ts +48 -0
  150. package/src/module/linked_attributes/linked_attributes.module.ts +16 -0
  151. package/src/module/linked_attributes/repository/linked_attribute.repository.ts +12 -0
  152. package/src/module/linked_attributes/service/linked_attributes.service.ts +22 -0
  153. package/src/module/mapper/service/field-mapper.service.ts +12 -7
  154. package/src/module/meta/controller/attribute-master.controller.ts +20 -0
  155. package/src/module/meta/controller/entity-master.controller.ts +13 -0
  156. package/src/module/meta/entity.module.ts +8 -0
  157. package/src/module/meta/repository/attribute-master.repository.ts +20 -0
  158. package/src/module/meta/repository/entity-attribute-update.repository.ts +44 -0
  159. package/src/module/meta/repository/entity-master.repository.ts +30 -0
  160. package/src/module/meta/service/attribute-master.service.ts +4 -0
  161. package/src/module/meta/service/entity-attribute-update.service.ts +29 -0
  162. package/src/module/meta/service/entity-master.service.ts +6 -0
  163. package/src/module/meta/service/resolver.service.ts +2 -2
  164. package/src/module/module/service/module-access.service.ts +3 -16
  165. package/src/module/workflow/entity/action.entity.ts +3 -0
  166. package/src/module/workflow/repository/action-data.repository.ts +1 -0
  167. package/src/module/workflow/repository/task.repository.ts +8 -0
  168. package/src/module/workflow/service/task.service.ts +47 -38
  169. package/src/module/workflow/service/workflow-meta.service.ts +47 -33
  170. package/src/module/workflow-automation/SCHEDULING_GUIDE.md +145 -0
  171. package/src/module/workflow-automation/controller/workflow-automation.controller.ts +22 -0
  172. package/src/module/workflow-automation/entity/workflow-automation.entity.ts +5 -0
  173. package/src/module/workflow-automation/service/schedule-handler.service.ts +149 -0
  174. package/src/module/workflow-automation/service/workflow-automation-engine.service.ts +1 -1
  175. package/src/module/workflow-automation/service/workflow-automation.service.ts +163 -2
  176. package/src/module/workflow-automation/workflow-automation.module.ts +14 -1
  177. package/src/module/workflow-schedule/INSTALLATION.md +244 -0
  178. package/src/module/workflow-schedule/MULTI_PROJECT_GUIDE.md +196 -0
  179. package/src/module/workflow-schedule/README.md +422 -0
  180. package/src/module/workflow-schedule/constants/schedule.constants.ts +48 -0
  181. package/src/module/workflow-schedule/controller/workflow-schedule.controller.ts +255 -0
  182. package/src/module/workflow-schedule/docs/CLAUDE_CODE_GUIDE.md +510 -0
  183. package/src/module/workflow-schedule/docs/CLAUDE_CODE_PROMPT.md +362 -0
  184. package/src/module/workflow-schedule/docs/RUN_CLAUDE_CODE.sh +68 -0
  185. package/src/module/workflow-schedule/dto/create-schedule.dto.ts +147 -0
  186. package/src/module/workflow-schedule/dto/get-execution-logs.dto.ts +119 -0
  187. package/src/module/workflow-schedule/dto/update-schedule.dto.ts +96 -0
  188. package/src/module/workflow-schedule/entities/scheduled-workflow.entity.ts +148 -0
  189. package/src/module/workflow-schedule/entities/workflow-execution-log.entity.ts +154 -0
  190. package/src/module/workflow-schedule/interfaces/schedule-job-data.interface.ts +53 -0
  191. package/src/module/workflow-schedule/interfaces/workflow-schedule-options.interface.ts +12 -0
  192. package/src/module/workflow-schedule/processors/schedule.processor.ts +584 -0
  193. package/src/module/workflow-schedule/service/workflow-schedule.service.ts +600 -0
  194. package/src/module/workflow-schedule/workflow-schedule.module.ts +67 -0
  195. package/src/resources/dev.properties.yaml +1 -1
  196. package/src/utils/service/loggingUtil.service.ts +70 -16
  197. package/src/utils/utils.module.ts +2 -0
@@ -0,0 +1,145 @@
1
+ # Workflow Automation Scheduling Guide
2
+
3
+ ## Overview
4
+ This module integrates with `WorkflowScheduleModule` to enable creating scheduled workflow automations. You can create schedules that run automatically via cron, or create them in a disabled state for manual triggering only.
5
+
6
+ ## Controlling Auto-Scheduling Behavior
7
+
8
+ ### Option 1: Create Schedules WITHOUT Auto-Execution
9
+ When creating a schedule, set `is_enabled: false` to prevent it from running automatically:
10
+
11
+ ```typescript
12
+ // Inject WorkflowScheduleService in your controller/service
13
+ constructor(
14
+ private readonly workflowScheduleService: WorkflowScheduleService,
15
+ ) {}
16
+
17
+ // Create schedule without auto-execution
18
+ const schedule = await this.workflowScheduleService.createSchedule(
19
+ {
20
+ workflow_id: workflowId,
21
+ workflow_name: 'My Workflow',
22
+ name: 'My Schedule',
23
+ cron_expression: '0 9 * * *', // Every day at 9 AM
24
+ timezone: 'America/New_York',
25
+ is_enabled: false, // 👈 This prevents auto-execution
26
+ // ... other fields
27
+ },
28
+ loggedInUser,
29
+ );
30
+ ```
31
+
32
+ ### Option 2: Create Schedules WITH Auto-Execution
33
+ Simply set `is_enabled: true` (or omit it, as it defaults to true):
34
+
35
+ ```typescript
36
+ const schedule = await this.workflowScheduleService.createSchedule(
37
+ {
38
+ workflow_id: workflowId,
39
+ workflow_name: 'My Workflow',
40
+ name: 'My Schedule',
41
+ cron_expression: '0 9 * * *',
42
+ timezone: 'America/New_York',
43
+ is_enabled: true, // 👈 Schedule will run automatically on cron
44
+ // ... other fields
45
+ },
46
+ loggedInUser,
47
+ );
48
+ ```
49
+
50
+ ## How It Works
51
+
52
+ The scheduling logic in `WorkflowScheduleService.createSchedule()` (line 101-103) only adds jobs to the Bull queue if:
53
+ 1. `is_enabled === true`
54
+ 2. `schedule_status === 'ACTIVE'`
55
+
56
+ If either condition is false, the schedule is saved to the database but NOT added to the queue, meaning the cron processor won't execute it.
57
+
58
+ ## Manual Triggering
59
+
60
+ You can manually trigger any schedule (enabled or disabled) using:
61
+
62
+ ```typescript
63
+ const result = await this.workflowScheduleService.triggerManualExecution(
64
+ scheduleId,
65
+ loggedInUser,
66
+ { /* optional metadata */ },
67
+ );
68
+ ```
69
+
70
+ ## Enabling/Disabling Schedules Later
71
+
72
+ ### To Enable a Disabled Schedule:
73
+ ```typescript
74
+ await this.workflowScheduleService.updateSchedule(
75
+ {
76
+ id: scheduleId,
77
+ is_enabled: true,
78
+ },
79
+ loggedInUser,
80
+ );
81
+ ```
82
+
83
+ ### To Disable an Active Schedule:
84
+ ```typescript
85
+ await this.workflowScheduleService.updateSchedule(
86
+ {
87
+ id: scheduleId,
88
+ is_enabled: false,
89
+ },
90
+ loggedInUser,
91
+ );
92
+ ```
93
+
94
+ ### To Pause a Schedule Temporarily:
95
+ ```typescript
96
+ await this.workflowScheduleService.pauseSchedule(scheduleId, loggedInUser);
97
+ ```
98
+
99
+ ### To Resume a Paused Schedule:
100
+ ```typescript
101
+ await this.workflowScheduleService.resumeSchedule(scheduleId, loggedInUser);
102
+ ```
103
+
104
+ ## Best Practices
105
+
106
+ 1. **Testing**: Create schedules with `is_enabled: false` during development and testing
107
+ 2. **Staged Rollout**: Create schedules disabled, test manually, then enable when ready
108
+ 3. **Monitoring**: Use `getExecutionLogs()` and `getExecutionStats()` to monitor schedule performance
109
+ 4. **Cleanup**: Use `deleteSchedule()` to soft-delete schedules you no longer need
110
+
111
+ ## Example: Complete Workflow
112
+
113
+ ```typescript
114
+ // 1. Create schedule (disabled)
115
+ const schedule = await this.workflowScheduleService.createSchedule({
116
+ workflow_id: 123,
117
+ workflow_name: 'Send Daily Report',
118
+ name: 'Daily Report Schedule',
119
+ cron_expression: '0 9 * * *',
120
+ is_enabled: false, // Start disabled
121
+ }, loggedInUser);
122
+
123
+ // 2. Test manually
124
+ const testResult = await this.workflowScheduleService.triggerManualExecution(
125
+ schedule.id,
126
+ loggedInUser,
127
+ );
128
+
129
+ // 3. Check execution logs
130
+ const logs = await this.workflowScheduleService.getExecutionLogs({
131
+ schedule_id: schedule.id,
132
+ }, loggedInUser);
133
+
134
+ // 4. If tests pass, enable for auto-execution
135
+ if (logs.data[0].execution_status === 'COMPLETED') {
136
+ await this.workflowScheduleService.updateSchedule({
137
+ id: schedule.id,
138
+ is_enabled: true, // Now it will run on cron
139
+ }, loggedInUser);
140
+ }
141
+ ```
142
+
143
+ ## Environment Configuration
144
+
145
+ The Bull queue (Redis) connection is configured in `src/config/bull.config.ts`. Ensure Redis is running and accessible for the scheduler to work.
@@ -1,4 +1,5 @@
1
1
  import {
2
+ BadRequestException,
2
3
  Body,
3
4
  Controller,
4
5
  HttpCode,
@@ -18,4 +19,25 @@ export class WorkflowAutomationController {
18
19
  @Inject('WorkflowAutomationService')
19
20
  private readonly workflowAutomationService: WorkflowAutomationService,
20
21
  ) {}
22
+
23
+ /**
24
+ * Endpoint to update the sequence of workflow automations.
25
+ * Accepts an array of objects with `id` and `sequence`.
26
+ */
27
+ @Post('/updateSequence')
28
+ @HttpCode(HttpStatus.OK)
29
+ async updateSequence(
30
+ @Body() body: any,
31
+ @Req() req: Request & { user?: any },
32
+ ) {
33
+ const loggedInUser = req.user?.userData;
34
+
35
+ if (!Array.isArray(body) || body.length === 0) {
36
+ throw new BadRequestException(
37
+ 'Invalid input. Expected a non-empty array.',
38
+ );
39
+ }
40
+
41
+ return this.workflowAutomationService.updateSequence(body, loggedInUser);
42
+ }
21
43
  }
@@ -32,4 +32,9 @@ export class WorkflowAutomation extends BaseEntity {
32
32
 
33
33
  @Column({ type: 'json', nullable: true })
34
34
  schedule: string;
35
+
36
+ @Column({ type: 'varchar', nullable: true })
37
+ cron_type: string;
38
+ @Column({ type: 'int', nullable: true })
39
+ sequence: number;
35
40
  }
@@ -0,0 +1,149 @@
1
+ import { Inject, Injectable, Logger } from '@nestjs/common';
2
+ import { FilterEvaluatorService } from 'src/module/filter/service/filter-evaluator.service';
3
+ import { DataSource } from 'typeorm';
4
+ import { WorkflowAutomationEngineService } from './workflow-automation-engine.service';
5
+
6
+ @Injectable()
7
+ export class ScheduleHandlerService {
8
+ private readonly logger = new Logger(ScheduleHandlerService.name);
9
+
10
+ constructor(
11
+ private readonly dataSource: DataSource,
12
+ private readonly filterEvaluator: FilterEvaluatorService,
13
+ // @Inject('WorkflowAutomationEngineService')
14
+ private readonly workflowAutomationEngineService: WorkflowAutomationEngineService,
15
+ ) {}
16
+
17
+ async scheduleQueryBuilder(workflowId: number, jobData: any) {
18
+ // 1️⃣ Fetch workflow automation config
19
+ const [workflow] = await this.dataSource.query(
20
+ `SELECT * FROM frm_wf_automation WHERE id = ? AND organization_id = ?`,
21
+ [workflowId, jobData.organizationId],
22
+ );
23
+
24
+ if (!workflow) throw new Error(`Workflow with ID ${workflowId} not found`);
25
+
26
+ const event = JSON.parse(workflow.event_json || '{}');
27
+ const scheduleJson = workflow.schedule;
28
+ const entityType = workflow.applicable_entity_type;
29
+
30
+ // 2️⃣ Get table name from frm_entity_master
31
+ const [entity] = await this.dataSource.query(
32
+ `SELECT data_source FROM frm_entity_master WHERE mapped_entity_type = ? AND organization_id = ?`,
33
+ [entityType, jobData.organizationId],
34
+ );
35
+ if (!entity?.data_source) throw new Error(`Entity ${entityType} not found`);
36
+
37
+ const tableName = entity.data_source;
38
+
39
+ // 3️⃣ Resolve executionDate (list master item name)
40
+ const [executionDateItem] = await this.dataSource.query(
41
+ `SELECT name FROM frm_list_master_items WHERE id = ${scheduleJson.executionDate}`
42
+ );
43
+ const executionDateName = executionDateItem?.name?.toLowerCase() || '';
44
+ const executionDataOrTime = scheduleJson.executionDateOrTime;
45
+
46
+ const executionUnits = Number(scheduleJson.executionDateUnits || 0);
47
+ const fixedTime = scheduleJson.fixedTime; // e.g. "16:00"
48
+
49
+ // Build time window logic
50
+ let comparisonDateCondition = '';
51
+
52
+ if (executionDateName.includes('after')) {
53
+ comparisonDateCondition = `
54
+ ${executionDataOrTime} >= CURDATE() + INTERVAL ${executionUnits} DAY
55
+ AND ${executionDataOrTime} < CURDATE() + INTERVAL ${executionUnits + 1} DAY
56
+ `;
57
+ } else if (executionDateName.includes('before')) {
58
+ comparisonDateCondition = `
59
+ ${executionDataOrTime} >= CURDATE() - INTERVAL ${executionUnits + 1} DAY
60
+ AND ${executionDataOrTime} < CURDATE() - INTERVAL ${executionUnits} DAY
61
+ `;
62
+ } else if (executionDateName.includes('same')) {
63
+ comparisonDateCondition = `
64
+ ${executionDataOrTime} >= CURDATE()
65
+ AND ${executionDataOrTime} < CURDATE() + INTERVAL 1 DAY
66
+ `;
67
+ }
68
+
69
+ const query = `
70
+ SELECT *
71
+ FROM ${tableName}
72
+ WHERE ${comparisonDateCondition}
73
+ AND organization_id = ?
74
+ `;
75
+
76
+ this.logger.debug(`Executing Scheduler Query: ${query}`);
77
+
78
+ const results = await this.dataSource.query(query, [
79
+ jobData.organizationId,
80
+ ]);
81
+
82
+ this.logger.log(
83
+ `Found ${results.length} scheduled records for ${tableName}`,
84
+ );
85
+
86
+ return { results, workflow, tableName };
87
+ }
88
+
89
+ // ⚙️ Step 2: Handle scheduled automation (main entry point)
90
+ async handleScheduledWorkflow(workflowId: number, jobData: any) {
91
+ const { results, workflow, tableName } = await this.scheduleQueryBuilder(
92
+ workflowId,
93
+ jobData,
94
+ );
95
+
96
+ if (!results?.length) {
97
+ this.logger.warn(`No records found for scheduled workflow ${workflowId}`);
98
+ return;
99
+ }
100
+
101
+ this.logger.log(
102
+ `Processing ${results.length} records for workflow ${workflowId}`,
103
+ );
104
+
105
+ // Parse the workflow event JSON again to get filter/action info
106
+ const event = JSON.parse(workflow.event_json || '{}');
107
+ const filter = workflow.condition_filter_code;
108
+ const mappedEntityType = workflow.applicable_entity_type;
109
+
110
+ const matchedEntities: any[] = [];
111
+
112
+ // 🔁 Step 2A: Evaluate criteria for each record
113
+ for (const record of results) {
114
+ const entityIdToUse = record.id; // assuming 'id' column in the table
115
+ const criteriaMatched = await this.filterEvaluator.evaluateCriteria(
116
+ mappedEntityType,
117
+ filter,
118
+ entityIdToUse,
119
+ jobData,
120
+ );
121
+
122
+ this.logger.debug(
123
+ `⚖️ Criteria check for entity ${entityIdToUse} -> ${criteriaMatched}`,
124
+ );
125
+
126
+ if (criteriaMatched) {
127
+ matchedEntities.push(record);
128
+ }
129
+ }
130
+
131
+ // 🧮 Step 3: Execute workflow actions for matched entities
132
+ if (!matchedEntities.length) {
133
+ this.logger.log(`No records passed criteria for workflow ${workflowId}`);
134
+ return;
135
+ }
136
+
137
+ this.logger.log(
138
+ `✅ ${matchedEntities.length} entities passed criteria, executing actions...`,
139
+ );
140
+
141
+ for (const entity of matchedEntities) {
142
+ await this.workflowAutomationEngineService.executeActions(
143
+ workflowId,
144
+ entity,
145
+ jobData,
146
+ );
147
+ }
148
+ }
149
+ }
@@ -145,7 +145,7 @@ export class WorkflowAutomationEngineService {
145
145
  }
146
146
 
147
147
 
148
- private async executeActions(
148
+ async executeActions(
149
149
  workflow_automation_id: number,
150
150
  entity: any,
151
151
  user: any,
@@ -1,4 +1,10 @@
1
- import { Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';
1
+ import {
2
+ BadRequestException,
3
+ Inject,
4
+ Injectable,
5
+ Logger,
6
+ NotFoundException,
7
+ } from '@nestjs/common';
2
8
  import { InjectRepository } from '@nestjs/typeorm';
3
9
  import { DataSource, Repository } from 'typeorm';
4
10
  import { WorkflowAutomation } from '../entity/workflow-automation.entity';
@@ -7,7 +13,9 @@ import { EntityServiceImpl } from 'src/module/meta/service/entity-service-impl.s
7
13
  import { UserData } from 'src/module/user/entity/user.entity';
8
14
  import { SavedFilterService } from 'src/module/filter/service/saved-filter.service';
9
15
  import { ENTITYTYPE_SAVEDFILTERMASTER } from 'src/constant/global.constant';
10
- import { app } from 'firebase-admin';
16
+ import { ScheduledWorkflow } from 'src/module/workflow-schedule/entities/scheduled-workflow.entity';
17
+ import { WorkflowScheduleService } from 'src/module/workflow-schedule/service/workflow-schedule.service';
18
+ import * as moment from 'moment';
11
19
 
12
20
  @Injectable()
13
21
  export class WorkflowAutomationService extends EntityServiceImpl {
@@ -20,6 +28,9 @@ export class WorkflowAutomationService extends EntityServiceImpl {
20
28
  @Inject('SavedFilterService')
21
29
  private readonly savedFilterService: SavedFilterService,
22
30
  private readonly dataSource: DataSource,
31
+ @InjectRepository(ScheduledWorkflow)
32
+ private readonly scheduledWorkflowRepository: Repository<ScheduledWorkflow>,
33
+ private readonly workflowScheduleService: WorkflowScheduleService,
23
34
  ) {
24
35
  super();
25
36
  }
@@ -131,11 +142,13 @@ export class WorkflowAutomationService extends EntityServiceImpl {
131
142
  if (event.triggerType === 'on_schedule') {
132
143
  // just store JSON directly into schedule column
133
144
  workflow.schedule = event?.scheduleJson ?? null;
145
+ workflow.trigger_type = 'on_schedule';
134
146
  this.logger.log(
135
147
  `Stored schedule JSON for workflow ${workflow.id}: ${JSON.stringify(
136
148
  workflow.schedule,
137
149
  )}`,
138
150
  );
151
+ await this.registerScheduleAutomation(workflow, loggedInUser);
139
152
  }
140
153
 
141
154
  workflow.trigger_type = event.triggerType;
@@ -344,4 +357,152 @@ export class WorkflowAutomationService extends EntityServiceImpl {
344
357
  this.logger.debug(`Fetched WorkflowAutomation (id=${id}) with relations`);
345
358
  return response;
346
359
  }
360
+
361
+ async registerScheduleAutomation(workflow: any, loggedInUser: UserData) {
362
+ this.logger.log(
363
+ `Registering schedule automation for workflow ${workflow.id}`,
364
+ );
365
+
366
+ const scheduleJson = workflow.schedule;
367
+ if (!scheduleJson) {
368
+ this.logger.warn(`No schedule JSON provided for workflow ${workflow.id}`);
369
+ return;
370
+ }
371
+
372
+ // Try to find an existing scheduled workflow by workflow_id
373
+ const existingSchedule = await this.scheduledWorkflowRepository.findOne({
374
+ where: { workflow_id: workflow.id },
375
+ });
376
+
377
+ const cronExpression = await this.generateDailyCron(scheduleJson.fixedTime);
378
+
379
+ const payload = {
380
+ workflow_id: workflow.id,
381
+ workflow_name: workflow.name,
382
+ name: scheduleJson.name ?? `Schedule_${workflow.id}`,
383
+ description: scheduleJson.description ?? '',
384
+ cron_expression: cronExpression,
385
+ timezone: scheduleJson.timezone ?? 'Asia/Kolkata',
386
+ start_date: scheduleJson.start_date ?? null,
387
+ end_date: scheduleJson.end_date ?? null,
388
+ max_executions: scheduleJson.max_executions ?? null,
389
+ retry_config: scheduleJson.retry_config ?? {},
390
+ actions: scheduleJson.actions ?? [],
391
+ metadata: scheduleJson.metadata ?? {},
392
+ is_enabled: scheduleJson.is_enabled ?? true,
393
+ organization_id: loggedInUser.organization_id,
394
+ enterprise_id: loggedInUser.enterprise_id,
395
+ level_id: loggedInUser.level_id,
396
+ level_type: loggedInUser.level_type,
397
+ appcode: loggedInUser.appcode,
398
+ };
399
+
400
+ if (existingSchedule) {
401
+ this.logger.log(
402
+ `Existing schedule found (id=${existingSchedule.id}), updating...`,
403
+ );
404
+ payload['id'] = existingSchedule.id;
405
+ // return await this.workflowScheduleService.updateSchedule(payload, loggedInUser);
406
+ } else {
407
+ this.logger.log(`No existing schedule found, creating new one...`);
408
+ return await this.workflowScheduleService.createSchedule(
409
+ payload,
410
+ loggedInUser,
411
+ );
412
+ }
413
+ }
414
+
415
+ // CRON
416
+
417
+ async generateDailyCron(executionTime: string): Promise<string> {
418
+ const time = moment(executionTime, 'HH:mm');
419
+
420
+ if (!time.isValid()) {
421
+ throw new Error('Invalid executionTime format (expected HH:mm)');
422
+ }
423
+
424
+ const minute = time.minute();
425
+ const hour = time.hour();
426
+
427
+ // Ensure cron has 5 fields: minute hour day month weekday
428
+ const cron = `${minute} ${hour} * * *`;
429
+
430
+ // ✅ Validate against your regex before returning
431
+ const cronRegex =
432
+ /^(\*|([0-5]?\d)) (\*|([01]?\d|2[0-3])) (\*|([01]?\d|2\d|3[01])) (\*|([1-9]|1[0-2])) (\*|([0-6]))$/;
433
+ if (!cronRegex.test(cron)) {
434
+ throw new Error(
435
+ `Generated cron expression "${cron}" does not match expected format`,
436
+ );
437
+ }
438
+
439
+ return '*/1 * * * *';
440
+ }
441
+ /**
442
+ * Updates the sequence of multiple workflow automations.
443
+ */
444
+ async updateSequence(
445
+ body: any[],
446
+ loggedInUser: any,
447
+ ): Promise<{ updated: number; results: any[] }> {
448
+ if (!Array.isArray(body) || body.length === 0) {
449
+ throw new BadRequestException(
450
+ 'Invalid input. Expected a non-empty array.',
451
+ );
452
+ }
453
+
454
+ const results: {
455
+ id: number | string | null;
456
+ success: boolean;
457
+ result?: any;
458
+ error?: string;
459
+ }[] = [];
460
+
461
+ for (const item of body) {
462
+ const { id, sequence } = item;
463
+
464
+ // Validate required fields
465
+ if (!id || sequence === undefined || sequence === null) {
466
+ results.push({
467
+ id: id || null,
468
+ success: false,
469
+ error: 'Missing id or sequence',
470
+ });
471
+ continue;
472
+ }
473
+
474
+ try {
475
+ // Check if workflow exists
476
+ const existing = await this.wfRepo.findOne({ where: { id } });
477
+ if (!existing) {
478
+ results.push({
479
+ id,
480
+ success: false,
481
+ error: `Workflow with id ${id} not found`,
482
+ });
483
+ continue;
484
+ }
485
+
486
+ // Update sequence + audit fields
487
+ existing.sequence = Number(sequence);
488
+ existing.modified_by =
489
+ loggedInUser?.id || loggedInUser?.user_id || null;
490
+ existing.modified_date = new Date();
491
+
492
+ const saved = await this.wfRepo.save(existing);
493
+ results.push({ id, success: true, result: saved });
494
+ } catch (err) {
495
+ results.push({
496
+ id,
497
+ success: false,
498
+ error: err.message || 'Unknown error occurred',
499
+ });
500
+ }
501
+ }
502
+
503
+ return {
504
+ updated: results.filter((r) => r.success).length,
505
+ results,
506
+ };
507
+ }
347
508
  }
@@ -9,12 +9,17 @@ import { WorkflowAutomationService } from './service/workflow-automation.service
9
9
  import { WorkflowAutomationActionEntity } from './entity/workflow-automation-action.entity';
10
10
  import { EntityModule } from '../meta/entity.module';
11
11
  import { ActionRegistryService } from './service/action-registery.service';
12
+ import { ScheduleHandlerService } from './service/schedule-handler.service';
13
+ import { ScheduledWorkflow } from '../workflow-schedule/entities/scheduled-workflow.entity';
14
+ import { WorkflowExecutionLog } from '../workflow-schedule/entities/workflow-execution-log.entity';
12
15
 
13
16
  @Module({
14
17
  imports: [
15
18
  TypeOrmModule.forFeature([
16
19
  WorkflowAutomation,
17
20
  WorkflowAutomationActionEntity,
21
+ ScheduledWorkflow, // 👈 Required by WorkflowAutomationService
22
+ WorkflowExecutionLog, // 👈 May be used by services
18
23
  ]),
19
24
  FilterModule,
20
25
  forwardRef(() => EntityModule),
@@ -26,9 +31,17 @@ import { ActionRegistryService } from './service/action-registery.service';
26
31
  provide: 'WorkflowAutomationService',
27
32
  useClass: WorkflowAutomationService,
28
33
  },
34
+ {
35
+ provide: 'ScheduleHandlerService',
36
+ useClass: ScheduleHandlerService,
37
+ },
29
38
  ActionRegistryService, // 👈 auto-registers actions
30
39
  ],
31
- exports: [WorkflowAutomationEngineService, 'WorkflowAutomationService'],
40
+ exports: [
41
+ WorkflowAutomationEngineService,
42
+ 'WorkflowAutomationService',
43
+ 'ScheduleHandlerService',
44
+ ],
32
45
  controllers: [WorkflowAutomationController],
33
46
  })
34
47
  export class WorkflowAutomationModule {}