rez_core 3.1.199 → 3.1.200

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 (393) hide show
  1. package/.claude/settings.local.json +26 -0
  2. package/.idea/250218_nodejs_core.iml +9 -0
  3. package/.idea/codeStyles/Project.xml +59 -0
  4. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  5. package/.idea/copilot.data.migration.agent.xml +6 -0
  6. package/.idea/copilot.data.migration.ask.xml +6 -0
  7. package/.idea/copilot.data.migration.ask2agent.xml +6 -0
  8. package/.idea/copilot.data.migration.edit.xml +6 -0
  9. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  10. package/.idea/misc.xml +6 -0
  11. package/.idea/modules.xml +8 -0
  12. package/.idea/prettier.xml +6 -0
  13. package/.idea/vcs.xml +6 -0
  14. package/.prettierrc +3 -3
  15. package/README.md +99 -99
  16. package/dist/module/auth/guards/role.guard.js +3 -3
  17. package/dist/module/auth/services/auth.service.js +2 -2
  18. package/dist/module/filter/repository/saved-filter.repository.js +4 -4
  19. package/dist/module/filter/service/filter-evaluator.service.js +2 -2
  20. package/dist/module/filter/service/filter.service.js +7 -7
  21. package/dist/module/integration/examples/usage.example.js +9 -9
  22. package/dist/module/integration/service/integration.service.js +1 -1
  23. package/dist/module/integration/service/wrapper.service.js +25 -25
  24. package/dist/module/listmaster/service/list-master-item.service.js +2 -2
  25. package/dist/module/listmaster/service/list-master.service.js +2 -2
  26. package/dist/module/mapper/service/field-mapper.service.js +4 -4
  27. package/dist/module/mapper/service/mapper.service.js +2 -2
  28. package/dist/module/meta/controller/media.controller.d.ts +3 -0
  29. package/dist/module/meta/controller/media.controller.js +15 -0
  30. package/dist/module/meta/controller/media.controller.js.map +1 -1
  31. package/dist/module/meta/entity/entity-master.entity.d.ts +2 -0
  32. package/dist/module/meta/entity/entity-master.entity.js +8 -0
  33. package/dist/module/meta/entity/entity-master.entity.js.map +1 -1
  34. package/dist/module/meta/service/entity-dynamic.service.js +18 -18
  35. package/dist/module/meta/service/entity-list.service.js +3 -3
  36. package/dist/module/meta/service/entity-master.service.js +3 -3
  37. package/dist/module/meta/service/entity-relation.service.js +11 -11
  38. package/dist/module/meta/service/entity-service-impl.service.js +3 -3
  39. package/dist/module/meta/service/media-data.service.d.ts +5 -1
  40. package/dist/module/meta/service/media-data.service.js +59 -2
  41. package/dist/module/meta/service/media-data.service.js.map +1 -1
  42. package/dist/module/meta/service/resolver.service.js +3 -3
  43. package/dist/module/module/repository/menu.repository.js +12 -12
  44. package/dist/module/notification/service/notification.service.js +9 -9
  45. package/dist/module/user/controller/login.controller.js +18 -18
  46. package/dist/module/user/service/role.service.js +4 -4
  47. package/dist/module/user/service/user-session.service.js +2 -2
  48. package/dist/module/workflow/repository/action.repository.js +16 -16
  49. package/dist/module/workflow/repository/comm-template.repository.js +6 -6
  50. package/dist/module/workflow/repository/form-master.repository.js +2 -2
  51. package/dist/module/workflow/repository/stage-group.repository.js +23 -23
  52. package/dist/module/workflow/repository/stage-movement.repository.js +11 -11
  53. package/dist/module/workflow/repository/stage.repository.js +8 -8
  54. package/dist/module/workflow/service/action-template-mapping.service.js +10 -10
  55. package/dist/module/workflow/service/action.service.js +7 -7
  56. package/dist/module/workflow/service/entity-modification.service.js +6 -6
  57. package/dist/module/workflow/service/stage-group.service.js +2 -2
  58. package/dist/module/workflow/service/stage.service.js +2 -2
  59. package/dist/module/workflow/service/task.service.js +28 -28
  60. package/dist/module/workflow/service/workflow-list-master.service.js +15 -15
  61. package/dist/module/workflow/service/workflow-meta.service.js +50 -50
  62. package/dist/module/workflow/service/workflow.service.js +2 -2
  63. package/dist/tsconfig.build.tsbuildinfo +1 -1
  64. package/dist/utils/service/reflection-helper.service.js +2 -2
  65. package/docs/modules/event-driven-integration-design.md +91 -91
  66. package/docs/modules/integration.md +250 -250
  67. package/eslint.config.mjs +34 -34
  68. package/nest-cli.json +14 -14
  69. package/package.json +118 -118
  70. package/server.log +850 -0
  71. package/src/app.controller.ts +12 -12
  72. package/src/app.module.ts +49 -49
  73. package/src/app.service.ts +8 -8
  74. package/src/config/config.module.ts +18 -18
  75. package/src/config/database.config.ts +23 -23
  76. package/src/constant/global.constant.ts +67 -67
  77. package/src/core.module.ts +81 -81
  78. package/src/decorators/roles.decorator.ts +7 -7
  79. package/src/dtos/response.dto.ts +6 -6
  80. package/src/dtos/response.ts +5 -5
  81. package/src/index.ts +1 -1
  82. package/src/module/auth/auth.module.ts +49 -49
  83. package/src/module/auth/controller/auth.controller.ts +28 -28
  84. package/src/module/auth/guards/google-auth.guard.ts +9 -9
  85. package/src/module/auth/guards/jwt.guard.ts +22 -22
  86. package/src/module/auth/guards/role.guard.ts +68 -68
  87. package/src/module/auth/services/auth.service.ts +50 -50
  88. package/src/module/auth/services/jwt.service.ts +11 -11
  89. package/src/module/auth/strategies/google.strategy.ts +54 -54
  90. package/src/module/auth/strategies/jwt.strategy.ts +58 -58
  91. package/src/module/auth/strategies/local.strategy.ts +13 -13
  92. package/src/module/dashboard/controller/dashboard.controller.ts +36 -36
  93. package/src/module/dashboard/dashboard.module.ts +21 -21
  94. package/src/module/dashboard/entity/dashboard_page_data.entity.ts +27 -27
  95. package/src/module/dashboard/entity/widget_master.entity.ts +18 -18
  96. package/src/module/dashboard/repository/dashboard.repository.ts +42 -42
  97. package/src/module/dashboard/service/dashboard.service.ts +73 -73
  98. package/src/module/dev/dev.module.ts +12 -12
  99. package/src/module/dev/service/dev.service.ts +7 -7
  100. package/src/module/enterprise/controller/organization.controller.ts +36 -36
  101. package/src/module/enterprise/enterprise.module.ts +30 -30
  102. package/src/module/enterprise/entity/enterprise.entity.ts +37 -37
  103. package/src/module/enterprise/entity/organization-app-mapping.entity.ts +13 -13
  104. package/src/module/enterprise/entity/organization.entity.ts +92 -92
  105. package/src/module/enterprise/repository/enterprise.repository.ts +31 -31
  106. package/src/module/enterprise/repository/organization.repository.ts +26 -26
  107. package/src/module/enterprise/repository/school.repository.ts +281 -281
  108. package/src/module/enterprise/service/brand.service.ts +5 -5
  109. package/src/module/enterprise/service/enterprise.service.ts +16 -16
  110. package/src/module/enterprise/service/organization-app-mapping.service.ts +4 -4
  111. package/src/module/enterprise/service/organization.service.ts +145 -145
  112. package/src/module/filter/controller/filter.controller.ts +84 -84
  113. package/src/module/filter/dto/filter-request.dto.ts +38 -38
  114. package/src/module/filter/entity/saved-filter-detail.entity.ts +41 -41
  115. package/src/module/filter/entity/saved-filter-master.entity.ts +23 -23
  116. package/src/module/filter/filter.module.ts +31 -31
  117. package/src/module/filter/repository/saved-filter.repository.ts +168 -168
  118. package/src/module/filter/service/filter-evaluator.service.ts +86 -86
  119. package/src/module/filter/service/filter.service.ts +868 -868
  120. package/src/module/filter/service/saved-filter.service.ts +170 -170
  121. package/src/module/ics/controller/ics.controller.ts +21 -21
  122. package/src/module/ics/dto/ics.dto.ts +55 -55
  123. package/src/module/ics/ics.module.ts +13 -13
  124. package/src/module/ics/service/ics.service.ts +57 -57
  125. package/src/module/integration/controller/calender-event.controller.ts +31 -31
  126. package/src/module/integration/controller/integration.controller.ts +662 -662
  127. package/src/module/integration/controller/wrapper.controller.ts +37 -37
  128. package/src/module/integration/dto/create-config.dto.ts +526 -526
  129. package/src/module/integration/entity/integration-config.entity.ts +112 -112
  130. package/src/module/integration/entity/integration-entity-mapper.entity.ts +14 -14
  131. package/src/module/integration/entity/integration-source.entity.ts +17 -17
  132. package/src/module/integration/entity/user-integration.entity.ts +71 -71
  133. package/src/module/integration/examples/usage.example.ts +338 -338
  134. package/src/module/integration/factories/base.factory.ts +7 -7
  135. package/src/module/integration/factories/email.factory.ts +49 -49
  136. package/src/module/integration/factories/integration.factory.ts +121 -121
  137. package/src/module/integration/factories/sms.factory.ts +51 -51
  138. package/src/module/integration/factories/telephone.factory.ts +41 -41
  139. package/src/module/integration/factories/whatsapp.factory.ts +56 -56
  140. package/src/module/integration/integration.module.ts +110 -110
  141. package/src/module/integration/service/calendar-event.service.ts +118 -118
  142. package/src/module/integration/service/integration-entity-mapper.service.ts +17 -17
  143. package/src/module/integration/service/integration-queue.service.ts +229 -229
  144. package/src/module/integration/service/integration.service.ts +2572 -2572
  145. package/src/module/integration/service/oauth.service.ts +224 -224
  146. package/src/module/integration/service/wrapper.service.ts +457 -457
  147. package/src/module/integration/strategies/email/gmail-api.strategy.ts +280 -280
  148. package/src/module/integration/strategies/email/outlook-api.strategy.ts +44 -44
  149. package/src/module/integration/strategies/email/outlook.strategy.ts +64 -64
  150. package/src/module/integration/strategies/email/sendgrid-api.strategy.ts +260 -260
  151. package/src/module/integration/strategies/integration.strategy.ts +97 -97
  152. package/src/module/integration/strategies/sms/gupshup-sms.strategy.ts +146 -146
  153. package/src/module/integration/strategies/sms/msg91-sms.strategy.ts +164 -164
  154. package/src/module/integration/strategies/sms/tubelight-sms.strategy.ts +163 -163
  155. package/src/module/integration/strategies/telephone/ozonetel-voice.strategy.ts +238 -238
  156. package/src/module/integration/strategies/telephone/tubelight-voice.strategy.ts +210 -210
  157. package/src/module/integration/strategies/whatsapp/gupshup-whatsapp.strategy.ts +359 -359
  158. package/src/module/integration/strategies/whatsapp/tubelight-whatsapp.strategy.ts +372 -372
  159. package/src/module/integration/strategies/whatsapp/whatsapp-cloud.strategy.ts +403 -403
  160. package/src/module/integration/strategies/whatsapp/whatsapp.strategy.ts +57 -57
  161. package/src/module/layout/controller/layout.controller.ts +47 -47
  162. package/src/module/layout/entity/header-items.entity.ts +28 -28
  163. package/src/module/layout/entity/header-section.entity.ts +19 -19
  164. package/src/module/layout/layout.module.ts +21 -21
  165. package/src/module/layout/repository/header-items.repository.ts +18 -18
  166. package/src/module/layout/repository/header-section.repository.ts +22 -22
  167. package/src/module/layout/service/header-section.service.ts +25 -25
  168. package/src/module/layout_preference/controller/layout_preference.controller.ts +47 -47
  169. package/src/module/layout_preference/entity/layout_preference.entity.ts +28 -28
  170. package/src/module/layout_preference/layout_preference.module.ts +18 -18
  171. package/src/module/layout_preference/repository/layout_preference.repository.ts +30 -30
  172. package/src/module/layout_preference/service/layout_preference.service.ts +172 -172
  173. package/src/module/lead/controller/lead.controller.ts +30 -30
  174. package/src/module/lead/lead.module.ts +14 -14
  175. package/src/module/lead/repository/lead.repository.ts +41 -41
  176. package/src/module/lead/service/lead.service.ts +54 -54
  177. package/src/module/listmaster/controller/list-master.controller.ts +187 -187
  178. package/src/module/listmaster/entity/list-master-items.entity.ts +41 -41
  179. package/src/module/listmaster/entity/list-master.entity.ts +32 -32
  180. package/src/module/listmaster/listmaster.module.ts +44 -44
  181. package/src/module/listmaster/repository/list-master-items.repository.ts +169 -169
  182. package/src/module/listmaster/repository/list-master.repository.ts +46 -46
  183. package/src/module/listmaster/service/list-master-engine.ts +19 -19
  184. package/src/module/listmaster/service/list-master-extension.interface.ts +4 -4
  185. package/src/module/listmaster/service/list-master-item.service.ts +292 -292
  186. package/src/module/listmaster/service/list-master-registry.ts +15 -15
  187. package/src/module/listmaster/service/list-master.service.ts +424 -424
  188. package/src/module/mapper/controller/field-mapper.controller.ts +69 -69
  189. package/src/module/mapper/controller/mapper.controller.ts +15 -15
  190. package/src/module/mapper/dto/field-mapper.dto.ts +14 -14
  191. package/src/module/mapper/entity/field-lovs.entity.ts +19 -19
  192. package/src/module/mapper/entity/field-mapper.entity.ts +53 -53
  193. package/src/module/mapper/entity/mapper.entity.ts +16 -16
  194. package/src/module/mapper/mapper.module.ts +34 -34
  195. package/src/module/mapper/repository/field-lovs.repository.ts +35 -35
  196. package/src/module/mapper/repository/field-mapper.repository.ts +42 -42
  197. package/src/module/mapper/repository/mapper.repository.ts +15 -15
  198. package/src/module/mapper/service/field-mapper.service.ts +245 -245
  199. package/src/module/mapper/service/mapper.service.ts +79 -79
  200. package/src/module/master/controller/master.controller.ts +74 -74
  201. package/src/module/master/service/master.service.ts +483 -483
  202. package/src/module/meta/controller/app-master.controller.ts +38 -38
  203. package/src/module/meta/controller/attribute-master.controller.ts +66 -66
  204. package/src/module/meta/controller/entity-dynamic.controller.ts +125 -125
  205. package/src/module/meta/controller/entity-master.controller.ts +28 -28
  206. package/src/module/meta/controller/entity-relation.controller.ts +36 -36
  207. package/src/module/meta/controller/entity.controller.ts +385 -385
  208. package/src/module/meta/controller/entity.public.controller.ts +75 -75
  209. package/src/module/meta/controller/media.controller.ts +92 -82
  210. package/src/module/meta/controller/meta.controller.ts +96 -96
  211. package/src/module/meta/controller/view-master.controller.ts +86 -86
  212. package/src/module/meta/dto/entity-list-data.dto.ts +6 -6
  213. package/src/module/meta/dto/entity-tab.dto.ts +4 -4
  214. package/src/module/meta/dto/entity-table.dto.ts +9 -9
  215. package/src/module/meta/entity/app-master.entity.ts +34 -34
  216. package/src/module/meta/entity/attribute-master.entity.ts +87 -87
  217. package/src/module/meta/entity/base-entity.entity.ts +75 -75
  218. package/src/module/meta/entity/entity-master.entity.ts +84 -78
  219. package/src/module/meta/entity/entity-relation-data.entity.ts +29 -29
  220. package/src/module/meta/entity/entity-relation.entity.ts +23 -23
  221. package/src/module/meta/entity/entity-table-column.entity.ts +61 -61
  222. package/src/module/meta/entity/entity-table.entity.ts +50 -50
  223. package/src/module/meta/entity/media-data.entity.ts +32 -32
  224. package/src/module/meta/entity/preference.entity.ts +62 -62
  225. package/src/module/meta/entity/view-master.entity.ts +41 -41
  226. package/src/module/meta/entity.module.ts +158 -158
  227. package/src/module/meta/repository/app-master.repository.ts +20 -20
  228. package/src/module/meta/repository/attribute-master.repository.ts +110 -110
  229. package/src/module/meta/repository/entity-master.repository.ts +69 -69
  230. package/src/module/meta/repository/entity-table-column.repository.ts +39 -39
  231. package/src/module/meta/repository/entity-table.repository.ts +53 -53
  232. package/src/module/meta/repository/media-data.repository.ts +50 -50
  233. package/src/module/meta/repository/preference.repository.ts +20 -20
  234. package/src/module/meta/repository/user-app-mapping.repository.ts +28 -28
  235. package/src/module/meta/repository/view-master.repository.ts +42 -42
  236. package/src/module/meta/service/app-master.service.ts +37 -37
  237. package/src/module/meta/service/attribute-master.service.ts +117 -117
  238. package/src/module/meta/service/common.service.ts +9 -9
  239. package/src/module/meta/service/entity-dynamic.service.ts +762 -762
  240. package/src/module/meta/service/entity-list.service.ts +205 -205
  241. package/src/module/meta/service/entity-master.service.ts +164 -164
  242. package/src/module/meta/service/entity-realation-data.service.ts +9 -9
  243. package/src/module/meta/service/entity-relation.service.ts +69 -69
  244. package/src/module/meta/service/entity-service-impl.service.ts +524 -524
  245. package/src/module/meta/service/entity-table-column.service.ts +39 -39
  246. package/src/module/meta/service/entity-table.service.ts +150 -150
  247. package/src/module/meta/service/entity-validation.service.ts +185 -185
  248. package/src/module/meta/service/entity.service.ts +67 -67
  249. package/src/module/meta/service/field-group.service.ts +103 -103
  250. package/src/module/meta/service/media-data.service.ts +240 -149
  251. package/src/module/meta/service/populate-meta.service.ts +173 -173
  252. package/src/module/meta/service/preference.service.ts +16 -16
  253. package/src/module/meta/service/resolver.service.ts +240 -240
  254. package/src/module/meta/service/section-master.service.ts +104 -104
  255. package/src/module/meta/service/update-form-json.service.ts +22 -22
  256. package/src/module/meta/service/user-app-mapping.service.ts +17 -17
  257. package/src/module/meta/service/view-master.service.ts +111 -111
  258. package/src/module/module/controller/menu.controller.ts +15 -15
  259. package/src/module/module/controller/module-access.controller.ts +134 -134
  260. package/src/module/module/entity/menu.entity.ts +43 -43
  261. package/src/module/module/entity/module-access.entity.ts +25 -25
  262. package/src/module/module/entity/module-action.entity.ts +17 -17
  263. package/src/module/module/entity/module.entity.ts +52 -52
  264. package/src/module/module/module.module.ts +42 -42
  265. package/src/module/module/repository/menu.repository.ts +184 -184
  266. package/src/module/module/repository/module-access.repository.ts +344 -344
  267. package/src/module/module/service/menu.service.ts +82 -82
  268. package/src/module/module/service/module-access.service.ts +209 -209
  269. package/src/module/notification/controller/notification.controller.ts +58 -58
  270. package/src/module/notification/controller/otp.controller.ts +117 -117
  271. package/src/module/notification/entity/notification.entity.ts +26 -26
  272. package/src/module/notification/entity/otp.entity.ts +28 -28
  273. package/src/module/notification/firebase-admin.config.ts +22 -22
  274. package/src/module/notification/notification.module.ts +69 -69
  275. package/src/module/notification/repository/otp.repository.ts +27 -27
  276. package/src/module/notification/service/email.service.ts +127 -127
  277. package/src/module/notification/service/notification.service.ts +164 -164
  278. package/src/module/notification/service/otp.service.ts +132 -132
  279. package/src/module/third-party-module/entity/third-party-api-registry.entity.ts +52 -52
  280. package/src/module/third-party-module/repository/third-party-api-registry.repository.ts +20 -20
  281. package/src/module/third-party-module/service/api-registry.service.ts +13 -13
  282. package/src/module/third-party-module/third-party.module.ts +12 -12
  283. package/src/module/user/controller/login.controller.ts +197 -197
  284. package/src/module/user/controller/user.controller.ts +40 -40
  285. package/src/module/user/dto/create-user.dto.ts +62 -62
  286. package/src/module/user/dto/update-user.dto.ts +4 -4
  287. package/src/module/user/entity/role.entity.ts +33 -33
  288. package/src/module/user/entity/user-role-mapping.entity.ts +38 -38
  289. package/src/module/user/entity/user-session.entity.ts +61 -61
  290. package/src/module/user/entity/user.entity.ts +71 -71
  291. package/src/module/user/repository/role.repository.ts +96 -96
  292. package/src/module/user/repository/user-role-mapping.repository.ts +126 -126
  293. package/src/module/user/repository/user.repository.ts +50 -50
  294. package/src/module/user/repository/userSession.repository.ts +33 -33
  295. package/src/module/user/service/login.service.ts +280 -280
  296. package/src/module/user/service/role.service.ts +189 -189
  297. package/src/module/user/service/user-role-mapping.service.ts +98 -98
  298. package/src/module/user/service/user-session.service.ts +168 -168
  299. package/src/module/user/service/user.service.ts +353 -353
  300. package/src/module/user/user.module.ts +65 -65
  301. package/src/module/workflow/controller/action-category.controller.ts +54 -54
  302. package/src/module/workflow/controller/action-resource-mapping.controller.ts +23 -23
  303. package/src/module/workflow/controller/action-template-mapping.controller.ts +35 -35
  304. package/src/module/workflow/controller/action.controller.ts +95 -95
  305. package/src/module/workflow/controller/activity-log.controller.ts +55 -55
  306. package/src/module/workflow/controller/comm-template.controller.ts +41 -41
  307. package/src/module/workflow/controller/entity-modification.controller.ts +35 -35
  308. package/src/module/workflow/controller/form-master.controller.ts +43 -43
  309. package/src/module/workflow/controller/stage-group.controller.ts +48 -48
  310. package/src/module/workflow/controller/stage.controller.ts +50 -50
  311. package/src/module/workflow/controller/task.controller.ts +77 -77
  312. package/src/module/workflow/controller/workflow-list-master.controller.ts +44 -44
  313. package/src/module/workflow/controller/workflow-meta.controller.ts +80 -80
  314. package/src/module/workflow/controller/workflow.controller.ts +67 -67
  315. package/src/module/workflow/entity/action-category.entity.ts +38 -38
  316. package/src/module/workflow/entity/action-data.entity.ts +55 -55
  317. package/src/module/workflow/entity/action-resources-mapping.entity.ts +29 -29
  318. package/src/module/workflow/entity/action-template-mapping.entity.ts +17 -17
  319. package/src/module/workflow/entity/action.entity.ts +50 -50
  320. package/src/module/workflow/entity/activity-log.entity.ts +43 -43
  321. package/src/module/workflow/entity/comm-template.entity.ts +43 -43
  322. package/src/module/workflow/entity/entity-modification.entity.ts +38 -38
  323. package/src/module/workflow/entity/form.entity.ts +25 -25
  324. package/src/module/workflow/entity/stage-action-mapping.entity.ts +17 -17
  325. package/src/module/workflow/entity/stage-group.entity.ts +23 -23
  326. package/src/module/workflow/entity/stage-movement-data.entity.ts +38 -38
  327. package/src/module/workflow/entity/stage.entity.ts +20 -20
  328. package/src/module/workflow/entity/task-data.entity.ts +88 -88
  329. package/src/module/workflow/entity/template-attach-mapper.entity.ts +30 -30
  330. package/src/module/workflow/entity/workflow-data.entity.ts +11 -11
  331. package/src/module/workflow/entity/workflow-level-mapping.entity.ts +18 -18
  332. package/src/module/workflow/entity/workflow.entity.ts +20 -20
  333. package/src/module/workflow/repository/action-category.repository.ts +79 -79
  334. package/src/module/workflow/repository/action-data.repository.ts +242 -242
  335. package/src/module/workflow/repository/action.repository.ts +277 -277
  336. package/src/module/workflow/repository/activity-log.repository.ts +149 -149
  337. package/src/module/workflow/repository/comm-template.repository.ts +149 -149
  338. package/src/module/workflow/repository/form-master.repository.ts +59 -59
  339. package/src/module/workflow/repository/stage-group.repository.ts +176 -176
  340. package/src/module/workflow/repository/stage-movement.repository.ts +227 -227
  341. package/src/module/workflow/repository/stage.repository.ts +172 -172
  342. package/src/module/workflow/repository/task.repository.ts +117 -117
  343. package/src/module/workflow/repository/workflow.repository.ts +42 -42
  344. package/src/module/workflow/service/action-category.service.ts +33 -33
  345. package/src/module/workflow/service/action-data.service.ts +62 -62
  346. package/src/module/workflow/service/action-resources-mapping.service.ts +10 -10
  347. package/src/module/workflow/service/action-template-mapping.service.ts +55 -55
  348. package/src/module/workflow/service/action.service.ts +263 -263
  349. package/src/module/workflow/service/activity-log.service.ts +107 -107
  350. package/src/module/workflow/service/comm-template.service.ts +176 -176
  351. package/src/module/workflow/service/entity-modification.service.ts +67 -67
  352. package/src/module/workflow/service/form-master.service.ts +35 -35
  353. package/src/module/workflow/service/populate-workflow.service.ts +303 -303
  354. package/src/module/workflow/service/stage-action-mapping.service.ts +5 -5
  355. package/src/module/workflow/service/stage-group.service.ts +307 -307
  356. package/src/module/workflow/service/stage.service.ts +199 -199
  357. package/src/module/workflow/service/task.service.ts +561 -561
  358. package/src/module/workflow/service/workflow-list-master.service.ts +60 -60
  359. package/src/module/workflow/service/workflow-meta.service.ts +581 -581
  360. package/src/module/workflow/service/workflow.service.ts +205 -205
  361. package/src/module/workflow/workflow.module.ts +174 -174
  362. package/src/module/workflow-automation/controller/workflow-automation.controller.ts +21 -21
  363. package/src/module/workflow-automation/entity/workflow-automation-action.entity.ts +26 -26
  364. package/src/module/workflow-automation/entity/workflow-automation.entity.ts +35 -35
  365. package/src/module/workflow-automation/interface/action.decorator.ts +7 -7
  366. package/src/module/workflow-automation/interface/action.interface.ts +5 -5
  367. package/src/module/workflow-automation/service/action-registery.service.ts +35 -35
  368. package/src/module/workflow-automation/service/workflow-automation-engine.service.ts +214 -214
  369. package/src/module/workflow-automation/service/workflow-automation.service.ts +345 -345
  370. package/src/module/workflow-automation/workflow-automation.module.ts +34 -34
  371. package/src/resources/dev.properties.yaml +30 -30
  372. package/src/resources/local.properties.yaml +27 -27
  373. package/src/resources/properties.module.ts +12 -12
  374. package/src/resources/properties.yaml.ts +11 -11
  375. package/src/resources/uat.properties.yaml +15 -15
  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 +34 -34
  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 +25 -25
  391. package/tsconfig.build.json +4 -4
  392. package/tsconfig.json +24 -24
  393. package/.vscode/extensions.json +0 -5
