rez_core 5.0.95 → 5.0.97

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 (406) hide show
  1. package/.prettierrc +3 -3
  2. package/.vscode/extensions.json +5 -0
  3. package/README.md +99 -99
  4. package/dist/module/auth/guards/role.guard.js +3 -3
  5. package/dist/module/filter/service/filter.service.js +20 -20
  6. package/dist/module/integration/examples/usage.example.js +9 -9
  7. package/dist/module/meta/repository/attribute-master.repository.js +8 -8
  8. package/dist/module/meta/service/entity-dynamic.service.js +21 -23
  9. package/dist/module/meta/service/entity-dynamic.service.js.map +1 -1
  10. package/dist/module/meta/service/entity-list.service.js +3 -3
  11. package/dist/module/meta/service/entity-service-impl.service.js +3 -3
  12. package/dist/module/meta/service/media-data.service.js +6 -6
  13. package/dist/module/meta/service/resolver.service.js +15 -15
  14. package/dist/module/module/repository/menu.repository.js +4 -4
  15. package/dist/module/notification/service/notification.service.js +6 -6
  16. package/dist/module/user/controller/login.controller.js +18 -18
  17. package/dist/module/workflow/repository/action-data.repository.js +1 -1
  18. package/dist/module/workflow/repository/action-data.repository.js.map +1 -1
  19. package/dist/module/workflow/repository/action.repository.js +2 -2
  20. package/dist/module/workflow/repository/stage-movement.repository.js +3 -1
  21. package/dist/module/workflow/repository/stage-movement.repository.js.map +1 -1
  22. package/dist/module/workflow/repository/stage.repository.js +8 -8
  23. package/dist/module/workflow/service/action-template-mapping.service.js +4 -4
  24. package/dist/module/workflow/service/action.service.js +10 -10
  25. package/dist/module/workflow/service/entity-modification.service.js +2 -2
  26. package/dist/module/workflow/service/task.service.js +5 -5
  27. package/dist/module/workflow-automation/service/schedule-handler.service.js +9 -9
  28. package/dist/tsconfig.build.tsbuildinfo +1 -1
  29. package/dist/utils/service/reflection-helper.service.js +2 -2
  30. package/docs/modules/event-driven-integration-design.md +91 -91
  31. package/docs/modules/integration.md +250 -250
  32. package/eslint.config.mjs +34 -34
  33. package/nest-cli.json +14 -14
  34. package/package.json +125 -125
  35. package/src/app.controller.ts +12 -12
  36. package/src/app.module.ts +66 -66
  37. package/src/app.service.ts +8 -8
  38. package/src/config/bull.config.ts +69 -69
  39. package/src/config/config.module.ts +17 -17
  40. package/src/config/database.config.ts +48 -48
  41. package/src/constant/global.constant.ts +67 -67
  42. package/src/core.module.ts +91 -91
  43. package/src/decorators/roles.decorator.ts +7 -7
  44. package/src/dtos/response.dto.ts +6 -6
  45. package/src/dtos/response.ts +5 -5
  46. package/src/index.ts +1 -1
  47. package/src/module/auth/auth.module.ts +49 -49
  48. package/src/module/auth/controller/auth.controller.ts +28 -28
  49. package/src/module/auth/guards/google-auth.guard.ts +9 -9
  50. package/src/module/auth/guards/jwt.guard.ts +22 -22
  51. package/src/module/auth/guards/role.guard.ts +68 -68
  52. package/src/module/auth/services/auth.service.ts +56 -56
  53. package/src/module/auth/services/jwt.service.ts +11 -11
  54. package/src/module/auth/strategies/google.strategy.ts +54 -54
  55. package/src/module/auth/strategies/jwt.strategy.ts +58 -58
  56. package/src/module/auth/strategies/local.strategy.ts +13 -13
  57. package/src/module/dashboard/controller/dashboard.controller.ts +36 -36
  58. package/src/module/dashboard/dashboard.module.ts +21 -21
  59. package/src/module/dashboard/entity/dashboard_page_data.entity.ts +27 -27
  60. package/src/module/dashboard/entity/widget_master.entity.ts +18 -18
  61. package/src/module/dashboard/repository/dashboard.repository.ts +51 -51
  62. package/src/module/dashboard/service/dashboard.service.ts +73 -73
  63. package/src/module/enterprise/controller/organization.controller.ts +36 -36
  64. package/src/module/enterprise/enterprise.module.ts +30 -30
  65. package/src/module/enterprise/entity/enterprise.entity.ts +37 -37
  66. package/src/module/enterprise/entity/organization-app-mapping.entity.ts +13 -13
  67. package/src/module/enterprise/entity/organization.entity.ts +92 -92
  68. package/src/module/enterprise/repository/enterprise.repository.ts +31 -31
  69. package/src/module/enterprise/repository/organization.repository.ts +26 -26
  70. package/src/module/enterprise/repository/school.repository.ts +272 -272
  71. package/src/module/enterprise/service/brand.service.ts +5 -5
  72. package/src/module/enterprise/service/enterprise.service.ts +16 -16
  73. package/src/module/enterprise/service/organization-app-mapping.service.ts +4 -4
  74. package/src/module/enterprise/service/organization.service.ts +145 -145
  75. package/src/module/entity_json/controller/entity_json.controller.ts +47 -47
  76. package/src/module/entity_json/entity/entityJson.entity.ts +39 -39
  77. package/src/module/entity_json/entity_json.module.ts +18 -18
  78. package/src/module/entity_json/service/entityJson.repository.ts +37 -37
  79. package/src/module/entity_json/service/entity_json.service.ts +234 -234
  80. package/src/module/filter/controller/filter.controller.ts +84 -84
  81. package/src/module/filter/dto/filter-request.dto.ts +38 -38
  82. package/src/module/filter/entity/saved-filter-detail.entity.ts +41 -41
  83. package/src/module/filter/entity/saved-filter-master.entity.ts +23 -23
  84. package/src/module/filter/filter.module.ts +33 -33
  85. package/src/module/filter/repository/saved-filter.repository.ts +168 -168
  86. package/src/module/filter/repository/saved.filter-detail.repository.ts +19 -19
  87. package/src/module/filter/service/filter-evaluator.service.ts +82 -82
  88. package/src/module/filter/service/filter.service.ts +1304 -1304
  89. package/src/module/filter/service/saved-filter.service.ts +170 -170
  90. package/src/module/ics/controller/ics.controller.ts +21 -21
  91. package/src/module/ics/dto/ics.dto.ts +55 -55
  92. package/src/module/ics/ics.module.ts +13 -13
  93. package/src/module/ics/service/ics.service.ts +57 -57
  94. package/src/module/integration/controller/calender-event.controller.ts +31 -31
  95. package/src/module/integration/controller/integration.controller.ts +662 -662
  96. package/src/module/integration/controller/wrapper.controller.ts +37 -37
  97. package/src/module/integration/dto/create-config.dto.ts +526 -526
  98. package/src/module/integration/entity/integration-config.entity.ts +112 -112
  99. package/src/module/integration/entity/integration-entity-mapper.entity.ts +14 -14
  100. package/src/module/integration/entity/integration-source.entity.ts +17 -17
  101. package/src/module/integration/entity/user-integration.entity.ts +71 -71
  102. package/src/module/integration/examples/usage.example.ts +338 -338
  103. package/src/module/integration/factories/base.factory.ts +7 -7
  104. package/src/module/integration/factories/email.factory.ts +49 -49
  105. package/src/module/integration/factories/integration.factory.ts +121 -121
  106. package/src/module/integration/factories/sms.factory.ts +51 -51
  107. package/src/module/integration/factories/telephone.factory.ts +41 -41
  108. package/src/module/integration/factories/whatsapp.factory.ts +56 -56
  109. package/src/module/integration/integration.module.ts +110 -110
  110. package/src/module/integration/service/calendar-event.service.ts +118 -118
  111. package/src/module/integration/service/integration-entity-mapper.service.ts +17 -17
  112. package/src/module/integration/service/integration-queue.service.ts +229 -229
  113. package/src/module/integration/service/integration.service.ts +2634 -2634
  114. package/src/module/integration/service/oauth.service.ts +224 -224
  115. package/src/module/integration/service/wrapper.service.ts +716 -716
  116. package/src/module/integration/strategies/email/gmail-api.strategy.ts +280 -280
  117. package/src/module/integration/strategies/email/outlook-api.strategy.ts +44 -44
  118. package/src/module/integration/strategies/email/outlook.strategy.ts +64 -64
  119. package/src/module/integration/strategies/email/sendgrid-api.strategy.ts +260 -260
  120. package/src/module/integration/strategies/integration.strategy.ts +97 -97
  121. package/src/module/integration/strategies/sms/gupshup-sms.strategy.ts +146 -146
  122. package/src/module/integration/strategies/sms/msg91-sms.strategy.ts +164 -164
  123. package/src/module/integration/strategies/sms/tubelight-sms.strategy.ts +163 -163
  124. package/src/module/integration/strategies/telephone/ozonetel-voice.strategy.ts +238 -238
  125. package/src/module/integration/strategies/telephone/tubelight-voice.strategy.ts +210 -210
  126. package/src/module/integration/strategies/whatsapp/gupshup-whatsapp.strategy.ts +359 -359
  127. package/src/module/integration/strategies/whatsapp/tubelight-whatsapp.strategy.ts +372 -372
  128. package/src/module/integration/strategies/whatsapp/whatsapp-cloud.strategy.ts +403 -403
  129. package/src/module/integration/strategies/whatsapp/whatsapp.strategy.ts +57 -57
  130. package/src/module/layout/controller/layout.controller.ts +47 -47
  131. package/src/module/layout/entity/header-items.entity.ts +28 -28
  132. package/src/module/layout/entity/header-section.entity.ts +19 -19
  133. package/src/module/layout/layout.module.ts +21 -21
  134. package/src/module/layout/repository/header-items.repository.ts +18 -18
  135. package/src/module/layout/repository/header-section.repository.ts +22 -22
  136. package/src/module/layout/service/header-section.service.ts +25 -25
  137. package/src/module/layout_preference/controller/layout_preference.controller.ts +73 -73
  138. package/src/module/layout_preference/entity/layout_preference.entity.ts +28 -28
  139. package/src/module/layout_preference/layout_preference.module.ts +22 -22
  140. package/src/module/layout_preference/repository/layout_preference.repository.ts +65 -65
  141. package/src/module/layout_preference/service/layout_preference.service.ts +191 -191
  142. package/src/module/lead/controller/lead.controller.ts +30 -30
  143. package/src/module/lead/lead.module.ts +14 -14
  144. package/src/module/lead/repository/lead.repository.ts +41 -41
  145. package/src/module/lead/service/lead.service.ts +54 -54
  146. package/src/module/linked_attributes/controller/linked_attributes.controller.ts +37 -37
  147. package/src/module/linked_attributes/entity/linked_attribute.entity.ts +51 -51
  148. package/src/module/linked_attributes/linked_attributes.module.ts +16 -16
  149. package/src/module/linked_attributes/repository/linked_attribute.repository.ts +12 -12
  150. package/src/module/linked_attributes/service/linked_attributes.service.ts +75 -75
  151. package/src/module/listmaster/controller/list-master.controller.ts +230 -230
  152. package/src/module/listmaster/entity/list-master-items.entity.ts +43 -43
  153. package/src/module/listmaster/entity/list-master.entity.ts +33 -33
  154. package/src/module/listmaster/listmaster.module.ts +46 -46
  155. package/src/module/listmaster/repository/list-master-items.repository.ts +173 -173
  156. package/src/module/listmaster/repository/list-master.repository.ts +56 -56
  157. package/src/module/listmaster/service/list-master-engine.ts +19 -19
  158. package/src/module/listmaster/service/list-master-extension.interface.ts +4 -4
  159. package/src/module/listmaster/service/list-master-item.service.ts +281 -281
  160. package/src/module/listmaster/service/list-master-registry.ts +15 -15
  161. package/src/module/listmaster/service/list-master.service.ts +535 -535
  162. package/src/module/mapper/controller/field-mapper.controller.ts +76 -76
  163. package/src/module/mapper/controller/mapper.controller.ts +20 -20
  164. package/src/module/mapper/dto/field-mapper.dto.ts +14 -14
  165. package/src/module/mapper/entity/field-lovs.entity.ts +19 -19
  166. package/src/module/mapper/entity/field-mapper.entity.ts +53 -53
  167. package/src/module/mapper/entity/mapper.entity.ts +16 -16
  168. package/src/module/mapper/mapper.module.ts +35 -35
  169. package/src/module/mapper/repository/field-lovs.repository.ts +35 -35
  170. package/src/module/mapper/repository/field-mapper.repository.ts +42 -42
  171. package/src/module/mapper/repository/mapper.repository.ts +32 -32
  172. package/src/module/mapper/service/field-mapper.service.ts +269 -269
  173. package/src/module/mapper/service/mapper.service.ts +81 -81
  174. package/src/module/master/controller/master.controller.ts +74 -74
  175. package/src/module/master/service/master.service.ts +483 -483
  176. package/src/module/meta/controller/app-master.controller.ts +38 -38
  177. package/src/module/meta/controller/attribute-master.controller.ts +84 -84
  178. package/src/module/meta/controller/entity-dynamic.controller.ts +125 -125
  179. package/src/module/meta/controller/entity-master.controller.ts +41 -41
  180. package/src/module/meta/controller/entity-relation.controller.ts +36 -36
  181. package/src/module/meta/controller/entity.controller.ts +392 -392
  182. package/src/module/meta/controller/entity.public.controller.ts +75 -75
  183. package/src/module/meta/controller/media.controller.ts +107 -107
  184. package/src/module/meta/controller/meta.controller.ts +96 -96
  185. package/src/module/meta/controller/view-master.controller.ts +86 -86
  186. package/src/module/meta/dto/entity-list-data.dto.ts +6 -6
  187. package/src/module/meta/dto/entity-tab.dto.ts +4 -4
  188. package/src/module/meta/dto/entity-table.dto.ts +9 -9
  189. package/src/module/meta/entity/app-master.entity.ts +34 -34
  190. package/src/module/meta/entity/attribute-master.entity.ts +92 -92
  191. package/src/module/meta/entity/base-entity.entity.ts +75 -75
  192. package/src/module/meta/entity/entity-master.entity.ts +85 -85
  193. package/src/module/meta/entity/entity-relation-data.entity.ts +29 -29
  194. package/src/module/meta/entity/entity-relation.entity.ts +23 -23
  195. package/src/module/meta/entity/entity-table-column.entity.ts +61 -61
  196. package/src/module/meta/entity/entity-table.entity.ts +50 -50
  197. package/src/module/meta/entity/media-data.entity.ts +32 -32
  198. package/src/module/meta/entity/preference.entity.ts +62 -62
  199. package/src/module/meta/entity/view-master.entity.ts +41 -41
  200. package/src/module/meta/entity.module.ts +166 -166
  201. package/src/module/meta/repository/app-master.repository.ts +20 -20
  202. package/src/module/meta/repository/attribute-master.repository.ts +156 -156
  203. package/src/module/meta/repository/entity-attribute-update.repository.ts +48 -48
  204. package/src/module/meta/repository/entity-master.repository.ts +110 -110
  205. package/src/module/meta/repository/entity-table-column.repository.ts +39 -39
  206. package/src/module/meta/repository/entity-table.repository.ts +53 -53
  207. package/src/module/meta/repository/media-data.repository.ts +50 -50
  208. package/src/module/meta/repository/preference.repository.ts +20 -20
  209. package/src/module/meta/repository/user-app-mapping.repository.ts +28 -28
  210. package/src/module/meta/repository/view-master.repository.ts +42 -42
  211. package/src/module/meta/service/app-master.service.ts +37 -37
  212. package/src/module/meta/service/attribute-master.service.ts +130 -130
  213. package/src/module/meta/service/common.service.ts +9 -9
  214. package/src/module/meta/service/entity-attribute-update.service.ts +28 -28
  215. package/src/module/meta/service/entity-dynamic.service.ts +818 -820
  216. package/src/module/meta/service/entity-list.service.ts +205 -205
  217. package/src/module/meta/service/entity-master.service.ts +171 -171
  218. package/src/module/meta/service/entity-realation-data.service.ts +9 -9
  219. package/src/module/meta/service/entity-relation.service.ts +69 -69
  220. package/src/module/meta/service/entity-service-impl.service.ts +525 -525
  221. package/src/module/meta/service/entity-table-column.service.ts +39 -39
  222. package/src/module/meta/service/entity-table.service.ts +150 -150
  223. package/src/module/meta/service/entity-validation.service.ts +187 -187
  224. package/src/module/meta/service/entity.service.ts +67 -67
  225. package/src/module/meta/service/field-group.service.ts +103 -103
  226. package/src/module/meta/service/media-data.service.ts +510 -510
  227. package/src/module/meta/service/populate-meta.service.ts +222 -222
  228. package/src/module/meta/service/preference.service.ts +16 -16
  229. package/src/module/meta/service/resolver.service.ts +293 -293
  230. package/src/module/meta/service/section-master.service.ts +104 -104
  231. package/src/module/meta/service/update-form-json.service.ts +22 -22
  232. package/src/module/meta/service/user-app-mapping.service.ts +17 -17
  233. package/src/module/meta/service/view-master.service.ts +127 -127
  234. package/src/module/microservice-client/microservice-clients.module.ts +13 -13
  235. package/src/module/microservice-client/service/microservice-client-factory.ts +37 -37
  236. package/src/module/microservice-client/service/microservice-clients.ts +4 -4
  237. package/src/module/module/controller/menu.controller.ts +15 -15
  238. package/src/module/module/controller/module-access.controller.ts +134 -134
  239. package/src/module/module/entity/menu.entity.ts +43 -43
  240. package/src/module/module/entity/module-access.entity.ts +25 -25
  241. package/src/module/module/entity/module-action.entity.ts +17 -17
  242. package/src/module/module/entity/module.entity.ts +52 -52
  243. package/src/module/module/module.module.ts +42 -42
  244. package/src/module/module/repository/menu.repository.ts +184 -184
  245. package/src/module/module/repository/module-access.repository.ts +344 -344
  246. package/src/module/module/service/menu.service.ts +82 -82
  247. package/src/module/module/service/module-access.service.ts +199 -199
  248. package/src/module/notification/controller/notification.controller.ts +58 -58
  249. package/src/module/notification/controller/otp.controller.ts +117 -117
  250. package/src/module/notification/entity/notification.entity.ts +26 -26
  251. package/src/module/notification/entity/otp.entity.ts +28 -28
  252. package/src/module/notification/firebase-admin.config.ts +22 -22
  253. package/src/module/notification/notification.module.ts +69 -69
  254. package/src/module/notification/repository/otp.repository.ts +27 -27
  255. package/src/module/notification/service/email.service.ts +127 -127
  256. package/src/module/notification/service/notification.service.ts +164 -164
  257. package/src/module/notification/service/otp.service.ts +133 -133
  258. package/src/module/third-party-module/entity/third-party-api-registry.entity.ts +52 -52
  259. package/src/module/third-party-module/repository/third-party-api-registry.repository.ts +20 -20
  260. package/src/module/third-party-module/service/api-registry.service.ts +13 -13
  261. package/src/module/third-party-module/third-party.module.ts +12 -12
  262. package/src/module/user/controller/login.controller.ts +198 -198
  263. package/src/module/user/controller/user.controller.ts +40 -40
  264. package/src/module/user/dto/create-user.dto.ts +62 -62
  265. package/src/module/user/dto/update-user.dto.ts +4 -4
  266. package/src/module/user/entity/role.entity.ts +33 -33
  267. package/src/module/user/entity/user-role-mapping.entity.ts +38 -38
  268. package/src/module/user/entity/user-session.entity.ts +73 -73
  269. package/src/module/user/entity/user.entity.ts +59 -59
  270. package/src/module/user/repository/role.repository.ts +96 -96
  271. package/src/module/user/repository/user-role-mapping.repository.ts +126 -126
  272. package/src/module/user/repository/user.repository.ts +50 -50
  273. package/src/module/user/repository/userSession.repository.ts +33 -33
  274. package/src/module/user/service/login.service.ts +326 -326
  275. package/src/module/user/service/role.service.ts +197 -197
  276. package/src/module/user/service/user-role-mapping.service.ts +98 -98
  277. package/src/module/user/service/user-session.service.ts +177 -177
  278. package/src/module/user/service/user.service.ts +368 -368
  279. package/src/module/user/user.module.ts +65 -65
  280. package/src/module/workflow/controller/action-category.controller.ts +54 -54
  281. package/src/module/workflow/controller/action-resource-mapping.controller.ts +23 -23
  282. package/src/module/workflow/controller/action-template-mapping.controller.ts +35 -35
  283. package/src/module/workflow/controller/action.controller.ts +111 -111
  284. package/src/module/workflow/controller/activity-log.controller.ts +55 -55
  285. package/src/module/workflow/controller/comm-template.controller.ts +43 -43
  286. package/src/module/workflow/controller/entity-modification.controller.ts +35 -35
  287. package/src/module/workflow/controller/form-master.controller.ts +43 -43
  288. package/src/module/workflow/controller/stage-group.controller.ts +48 -48
  289. package/src/module/workflow/controller/stage.controller.ts +50 -50
  290. package/src/module/workflow/controller/task.controller.ts +77 -77
  291. package/src/module/workflow/controller/workflow-list-master.controller.ts +44 -44
  292. package/src/module/workflow/controller/workflow-meta.controller.ts +80 -80
  293. package/src/module/workflow/controller/workflow.controller.ts +67 -67
  294. package/src/module/workflow/entity/action-category.entity.ts +38 -38
  295. package/src/module/workflow/entity/action-data.entity.ts +55 -55
  296. package/src/module/workflow/entity/action-resources-mapping.entity.ts +29 -29
  297. package/src/module/workflow/entity/action-template-mapping.entity.ts +17 -17
  298. package/src/module/workflow/entity/action.entity.ts +53 -53
  299. package/src/module/workflow/entity/activity-log.entity.ts +43 -43
  300. package/src/module/workflow/entity/comm-template.entity.ts +43 -43
  301. package/src/module/workflow/entity/entity-modification.entity.ts +38 -38
  302. package/src/module/workflow/entity/form.entity.ts +25 -25
  303. package/src/module/workflow/entity/stage-action-mapping.entity.ts +17 -17
  304. package/src/module/workflow/entity/stage-group.entity.ts +23 -23
  305. package/src/module/workflow/entity/stage-movement-data.entity.ts +38 -38
  306. package/src/module/workflow/entity/stage.entity.ts +20 -20
  307. package/src/module/workflow/entity/task-data.entity.ts +88 -88
  308. package/src/module/workflow/entity/template-attach-mapper.entity.ts +30 -30
  309. package/src/module/workflow/entity/workflow-data.entity.ts +11 -11
  310. package/src/module/workflow/entity/workflow-level-mapping.entity.ts +18 -18
  311. package/src/module/workflow/entity/workflow.entity.ts +20 -20
  312. package/src/module/workflow/repository/action-category.repository.ts +79 -79
  313. package/src/module/workflow/repository/action-data.repository.ts +346 -344
  314. package/src/module/workflow/repository/action.repository.ts +338 -338
  315. package/src/module/workflow/repository/activity-log.repository.ts +148 -148
  316. package/src/module/workflow/repository/comm-template.repository.ts +157 -157
  317. package/src/module/workflow/repository/form-master.repository.ts +50 -50
  318. package/src/module/workflow/repository/stage-group.repository.ts +186 -186
  319. package/src/module/workflow/repository/stage-movement.repository.ts +262 -256
  320. package/src/module/workflow/repository/stage.repository.ts +160 -160
  321. package/src/module/workflow/repository/task.repository.ts +151 -151
  322. package/src/module/workflow/repository/workflow.repository.ts +42 -42
  323. package/src/module/workflow/service/action-category.service.ts +33 -33
  324. package/src/module/workflow/service/action-data.service.ts +62 -62
  325. package/src/module/workflow/service/action-resources-mapping.service.ts +10 -10
  326. package/src/module/workflow/service/action-template-mapping.service.ts +131 -131
  327. package/src/module/workflow/service/action.service.ts +306 -306
  328. package/src/module/workflow/service/activity-log.service.ts +107 -107
  329. package/src/module/workflow/service/comm-template.service.ts +180 -180
  330. package/src/module/workflow/service/entity-modification.service.ts +61 -61
  331. package/src/module/workflow/service/form-master.service.ts +35 -35
  332. package/src/module/workflow/service/populate-workflow.service.ts +320 -320
  333. package/src/module/workflow/service/stage-action-mapping.service.ts +5 -5
  334. package/src/module/workflow/service/stage-group.service.ts +344 -344
  335. package/src/module/workflow/service/stage.service.ts +207 -207
  336. package/src/module/workflow/service/task.service.ts +546 -546
  337. package/src/module/workflow/service/workflow-list-master.service.ts +68 -68
  338. package/src/module/workflow/service/workflow-meta.service.ts +639 -639
  339. package/src/module/workflow/service/workflow.service.ts +213 -213
  340. package/src/module/workflow/workflow.module.ts +180 -180
  341. package/src/module/workflow-automation/SCHEDULING_GUIDE.md +145 -145
  342. package/src/module/workflow-automation/controller/workflow-automation.controller.ts +43 -43
  343. package/src/module/workflow-automation/entity/workflow-automation-action.entity.ts +26 -26
  344. package/src/module/workflow-automation/entity/workflow-automation.entity.ts +40 -40
  345. package/src/module/workflow-automation/interface/action.decorator.ts +7 -7
  346. package/src/module/workflow-automation/interface/action.interface.ts +5 -5
  347. package/src/module/workflow-automation/service/action-registery.service.ts +35 -35
  348. package/src/module/workflow-automation/service/schedule-handler.service.ts +168 -168
  349. package/src/module/workflow-automation/service/workflow-automation-engine.service.ts +219 -219
  350. package/src/module/workflow-automation/service/workflow-automation.service.ts +515 -515
  351. package/src/module/workflow-automation/workflow-automation.module.ts +54 -54
  352. package/src/module/workflow-schedule/INSTALLATION.md +244 -244
  353. package/src/module/workflow-schedule/MULTI_PROJECT_GUIDE.md +196 -196
  354. package/src/module/workflow-schedule/README.md +422 -422
  355. package/src/module/workflow-schedule/constants/schedule.constants.ts +48 -48
  356. package/src/module/workflow-schedule/controller/workflow-schedule.controller.ts +255 -255
  357. package/src/module/workflow-schedule/docs/CLAUDE_CODE_GUIDE.md +510 -510
  358. package/src/module/workflow-schedule/docs/CLAUDE_CODE_PROMPT.md +362 -362
  359. package/src/module/workflow-schedule/docs/RUN_CLAUDE_CODE.sh +68 -68
  360. package/src/module/workflow-schedule/dto/create-schedule.dto.ts +147 -147
  361. package/src/module/workflow-schedule/dto/get-execution-logs.dto.ts +119 -119
  362. package/src/module/workflow-schedule/dto/update-schedule.dto.ts +96 -96
  363. package/src/module/workflow-schedule/entities/scheduled-workflow.entity.ts +148 -148
  364. package/src/module/workflow-schedule/entities/workflow-execution-log.entity.ts +154 -154
  365. package/src/module/workflow-schedule/interfaces/schedule-job-data.interface.ts +53 -53
  366. package/src/module/workflow-schedule/interfaces/workflow-schedule-options.interface.ts +12 -12
  367. package/src/module/workflow-schedule/processors/schedule.processor.ts +620 -620
  368. package/src/module/workflow-schedule/service/workflow-schedule.service.ts +598 -598
  369. package/src/module/workflow-schedule/workflow-schedule.module.ts +67 -67
  370. package/src/resources/dev.properties.yaml +31 -31
  371. package/src/resources/local.properties.yaml +27 -27
  372. package/src/resources/properties.module.ts +12 -12
  373. package/src/resources/properties.yaml.ts +11 -11
  374. package/src/resources/uat.properties.yaml +31 -31
  375. package/src/table.config.ts +133 -133
  376. package/src/utils/dto/excel-data.dto.ts +14 -14
  377. package/src/utils/dto/excelsheet-data.dto.ts +5 -5
  378. package/src/utils/service/base64util.service.ts +18 -18
  379. package/src/utils/service/clockIDGenUtil.service.ts +21 -21
  380. package/src/utils/service/codeGenerator.service.ts +22 -22
  381. package/src/utils/service/dateUtil.service.ts +17 -17
  382. package/src/utils/service/encryptUtil.service.ts +97 -97
  383. package/src/utils/service/excel-helper.service.ts +72 -72
  384. package/src/utils/service/excelUtil.service.ts +15 -15
  385. package/src/utils/service/file-util.service.ts +11 -11
  386. package/src/utils/service/json-util.service.ts +23 -23
  387. package/src/utils/service/loggingUtil.service.ts +88 -88
  388. package/src/utils/service/reflection-helper.service.ts +62 -62
  389. package/src/utils/service/wbsCodeGen.service.ts +8 -8
  390. package/src/utils/utils.module.ts +27 -27
  391. package/tsconfig.build.json +4 -4
  392. package/tsconfig.json +24 -24
  393. package/.claude/settings.local.json +0 -26
  394. package/.idea/250218_nodejs_core.iml +0 -9
  395. package/.idea/codeStyles/Project.xml +0 -59
  396. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  397. package/.idea/copilot.data.migration.agent.xml +0 -6
  398. package/.idea/copilot.data.migration.ask.xml +0 -6
  399. package/.idea/copilot.data.migration.ask2agent.xml +0 -6
  400. package/.idea/copilot.data.migration.edit.xml +0 -6
  401. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  402. package/.idea/misc.xml +0 -6
  403. package/.idea/modules.xml +0 -8
  404. package/.idea/prettier.xml +0 -6
  405. package/.idea/vcs.xml +0 -6
  406. package/server.log +0 -850
