rez_core 5.0.27 → 5.0.29

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