rez_core 5.0.169 → 5.0.172

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