@@ -1,620 +1,620 @@
1
- import {
2
- Process,
3
- Processor,
4
- OnQueueActive,
5
- OnQueueCompleted,
6
- OnQueueFailed,
7
- } from '@nestjs/bull';
8
- import { Logger, Inject } from '@nestjs/common';
9
- import { Job } from 'bull';
10
- import { InjectRepository } from '@nestjs/typeorm';
11
- import { Repository, DataSource } from 'typeorm';
12
- import { ScheduledWorkflow } from '../entities/scheduled-workflow.entity';
13
- import { WorkflowExecutionLog } from '../entities/workflow-execution-log.entity';
14
- import {
15
- WORKFLOW_SCHEDULE_QUEUE,
16
- EXECUTE_SCHEDULED_WORKFLOW_JOB,
17
- EXECUTION_STATUS_PENDING,
18
- EXECUTION_STATUS_RUNNING,
19
- EXECUTION_STATUS_COMPLETED,
20
- EXECUTION_STATUS_FAILED,
21
- EXECUTION_STATUS_PARTIAL,
22
- DEFAULT_BATCH_SIZE,
23
- } from '../constants/schedule.constants';
24
- import {
25
- ScheduleJobData,
26
- BatchProcessingResult,
27
- } from '../interfaces/schedule-job-data.interface';
28
- import { ScheduleHandlerService } from 'src/module/workflow-automation/service/schedule-handler.service';
29
- import { ReflectionHelper } from 'src/utils/service/reflection-helper.service';
30
-
31
- /**
32
- * Schedule Processor
33
- * Processes scheduled workflow execution jobs from Bull queue
34
- */
35
- @Processor(WORKFLOW_SCHEDULE_QUEUE)
36
- export class ScheduleProcessor {
37
- private readonly logger = new Logger(ScheduleProcessor.name);
38
-
39
- constructor(
40
- @InjectRepository(ScheduledWorkflow)
41
- private readonly scheduledWorkflowRepository: Repository<ScheduledWorkflow>,
42
- @InjectRepository(WorkflowExecutionLog)
43
- private readonly executionLogRepository: Repository<WorkflowExecutionLog>,
44
- @Inject('ScheduleHandlerService')
45
- private readonly scheduleHandlerService: ScheduleHandlerService,
46
- private readonly reflectionHelper: ReflectionHelper,
47
- private readonly dataSource: DataSource
48
- ) {}
49
-
50
- /**
51
- * Main job processor for scheduled workflow execution
52
- */
53
- @Process(EXECUTE_SCHEDULED_WORKFLOW_JOB)
54
- async handleScheduledWorkflowExecution(job: Job<ScheduleJobData>) {
55
- const { scheduleId, workflowId, organizationId, triggeredBy, createdBy } =
56
- job.data;
57
-
58
- this.logger.log(
59
- `🚀 [handleScheduledWorkflowExecution] Invoked for scheduleId=${scheduleId}, workflowId=${workflowId}`,
60
- );
61
-
62
- // Create execution log entry
63
- const executionLog = this.executionLogRepository.create({
64
- schedule_id: scheduleId,
65
- workflow_id: workflowId,
66
- job_id: job.id.toString(),
67
- execution_status: EXECUTION_STATUS_PENDING,
68
- triggered_by: triggeredBy,
69
- triggered_by_user_id: triggeredBy === 'MANUAL' ? createdBy : null,
70
- organization_id: organizationId,
71
- enterprise_id: job.data.enterpriseId,
72
- created_by: createdBy,
73
- entity_type: 'WFEL',
74
- });
75
-
76
- this.logger.debug(`🧾 Creating execution log for jobId=${job.id}`);
77
- await this.executionLogRepository.save(executionLog);
78
-
79
- try {
80
- // Update status to running
81
- executionLog.execution_status = EXECUTION_STATUS_RUNNING;
82
- executionLog.started_at = new Date();
83
- await this.executionLogRepository.save(executionLog);
84
-
85
- this.logger.log(
86
- `🏃 Workflow execution started for scheduleId=${scheduleId}`,
87
- );
88
-
89
- // Get scheduled workflow details
90
- const schedule = await this.scheduledWorkflowRepository.findOne({
91
- where: { id: scheduleId },
92
- });
93
-
94
- if (!schedule) {
95
- throw new Error(`Scheduled workflow not found: ${scheduleId}`);
96
- }
97
-
98
- this.logger.debug(
99
- `📋 Loaded schedule from DB: ${JSON.stringify(schedule)}`,
100
- );
101
-
102
- // Execute workflow actions
103
- this.logger.log(`⚙️ Executing workflow actions...`);
104
- const result = await this.executeWorkflowActions(schedule, job.data);
105
- this.logger.debug(`🧮 Execution result: ${JSON.stringify(result)}`);
106
-
107
- // Update execution log with results
108
- const completedAt = new Date();
109
- executionLog.execution_status =
110
- result.failedRecords > 0 && result.successfulRecords > 0
111
- ? EXECUTION_STATUS_PARTIAL
112
- : result.failedRecords > 0
113
- ? EXECUTION_STATUS_FAILED
114
- : EXECUTION_STATUS_COMPLETED;
115
- executionLog.completed_at = completedAt;
116
- executionLog.duration_ms =
117
- completedAt.getTime() - executionLog.started_at.getTime();
118
- executionLog.total_records = result.totalRecords;
119
- executionLog.successful_records = result.successfulRecords;
120
- executionLog.failed_records = result.failedRecords;
121
- executionLog.execution_details = {
122
- batchesProcessed: Math.ceil(result.totalRecords / DEFAULT_BATCH_SIZE),
123
- errors: result.errors,
124
- };
125
-
126
- await this.executionLogRepository.save(executionLog);
127
-
128
- // Update schedule execution count and last execution time
129
- schedule.execution_count += 1;
130
- schedule.last_execution_at = completedAt;
131
- await this.scheduledWorkflowRepository.save(schedule);
132
-
133
- this.logger.log(
134
- `✅ Workflow execution completed: scheduleId=${scheduleId}, status=${executionLog.execution_status}, processed=${result.totalRecords}`,
135
- );
136
-
137
- return {
138
- success: true,
139
- executionLogId: executionLog.id,
140
- result,
141
- };
142
- } catch (error) {
143
- this.logger.error(
144
- `🔥 Workflow execution failed: scheduleId=${scheduleId}, error=${error.message}`,
145
- error.stack,
146
- );
147
-
148
- // Update execution log with error
149
- executionLog.execution_status = EXECUTION_STATUS_FAILED;
150
- executionLog.completed_at = new Date();
151
- executionLog.duration_ms = executionLog.started_at
152
- ? executionLog.completed_at.getTime() -
153
- executionLog.started_at.getTime()
154
- : 0;
155
- executionLog.error_message = error.message;
156
- executionLog.error_stack = error.stack;
157
-
158
- await this.executionLogRepository.save(executionLog);
159
-
160
- throw error;
161
- }
162
- }
163
-
164
- /**
165
- * Execute all actions defined in the workflow
166
- */
167
- private async executeWorkflowActions(
168
- schedule: ScheduledWorkflow,
169
- jobData: ScheduleJobData,
170
- ): Promise<BatchProcessingResult> {
171
- const result: BatchProcessingResult = {
172
- totalRecords: 0,
173
- processedRecords: 0,
174
- successfulRecords: 0,
175
- failedRecords: 0,
176
- errors: [],
177
- };
178
-
179
- const resultData: any =
180
- await this.scheduleHandlerService.handleScheduledWorkflow(
181
- jobData.workflowId,
182
- jobData,
183
- );
184
-
185
- if (!schedule.actions || schedule.actions.length === 0) {
186
- this.logger.warn(`No actions defined for schedule: ${schedule.id}`);
187
- return result;
188
- }
189
-
190
- // Execute each action sequentially
191
- for (const action of schedule.actions) {
192
- try {
193
- const actionResult = await this.executeAction(action, jobData);
194
- result.totalRecords += actionResult.totalRecords;
195
- result.processedRecords += actionResult.processedRecords;
196
- result.successfulRecords += actionResult.successfulRecords;
197
- result.failedRecords += actionResult.failedRecords;
198
- result.errors.push(...actionResult.errors);
199
- } catch (error) {
200
- this.logger.error(
201
- `Action execution failed: actionType=${action.actionType}, error=${error.message}`,
202
- );
203
- result.failedRecords += 1;
204
- result.errors.push({
205
- error: `Action ${action.actionType} failed: ${error.message}`,
206
- });
207
- }
208
- }
209
-
210
- return resultData;
211
- }
212
-
213
- /**
214
- * Execute a single workflow action
215
- */
216
- private async executeAction(action: any, jobData: ScheduleJobData) {
217
- this.logger.log(`🚀 Executing scheduled action: ${action.actionType}`);
218
-
219
- try {
220
- // We’ll assume jobData contains workflowId and user info
221
- const { workflowId, loggedInUser } = jobData;
222
-
223
- // 🧠 Call your handler that performs filtering and workflow execution
224
- const result: any =
225
- await this.scheduleHandlerService.handleScheduledWorkflow(
226
- workflowId,
227
- loggedInUser,
228
- );
229
-
230
- this.logger.log(
231
- `✅ Scheduled workflow ${workflowId} executed successfully`,
232
- );
233
- return {
234
- totalRecords: result?.length || 0,
235
- processedRecords: result?.length || 0,
236
- successfulRecords: result?.length || 0,
237
- failedRecords: 0,
238
- errors: [],
239
- };
240
- } catch (error) {
241
- this.logger.error(
242
- `🔥 Error executing scheduled workflow action: ${error.message}`,
243
- error.stack,
244
- );
245
- return {
246
- totalRecords: 0,
247
- processedRecords: 0,
248
- successfulRecords: 0,
249
- failedRecords: 1,
250
- errors: [{ error: error.message }],
251
- };
252
- }
253
- }
254
-
255
- /**
256
- * Execute send email action
257
- */
258
- private async executeSendEmailAction(
259
- action: any,
260
- jobData: ScheduleJobData,
261
- ): Promise<BatchProcessingResult> {
262
- const result: BatchProcessingResult = {
263
- totalRecords: 0,
264
- processedRecords: 0,
265
- successfulRecords: 0,
266
- failedRecords: 0,
267
- errors: [],
268
- };
269
-
270
- try {
271
- // Get target records based on filter criteria
272
- const records = await this.getTargetRecords(
273
- action.targetEntityType,
274
- action.filterCriteria,
275
- jobData,
276
- );
277
-
278
- result.totalRecords = records.length;
279
-
280
- // Process in batches
281
- const batches = this.chunkArray(records, DEFAULT_BATCH_SIZE);
282
-
283
- for (const batch of batches) {
284
- for (const record of batch) {
285
- try {
286
- // TODO: Integrate with email service
287
- // await this.emailService.sendEmail({
288
- // to: record.email,
289
- // subject: action.actionConfig.subject,
290
- // template: action.actionConfig.template,
291
- // data: record,
292
- // });
293
-
294
- result.processedRecords += 1;
295
- result.successfulRecords += 1;
296
- } catch (error) {
297
- result.processedRecords += 1;
298
- result.failedRecords += 1;
299
- result.errors.push({
300
- recordId: record.id,
301
- error: error.message,
302
- });
303
- }
304
- }
305
- }
306
- } catch (error) {
307
- throw new Error(`Send email action failed: ${error.message}`);
308
- }
309
-
310
- return result;
311
- }
312
-
313
- /**
314
- * Execute update records action
315
- */
316
- private async executeUpdateRecordsAction(
317
- action: any,
318
- jobData: ScheduleJobData,
319
- ): Promise<BatchProcessingResult> {
320
- const result: BatchProcessingResult = {
321
- totalRecords: 0,
322
- processedRecords: 0,
323
- successfulRecords: 0,
324
- failedRecords: 0,
325
- errors: [],
326
- };
327
-
328
- try {
329
- // Get target records
330
- const records = await this.getTargetRecords(
331
- action.targetEntityType,
332
- action.filterCriteria,
333
- jobData,
334
- );
335
-
336
- result.totalRecords = records.length;
337
-
338
- // Process in batches
339
- const batches = this.chunkArray(records, DEFAULT_BATCH_SIZE);
340
-
341
- for (const batch of batches) {
342
- const queryRunner = this.dataSource.createQueryRunner();
343
- await queryRunner.connect();
344
- await queryRunner.startTransaction();
345
-
346
- try {
347
- for (const record of batch) {
348
- // Build update query based on action config
349
- const updateFields = action.actionConfig.updateFields || {};
350
- const updateValues = Object.keys(updateFields).map((key) => {
351
- return `${key} = ?`;
352
- });
353
- const values = Object.values(updateFields);
354
-
355
- if (updateValues.length > 0) {
356
- const tableName = this.getTableNameForEntityType(
357
- action.targetEntityType,
358
- );
359
- await queryRunner.query(
360
- `UPDATE ${tableName} SET ${updateValues.join(', ')} WHERE id = ?`,
361
- [...values, record.id],
362
- );
363
- }
364
-
365
- result.processedRecords += 1;
366
- result.successfulRecords += 1;
367
- }
368
-
369
- await queryRunner.commitTransaction();
370
- } catch (error) {
371
- await queryRunner.rollbackTransaction();
372
- result.failedRecords += batch.length;
373
- result.errors.push({
374
- error: `Batch update failed: ${error.message}`,
375
- });
376
- } finally {
377
- await queryRunner.release();
378
- }
379
- }
380
- } catch (error) {
381
- throw new Error(`Update records action failed: ${error.message}`);
382
- }
383
-
384
- return result;
385
- }
386
-
387
- /**
388
- * Execute create task action
389
- */
390
- private async executeCreateTaskAction(
391
- action: any,
392
- jobData: ScheduleJobData,
393
- ): Promise<BatchProcessingResult> {
394
- const result: BatchProcessingResult = {
395
- totalRecords: 0,
396
- processedRecords: 0,
397
- successfulRecords: 0,
398
- failedRecords: 0,
399
- errors: [],
400
- };
401
-
402
- try {
403
- // Get target records
404
- const records = await this.getTargetRecords(
405
- action.targetEntityType,
406
- action.filterCriteria,
407
- jobData,
408
- );
409
-
410
- result.totalRecords = records.length;
411
-
412
- // Task repo (cr_wf_task)
413
- const taskRepo = this.reflectionHelper.getRepoService('TaskDataEntity');
414
-
415
- // Process in batches
416
- const batches = this.chunkArray(records, DEFAULT_BATCH_SIZE);
417
-
418
- for (const batch of batches) {
419
- for (const record of batch) {
420
- try {
421
- // Build task object
422
- const task = {
423
- name: action.actionConfig.taskName || 'Scheduled Task',
424
- description: action.actionConfig.taskDescription || '',
425
- status: 'PENDING',
426
- mapped_entity_id: record.id,
427
- mapped_entity_type: action.targetEntityType,
428
- organization_id: jobData.organizationId,
429
- enterprise_id: jobData.enterpriseId,
430
- created_by: jobData.createdBy,
431
- created_date: new Date(), // NOW()
432
- entity_type: 'WFTK',
433
- };
434
-
435
- // Insert using TypeORM repository
436
- await taskRepo.insert(task);
437
-
438
- result.processedRecords += 1;
439
- result.successfulRecords += 1;
440
- } catch (error) {
441
- result.processedRecords += 1;
442
- result.failedRecords += 1;
443
-
444
- result.errors.push({
445
- recordId: record.id,
446
- error: error.message,
447
- });
448
- }
449
- }
450
- }
451
- } catch (error) {
452
- throw new Error(`Create task action failed: ${error.message}`);
453
- }
454
-
455
- return result;
456
- }
457
-
458
- /**
459
- * Execute send notification action
460
- */
461
- private async executeSendNotificationAction(
462
- action: any,
463
- jobData: ScheduleJobData,
464
- ): Promise<BatchProcessingResult> {
465
- const result: BatchProcessingResult = {
466
- totalRecords: 0,
467
- processedRecords: 0,
468
- successfulRecords: 0,
469
- failedRecords: 0,
470
- errors: [],
471
- };
472
-
473
- try {
474
- // Get target records
475
- const records = await this.getTargetRecords(
476
- action.targetEntityType,
477
- action.filterCriteria,
478
- jobData,
479
- );
480
-
481
- result.totalRecords = records.length;
482
-
483
- // Prepare repo
484
- const notificationRepo = this.reflectionHelper.getRepoService(
485
- 'NotificationData', // cr_notification repo
486
- );
487
-
488
- // Process in batches
489
- const batches = this.chunkArray(records, DEFAULT_BATCH_SIZE);
490
-
491
- for (const batch of batches) {
492
- for (const record of batch) {
493
- try {
494
- // Build notification object
495
- const notification = {
496
- user_id: record.user_id || jobData.createdBy,
497
- event_type: action.actionConfig.eventType || 'WORKFLOW_SCHEDULED',
498
- message:
499
- action.actionConfig.message || 'Scheduled workflow executed',
500
- mapped_entity_id: record.id,
501
- mapped_entity_type: action.targetEntityType,
502
- is_read: 0,
503
- organization_id: jobData.organizationId,
504
- created_date: new Date(), // NOW()
505
- entity_type: 'NOTF',
506
- status: 'ACTIVE',
507
- };
508
-
509
- // Insert using TypeORM (replaces raw SQL)
510
- await notificationRepo.insert(notification);
511
-
512
- result.processedRecords += 1;
513
- result.successfulRecords += 1;
514
- } catch (error) {
515
- result.processedRecords += 1;
516
- result.failedRecords += 1;
517
-
518
- result.errors.push({
519
- recordId: record.id,
520
- error: error.message,
521
- });
522
- }
523
- }
524
- }
525
- } catch (error) {
526
- throw new Error(`Send notification action failed: ${error.message}`);
527
- }
528
-
529
- return result;
530
- }
531
-
532
- /**
533
- * Get target records based on entity type and filter criteria
534
- */
535
- private async getTargetRecords(
536
- entityType: string,
537
- filterCriteria: any,
538
- jobData: ScheduleJobData,
539
- ): Promise<any[]> {
540
- // Get repository dynamically based on entityType
541
- const repo = this.reflectionHelper.getRepoService(entityType);
542
-
543
- // Start QueryBuilder
544
- const qb = repo.createQueryBuilder('e');
545
-
546
- // Mandatory organization filter
547
- qb.where('e.organization_id = :orgId', {
548
- orgId: jobData.organizationId,
549
- });
550
-
551
- // Apply additional filters
552
- if (filterCriteria && Object.keys(filterCriteria).length > 0) {
553
- for (const key of Object.keys(filterCriteria)) {
554
- qb.andWhere(`e.${key} = :${key}`, {
555
- [key]: filterCriteria[key],
556
- });
557
- }
558
- }
559
-
560
- const records = await qb.getMany();
561
- return records;
562
- }
563
-
564
- /**
565
- * Get table name for entity type
566
- */
567
- private getTableNameForEntityType(entityType: string): string {
568
- // Map entity types to table names
569
- const entityTypeMap: Record<string, string> = {
570
- USR: 'sso_user',
571
- LEAD: 'cr_lead',
572
- TASK: 'cr_wf_task',
573
- // Add more mappings as needed
574
- };
575
-
576
- return entityTypeMap[entityType] || 'unknown_table';
577
- }
578
-
579
- /**
580
- * Split array into chunks
581
- */
582
- private chunkArray<T>(array: T[], chunkSize: number): T[][] {
583
- const chunks: T[][] = [];
584
- for (let i = 0; i < array.length; i += chunkSize) {
585
- chunks.push(array.slice(i, i + chunkSize));
586
- }
587
- return chunks;
588
- }
589
-
590
- /**
591
- * Event handler for when job becomes active
592
- */
593
- @OnQueueActive()
594
- onActive(job: Job<ScheduleJobData>) {
595
- this.logger.log(
596
- `Processing job ${job.id} of type ${job.name} for schedule ${job.data.scheduleId}`,
597
- );
598
- }
599
-
600
- /**
601
- * Event handler for when job completes
602
- */
603
- @OnQueueCompleted()
604
- onCompleted(job: Job<ScheduleJobData>, result: any) {
605
- this.logger.log(
606
- `Job ${job.id} completed for schedule ${job.data.scheduleId} with result: ${JSON.stringify(result)}`,
607
- );
608
- }
609
-
610
- /**
611
- * Event handler for when job fails
612
- */
613
- @OnQueueFailed()
614
- onFailed(job: Job<ScheduleJobData>, error: Error) {
615
- this.logger.error(
616
- `Job ${job.id} failed for schedule ${job.data.scheduleId} with error: ${error.message}`,
617
- error.stack,
618
- );
619
- }
620
- }
1
+ import {
2
+ Process,
3
+ Processor,
4
+ OnQueueActive,
5
+ OnQueueCompleted,
6
+ OnQueueFailed,
7
+ } from '@nestjs/bull';
8
+ import { Logger, Inject } from '@nestjs/common';
9
+ import { Job } from 'bull';
10
+ import { InjectRepository } from '@nestjs/typeorm';
11
+ import { Repository, DataSource } from 'typeorm';
12
+ import { ScheduledWorkflow } from '../entities/scheduled-workflow.entity';
13
+ import { WorkflowExecutionLog } from '../entities/workflow-execution-log.entity';
14
+ import {
15
+ WORKFLOW_SCHEDULE_QUEUE,
16
+ EXECUTE_SCHEDULED_WORKFLOW_JOB,
17
+ EXECUTION_STATUS_PENDING,
18
+ EXECUTION_STATUS_RUNNING,
19
+ EXECUTION_STATUS_COMPLETED,
20
+ EXECUTION_STATUS_FAILED,
21
+ EXECUTION_STATUS_PARTIAL,
22
+ DEFAULT_BATCH_SIZE,
23
+ } from '../constants/schedule.constants';
24
+ import {
25
+ ScheduleJobData,
26
+ BatchProcessingResult,
27
+ } from '../interfaces/schedule-job-data.interface';
28
+ import { ScheduleHandlerService } from 'src/module/workflow-automation/service/schedule-handler.service';
29
+ import { ReflectionHelper } from 'src/utils/service/reflection-helper.service';
30
+
31
+ /**
32
+ * Schedule Processor
33
+ * Processes scheduled workflow execution jobs from Bull queue
34
+ */
35
+ @Processor(WORKFLOW_SCHEDULE_QUEUE)
36
+ export class ScheduleProcessor {
37
+ private readonly logger = new Logger(ScheduleProcessor.name);
38
+
39
+ constructor(
40
+ @InjectRepository(ScheduledWorkflow)
41
+ private readonly scheduledWorkflowRepository: Repository<ScheduledWorkflow>,
42
+ @InjectRepository(WorkflowExecutionLog)
43
+ private readonly executionLogRepository: Repository<WorkflowExecutionLog>,
44
+ @Inject('ScheduleHandlerService')
45
+ private readonly scheduleHandlerService: ScheduleHandlerService,
46
+ private readonly reflectionHelper: ReflectionHelper,
47
+ private readonly dataSource: DataSource
48
+ ) {}
49
+
50
+ /**
51
+ * Main job processor for scheduled workflow execution
52
+ */
53
+ @Process(EXECUTE_SCHEDULED_WORKFLOW_JOB)
54
+ async handleScheduledWorkflowExecution(job: Job<ScheduleJobData>) {
55
+ const { scheduleId, workflowId, organizationId, triggeredBy, createdBy } =
56
+ job.data;
57
+
58
+ this.logger.log(
59
+ `🚀 [handleScheduledWorkflowExecution] Invoked for scheduleId=${scheduleId}, workflowId=${workflowId}`,
60
+ );
61
+
62
+ // Create execution log entry
63
+ const executionLog = this.executionLogRepository.create({
64
+ schedule_id: scheduleId,
65
+ workflow_id: workflowId,
66
+ job_id: job.id.toString(),
67
+ execution_status: EXECUTION_STATUS_PENDING,
68
+ triggered_by: triggeredBy,
69
+ triggered_by_user_id: triggeredBy === 'MANUAL' ? createdBy : null,
70
+ organization_id: organizationId,
71
+ enterprise_id: job.data.enterpriseId,
72
+ created_by: createdBy,
73
+ entity_type: 'WFEL',
74
+ });
75
+
76
+ this.logger.debug(`🧾 Creating execution log for jobId=${job.id}`);
77
+ await this.executionLogRepository.save(executionLog);
78
+
79
+ try {
80
+ // Update status to running
81
+ executionLog.execution_status = EXECUTION_STATUS_RUNNING;
82
+ executionLog.started_at = new Date();
83
+ await this.executionLogRepository.save(executionLog);
84
+
85
+ this.logger.log(
86
+ `🏃 Workflow execution started for scheduleId=${scheduleId}`,
87
+ );
88
+
89
+ // Get scheduled workflow details
90
+ const schedule = await this.scheduledWorkflowRepository.findOne({
91
+ where: { id: scheduleId },
92
+ });
93
+
94
+ if (!schedule) {
95
+ throw new Error(`Scheduled workflow not found: ${scheduleId}`);
96
+ }
97
+
98
+ this.logger.debug(
99
+ `📋 Loaded schedule from DB: ${JSON.stringify(schedule)}`,
100
+ );
101
+
102
+ // Execute workflow actions
103
+ this.logger.log(`⚙️ Executing workflow actions...`);
104
+ const result = await this.executeWorkflowActions(schedule, job.data);
105
+ this.logger.debug(`🧮 Execution result: ${JSON.stringify(result)}`);
106
+
107
+ // Update execution log with results
108
+ const completedAt = new Date();
109
+ executionLog.execution_status =
110
+ result.failedRecords > 0 && result.successfulRecords > 0
111
+ ? EXECUTION_STATUS_PARTIAL
112
+ : result.failedRecords > 0
113
+ ? EXECUTION_STATUS_FAILED
114
+ : EXECUTION_STATUS_COMPLETED;
115
+ executionLog.completed_at = completedAt;
116
+ executionLog.duration_ms =
117
+ completedAt.getTime() - executionLog.started_at.getTime();
118
+ executionLog.total_records = result.totalRecords;
119
+ executionLog.successful_records = result.successfulRecords;
120
+ executionLog.failed_records = result.failedRecords;
121
+ executionLog.execution_details = {
122
+ batchesProcessed: Math.ceil(result.totalRecords / DEFAULT_BATCH_SIZE),
123
+ errors: result.errors,
124
+ };
125
+
126
+ await this.executionLogRepository.save(executionLog);
127
+
128
+ // Update schedule execution count and last execution time
129
+ schedule.execution_count += 1;
130
+ schedule.last_execution_at = completedAt;
131
+ await this.scheduledWorkflowRepository.save(schedule);
132
+
133
+ this.logger.log(
134
+ `✅ Workflow execution completed: scheduleId=${scheduleId}, status=${executionLog.execution_status}, processed=${result.totalRecords}`,
135
+ );
136
+
137
+ return {
138
+ success: true,
139
+ executionLogId: executionLog.id,
140
+ result,
141
+ };
142
+ } catch (error) {
143
+ this.logger.error(
144
+ `🔥 Workflow execution failed: scheduleId=${scheduleId}, error=${error.message}`,
145
+ error.stack,
146
+ );
147
+
148
+ // Update execution log with error
149
+ executionLog.execution_status = EXECUTION_STATUS_FAILED;
150
+ executionLog.completed_at = new Date();
151
+ executionLog.duration_ms = executionLog.started_at
152
+ ? executionLog.completed_at.getTime() -
153
+ executionLog.started_at.getTime()
154
+ : 0;
155
+ executionLog.error_message = error.message;
156
+ executionLog.error_stack = error.stack;
157
+
158
+ await this.executionLogRepository.save(executionLog);
159
+
160
+ throw error;
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Execute all actions defined in the workflow
166
+ */
167
+ private async executeWorkflowActions(
168
+ schedule: ScheduledWorkflow,
169
+ jobData: ScheduleJobData,
170
+ ): Promise<BatchProcessingResult> {
171
+ const result: BatchProcessingResult = {
172
+ totalRecords: 0,
173
+ processedRecords: 0,
174
+ successfulRecords: 0,
175
+ failedRecords: 0,
176
+ errors: [],
177
+ };
178
+
179
+ const resultData: any =
180
+ await this.scheduleHandlerService.handleScheduledWorkflow(
181
+ jobData.workflowId,
182
+ jobData,
183
+ );
184
+
185
+ if (!schedule.actions || schedule.actions.length === 0) {
186
+ this.logger.warn(`No actions defined for schedule: ${schedule.id}`);
187
+ return result;
188
+ }
189
+
190
+ // Execute each action sequentially
191
+ for (const action of schedule.actions) {
192
+ try {
193
+ const actionResult = await this.executeAction(action, jobData);
194
+ result.totalRecords += actionResult.totalRecords;
195
+ result.processedRecords += actionResult.processedRecords;
196
+ result.successfulRecords += actionResult.successfulRecords;
197
+ result.failedRecords += actionResult.failedRecords;
198
+ result.errors.push(...actionResult.errors);
199
+ } catch (error) {
200
+ this.logger.error(
201
+ `Action execution failed: actionType=${action.actionType}, error=${error.message}`,
202
+ );
203
+ result.failedRecords += 1;
204
+ result.errors.push({
205
+ error: `Action ${action.actionType} failed: ${error.message}`,
206
+ });
207
+ }
208
+ }
209
+
210
+ return resultData;
211
+ }
212
+
213
+ /**
214
+ * Execute a single workflow action
215
+ */
216
+ private async executeAction(action: any, jobData: ScheduleJobData) {
217
+ this.logger.log(`🚀 Executing scheduled action: ${action.actionType}`);
218
+
219
+ try {
220
+ // We’ll assume jobData contains workflowId and user info
221
+ const { workflowId, loggedInUser } = jobData;
222
+
223
+ // 🧠 Call your handler that performs filtering and workflow execution
224
+ const result: any =
225
+ await this.scheduleHandlerService.handleScheduledWorkflow(
226
+ workflowId,
227
+ loggedInUser,
228
+ );
229
+
230
+ this.logger.log(
231
+ `✅ Scheduled workflow ${workflowId} executed successfully`,
232
+ );
233
+ return {
234
+ totalRecords: result?.length || 0,
235
+ processedRecords: result?.length || 0,
236
+ successfulRecords: result?.length || 0,
237
+ failedRecords: 0,
238
+ errors: [],
239
+ };
240
+ } catch (error) {
241
+ this.logger.error(
242
+ `🔥 Error executing scheduled workflow action: ${error.message}`,
243
+ error.stack,
244
+ );
245
+ return {
246
+ totalRecords: 0,
247
+ processedRecords: 0,
248
+ successfulRecords: 0,
249
+ failedRecords: 1,
250
+ errors: [{ error: error.message }],
251
+ };
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Execute send email action
257
+ */
258
+ private async executeSendEmailAction(
259
+ action: any,
260
+ jobData: ScheduleJobData,
261
+ ): Promise<BatchProcessingResult> {
262
+ const result: BatchProcessingResult = {
263
+ totalRecords: 0,
264
+ processedRecords: 0,
265
+ successfulRecords: 0,
266
+ failedRecords: 0,
267
+ errors: [],
268
+ };
269
+
270
+ try {
271
+ // Get target records based on filter criteria
272
+ const records = await this.getTargetRecords(
273
+ action.targetEntityType,
274
+ action.filterCriteria,
275
+ jobData,
276
+ );
277
+
278
+ result.totalRecords = records.length;
279
+
280
+ // Process in batches
281
+ const batches = this.chunkArray(records, DEFAULT_BATCH_SIZE);
282
+
283
+ for (const batch of batches) {
284
+ for (const record of batch) {
285
+ try {
286
+ // TODO: Integrate with email service
287
+ // await this.emailService.sendEmail({
288
+ // to: record.email,
289
+ // subject: action.actionConfig.subject,
290
+ // template: action.actionConfig.template,
291
+ // data: record,
292
+ // });
293
+
294
+ result.processedRecords += 1;
295
+ result.successfulRecords += 1;
296
+ } catch (error) {
297
+ result.processedRecords += 1;
298
+ result.failedRecords += 1;
299
+ result.errors.push({
300
+ recordId: record.id,
301
+ error: error.message,
302
+ });
303
+ }
304
+ }
305
+ }
306
+ } catch (error) {
307
+ throw new Error(`Send email action failed: ${error.message}`);
308
+ }
309
+
310
+ return result;
311
+ }
312
+
313
+ /**
314
+ * Execute update records action
315
+ */
316
+ private async executeUpdateRecordsAction(
317
+ action: any,
318
+ jobData: ScheduleJobData,
319
+ ): Promise<BatchProcessingResult> {
320
+ const result: BatchProcessingResult = {
321
+ totalRecords: 0,
322
+ processedRecords: 0,
323
+ successfulRecords: 0,
324
+ failedRecords: 0,
325
+ errors: [],
326
+ };
327
+
328
+ try {
329
+ // Get target records
330
+ const records = await this.getTargetRecords(
331
+ action.targetEntityType,
332
+ action.filterCriteria,
333
+ jobData,
334
+ );
335
+
336
+ result.totalRecords = records.length;
337
+
338
+ // Process in batches
339
+ const batches = this.chunkArray(records, DEFAULT_BATCH_SIZE);
340
+
341
+ for (const batch of batches) {
342
+ const queryRunner = this.dataSource.createQueryRunner();
343
+ await queryRunner.connect();
344
+ await queryRunner.startTransaction();
345
+
346
+ try {
347
+ for (const record of batch) {
348
+ // Build update query based on action config
349
+ const updateFields = action.actionConfig.updateFields || {};
350
+ const updateValues = Object.keys(updateFields).map((key) => {
351
+ return `${key} = ?`;
352
+ });
353
+ const values = Object.values(updateFields);
354
+
355
+ if (updateValues.length > 0) {
356
+ const tableName = this.getTableNameForEntityType(
357
+ action.targetEntityType,
358
+ );
359
+ await queryRunner.query(
360
+ `UPDATE ${tableName} SET ${updateValues.join(', ')} WHERE id = ?`,
361
+ [...values, record.id],
362
+ );
363
+ }
364
+
365
+ result.processedRecords += 1;
366
+ result.successfulRecords += 1;
367
+ }
368
+
369
+ await queryRunner.commitTransaction();
370
+ } catch (error) {
371
+ await queryRunner.rollbackTransaction();
372
+ result.failedRecords += batch.length;
373
+ result.errors.push({
374
+ error: `Batch update failed: ${error.message}`,
375
+ });
376
+ } finally {
377
+ await queryRunner.release();
378
+ }
379
+ }
380
+ } catch (error) {
381
+ throw new Error(`Update records action failed: ${error.message}`);
382
+ }
383
+
384
+ return result;
385
+ }
386
+
387
+ /**
388
+ * Execute create task action
389
+ */
390
+ private async executeCreateTaskAction(
391
+ action: any,
392
+ jobData: ScheduleJobData,
393
+ ): Promise<BatchProcessingResult> {
394
+ const result: BatchProcessingResult = {
395
+ totalRecords: 0,
396
+ processedRecords: 0,
397
+ successfulRecords: 0,
398
+ failedRecords: 0,
399
+ errors: [],
400
+ };
401
+
402
+ try {
403
+ // Get target records
404
+ const records = await this.getTargetRecords(
405
+ action.targetEntityType,
406
+ action.filterCriteria,
407
+ jobData,
408
+ );
409
+
410
+ result.totalRecords = records.length;
411
+
412
+ // Task repo (cr_wf_task)
413
+ const taskRepo = this.reflectionHelper.getRepoService('TaskDataEntity');
414
+
415
+ // Process in batches
416
+ const batches = this.chunkArray(records, DEFAULT_BATCH_SIZE);
417
+
418
+ for (const batch of batches) {
419
+ for (const record of batch) {
420
+ try {
421
+ // Build task object
422
+ const task = {
423
+ name: action.actionConfig.taskName || 'Scheduled Task',
424
+ description: action.actionConfig.taskDescription || '',
425
+ status: 'PENDING',
426
+ mapped_entity_id: record.id,
427
+ mapped_entity_type: action.targetEntityType,
428
+ organization_id: jobData.organizationId,
429
+ enterprise_id: jobData.enterpriseId,
430
+ created_by: jobData.createdBy,
431
+ created_date: new Date(), // NOW()
432
+ entity_type: 'WFTK',
433
+ };
434
+
435
+ // Insert using TypeORM repository
436
+ await taskRepo.insert(task);
437
+
438
+ result.processedRecords += 1;
439
+ result.successfulRecords += 1;
440
+ } catch (error) {
441
+ result.processedRecords += 1;
442
+ result.failedRecords += 1;
443
+
444
+ result.errors.push({
445
+ recordId: record.id,
446
+ error: error.message,
447
+ });
448
+ }
449
+ }
450
+ }
451
+ } catch (error) {
452
+ throw new Error(`Create task action failed: ${error.message}`);
453
+ }
454
+
455
+ return result;
456
+ }
457
+
458
+ /**
459
+ * Execute send notification action
460
+ */
461
+ private async executeSendNotificationAction(
462
+ action: any,
463
+ jobData: ScheduleJobData,
464
+ ): Promise<BatchProcessingResult> {
465
+ const result: BatchProcessingResult = {
466
+ totalRecords: 0,
467
+ processedRecords: 0,
468
+ successfulRecords: 0,
469
+ failedRecords: 0,
470
+ errors: [],
471
+ };
472
+
473
+ try {
474
+ // Get target records
475
+ const records = await this.getTargetRecords(
476
+ action.targetEntityType,
477
+ action.filterCriteria,
478
+ jobData,
479
+ );
480
+
481
+ result.totalRecords = records.length;
482
+
483
+ // Prepare repo
484
+ const notificationRepo = this.reflectionHelper.getRepoService(
485
+ 'NotificationData', // cr_notification repo
486
+ );
487
+
488
+ // Process in batches
489
+ const batches = this.chunkArray(records, DEFAULT_BATCH_SIZE);
490
+
491
+ for (const batch of batches) {
492
+ for (const record of batch) {
493
+ try {
494
+ // Build notification object
495
+ const notification = {
496
+ user_id: record.user_id || jobData.createdBy,
497
+ event_type: action.actionConfig.eventType || 'WORKFLOW_SCHEDULED',
498
+ message:
499
+ action.actionConfig.message || 'Scheduled workflow executed',
500
+ mapped_entity_id: record.id,
501
+ mapped_entity_type: action.targetEntityType,
502
+ is_read: 0,
503
+ organization_id: jobData.organizationId,
504
+ created_date: new Date(), // NOW()
505
+ entity_type: 'NOTF',
506
+ status: 'ACTIVE',
507
+ };
508
+
509
+ // Insert using TypeORM (replaces raw SQL)
510
+ await notificationRepo.insert(notification);
511
+
512
+ result.processedRecords += 1;
513
+ result.successfulRecords += 1;
514
+ } catch (error) {
515
+ result.processedRecords += 1;
516
+ result.failedRecords += 1;
517
+
518
+ result.errors.push({
519
+ recordId: record.id,
520
+ error: error.message,
521
+ });
522
+ }
523
+ }
524
+ }
525
+ } catch (error) {
526
+ throw new Error(`Send notification action failed: ${error.message}`);
527
+ }
528
+
529
+ return result;
530
+ }
531
+
532
+ /**
533
+ * Get target records based on entity type and filter criteria
534
+ */
535
+ private async getTargetRecords(
536
+ entityType: string,
537
+ filterCriteria: any,
538
+ jobData: ScheduleJobData,
539
+ ): Promise<any[]> {
540
+ // Get repository dynamically based on entityType
541
+ const repo = this.reflectionHelper.getRepoService(entityType);
542
+
543
+ // Start QueryBuilder
544
+ const qb = repo.createQueryBuilder('e');
545
+
546
+ // Mandatory organization filter
547
+ qb.where('e.organization_id = :orgId', {
548
+ orgId: jobData.organizationId,
549
+ });
550
+
551
+ // Apply additional filters
552
+ if (filterCriteria && Object.keys(filterCriteria).length > 0) {
553
+ for (const key of Object.keys(filterCriteria)) {
554
+ qb.andWhere(`e.${key} = :${key}`, {
555
+ [key]: filterCriteria[key],
556
+ });
557
+ }
558
+ }
559
+
560
+ const records = await qb.getMany();
561
+ return records;
562
+ }
563
+
564
+ /**
565
+ * Get table name for entity type
566
+ */
567
+ private getTableNameForEntityType(entityType: string): string {
568
+ // Map entity types to table names
569
+ const entityTypeMap: Record<string, string> = {
570
+ USR: 'sso_user',
571
+ LEAD: 'cr_lead',
572
+ TASK: 'cr_wf_task',
573
+ // Add more mappings as needed
574
+ };
575
+
576
+ return entityTypeMap[entityType] || 'unknown_table';
577
+ }
578
+
579
+ /**
580
+ * Split array into chunks
581
+ */
582
+ private chunkArray<T>(array: T[], chunkSize: number): T[][] {
583
+ const chunks: T[][] = [];
584
+ for (let i = 0; i < array.length; i += chunkSize) {
585
+ chunks.push(array.slice(i, i + chunkSize));
586
+ }
587
+ return chunks;
588
+ }
589
+
590
+ /**
591
+ * Event handler for when job becomes active
592
+ */
593
+ @OnQueueActive()
594
+ onActive(job: Job<ScheduleJobData>) {
595
+ this.logger.log(
596
+ `Processing job ${job.id} of type ${job.name} for schedule ${job.data.scheduleId}`,
597
+ );
598
+ }
599
+
600
+ /**
601
+ * Event handler for when job completes
602
+ */
603
+ @OnQueueCompleted()
604
+ onCompleted(job: Job<ScheduleJobData>, result: any) {
605
+ this.logger.log(
606
+ `Job ${job.id} completed for schedule ${job.data.scheduleId} with result: ${JSON.stringify(result)}`,
607
+ );
608
+ }
609
+
610
+ /**
611
+ * Event handler for when job fails
612
+ */
613
+ @OnQueueFailed()
614
+ onFailed(job: Job<ScheduleJobData>, error: Error) {
615
+ this.logger.error(
616
+ `Job ${job.id} failed for schedule ${job.data.scheduleId} with error: ${error.message}`,
617
+ error.stack,
618
+ );
619
+ }
620
+ }