@@ -1,762 +1,762 @@
1
- import { level } from 'winston';
2
- import { Injectable } from '@nestjs/common';
3
- import {
4
- ENTITYTYPE_ENTITYMASTER,
5
- STATUS_ACTIVE,
6
- } from 'src/constant/global.constant';
7
- import { DataSource } from 'typeorm';
8
- import { UserData } from 'src/module/user/entity/user.entity';
9
- import { MediaDataService } from './media-data.service';
10
- import { ResolverService } from './resolver.service';
11
-
12
- @Injectable()
13
- export class EntityDynamicService {
14
- constructor(
15
- private readonly dataSource: DataSource,
16
- private readonly mediaDataService: MediaDataService,
17
- private readonly resolverService: ResolverService,
18
- ) {}
19
-
20
- // -----------------------------
21
- async createEntity(
22
- entityType: string,
23
- entityData: Record<string, any>,
24
- loggedInUser: any,
25
- mainID?: number,
26
- ): Promise<any> {
27
- const organizationId = loggedInUser.organization_id;
28
-
29
- const tableName = await this.getTableName(entityType, organizationId);
30
- const validAttributes = await this.getAttributeCodes(
31
- entityType,
32
- organizationId,
33
- );
34
-
35
- const statusList = await this.dataSource.query(
36
- `SELECT id FROM cr_list_master_items WHERE code = ? AND organization_id = ?`,
37
- [STATUS_ACTIVE, loggedInUser?.organization_id || 0],
38
- );
39
-
40
- entityData.created_date = new Date();
41
- if (loggedInUser) {
42
- entityData.created_by = loggedInUser.id;
43
- if (!entityData.organization_id)
44
- entityData.organization_id = loggedInUser.organization_id;
45
- if (!entityData.enterprise_id)
46
- entityData.enterprise_id = loggedInUser.enterprise_id;
47
- if (!entityData.level_type)
48
- entityData.level_type = loggedInUser.level_type;
49
- if (!entityData.level_id) entityData.level_id = loggedInUser.level_id;
50
- if (!entityData.status) entityData.status = statusList[0].id;
51
- if (!entityData.entity_type) entityData.entity_type = entityType;
52
- }
53
-
54
- if (!entityData.code && loggedInUser) {
55
- const result = await this.dataSource.query(
56
- `SELECT MAX(CAST(SUBSTRING(code, LENGTH(entity_type) + 1) AS UNSIGNED)) AS max_seq_no
57
- FROM ${tableName}
58
- WHERE entity_type = ?`,
59
- [entityData.entity_type],
60
- );
61
-
62
- // result will be like [ { max_seq_no: 12 } ]
63
- let maxSeqNo = result?.[0]?.max_seq_no ? Number(result[0].max_seq_no) : 0;
64
-
65
- maxSeqNo += 1;
66
- entityData.code = `${entityData.entity_type}${maxSeqNo}`;
67
- }
68
-
69
- // Set parent_id if mainID is provided
70
- if (mainID) {
71
- entityData.parent_id = mainID;
72
- }
73
-
74
- const bypassColumn = [
75
- {
76
- attribute_key: 'created_date',
77
- db_datatype: 'datetime',
78
- element_type: 'date',
79
- },
80
- {
81
- attribute_key: 'created_by',
82
- db_datatype: 'int',
83
- element_type: 'number',
84
- },
85
- {
86
- attribute_key: 'organization_id',
87
- db_datatype: 'datetime',
88
- element_type: 'date',
89
- },
90
- {
91
- attribute_key: 'enterprise_id',
92
- db_datatype: 'int',
93
- element_type: 'number',
94
- },
95
- { attribute_key: 'level_type', db_datatype: 'int', element_type: 'text' },
96
- { attribute_key: 'level_id', db_datatype: 'int', element_type: 'number' },
97
- { attribute_key: 'status', db_datatype: 'varchar', element_type: 'text' },
98
- {
99
- attribute_key: 'entity_type',
100
- db_datatype: 'varchar',
101
- element_type: 'text',
102
- },
103
- { attribute_key: 'code', db_datatype: 'varchar', element_type: 'text' },
104
- {
105
- attribute_key: 'parent_id',
106
- db_datatype: 'int',
107
- element_type: 'number',
108
- },
109
- ];
110
-
111
- // Only push bypassColumn attributes that don't already exist in validAttributes
112
- const existingAttributeKeys = validAttributes.map(
113
- (attr) => attr.attribute_key,
114
- );
115
- const newBypassColumns = bypassColumn.filter(
116
- (bypass) => !existingAttributeKeys.includes(bypass.attribute_key),
117
- );
118
- validAttributes.push(...newBypassColumns);
119
-
120
- const columns: string[] = [];
121
- const values: any[] = [];
122
-
123
- validAttributes.forEach((attr) => {
124
- columns.push(attr.attribute_key);
125
- values.push(
126
- attr.attribute_key in entityData
127
- ? entityData[attr.attribute_key]
128
- : null,
129
- );
130
- });
131
-
132
- const placeholders = columns.map(() => '?').join(', ');
133
- const escapedColumns = columns.map((col) => `\`${col}\``).join(', ');
134
- const insertQuery = `INSERT INTO \`${tableName}\` (${escapedColumns}) VALUES (${placeholders})`;
135
-
136
- const result = await this.dataSource.query(insertQuery, values);
137
- return result;
138
- }
139
-
140
- // ----------------------------- get entity with relations
141
-
142
- // ----------------------------- create entity with relations
143
- async createEntityWithRelation(
144
- entityType: string,
145
- data: Record<string, any>,
146
- loggedInUser: any,
147
- ): Promise<any> {
148
- const organizationId = loggedInUser.organization_id;
149
-
150
- const getRelation = await this.dataSource.query(
151
- `SELECT * FROM cr_entity_relation WHERE organization_id = ? AND source_entity_type = ?`,
152
- [organizationId, entityType],
153
- );
154
-
155
- const { mappedEntities, ...mainData } = data;
156
-
157
- // create main entity
158
- const createdEntityData = await this.createEntity(
159
- entityType,
160
- mainData,
161
- loggedInUser,
162
- );
163
- const mainID = createdEntityData.insertId || createdEntityData.id;
164
-
165
- if (mappedEntities && getRelation.length > 0) {
166
- for (const relation of getRelation) {
167
- const targetEntityType = relation.target_entity_type;
168
- const relationType = relation.relation_type;
169
- const relationId = relation.relation_id;
170
-
171
- if (!mappedEntities[targetEntityType]) continue;
172
-
173
- // normalize: always array
174
- const entityDataArray = Array.isArray(mappedEntities[targetEntityType])
175
- ? mappedEntities[targetEntityType]
176
- : [mappedEntities[targetEntityType]];
177
-
178
- for (const item of entityDataArray) {
179
- const itemWithRef = {
180
- ...item,
181
- entity_type: targetEntityType,
182
- };
183
-
184
- const createdRelatedEntity = await this.createEntity(
185
- targetEntityType,
186
- itemWithRef,
187
- loggedInUser,
188
- mainID, // this will pass for parent_id
189
- );
190
-
191
- await this.dataSource.query(
192
- `INSERT INTO cr_entity_relation_data (organization_id, source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type) VALUES (?, ?, ?, ?, ?,?)`,
193
- [
194
- organizationId,
195
- mainID,
196
- entityType,
197
- createdRelatedEntity.insertId,
198
- targetEntityType,
199
- relationType,
200
- ],
201
- );
202
- }
203
- }
204
- }
205
-
206
- return {
207
- mainEntity: {
208
- id: mainID,
209
- entityType,
210
- data: createdEntityData,
211
- },
212
- };
213
- }
214
-
215
- // ----------------------------- get entity with relations
216
- async getEntityWithRelation(
217
- entityType: string,
218
- id: number | string,
219
- loggedInUser: any,
220
- ): Promise<any> {
221
- const mainEntity = await this.getEntity(entityType, id, loggedInUser);
222
-
223
- const relatedEntities = await this.dataSource.query(
224
- `SELECT * FROM cr_entity_relation_data WHERE source_entity_id = ? AND target_entity_type IN (
225
- SELECT target_entity_type FROM cr_entity_relation WHERE source_entity_type = ?)`,
226
- [id, entityType],
227
- );
228
-
229
- // Format response to match create entity structure
230
- const response: any = {
231
- entity_type: entityType,
232
- ...mainEntity,
233
- };
234
-
235
- if (relatedEntities.length > 0) {
236
- response.mappedEntities = await this.formatMappedEntities(
237
- relatedEntities,
238
- loggedInUser,
239
- );
240
- }
241
-
242
- return response;
243
- }
244
-
245
- // ----------------------------- formatMappedEntities
246
- async formatMappedEntities(
247
- relatedEntities: any[],
248
- loggedInUser: any,
249
- ): Promise<any> {
250
- const mappedEntities: any = {};
251
-
252
- for (const relation of relatedEntities) {
253
- const targetEntityType = relation.target_entity_type;
254
- const targetEntityId = relation.target_entity_id;
255
-
256
- const entityData = await this.getEntity(
257
- targetEntityType,
258
- targetEntityId,
259
- loggedInUser,
260
- );
261
-
262
- if (!mappedEntities[targetEntityType]) {
263
- mappedEntities[targetEntityType] = [];
264
- }
265
-
266
- mappedEntities[targetEntityType].push(entityData);
267
- }
268
-
269
- return mappedEntities;
270
- }
271
-
272
- // ----------------------------- update with relations
273
-
274
- // ----------------------------- update entity with relations
275
- async updateEntityWithRelations(
276
- entityType: string,
277
- id: number | string,
278
- data: Record<string, any>,
279
- loggedInUser: any,
280
- ): Promise<any> {
281
- const organizationId = loggedInUser.organization_id;
282
- const { mappedEntities, ...mainData } = data;
283
-
284
- // Update main entity
285
- const updatedMainEntity = await this.updateEntity(
286
- entityType,
287
- id,
288
- mainData,
289
- loggedInUser,
290
- );
291
-
292
- const updatedRelations: Record<string, any> = {};
293
-
294
- if (mappedEntities) {
295
- const getRelationDefs = await this.dataSource.query(
296
- `SELECT * FROM cr_entity_relation WHERE organization_id = ? AND source_entity_type = ?`,
297
- [organizationId, entityType],
298
- );
299
-
300
- for (const [targetEntityType, rawEntityData] of Object.entries(
301
- mappedEntities,
302
- )) {
303
- const relationDef = getRelationDefs.find(
304
- (r) => r.target_entity_type === targetEntityType,
305
- );
306
- if (!relationDef) continue;
307
-
308
- const relationType = relationDef.relation_type;
309
- const entityArray = Array.isArray(rawEntityData)
310
- ? rawEntityData
311
- : [rawEntityData];
312
-
313
- // Delete previous relations and related entities
314
- const existingRelationsForType = await this.dataSource.query(
315
- `SELECT * FROM cr_entity_relation_data WHERE source_entity_type = ? AND source_entity_id = ? AND target_entity_type = ?`,
316
- [entityType, id, targetEntityType],
317
- );
318
-
319
- for (const existingRel of existingRelationsForType) {
320
- // Delete the related entity
321
- await this.deleteEntity(
322
- existingRel.target_entity_type,
323
- existingRel.target_entity_id,
324
- loggedInUser,
325
- );
326
-
327
- // Delete the relation row
328
- await this.dataSource.query(
329
- `DELETE FROM cr_entity_relation_data WHERE id = ?`,
330
- [existingRel.id],
331
- );
332
- }
333
-
334
- // Create/update new entities & relations
335
- const updatedEntities: any[] = [];
336
-
337
- for (const item of entityArray) {
338
- let targetEntityId;
339
- let entityData;
340
-
341
- if (item.id) {
342
- // Update existing entity
343
- await this.updateEntity(
344
- targetEntityType,
345
- item.id,
346
- item,
347
- loggedInUser,
348
- Number(id), // pass main entity id as parent_id
349
- );
350
- targetEntityId = item.id;
351
- entityData = await this.getEntity(
352
- targetEntityType,
353
- targetEntityId,
354
- loggedInUser,
355
- );
356
- } else {
357
- // Create new entity
358
- const createdEntity = await this.createEntity(
359
- targetEntityType,
360
- item,
361
- loggedInUser,
362
- Number(id), // pass main entity id as parent_id
363
- );
364
- targetEntityId = createdEntity.insertId || createdEntity.id;
365
- entityData = await this.getEntity(
366
- targetEntityType,
367
- targetEntityId,
368
- loggedInUser,
369
- );
370
- }
371
-
372
- // Insert relation
373
- await this.dataSource.query(
374
- `INSERT INTO cr_entity_relation_data
375
- (organization_id, source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type)
376
- VALUES (?, ?, ?, ?, ?,?)`,
377
- [
378
- organizationId,
379
- id,
380
- entityType,
381
- targetEntityId,
382
- targetEntityType,
383
- relationType,
384
- ],
385
- );
386
-
387
- if (relationType === 'ONE_TO_MANY') {
388
- updatedEntities.push(entityData);
389
- } else if (
390
- relationType === 'ONE_TO_ONE' ||
391
- relationType === 'MANY_TO_ONE'
392
- ) {
393
- updatedEntities[0] = entityData; // single object
394
- }
395
- }
396
-
397
- // Assign to response mappedEntities
398
- updatedRelations[targetEntityType] =
399
- relationType === 'ONE_TO_MANY' ? updatedEntities : updatedEntities[0];
400
- }
401
- }
402
-
403
- return {
404
- mainEntity: {
405
- id,
406
- entityType,
407
- data: updatedMainEntity,
408
- },
409
- relatedEntities: updatedRelations,
410
- };
411
- }
412
-
413
- // -----------------------------
414
- async updateEntity(
415
- entityType: string,
416
- id: number | string,
417
- entityData: Record<string, any>,
418
- loggedInUser: any,
419
- mainID?: number,
420
- ): Promise<any> {
421
- const organizationId = loggedInUser.organization_id;
422
-
423
- const tableName = await this.getTableName(entityType, organizationId);
424
- const validAttributes = await this.getAttributeCodes(
425
- entityType,
426
- organizationId,
427
- );
428
-
429
- const updates: string[] = [];
430
- const values: any[] = [];
431
-
432
- entityData.modified_date = new Date();
433
- if (loggedInUser) {
434
- entityData.modified_by = loggedInUser.id;
435
- if (!entityData.organization_id && entityData.entity_type !== 'ORG')
436
- entityData.organization_id = loggedInUser.organization_id;
437
- if (!entityData.enterprise_id)
438
- entityData.enterprise_id = loggedInUser.enterprise_id;
439
- }
440
-
441
- if (!entityData.code && loggedInUser) {
442
- const result = await this.dataSource.query(
443
- `SELECT MAX(CAST(SUBSTRING(code, LENGTH(entity_type) + 1) AS UNSIGNED)) AS max_seq_no
444
- FROM ${tableName}
445
- WHERE entity_type = ?`,
446
- [entityData.entity_type],
447
- );
448
-
449
- // result will be like [ { max_seq_no: 12 } ]
450
- let maxSeqNo = result?.[0]?.max_seq_no ? Number(result[0].max_seq_no) : 0;
451
-
452
- maxSeqNo += 1;
453
- entityData.code = `${entityData.entity_type}${maxSeqNo}`;
454
- }
455
-
456
- // Set parent_id if mainID is provided
457
- if (mainID) {
458
- entityData.parent_id = mainID;
459
- }
460
-
461
- const bypassColumn = [
462
- {
463
- attribute_key: 'created_date',
464
- db_datatype: 'datetime',
465
- element_type: 'date',
466
- },
467
- {
468
- attribute_key: 'created_by',
469
- db_datatype: 'int',
470
- element_type: 'number',
471
- },
472
- {
473
- attribute_key: 'modified_date',
474
- db_datatype: 'datetime',
475
- element_type: 'date',
476
- },
477
- {
478
- attribute_key: 'modified_by',
479
- db_datatype: 'int',
480
- element_type: 'number',
481
- },
482
- {
483
- attribute_key: 'organization_id',
484
- db_datatype: 'int',
485
- element_type: 'number',
486
- },
487
- {
488
- attribute_key: 'enterprise_id',
489
- db_datatype: 'int',
490
- element_type: 'number',
491
- },
492
- {
493
- attribute_key: 'level_type',
494
- db_datatype: 'varchar',
495
- element_type: 'text',
496
- },
497
- { attribute_key: 'level_id', db_datatype: 'int', element_type: 'number' },
498
- { attribute_key: 'status', db_datatype: 'varchar', element_type: 'text' },
499
- {
500
- attribute_key: 'entity_type',
501
- db_datatype: 'varchar',
502
- element_type: 'text',
503
- },
504
- { attribute_key: 'code', db_datatype: 'varchar', element_type: 'text' },
505
- {
506
- attribute_key: 'parent_id',
507
- db_datatype: 'int',
508
- element_type: 'number',
509
- },
510
- ];
511
-
512
- // Only push bypassColumn attributes that don't already exist in validAttributes
513
- const existingAttributeKeys = validAttributes.map(
514
- (attr) => attr.attribute_key,
515
- );
516
- const newBypassColumns = bypassColumn.filter(
517
- (bypass) => !existingAttributeKeys.includes(bypass.attribute_key),
518
- );
519
- validAttributes.push(...newBypassColumns);
520
-
521
- for (const key of Object.keys(entityData)) {
522
- if (validAttributes.some((attr) => attr.attribute_key === key)) {
523
- updates.push(`\`${key}\` = ?`);
524
- values.push(entityData[key]);
525
- }
526
- }
527
-
528
- if (updates.length === 0) {
529
- throw new Error('No valid attributes to update.');
530
- }
531
-
532
- const updateQuery = `UPDATE \`${tableName}\` SET ${updates.join(', ')} WHERE id = ?`;
533
- values.push(id); // Add id for WHERE clause
534
-
535
- const result = await this.dataSource.query(updateQuery, values);
536
- return result;
537
- }
538
-
539
- // -----------------------------
540
- async getEntity(
541
- entityType: string,
542
- id: number | string,
543
- loggedInUser: any,
544
- ): Promise<any> {
545
- const organizationId = loggedInUser.organization_id;
546
-
547
- const tableName = await this.getTableName(entityType, organizationId);
548
- const validAttributes = await this.getAttributeCodes(
549
- entityType,
550
- organizationId,
551
- );
552
-
553
- const columns = validAttributes
554
- .map((attr) => `\`${attr.attribute_key}\``)
555
- .join(', ');
556
- const selectQuery = `SELECT ${columns} FROM \`${tableName}\` WHERE id = ?`;
557
-
558
- const result = await this.dataSource.query(selectQuery, [id]);
559
- if (!result.length) return null;
560
-
561
- const row = result[0];
562
-
563
- // Convert boolean columns (1/0) into true/false
564
- for (const attr of validAttributes) {
565
- if (
566
- attr.db_datatype == 'boolean' &&
567
- row[attr.attribute_key] !== undefined
568
- ) {
569
- row[attr.attribute_key] = row[attr.attribute_key] == 1 ? true : false;
570
- } else if (
571
- attr.element_type == 'upload' &&
572
- row[attr.attribute_key] !== undefined
573
- ) {
574
- // fetch media data
575
- // console.log(
576
- // 'Fetching media for',
577
- // attr.attribute_key,
578
- // row[attr.attribute_key],
579
- // );
580
-
581
- row[attr.attribute_key] =
582
- row[attr.attribute_key] != null
583
- ? await this.mediaDataService.getMediaDownloadUrl(
584
- Number(row[attr.attribute_key]),
585
- loggedInUser,
586
- )
587
- : null;
588
-
589
- // console.log('Fetched media:', row[attr.attribute_key]);
590
- }
591
- }
592
-
593
- return row;
594
- }
595
-
596
- // -----------------------------
597
- private async getTableName(
598
- entityType: string,
599
- organizationId: string,
600
- ): Promise<string> {
601
- const result = await this.dataSource.query(
602
- `SELECT db_table_name FROM cr_entity_master WHERE organization_id = ? AND mapped_entity_type = ?`,
603
- [organizationId, entityType],
604
- );
605
-
606
- if (!result.length) {
607
- console.log(`Entity type '${entityType}' not found in cr_entity_master`);
608
- }
609
-
610
- return result[0].db_table_name;
611
- }
612
-
613
- private async getAttributeCodes(
614
- entityType: string,
615
- organizationId: string,
616
- ): Promise<
617
- {
618
- attribute_key: string;
619
- db_datatype: string;
620
- element_type: string;
621
- is_hidden?: boolean;
622
- }[]
623
- > {
624
- const result = await this.dataSource.query(
625
- `SELECT attribute_key,
626
- MAX(db_datatype) AS db_datatype,
627
- MAX(element_type) AS element_type,
628
- MAX(is_hidden) AS is_hidden
629
- FROM cr_entity_attribute
630
- WHERE mapped_entity_type = ? AND organization_id = ?
631
- and (is_hidden IS NULL OR is_hidden = 0) -- Exclude hidden attributes
632
- GROUP BY attribute_key`,
633
- [entityType, organizationId],
634
- );
635
-
636
- if (!result.length) {
637
- console.log(
638
- `No attributes found for entity '${entityType}' and org '${organizationId}'`,
639
- );
640
- }
641
-
642
- return result.map((row: any) => ({
643
- attribute_key: row.attribute_key,
644
- db_datatype: row.db_datatype,
645
- element_type: row.element_type,
646
- is_hidden: row.is_hidden,
647
- }));
648
- }
649
-
650
- private async deleteEntity(
651
- entityType: string,
652
- id: number | string,
653
- loggedInUser: any,
654
- ): Promise<any> {
655
- const organizationId = loggedInUser.organization_id;
656
-
657
- const tableName = await this.getTableName(entityType, organizationId);
658
-
659
- const deleteQuery = `DELETE FROM \`${tableName}\` WHERE id = ?`;
660
- const result = await this.dataSource.query(deleteQuery, [id]);
661
- return result;
662
- }
663
-
664
- // -----------------------------
665
-
666
- async getEntitiesDropdownList(
667
- loggedInUser: any,
668
- appcode?: string,
669
- ): Promise<any> {
670
- const organizationId = loggedInUser.organization_id;
671
-
672
- let query = `SELECT name as label,mapped_entity_type as value FROM cr_entity_master WHERE organization_id = ?`;
673
- const params = [organizationId];
674
-
675
- if (appcode) {
676
- query += ` AND appcode = ?`;
677
- params.push(appcode);
678
- }
679
-
680
- const dropdown = await this.dataSource.query(query, params);
681
- return dropdown;
682
- }
683
-
684
- async getCode(entityType: string, loggedInUser: any): Promise<string> {
685
- const organizationId = loggedInUser.organization_id;
686
-
687
- // 1. Get db_table_name from entity master
688
- const result = await this.dataSource.query(
689
- `SELECT db_table_name
690
- FROM cr_entity_master
691
- WHERE mapped_entity_type = ? AND organization_id = ?`,
692
- [entityType, organizationId],
693
- );
694
-
695
- if (!result.length) {
696
- throw new Error(
697
- `Entity type '${entityType}' not found in cr_entity_master for org '${organizationId}'`,
698
- );
699
- }
700
-
701
- const tableName = result[0].db_table_name;
702
-
703
- // 2. Get current max sequence number from that table
704
- const seqResult = await this.dataSource.query(
705
- `SELECT MAX(CAST(SUBSTRING(code, LENGTH(entity_type) + 1) AS UNSIGNED)) AS max_seq_no
706
- FROM \`${tableName}\`
707
- WHERE entity_type = ?`,
708
- [entityType],
709
- );
710
-
711
- let maxSeqNo = seqResult?.[0]?.max_seq_no
712
- ? Number(seqResult[0].max_seq_no)
713
- : 0;
714
-
715
- maxSeqNo += 1;
716
-
717
- // 3. Return generated code
718
- return `${entityType}${maxSeqNo}`;
719
- }
720
-
721
- async getResolvedEntity(
722
- id: number,
723
- entity: string,
724
- loggedInUser: UserData,
725
- ): Promise<any> {
726
- const leadData = await this.getEntityWithRelation(entity, id, loggedInUser);
727
-
728
- const { mappedEntities, ...data } = leadData as any;
729
-
730
- const resolvedData = await this.resolverService.getResolvedData(
731
- loggedInUser,
732
- data,
733
- entity,
734
- );
735
-
736
- if (mappedEntities) {
737
- resolvedData.mappedEntities = {};
738
- for (const [entityType, entities] of Object.entries(mappedEntities)) {
739
- if (Array.isArray(entities)) {
740
- resolvedData.mappedEntities[entityType] = [];
741
- for (const item of entities) {
742
- const resolvedItem = await this.resolverService.getResolvedData(
743
- loggedInUser,
744
- item,
745
- entityType,
746
- );
747
- resolvedData.mappedEntities[entityType].push(resolvedItem);
748
- }
749
- } else {
750
- resolvedData.mappedEntities[entityType] =
751
- await this.resolverService.getResolvedData(
752
- loggedInUser,
753
- entities,
754
- entityType,
755
- );
756
- }
757
- }
758
- }
759
-
760
- return resolvedData;
761
- }
762
- }
1
+ import { level } from 'winston';
2
+ import { Injectable } from '@nestjs/common';
3
+ import {
4
+ ENTITYTYPE_ENTITYMASTER,
5
+ STATUS_ACTIVE,
6
+ } from 'src/constant/global.constant';
7
+ import { DataSource } from 'typeorm';
8
+ import { UserData } from 'src/module/user/entity/user.entity';
9
+ import { MediaDataService } from './media-data.service';
10
+ import { ResolverService } from './resolver.service';
11
+
12
+ @Injectable()
13
+ export class EntityDynamicService {
14
+ constructor(
15
+ private readonly dataSource: DataSource,
16
+ private readonly mediaDataService: MediaDataService,
17
+ private readonly resolverService: ResolverService,
18
+ ) {}
19
+
20
+ // -----------------------------
21
+ async createEntity(
22
+ entityType: string,
23
+ entityData: Record<string, any>,
24
+ loggedInUser: any,
25
+ mainID?: number,
26
+ ): Promise<any> {
27
+ const organizationId = loggedInUser.organization_id;
28
+
29
+ const tableName = await this.getTableName(entityType, organizationId);
30
+ const validAttributes = await this.getAttributeCodes(
31
+ entityType,
32
+ organizationId,
33
+ );
34
+
35
+ const statusList = await this.dataSource.query(
36
+ `SELECT id FROM cr_list_master_items WHERE code = ? AND organization_id = ?`,
37
+ [STATUS_ACTIVE, loggedInUser?.organization_id || 0],
38
+ );
39
+
40
+ entityData.created_date = new Date();
41
+ if (loggedInUser) {
42
+ entityData.created_by = loggedInUser.id;
43
+ if (!entityData.organization_id)
44
+ entityData.organization_id = loggedInUser.organization_id;
45
+ if (!entityData.enterprise_id)
46
+ entityData.enterprise_id = loggedInUser.enterprise_id;
47
+ if (!entityData.level_type)
48
+ entityData.level_type = loggedInUser.level_type;
49
+ if (!entityData.level_id) entityData.level_id = loggedInUser.level_id;
50
+ if (!entityData.status) entityData.status = statusList[0].id;
51
+ if (!entityData.entity_type) entityData.entity_type = entityType;
52
+ }
53
+
54
+ if (!entityData.code && loggedInUser) {
55
+ const result = await this.dataSource.query(
56
+ `SELECT MAX(CAST(SUBSTRING(code, LENGTH(entity_type) + 1) AS UNSIGNED)) AS max_seq_no
57
+ FROM ${tableName}
58
+ WHERE entity_type = ?`,
59
+ [entityData.entity_type],
60
+ );
61
+
62
+ // result will be like [ { max_seq_no: 12 } ]
63
+ let maxSeqNo = result?.[0]?.max_seq_no ? Number(result[0].max_seq_no) : 0;
64
+
65
+ maxSeqNo += 1;
66
+ entityData.code = `${entityData.entity_type}${maxSeqNo}`;
67
+ }
68
+
69
+ // Set parent_id if mainID is provided
70
+ if (mainID) {
71
+ entityData.parent_id = mainID;
72
+ }
73
+
74
+ const bypassColumn = [
75
+ {
76
+ attribute_key: 'created_date',
77
+ db_datatype: 'datetime',
78
+ element_type: 'date',
79
+ },
80
+ {
81
+ attribute_key: 'created_by',
82
+ db_datatype: 'int',
83
+ element_type: 'number',
84
+ },
85
+ {
86
+ attribute_key: 'organization_id',
87
+ db_datatype: 'datetime',
88
+ element_type: 'date',
89
+ },
90
+ {
91
+ attribute_key: 'enterprise_id',
92
+ db_datatype: 'int',
93
+ element_type: 'number',
94
+ },
95
+ { attribute_key: 'level_type', db_datatype: 'int', element_type: 'text' },
96
+ { attribute_key: 'level_id', db_datatype: 'int', element_type: 'number' },
97
+ { attribute_key: 'status', db_datatype: 'varchar', element_type: 'text' },
98
+ {
99
+ attribute_key: 'entity_type',
100
+ db_datatype: 'varchar',
101
+ element_type: 'text',
102
+ },
103
+ { attribute_key: 'code', db_datatype: 'varchar', element_type: 'text' },
104
+ {
105
+ attribute_key: 'parent_id',
106
+ db_datatype: 'int',
107
+ element_type: 'number',
108
+ },
109
+ ];
110
+
111
+ // Only push bypassColumn attributes that don't already exist in validAttributes
112
+ const existingAttributeKeys = validAttributes.map(
113
+ (attr) => attr.attribute_key,
114
+ );
115
+ const newBypassColumns = bypassColumn.filter(
116
+ (bypass) => !existingAttributeKeys.includes(bypass.attribute_key),
117
+ );
118
+ validAttributes.push(...newBypassColumns);
119
+
120
+ const columns: string[] = [];
121
+ const values: any[] = [];
122
+
123
+ validAttributes.forEach((attr) => {
124
+ columns.push(attr.attribute_key);
125
+ values.push(
126
+ attr.attribute_key in entityData
127
+ ? entityData[attr.attribute_key]
128
+ : null,
129
+ );
130
+ });
131
+
132
+ const placeholders = columns.map(() => '?').join(', ');
133
+ const escapedColumns = columns.map((col) => `\`${col}\``).join(', ');
134
+ const insertQuery = `INSERT INTO \`${tableName}\` (${escapedColumns}) VALUES (${placeholders})`;
135
+
136
+ const result = await this.dataSource.query(insertQuery, values);
137
+ return result;
138
+ }
139
+
140
+ // ----------------------------- get entity with relations
141
+
142
+ // ----------------------------- create entity with relations
143
+ async createEntityWithRelation(
144
+ entityType: string,
145
+ data: Record<string, any>,
146
+ loggedInUser: any,
147
+ ): Promise<any> {
148
+ const organizationId = loggedInUser.organization_id;
149
+
150
+ const getRelation = await this.dataSource.query(
151
+ `SELECT * FROM cr_entity_relation WHERE organization_id = ? AND source_entity_type = ?`,
152
+ [organizationId, entityType],
153
+ );
154
+
155
+ const { mappedEntities, ...mainData } = data;
156
+
157
+ // create main entity
158
+ const createdEntityData = await this.createEntity(
159
+ entityType,
160
+ mainData,
161
+ loggedInUser,
162
+ );
163
+ const mainID = createdEntityData.insertId || createdEntityData.id;
164
+
165
+ if (mappedEntities && getRelation.length > 0) {
166
+ for (const relation of getRelation) {
167
+ const targetEntityType = relation.target_entity_type;
168
+ const relationType = relation.relation_type;
169
+ const relationId = relation.relation_id;
170
+
171
+ if (!mappedEntities[targetEntityType]) continue;
172
+
173
+ // normalize: always array
174
+ const entityDataArray = Array.isArray(mappedEntities[targetEntityType])
175
+ ? mappedEntities[targetEntityType]
176
+ : [mappedEntities[targetEntityType]];
177
+
178
+ for (const item of entityDataArray) {
179
+ const itemWithRef = {
180
+ ...item,
181
+ entity_type: targetEntityType,
182
+ };
183
+
184
+ const createdRelatedEntity = await this.createEntity(
185
+ targetEntityType,
186
+ itemWithRef,
187
+ loggedInUser,
188
+ mainID, // this will pass for parent_id
189
+ );
190
+
191
+ await this.dataSource.query(
192
+ `INSERT INTO cr_entity_relation_data (organization_id, source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type) VALUES (?, ?, ?, ?, ?,?)`,
193
+ [
194
+ organizationId,
195
+ mainID,
196
+ entityType,
197
+ createdRelatedEntity.insertId,
198
+ targetEntityType,
199
+ relationType,
200
+ ],
201
+ );
202
+ }
203
+ }
204
+ }
205
+
206
+ return {
207
+ mainEntity: {
208
+ id: mainID,
209
+ entityType,
210
+ data: createdEntityData,
211
+ },
212
+ };
213
+ }
214
+
215
+ // ----------------------------- get entity with relations
216
+ async getEntityWithRelation(
217
+ entityType: string,
218
+ id: number | string,
219
+ loggedInUser: any,
220
+ ): Promise<any> {
221
+ const mainEntity = await this.getEntity(entityType, id, loggedInUser);
222
+
223
+ const relatedEntities = await this.dataSource.query(
224
+ `SELECT * FROM cr_entity_relation_data WHERE source_entity_id = ? AND target_entity_type IN (
225
+ SELECT target_entity_type FROM cr_entity_relation WHERE source_entity_type = ?)`,
226
+ [id, entityType],
227
+ );
228
+
229
+ // Format response to match create entity structure
230
+ const response: any = {
231
+ entity_type: entityType,
232
+ ...mainEntity,
233
+ };
234
+
235
+ if (relatedEntities.length > 0) {
236
+ response.mappedEntities = await this.formatMappedEntities(
237
+ relatedEntities,
238
+ loggedInUser,
239
+ );
240
+ }
241
+
242
+ return response;
243
+ }
244
+
245
+ // ----------------------------- formatMappedEntities
246
+ async formatMappedEntities(
247
+ relatedEntities: any[],
248
+ loggedInUser: any,
249
+ ): Promise<any> {
250
+ const mappedEntities: any = {};
251
+
252
+ for (const relation of relatedEntities) {
253
+ const targetEntityType = relation.target_entity_type;
254
+ const targetEntityId = relation.target_entity_id;
255
+
256
+ const entityData = await this.getEntity(
257
+ targetEntityType,
258
+ targetEntityId,
259
+ loggedInUser,
260
+ );
261
+
262
+ if (!mappedEntities[targetEntityType]) {
263
+ mappedEntities[targetEntityType] = [];
264
+ }
265
+
266
+ mappedEntities[targetEntityType].push(entityData);
267
+ }
268
+
269
+ return mappedEntities;
270
+ }
271
+
272
+ // ----------------------------- update with relations
273
+
274
+ // ----------------------------- update entity with relations
275
+ async updateEntityWithRelations(
276
+ entityType: string,
277
+ id: number | string,
278
+ data: Record<string, any>,
279
+ loggedInUser: any,
280
+ ): Promise<any> {
281
+ const organizationId = loggedInUser.organization_id;
282
+ const { mappedEntities, ...mainData } = data;
283
+
284
+ // Update main entity
285
+ const updatedMainEntity = await this.updateEntity(
286
+ entityType,
287
+ id,
288
+ mainData,
289
+ loggedInUser,
290
+ );
291
+
292
+ const updatedRelations: Record<string, any> = {};
293
+
294
+ if (mappedEntities) {
295
+ const getRelationDefs = await this.dataSource.query(
296
+ `SELECT * FROM cr_entity_relation WHERE organization_id = ? AND source_entity_type = ?`,
297
+ [organizationId, entityType],
298
+ );
299
+
300
+ for (const [targetEntityType, rawEntityData] of Object.entries(
301
+ mappedEntities,
302
+ )) {
303
+ const relationDef = getRelationDefs.find(
304
+ (r) => r.target_entity_type === targetEntityType,
305
+ );
306
+ if (!relationDef) continue;
307
+
308
+ const relationType = relationDef.relation_type;
309
+ const entityArray = Array.isArray(rawEntityData)
310
+ ? rawEntityData
311
+ : [rawEntityData];
312
+
313
+ // Delete previous relations and related entities
314
+ const existingRelationsForType = await this.dataSource.query(
315
+ `SELECT * FROM cr_entity_relation_data WHERE source_entity_type = ? AND source_entity_id = ? AND target_entity_type = ?`,
316
+ [entityType, id, targetEntityType],
317
+ );
318
+
319
+ for (const existingRel of existingRelationsForType) {
320
+ // Delete the related entity
321
+ await this.deleteEntity(
322
+ existingRel.target_entity_type,
323
+ existingRel.target_entity_id,
324
+ loggedInUser,
325
+ );
326
+
327
+ // Delete the relation row
328
+ await this.dataSource.query(
329
+ `DELETE FROM cr_entity_relation_data WHERE id = ?`,
330
+ [existingRel.id],
331
+ );
332
+ }
333
+
334
+ // Create/update new entities & relations
335
+ const updatedEntities: any[] = [];
336
+
337
+ for (const item of entityArray) {
338
+ let targetEntityId;
339
+ let entityData;
340
+
341
+ if (item.id) {
342
+ // Update existing entity
343
+ await this.updateEntity(
344
+ targetEntityType,
345
+ item.id,
346
+ item,
347
+ loggedInUser,
348
+ Number(id), // pass main entity id as parent_id
349
+ );
350
+ targetEntityId = item.id;
351
+ entityData = await this.getEntity(
352
+ targetEntityType,
353
+ targetEntityId,
354
+ loggedInUser,
355
+ );
356
+ } else {
357
+ // Create new entity
358
+ const createdEntity = await this.createEntity(
359
+ targetEntityType,
360
+ item,
361
+ loggedInUser,
362
+ Number(id), // pass main entity id as parent_id
363
+ );
364
+ targetEntityId = createdEntity.insertId || createdEntity.id;
365
+ entityData = await this.getEntity(
366
+ targetEntityType,
367
+ targetEntityId,
368
+ loggedInUser,
369
+ );
370
+ }
371
+
372
+ // Insert relation
373
+ await this.dataSource.query(
374
+ `INSERT INTO cr_entity_relation_data
375
+ (organization_id, source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type)
376
+ VALUES (?, ?, ?, ?, ?,?)`,
377
+ [
378
+ organizationId,
379
+ id,
380
+ entityType,
381
+ targetEntityId,
382
+ targetEntityType,
383
+ relationType,
384
+ ],
385
+ );
386
+
387
+ if (relationType === 'ONE_TO_MANY') {
388
+ updatedEntities.push(entityData);
389
+ } else if (
390
+ relationType === 'ONE_TO_ONE' ||
391
+ relationType === 'MANY_TO_ONE'
392
+ ) {
393
+ updatedEntities[0] = entityData; // single object
394
+ }
395
+ }
396
+
397
+ // Assign to response mappedEntities
398
+ updatedRelations[targetEntityType] =
399
+ relationType === 'ONE_TO_MANY' ? updatedEntities : updatedEntities[0];
400
+ }
401
+ }
402
+
403
+ return {
404
+ mainEntity: {
405
+ id,
406
+ entityType,
407
+ data: updatedMainEntity,
408
+ },
409
+ relatedEntities: updatedRelations,
410
+ };
411
+ }
412
+
413
+ // -----------------------------
414
+ async updateEntity(
415
+ entityType: string,
416
+ id: number | string,
417
+ entityData: Record<string, any>,
418
+ loggedInUser: any,
419
+ mainID?: number,
420
+ ): Promise<any> {
421
+ const organizationId = loggedInUser.organization_id;
422
+
423
+ const tableName = await this.getTableName(entityType, organizationId);
424
+ const validAttributes = await this.getAttributeCodes(
425
+ entityType,
426
+ organizationId,
427
+ );
428
+
429
+ const updates: string[] = [];
430
+ const values: any[] = [];
431
+
432
+ entityData.modified_date = new Date();
433
+ if (loggedInUser) {
434
+ entityData.modified_by = loggedInUser.id;
435
+ if (!entityData.organization_id && entityData.entity_type !== 'ORG')
436
+ entityData.organization_id = loggedInUser.organization_id;
437
+ if (!entityData.enterprise_id)
438
+ entityData.enterprise_id = loggedInUser.enterprise_id;
439
+ }
440
+
441
+ if (!entityData.code && loggedInUser) {
442
+ const result = await this.dataSource.query(
443
+ `SELECT MAX(CAST(SUBSTRING(code, LENGTH(entity_type) + 1) AS UNSIGNED)) AS max_seq_no
444
+ FROM ${tableName}
445
+ WHERE entity_type = ?`,
446
+ [entityData.entity_type],
447
+ );
448
+
449
+ // result will be like [ { max_seq_no: 12 } ]
450
+ let maxSeqNo = result?.[0]?.max_seq_no ? Number(result[0].max_seq_no) : 0;
451
+
452
+ maxSeqNo += 1;
453
+ entityData.code = `${entityData.entity_type}${maxSeqNo}`;
454
+ }
455
+
456
+ // Set parent_id if mainID is provided
457
+ if (mainID) {
458
+ entityData.parent_id = mainID;
459
+ }
460
+
461
+ const bypassColumn = [
462
+ {
463
+ attribute_key: 'created_date',
464
+ db_datatype: 'datetime',
465
+ element_type: 'date',
466
+ },
467
+ {
468
+ attribute_key: 'created_by',
469
+ db_datatype: 'int',
470
+ element_type: 'number',
471
+ },
472
+ {
473
+ attribute_key: 'modified_date',
474
+ db_datatype: 'datetime',
475
+ element_type: 'date',
476
+ },
477
+ {
478
+ attribute_key: 'modified_by',
479
+ db_datatype: 'int',
480
+ element_type: 'number',
481
+ },
482
+ {
483
+ attribute_key: 'organization_id',
484
+ db_datatype: 'int',
485
+ element_type: 'number',
486
+ },
487
+ {
488
+ attribute_key: 'enterprise_id',
489
+ db_datatype: 'int',
490
+ element_type: 'number',
491
+ },
492
+ {
493
+ attribute_key: 'level_type',
494
+ db_datatype: 'varchar',
495
+ element_type: 'text',
496
+ },
497
+ { attribute_key: 'level_id', db_datatype: 'int', element_type: 'number' },
498
+ { attribute_key: 'status', db_datatype: 'varchar', element_type: 'text' },
499
+ {
500
+ attribute_key: 'entity_type',
501
+ db_datatype: 'varchar',
502
+ element_type: 'text',
503
+ },
504
+ { attribute_key: 'code', db_datatype: 'varchar', element_type: 'text' },
505
+ {
506
+ attribute_key: 'parent_id',
507
+ db_datatype: 'int',
508
+ element_type: 'number',
509
+ },
510
+ ];
511
+
512
+ // Only push bypassColumn attributes that don't already exist in validAttributes
513
+ const existingAttributeKeys = validAttributes.map(
514
+ (attr) => attr.attribute_key,
515
+ );
516
+ const newBypassColumns = bypassColumn.filter(
517
+ (bypass) => !existingAttributeKeys.includes(bypass.attribute_key),
518
+ );
519
+ validAttributes.push(...newBypassColumns);
520
+
521
+ for (const key of Object.keys(entityData)) {
522
+ if (validAttributes.some((attr) => attr.attribute_key === key)) {
523
+ updates.push(`\`${key}\` = ?`);
524
+ values.push(entityData[key]);
525
+ }
526
+ }
527
+
528
+ if (updates.length === 0) {
529
+ throw new Error('No valid attributes to update.');
530
+ }
531
+
532
+ const updateQuery = `UPDATE \`${tableName}\` SET ${updates.join(', ')} WHERE id = ?`;
533
+ values.push(id); // Add id for WHERE clause
534
+
535
+ const result = await this.dataSource.query(updateQuery, values);
536
+ return result;
537
+ }
538
+
539
+ // -----------------------------
540
+ async getEntity(
541
+ entityType: string,
542
+ id: number | string,
543
+ loggedInUser: any,
544
+ ): Promise<any> {
545
+ const organizationId = loggedInUser.organization_id;
546
+
547
+ const tableName = await this.getTableName(entityType, organizationId);
548
+ const validAttributes = await this.getAttributeCodes(
549
+ entityType,
550
+ organizationId,
551
+ );
552
+
553
+ const columns = validAttributes
554
+ .map((attr) => `\`${attr.attribute_key}\``)
555
+ .join(', ');
556
+ const selectQuery = `SELECT ${columns} FROM \`${tableName}\` WHERE id = ?`;
557
+
558
+ const result = await this.dataSource.query(selectQuery, [id]);
559
+ if (!result.length) return null;
560
+
561
+ const row = result[0];
562
+
563
+ // Convert boolean columns (1/0) into true/false
564
+ for (const attr of validAttributes) {
565
+ if (
566
+ attr.db_datatype == 'boolean' &&
567
+ row[attr.attribute_key] !== undefined
568
+ ) {
569
+ row[attr.attribute_key] = row[attr.attribute_key] == 1 ? true : false;
570
+ } else if (
571
+ attr.element_type == 'upload' &&
572
+ row[attr.attribute_key] !== undefined
573
+ ) {
574
+ // fetch media data
575
+ // console.log(
576
+ // 'Fetching media for',
577
+ // attr.attribute_key,
578
+ // row[attr.attribute_key],
579
+ // );
580
+
581
+ row[attr.attribute_key] =
582
+ row[attr.attribute_key] != null
583
+ ? await this.mediaDataService.getMediaDownloadUrl(
584
+ Number(row[attr.attribute_key]),
585
+ loggedInUser,
586
+ )
587
+ : null;
588
+
589
+ // console.log('Fetched media:', row[attr.attribute_key]);
590
+ }
591
+ }
592
+
593
+ return row;
594
+ }
595
+
596
+ // -----------------------------
597
+ private async getTableName(
598
+ entityType: string,
599
+ organizationId: string,
600
+ ): Promise<string> {
601
+ const result = await this.dataSource.query(
602
+ `SELECT db_table_name FROM cr_entity_master WHERE organization_id = ? AND mapped_entity_type = ?`,
603
+ [organizationId, entityType],
604
+ );
605
+
606
+ if (!result.length) {
607
+ console.log(`Entity type '${entityType}' not found in cr_entity_master`);
608
+ }
609
+
610
+ return result[0].db_table_name;
611
+ }
612
+
613
+ private async getAttributeCodes(
614
+ entityType: string,
615
+ organizationId: string,
616
+ ): Promise<
617
+ {
618
+ attribute_key: string;
619
+ db_datatype: string;
620
+ element_type: string;
621
+ is_hidden?: boolean;
622
+ }[]
623
+ > {
624
+ const result = await this.dataSource.query(
625
+ `SELECT attribute_key,
626
+ MAX(db_datatype) AS db_datatype,
627
+ MAX(element_type) AS element_type,
628
+ MAX(is_hidden) AS is_hidden
629
+ FROM cr_entity_attribute
630
+ WHERE mapped_entity_type = ? AND organization_id = ?
631
+ and (is_hidden IS NULL OR is_hidden = 0) -- Exclude hidden attributes
632
+ GROUP BY attribute_key`,
633
+ [entityType, organizationId],
634
+ );
635
+
636
+ if (!result.length) {
637
+ console.log(
638
+ `No attributes found for entity '${entityType}' and org '${organizationId}'`,
639
+ );
640
+ }
641
+
642
+ return result.map((row: any) => ({
643
+ attribute_key: row.attribute_key,
644
+ db_datatype: row.db_datatype,
645
+ element_type: row.element_type,
646
+ is_hidden: row.is_hidden,
647
+ }));
648
+ }
649
+
650
+ private async deleteEntity(
651
+ entityType: string,
652
+ id: number | string,
653
+ loggedInUser: any,
654
+ ): Promise<any> {
655
+ const organizationId = loggedInUser.organization_id;
656
+
657
+ const tableName = await this.getTableName(entityType, organizationId);
658
+
659
+ const deleteQuery = `DELETE FROM \`${tableName}\` WHERE id = ?`;
660
+ const result = await this.dataSource.query(deleteQuery, [id]);
661
+ return result;
662
+ }
663
+
664
+ // -----------------------------
665
+
666
+ async getEntitiesDropdownList(
667
+ loggedInUser: any,
668
+ appcode?: string,
669
+ ): Promise<any> {
670
+ const organizationId = loggedInUser.organization_id;
671
+
672
+ let query = `SELECT name as label,mapped_entity_type as value FROM cr_entity_master WHERE organization_id = ?`;
673
+ const params = [organizationId];
674
+
675
+ if (appcode) {
676
+ query += ` AND appcode = ?`;
677
+ params.push(appcode);
678
+ }
679
+
680
+ const dropdown = await this.dataSource.query(query, params);
681
+ return dropdown;
682
+ }
683
+
684
+ async getCode(entityType: string, loggedInUser: any): Promise<string> {
685
+ const organizationId = loggedInUser.organization_id;
686
+
687
+ // 1. Get db_table_name from entity master
688
+ const result = await this.dataSource.query(
689
+ `SELECT db_table_name
690
+ FROM cr_entity_master
691
+ WHERE mapped_entity_type = ? AND organization_id = ?`,
692
+ [entityType, organizationId],
693
+ );
694
+
695
+ if (!result.length) {
696
+ throw new Error(
697
+ `Entity type '${entityType}' not found in cr_entity_master for org '${organizationId}'`,
698
+ );
699
+ }
700
+
701
+ const tableName = result[0].db_table_name;
702
+
703
+ // 2. Get current max sequence number from that table
704
+ const seqResult = await this.dataSource.query(
705
+ `SELECT MAX(CAST(SUBSTRING(code, LENGTH(entity_type) + 1) AS UNSIGNED)) AS max_seq_no
706
+ FROM \`${tableName}\`
707
+ WHERE entity_type = ?`,
708
+ [entityType],
709
+ );
710
+
711
+ let maxSeqNo = seqResult?.[0]?.max_seq_no
712
+ ? Number(seqResult[0].max_seq_no)
713
+ : 0;
714
+
715
+ maxSeqNo += 1;
716
+
717
+ // 3. Return generated code
718
+ return `${entityType}${maxSeqNo}`;
719
+ }
720
+
721
+ async getResolvedEntity(
722
+ id: number,
723
+ entity: string,
724
+ loggedInUser: UserData,
725
+ ): Promise<any> {
726
+ const leadData = await this.getEntityWithRelation(entity, id, loggedInUser);
727
+
728
+ const { mappedEntities, ...data } = leadData as any;
729
+
730
+ const resolvedData = await this.resolverService.getResolvedData(
731
+ loggedInUser,
732
+ data,
733
+ entity,
734
+ );
735
+
736
+ if (mappedEntities) {
737
+ resolvedData.mappedEntities = {};
738
+ for (const [entityType, entities] of Object.entries(mappedEntities)) {
739
+ if (Array.isArray(entities)) {
740
+ resolvedData.mappedEntities[entityType] = [];
741
+ for (const item of entities) {
742
+ const resolvedItem = await this.resolverService.getResolvedData(
743
+ loggedInUser,
744
+ item,
745
+ entityType,
746
+ );
747
+ resolvedData.mappedEntities[entityType].push(resolvedItem);
748
+ }
749
+ } else {
750
+ resolvedData.mappedEntities[entityType] =
751
+ await this.resolverService.getResolvedData(
752
+ loggedInUser,
753
+ entities,
754
+ entityType,
755
+ );
756
+ }
757
+ }
758
+ }
759
+
760
+ return resolvedData;
761
+ }
762
+ }