@open-mercato/core 0.6.4-develop.4210.1.d412061cfe → 0.6.4-develop.4236.1.9fa6806b34

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 (370) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/staff_time_entry/index.js +37 -0
  3. package/dist/generated/entities/staff_time_entry/index.js.map +7 -0
  4. package/dist/generated/entities/staff_time_entry_segment/index.js +23 -0
  5. package/dist/generated/entities/staff_time_entry_segment/index.js.map +7 -0
  6. package/dist/generated/entities/staff_time_project/index.js +35 -0
  7. package/dist/generated/entities/staff_time_project/index.js.map +7 -0
  8. package/dist/generated/entities/staff_time_project_member/index.js +29 -0
  9. package/dist/generated/entities/staff_time_project_member/index.js.map +7 -0
  10. package/dist/generated/entities.ids.generated.js +5 -1
  11. package/dist/generated/entities.ids.generated.js.map +2 -2
  12. package/dist/generated/entity-fields-registry.js +64 -0
  13. package/dist/generated/entity-fields-registry.js.map +2 -2
  14. package/dist/helpers/integration/timesheetFixtures.js +50 -0
  15. package/dist/helpers/integration/timesheetFixtures.js.map +7 -0
  16. package/dist/modules/attachments/api/library/[id]/route.js +20 -16
  17. package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
  18. package/dist/modules/attachments/api/route.js +18 -14
  19. package/dist/modules/attachments/api/route.js.map +2 -2
  20. package/dist/modules/auth/api/roles/acl/route.js +10 -4
  21. package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
  22. package/dist/modules/auth/api/sidebar/preferences/route.js +27 -20
  23. package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
  24. package/dist/modules/auth/api/users/acl/route.js +16 -11
  25. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  26. package/dist/modules/auth/commands/users.js +87 -71
  27. package/dist/modules/auth/commands/users.js.map +2 -2
  28. package/dist/modules/auth/services/sidebarPreferencesService.js +39 -30
  29. package/dist/modules/auth/services/sidebarPreferencesService.js.map +2 -2
  30. package/dist/modules/catalog/commands/categories.js +61 -12
  31. package/dist/modules/catalog/commands/categories.js.map +2 -2
  32. package/dist/modules/catalog/commands/products.js +79 -54
  33. package/dist/modules/catalog/commands/products.js.map +2 -2
  34. package/dist/modules/catalog/commands/variants.js +29 -16
  35. package/dist/modules/catalog/commands/variants.js.map +2 -2
  36. package/dist/modules/currencies/commands/currencies.js +15 -8
  37. package/dist/modules/currencies/commands/currencies.js.map +2 -2
  38. package/dist/modules/customer_accounts/api/admin/users.js +27 -26
  39. package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
  40. package/dist/modules/customer_accounts/api/password/reset-confirm.js +5 -5
  41. package/dist/modules/customer_accounts/api/password/reset-confirm.js.map +2 -2
  42. package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js +11 -10
  43. package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js.map +2 -2
  44. package/dist/modules/customers/commands/addresses.js +35 -21
  45. package/dist/modules/customers/commands/addresses.js.map +2 -2
  46. package/dist/modules/customers/commands/companies.js +163 -162
  47. package/dist/modules/customers/commands/companies.js.map +2 -2
  48. package/dist/modules/customers/commands/deals.js +3 -4
  49. package/dist/modules/customers/commands/deals.js.map +2 -2
  50. package/dist/modules/customers/commands/interactions.js +19 -22
  51. package/dist/modules/customers/commands/interactions.js.map +2 -2
  52. package/dist/modules/customers/commands/people.js +18 -15
  53. package/dist/modules/customers/commands/people.js.map +2 -2
  54. package/dist/modules/customers/commands/personCompanyLinks.js +105 -94
  55. package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
  56. package/dist/modules/customers/commands/pipeline-stages.js +30 -23
  57. package/dist/modules/customers/commands/pipeline-stages.js.map +2 -2
  58. package/dist/modules/customers/commands/pipelines.js +27 -20
  59. package/dist/modules/customers/commands/pipelines.js.map +2 -2
  60. package/dist/modules/customers/commands/tags.js +13 -5
  61. package/dist/modules/customers/commands/tags.js.map +2 -2
  62. package/dist/modules/dashboards/api/users/widgets/route.js +0 -1
  63. package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
  64. package/dist/modules/dashboards/api/widgets/data/route.js +29 -1
  65. package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
  66. package/dist/modules/data_sync/lib/sync-engine.js +4 -4
  67. package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
  68. package/dist/modules/data_sync/lib/sync-run-service.js +51 -27
  69. package/dist/modules/data_sync/lib/sync-run-service.js.map +2 -2
  70. package/dist/modules/directory/commands/organizations.js +192 -158
  71. package/dist/modules/directory/commands/organizations.js.map +3 -3
  72. package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js +22 -16
  73. package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js.map +2 -2
  74. package/dist/modules/messages/commands/messages.js +77 -75
  75. package/dist/modules/messages/commands/messages.js.map +2 -2
  76. package/dist/modules/messages/commands/shared.js +132 -132
  77. package/dist/modules/messages/commands/shared.js.map +2 -2
  78. package/dist/modules/perspectives/api/[tableId]/route.js +37 -26
  79. package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
  80. package/dist/modules/resources/commands/resources.js +125 -117
  81. package/dist/modules/resources/commands/resources.js.map +2 -2
  82. package/dist/modules/resources/commands/tags.js +7 -3
  83. package/dist/modules/resources/commands/tags.js.map +2 -2
  84. package/dist/modules/sales/api/quotes/send/route.js +12 -11
  85. package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
  86. package/dist/modules/sales/commands/documents.js +629 -478
  87. package/dist/modules/sales/commands/documents.js.map +2 -2
  88. package/dist/modules/sales/commands/payments.js +146 -146
  89. package/dist/modules/sales/commands/payments.js.map +2 -2
  90. package/dist/modules/sales/commands/returns.js +68 -60
  91. package/dist/modules/sales/commands/returns.js.map +2 -2
  92. package/dist/modules/staff/acl.js +10 -1
  93. package/dist/modules/staff/acl.js.map +2 -2
  94. package/dist/modules/staff/analytics.js +33 -0
  95. package/dist/modules/staff/analytics.js.map +7 -0
  96. package/dist/modules/staff/api/guards.js +31 -0
  97. package/dist/modules/staff/api/guards.js.map +7 -0
  98. package/dist/modules/staff/api/interceptors.js +96 -0
  99. package/dist/modules/staff/api/interceptors.js.map +7 -0
  100. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +170 -0
  101. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +7 -0
  102. package/dist/modules/staff/api/timesheets/my-projects/route.js +103 -0
  103. package/dist/modules/staff/api/timesheets/my-projects/route.js.map +7 -0
  104. package/dist/modules/staff/api/timesheets/projects/kpis/route.js +147 -0
  105. package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +7 -0
  106. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js +171 -0
  107. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js.map +7 -0
  108. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +180 -0
  109. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +7 -0
  110. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +155 -0
  111. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +7 -0
  112. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +173 -0
  113. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +7 -0
  114. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +260 -0
  115. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +7 -0
  116. package/dist/modules/staff/api/timesheets/time-entries/route.js +188 -0
  117. package/dist/modules/staff/api/timesheets/time-entries/route.js.map +7 -0
  118. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js +159 -0
  119. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js.map +7 -0
  120. package/dist/modules/staff/api/timesheets/time-projects/route.js +230 -0
  121. package/dist/modules/staff/api/timesheets/time-projects/route.js.map +7 -0
  122. package/dist/modules/staff/backend/staff/timesheets/page.js +710 -0
  123. package/dist/modules/staff/backend/staff/timesheets/page.js.map +7 -0
  124. package/dist/modules/staff/backend/staff/timesheets/page.meta.js +22 -0
  125. package/dist/modules/staff/backend/staff/timesheets/page.meta.js.map +7 -0
  126. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js +125 -0
  127. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js.map +7 -0
  128. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js +16 -0
  129. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js.map +7 -0
  130. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js +418 -0
  131. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +7 -0
  132. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js +16 -0
  133. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js.map +7 -0
  134. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js +79 -0
  135. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js.map +7 -0
  136. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js +16 -0
  137. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js.map +7 -0
  138. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +602 -0
  139. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +7 -0
  140. package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js +25 -0
  141. package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js.map +7 -0
  142. package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js +123 -0
  143. package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js.map +7 -0
  144. package/dist/modules/staff/cli.js +38 -1
  145. package/dist/modules/staff/cli.js.map +2 -2
  146. package/dist/modules/staff/commands/index.js +2 -0
  147. package/dist/modules/staff/commands/index.js.map +2 -2
  148. package/dist/modules/staff/commands/leave-requests.js +30 -28
  149. package/dist/modules/staff/commands/leave-requests.js.map +3 -3
  150. package/dist/modules/staff/commands/team-members.js +21 -20
  151. package/dist/modules/staff/commands/team-members.js.map +2 -2
  152. package/dist/modules/staff/commands/timesheets-entries.js +409 -0
  153. package/dist/modules/staff/commands/timesheets-entries.js.map +7 -0
  154. package/dist/modules/staff/commands/timesheets-projects.js +618 -0
  155. package/dist/modules/staff/commands/timesheets-projects.js.map +7 -0
  156. package/dist/modules/staff/data/enrichers.js +104 -0
  157. package/dist/modules/staff/data/enrichers.js.map +7 -0
  158. package/dist/modules/staff/data/entities.js +226 -1
  159. package/dist/modules/staff/data/entities.js.map +2 -2
  160. package/dist/modules/staff/data/validators.js +113 -1
  161. package/dist/modules/staff/data/validators.js.map +2 -2
  162. package/dist/modules/staff/events.js +13 -1
  163. package/dist/modules/staff/events.js.map +2 -2
  164. package/dist/modules/staff/lib/crud.js +7 -1
  165. package/dist/modules/staff/lib/crud.js.map +2 -2
  166. package/dist/modules/staff/lib/staffMemberResolver.js +15 -0
  167. package/dist/modules/staff/lib/staffMemberResolver.js.map +7 -0
  168. package/dist/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.js +60 -0
  169. package/dist/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.js.map +7 -0
  170. package/dist/modules/staff/lib/timesheets-projects/computeProjectsKpis.js +260 -0
  171. package/dist/modules/staff/lib/timesheets-projects/computeProjectsKpis.js.map +7 -0
  172. package/dist/modules/staff/lib/timesheets-projects/dateBuckets.js +41 -0
  173. package/dist/modules/staff/lib/timesheets-projects/dateBuckets.js.map +7 -0
  174. package/dist/modules/staff/lib/timesheets-projects/initials.js +10 -0
  175. package/dist/modules/staff/lib/timesheets-projects/initials.js.map +7 -0
  176. package/dist/modules/staff/lib/timesheets-projects/kpiMath.js +12 -0
  177. package/dist/modules/staff/lib/timesheets-projects/kpiMath.js.map +7 -0
  178. package/dist/modules/staff/lib/timesheets-projects/listProjectMembersPreview.js +55 -0
  179. package/dist/modules/staff/lib/timesheets-projects/listProjectMembersPreview.js.map +7 -0
  180. package/dist/modules/staff/lib/timesheets-projects-ui/HoursSparkline.js +66 -0
  181. package/dist/modules/staff/lib/timesheets-projects-ui/HoursSparkline.js.map +7 -0
  182. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js +81 -0
  183. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js.map +7 -0
  184. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.js +58 -0
  185. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.js.map +7 -0
  186. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.js +152 -0
  187. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.js.map +7 -0
  188. package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js +37 -0
  189. package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js.map +7 -0
  190. package/dist/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.js +57 -0
  191. package/dist/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.js.map +7 -0
  192. package/dist/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.js +50 -0
  193. package/dist/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.js.map +7 -0
  194. package/dist/modules/staff/lib/timesheets-ui/AddRowDropdown.js +163 -0
  195. package/dist/modules/staff/lib/timesheets-ui/AddRowDropdown.js.map +7 -0
  196. package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js +209 -0
  197. package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js.map +7 -0
  198. package/dist/modules/staff/lib/timesheets-ui/ColorPicker.js +52 -0
  199. package/dist/modules/staff/lib/timesheets-ui/ColorPicker.js.map +7 -0
  200. package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js +77 -0
  201. package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js.map +7 -0
  202. package/dist/modules/staff/lib/timesheets-ui/ListView.js +173 -0
  203. package/dist/modules/staff/lib/timesheets-ui/ListView.js.map +7 -0
  204. package/dist/modules/staff/lib/timesheets-ui/ProjectColorDot.js +32 -0
  205. package/dist/modules/staff/lib/timesheets-ui/ProjectColorDot.js.map +7 -0
  206. package/dist/modules/staff/lib/timesheets-ui/TimerBar.js +270 -0
  207. package/dist/modules/staff/lib/timesheets-ui/TimerBar.js.map +7 -0
  208. package/dist/modules/staff/lib/timesheets-ui/ViewSwitcher.js +57 -0
  209. package/dist/modules/staff/lib/timesheets-ui/ViewSwitcher.js.map +7 -0
  210. package/dist/modules/staff/lib/timesheets-ui/colors.js +43 -0
  211. package/dist/modules/staff/lib/timesheets-ui/colors.js.map +7 -0
  212. package/dist/modules/staff/migrations/Migration20260326135612.js +24 -0
  213. package/dist/modules/staff/migrations/Migration20260326135612.js.map +7 -0
  214. package/dist/modules/staff/migrations/Migration20260413102715.js +23 -0
  215. package/dist/modules/staff/migrations/Migration20260413102715.js.map +7 -0
  216. package/dist/modules/staff/migrations/Migration20260413111602.js +13 -0
  217. package/dist/modules/staff/migrations/Migration20260413111602.js.map +7 -0
  218. package/dist/modules/staff/migrations/Migration20260511112759.js +19 -0
  219. package/dist/modules/staff/migrations/Migration20260511112759.js.map +7 -0
  220. package/dist/modules/staff/search.js +35 -0
  221. package/dist/modules/staff/search.js.map +2 -2
  222. package/dist/modules/staff/setup.js +15 -1
  223. package/dist/modules/staff/setup.js.map +2 -2
  224. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.js +16 -0
  225. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.js.map +7 -0
  226. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js +126 -0
  227. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js.map +7 -0
  228. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.js +26 -0
  229. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.js.map +7 -0
  230. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/config.js +15 -0
  231. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/config.js.map +7 -0
  232. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js +238 -0
  233. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js.map +7 -0
  234. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.js +26 -0
  235. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.js.map +7 -0
  236. package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js +145 -0
  237. package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js.map +7 -0
  238. package/dist/modules/staff/widgets/injection-table.js +12 -0
  239. package/dist/modules/staff/widgets/injection-table.js.map +7 -0
  240. package/dist/modules/sync_excel/api/import/route.js +19 -17
  241. package/dist/modules/sync_excel/api/import/route.js.map +2 -2
  242. package/dist/modules/translations/commands/translations.js +22 -19
  243. package/dist/modules/translations/commands/translations.js.map +2 -2
  244. package/generated/entities/staff_time_entry/index.ts +17 -0
  245. package/generated/entities/staff_time_entry_segment/index.ts +10 -0
  246. package/generated/entities/staff_time_project/index.ts +16 -0
  247. package/generated/entities/staff_time_project_member/index.ts +13 -0
  248. package/generated/entities.ids.generated.ts +5 -1
  249. package/generated/entity-fields-registry.ts +64 -0
  250. package/package.json +7 -7
  251. package/src/helpers/integration/timesheetFixtures.ts +61 -0
  252. package/src/modules/attachments/api/library/[id]/route.ts +24 -17
  253. package/src/modules/attachments/api/route.ts +20 -14
  254. package/src/modules/auth/api/roles/acl/route.ts +11 -5
  255. package/src/modules/auth/api/sidebar/preferences/route.ts +33 -24
  256. package/src/modules/auth/api/users/acl/route.ts +17 -12
  257. package/src/modules/auth/commands/users.ts +96 -80
  258. package/src/modules/auth/services/sidebarPreferencesService.ts +40 -32
  259. package/src/modules/catalog/commands/categories.ts +61 -12
  260. package/src/modules/catalog/commands/products.ts +93 -60
  261. package/src/modules/catalog/commands/variants.ts +29 -16
  262. package/src/modules/currencies/commands/currencies.ts +27 -14
  263. package/src/modules/customer_accounts/api/admin/users.ts +31 -26
  264. package/src/modules/customer_accounts/api/password/reset-confirm.ts +5 -6
  265. package/src/modules/customer_accounts/api/portal/users/[id]/roles.ts +14 -13
  266. package/src/modules/customers/commands/addresses.ts +35 -23
  267. package/src/modules/customers/commands/companies.ts +166 -165
  268. package/src/modules/customers/commands/deals.ts +2 -4
  269. package/src/modules/customers/commands/interactions.ts +20 -26
  270. package/src/modules/customers/commands/people.ts +18 -15
  271. package/src/modules/customers/commands/personCompanyLinks.ts +109 -100
  272. package/src/modules/customers/commands/pipeline-stages.ts +31 -27
  273. package/src/modules/customers/commands/pipelines.ts +29 -23
  274. package/src/modules/customers/commands/tags.ts +13 -5
  275. package/src/modules/dashboards/api/users/widgets/route.ts +0 -1
  276. package/src/modules/dashboards/api/widgets/data/route.ts +36 -1
  277. package/src/modules/data_sync/lib/sync-engine.ts +4 -5
  278. package/src/modules/data_sync/lib/sync-run-service.ts +57 -28
  279. package/src/modules/directory/commands/organizations.ts +203 -166
  280. package/src/modules/inbox_ops/api/emails/[id]/reprocess/route.ts +26 -18
  281. package/src/modules/messages/commands/messages.ts +82 -80
  282. package/src/modules/messages/commands/shared.ts +138 -133
  283. package/src/modules/perspectives/api/[tableId]/route.ts +38 -27
  284. package/src/modules/resources/commands/resources.ts +127 -117
  285. package/src/modules/resources/commands/tags.ts +7 -3
  286. package/src/modules/sales/api/quotes/send/route.ts +17 -12
  287. package/src/modules/sales/commands/documents.ts +673 -481
  288. package/src/modules/sales/commands/payments.ts +158 -152
  289. package/src/modules/sales/commands/returns.ts +74 -63
  290. package/src/modules/staff/acl.ts +11 -0
  291. package/src/modules/staff/analytics.ts +30 -0
  292. package/src/modules/staff/api/guards.ts +59 -0
  293. package/src/modules/staff/api/interceptors.ts +122 -0
  294. package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +191 -0
  295. package/src/modules/staff/api/timesheets/my-projects/route.ts +115 -0
  296. package/src/modules/staff/api/timesheets/projects/kpis/route.ts +159 -0
  297. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.ts +187 -0
  298. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +191 -0
  299. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +168 -0
  300. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +191 -0
  301. package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +292 -0
  302. package/src/modules/staff/api/timesheets/time-entries/route.ts +193 -0
  303. package/src/modules/staff/api/timesheets/time-projects/[id]/employees/route.ts +167 -0
  304. package/src/modules/staff/api/timesheets/time-projects/route.ts +244 -0
  305. package/src/modules/staff/backend/staff/timesheets/page.meta.ts +20 -0
  306. package/src/modules/staff/backend/staff/timesheets/page.tsx +899 -0
  307. package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.ts +12 -0
  308. package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.tsx +141 -0
  309. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.ts +12 -0
  310. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +579 -0
  311. package/src/modules/staff/backend/staff/timesheets/projects/create/page.meta.ts +12 -0
  312. package/src/modules/staff/backend/staff/timesheets/projects/create/page.tsx +90 -0
  313. package/src/modules/staff/backend/staff/timesheets/projects/page.meta.ts +23 -0
  314. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +765 -0
  315. package/src/modules/staff/backend/staff/timesheets/projects/projectFormConfig.ts +138 -0
  316. package/src/modules/staff/cli.ts +40 -1
  317. package/src/modules/staff/commands/index.ts +2 -0
  318. package/src/modules/staff/commands/leave-requests.ts +37 -29
  319. package/src/modules/staff/commands/team-members.ts +25 -20
  320. package/src/modules/staff/commands/timesheets-entries.ts +504 -0
  321. package/src/modules/staff/commands/timesheets-projects.ts +699 -0
  322. package/src/modules/staff/data/enrichers.ts +134 -0
  323. package/src/modules/staff/data/entities.ts +198 -0
  324. package/src/modules/staff/data/validators.ts +129 -0
  325. package/src/modules/staff/events.ts +13 -0
  326. package/src/modules/staff/i18n/de.json +209 -1
  327. package/src/modules/staff/i18n/en.json +209 -1
  328. package/src/modules/staff/i18n/es.json +209 -1
  329. package/src/modules/staff/i18n/pl.json +209 -1
  330. package/src/modules/staff/lib/crud.ts +8 -0
  331. package/src/modules/staff/lib/staffMemberResolver.ts +22 -0
  332. package/src/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.ts +89 -0
  333. package/src/modules/staff/lib/timesheets-projects/computeProjectsKpis.ts +311 -0
  334. package/src/modules/staff/lib/timesheets-projects/dateBuckets.ts +37 -0
  335. package/src/modules/staff/lib/timesheets-projects/initials.ts +6 -0
  336. package/src/modules/staff/lib/timesheets-projects/kpiMath.ts +8 -0
  337. package/src/modules/staff/lib/timesheets-projects/listProjectMembersPreview.ts +83 -0
  338. package/src/modules/staff/lib/timesheets-projects-ui/HoursSparkline.tsx +75 -0
  339. package/src/modules/staff/lib/timesheets-projects-ui/ProjectCard.tsx +110 -0
  340. package/src/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.tsx +73 -0
  341. package/src/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.tsx +185 -0
  342. package/src/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.tsx +53 -0
  343. package/src/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.tsx +63 -0
  344. package/src/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.ts +63 -0
  345. package/src/modules/staff/lib/timesheets-ui/AddRowDropdown.tsx +188 -0
  346. package/src/modules/staff/lib/timesheets-ui/CalendarPicker.tsx +229 -0
  347. package/src/modules/staff/lib/timesheets-ui/ColorPicker.tsx +65 -0
  348. package/src/modules/staff/lib/timesheets-ui/CreateProjectDialog.tsx +99 -0
  349. package/src/modules/staff/lib/timesheets-ui/ListView.tsx +230 -0
  350. package/src/modules/staff/lib/timesheets-ui/ProjectColorDot.tsx +40 -0
  351. package/src/modules/staff/lib/timesheets-ui/TimerBar.tsx +327 -0
  352. package/src/modules/staff/lib/timesheets-ui/ViewSwitcher.tsx +60 -0
  353. package/src/modules/staff/lib/timesheets-ui/colors.ts +58 -0
  354. package/src/modules/staff/migrations/.snapshot-open-mercato.json +1148 -0
  355. package/src/modules/staff/migrations/Migration20260326135612.ts +26 -0
  356. package/src/modules/staff/migrations/Migration20260413102715.ts +25 -0
  357. package/src/modules/staff/migrations/Migration20260413111602.ts +13 -0
  358. package/src/modules/staff/migrations/Migration20260511112759.ts +21 -0
  359. package/src/modules/staff/search.ts +35 -0
  360. package/src/modules/staff/setup.ts +15 -0
  361. package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.ts +17 -0
  362. package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.tsx +158 -0
  363. package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.ts +25 -0
  364. package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/config.ts +15 -0
  365. package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.tsx +297 -0
  366. package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.ts +25 -0
  367. package/src/modules/staff/widgets/injection/timer-sidebar-indicator/widget.tsx +161 -0
  368. package/src/modules/staff/widgets/injection-table.ts +10 -0
  369. package/src/modules/sync_excel/api/import/route.ts +23 -18
  370. package/src/modules/translations/commands/translations.ts +49 -41
@@ -6,6 +6,7 @@ import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
6
6
  import { logCrudAccess } from '@open-mercato/shared/lib/crud/factory'
7
7
  import { forbidden, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
8
8
  import { UserAcl } from '@open-mercato/core/modules/auth/data/entities'
9
+ import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
9
10
  import { assertActorCanModifySuperAdminUserTarget } from '@open-mercato/core/modules/auth/lib/grantChecks'
10
11
  import type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'
11
12
  import type { EntityManager } from '@mikro-orm/postgresql'
@@ -150,18 +151,22 @@ export async function PUT(req: Request) {
150
151
 
151
152
  const hasCustomAcl = effectiveIsSuperAdmin || effectiveFeatures.length > 0
152
153
 
153
- if (!hasCustomAcl) {
154
- if (acl) await em.remove(acl).flush()
155
- } else {
156
- if (!acl) {
157
- acl = em.create(UserAcl, { user: parsed.data.userId as any, tenantId: auth.tenantId as any })
158
- }
159
- const aclRecord = acl as any
160
- aclRecord.isSuperAdmin = effectiveIsSuperAdmin
161
- aclRecord.featuresJson = effectiveFeatures
162
- aclRecord.organizationsJson = organizations
163
- await em.persist(acl).flush()
164
- }
154
+ await withAtomicFlush(em, [
155
+ () => {
156
+ if (!hasCustomAcl) {
157
+ if (acl) em.remove(acl)
158
+ } else {
159
+ if (!acl) {
160
+ acl = em.create(UserAcl, { user: parsed.data.userId as any, tenantId: auth.tenantId as any })
161
+ }
162
+ const aclRecord = acl as any
163
+ aclRecord.isSuperAdmin = effectiveIsSuperAdmin
164
+ aclRecord.featuresJson = effectiveFeatures
165
+ aclRecord.organizationsJson = organizations
166
+ em.persist(acl)
167
+ }
168
+ },
169
+ ], { transaction: true })
165
170
 
166
171
  // Invalidate cache for this user
167
172
  await rbacService.invalidateUserCache(parsed.data.userId)
@@ -25,6 +25,7 @@ import {
25
25
  diffCustomFieldChanges,
26
26
  } from '@open-mercato/shared/lib/commands/customFieldSnapshots'
27
27
  import { extractUndoPayload, type UndoPayload } from '@open-mercato/shared/lib/commands/undo'
28
+ import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
28
29
  import { normalizeTenantId } from '@open-mercato/core/modules/auth/lib/tenantAccess'
29
30
  import { computeEmailHash } from '@open-mercato/core/modules/auth/lib/emailHash'
30
31
  import { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
@@ -300,31 +301,37 @@ const createUserCommand: CommandHandler<Record<string, unknown>, CreateUserResul
300
301
  if (!userId) return
301
302
  const snapshot = logEntry?.snapshotAfter as SerializedUser | undefined
302
303
  const em = (ctx.container.resolve('em') as EntityManager)
303
- await em.nativeDelete(UserAcl, { user: userId })
304
- await em.nativeDelete(UserRole, { user: userId })
305
- await em.nativeDelete(Session, { user: userId })
306
- await em.nativeDelete(PasswordReset, { user: userId })
307
-
308
304
  const de = (ctx.container.resolve('dataEngine') as DataEngine)
309
- if (snapshot?.custom && Object.keys(snapshot.custom).length) {
310
- const reset = buildCustomFieldResetMap(undefined, snapshot.custom)
311
- if (Object.keys(reset).length) {
312
- await setCustomFieldsIfAny({
313
- dataEngine: de,
314
- entityId: E.auth.user,
315
- recordId: userId,
316
- organizationId: snapshot.organizationId,
317
- tenantId: snapshot.tenantId,
318
- values: reset,
319
- notify: false,
305
+
306
+ let removed: User | null = null
307
+ await withAtomicFlush(em, [
308
+ async () => {
309
+ await em.nativeDelete(UserAcl, { user: userId })
310
+ await em.nativeDelete(UserRole, { user: userId })
311
+ await em.nativeDelete(Session, { user: userId })
312
+ await em.nativeDelete(PasswordReset, { user: userId })
313
+
314
+ if (snapshot?.custom && Object.keys(snapshot.custom).length) {
315
+ const reset = buildCustomFieldResetMap(undefined, snapshot.custom)
316
+ if (Object.keys(reset).length) {
317
+ await setCustomFieldsIfAny({
318
+ dataEngine: de,
319
+ entityId: E.auth.user,
320
+ recordId: userId,
321
+ organizationId: snapshot.organizationId,
322
+ tenantId: snapshot.tenantId,
323
+ values: reset,
324
+ notify: false,
325
+ })
326
+ }
327
+ }
328
+ removed = await de.deleteOrmEntity({
329
+ entity: User,
330
+ where: { id: userId, deletedAt: null } as FilterQuery<User>,
331
+ soft: false,
320
332
  })
321
- }
322
- }
323
- const removed = await de.deleteOrmEntity({
324
- entity: User,
325
- where: { id: userId, deletedAt: null } as FilterQuery<User>,
326
- soft: false,
327
- })
333
+ },
334
+ ], { transaction: true })
328
335
 
329
336
  await emitCrudUndoSideEffects({
330
337
  dataEngine: de,
@@ -648,19 +655,24 @@ const deleteUserCommand: CommandHandler<{ body?: Record<string, unknown>; query?
648
655
  async execute(input, ctx) {
649
656
  const id = requireId(input, 'User id required')
650
657
  const em = (ctx.container.resolve('em') as EntityManager)
651
-
652
- await em.nativeDelete(UserAcl, { user: id })
653
- await em.nativeDelete(UserRole, { user: id })
654
- await em.nativeDelete(Session, { user: id })
655
- await em.nativeDelete(PasswordReset, { user: id })
656
-
657
658
  const de = (ctx.container.resolve('dataEngine') as DataEngine)
658
- const user = await de.deleteOrmEntity({
659
- entity: User,
660
- where: { id, deletedAt: null } as FilterQuery<User>,
661
- soft: false,
662
- })
663
- if (!user) throw new CrudHttpError(404, { error: 'User not found' })
659
+
660
+ let user!: User
661
+ await withAtomicFlush(em, [
662
+ async () => {
663
+ await em.nativeDelete(UserAcl, { user: id })
664
+ await em.nativeDelete(UserRole, { user: id })
665
+ await em.nativeDelete(Session, { user: id })
666
+ await em.nativeDelete(PasswordReset, { user: id })
667
+ const removed = await de.deleteOrmEntity({
668
+ entity: User,
669
+ where: { id, deletedAt: null } as FilterQuery<User>,
670
+ soft: false,
671
+ })
672
+ if (!removed) throw new CrudHttpError(404, { error: 'User not found' })
673
+ user = removed
674
+ },
675
+ ], { transaction: true })
664
676
 
665
677
  await emitCrudSideEffects({
666
678
  dataEngine: de,
@@ -707,51 +719,55 @@ const deleteUserCommand: CommandHandler<{ body?: Record<string, unknown>; query?
707
719
  let user = await findOneWithDecryption(em, User, { id: before.id }, {}, { tenantId: null, organizationId: null })
708
720
  const de = (ctx.container.resolve('dataEngine') as DataEngine)
709
721
 
710
- if (user) {
711
- if (user.deletedAt) {
712
- user.deletedAt = null
713
- }
714
- user.email = before.email
715
- user.organizationId = before.organizationId ?? null
716
- user.tenantId = before.tenantId ?? null
717
- user.passwordHash = before.passwordHash ?? null
718
- user.name = before.name ?? null
719
- user.isConfirmed = before.isConfirmed
720
- await em.flush()
721
- } else {
722
- user = await de.createOrmEntity({
723
- entity: User,
724
- data: {
725
- id: before.id,
726
- email: before.email,
727
- organizationId: before.organizationId ?? null,
728
- tenantId: before.tenantId ?? null,
729
- passwordHash: before.passwordHash ?? null,
730
- name: before.name ?? null,
731
- isConfirmed: before.isConfirmed,
732
- },
733
- })
734
- }
735
-
736
- if (!user) return
737
-
738
- await em.nativeDelete(UserRole, { user: before.id })
739
- await syncUserRoles(em, user, before.roles, before.tenantId)
740
-
741
- await restoreUserAcls(em, user, before.acls)
742
-
743
- const reset = buildCustomFieldResetMap(before.custom, undefined)
744
- if (Object.keys(reset).length) {
745
- await setCustomFieldsIfAny({
746
- dataEngine: de,
747
- entityId: E.auth.user,
748
- recordId: before.id,
749
- organizationId: before.organizationId ?? null,
750
- tenantId: before.tenantId ?? null,
751
- values: reset,
752
- notify: false,
753
- })
754
- }
722
+ await withAtomicFlush(em, [
723
+ async () => {
724
+ if (user) {
725
+ if (user.deletedAt) {
726
+ user.deletedAt = null
727
+ }
728
+ user.email = before.email
729
+ user.organizationId = before.organizationId ?? null
730
+ user.tenantId = before.tenantId ?? null
731
+ user.passwordHash = before.passwordHash ?? null
732
+ user.name = before.name ?? null
733
+ user.isConfirmed = before.isConfirmed
734
+ await em.flush()
735
+ } else {
736
+ user = await de.createOrmEntity({
737
+ entity: User,
738
+ data: {
739
+ id: before.id,
740
+ email: before.email,
741
+ organizationId: before.organizationId ?? null,
742
+ tenantId: before.tenantId ?? null,
743
+ passwordHash: before.passwordHash ?? null,
744
+ name: before.name ?? null,
745
+ isConfirmed: before.isConfirmed,
746
+ },
747
+ })
748
+ }
749
+
750
+ if (!user) return
751
+
752
+ await em.nativeDelete(UserRole, { user: before.id })
753
+ await syncUserRoles(em, user, before.roles, before.tenantId)
754
+
755
+ await restoreUserAcls(em, user, before.acls)
756
+
757
+ const reset = buildCustomFieldResetMap(before.custom, undefined)
758
+ if (Object.keys(reset).length) {
759
+ await setCustomFieldsIfAny({
760
+ dataEngine: de,
761
+ entityId: E.auth.user,
762
+ recordId: before.id,
763
+ organizationId: before.organizationId ?? null,
764
+ tenantId: before.tenantId ?? null,
765
+ values: reset,
766
+ notify: false,
767
+ })
768
+ }
769
+ },
770
+ ], { transaction: true })
755
771
 
756
772
  await invalidateUserCache(ctx, before.id)
757
773
  },
@@ -1,5 +1,6 @@
1
1
  import { EntityManager, type FilterQuery } from '@mikro-orm/postgresql'
2
2
  import { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
3
+ import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
3
4
  import { Role, RoleSidebarPreference, SidebarVariant, User, UserSidebarPreference } from '../data/entities'
4
5
  import {
5
6
  SIDEBAR_PREFERENCES_VERSION,
@@ -346,21 +347,24 @@ export async function createSidebarVariant(
346
347
  version: input.settings?.version ?? SIDEBAR_PREFERENCES_VERSION,
347
348
  })
348
349
 
349
- if (input.isActive === true) {
350
- await deactivateAllVariants(em, scope)
351
- }
352
-
353
- const variant = em.create(SidebarVariant, {
354
- user: em.getReference(User, userId),
355
- tenantId,
356
- organizationId,
357
- locale,
358
- name: finalName,
359
- settingsJson: settings,
360
- isActive: input.isActive === true,
361
- createdAt: new Date(),
362
- })
363
- await em.flush()
350
+ let variant!: SidebarVariant
351
+ await withAtomicFlush(em, [
352
+ async () => {
353
+ if (input.isActive === true) {
354
+ await deactivateAllVariants(em, scope)
355
+ }
356
+ variant = em.create(SidebarVariant, {
357
+ user: em.getReference(User, userId),
358
+ tenantId,
359
+ organizationId,
360
+ locale,
361
+ name: finalName,
362
+ settingsJson: settings,
363
+ isActive: input.isActive === true,
364
+ createdAt: new Date(),
365
+ })
366
+ },
367
+ ], { transaction: true })
364
368
  return toVariantRecord(variant)
365
369
  }
366
370
 
@@ -383,23 +387,27 @@ export async function updateSidebarVariant(
383
387
  { tenantId, organizationId },
384
388
  )
385
389
  if (!variant) return null
386
- if (typeof input.name === 'string' && input.name.trim().length > 0) {
387
- variant.name = input.name.trim()
388
- }
389
- if (input.settings) {
390
- variant.settingsJson = normalizeSidebarSettings({
391
- ...input.settings,
392
- version: input.settings.version ?? SIDEBAR_PREFERENCES_VERSION,
393
- })
394
- }
395
- if (typeof input.isActive === 'boolean') {
396
- if (input.isActive) {
397
- await deactivateAllVariants(em, scope, variantId)
398
- }
399
- variant.isActive = input.isActive
400
- }
401
- await em.flush()
402
- return toVariantRecord(variant)
390
+ const target = variant
391
+ await withAtomicFlush(em, [
392
+ async () => {
393
+ if (typeof input.name === 'string' && input.name.trim().length > 0) {
394
+ target.name = input.name.trim()
395
+ }
396
+ if (input.settings) {
397
+ target.settingsJson = normalizeSidebarSettings({
398
+ ...input.settings,
399
+ version: input.settings.version ?? SIDEBAR_PREFERENCES_VERSION,
400
+ })
401
+ }
402
+ if (typeof input.isActive === 'boolean') {
403
+ if (input.isActive) {
404
+ await deactivateAllVariants(em, scope, variantId)
405
+ }
406
+ target.isActive = input.isActive
407
+ }
408
+ },
409
+ ], { transaction: true })
410
+ return toVariantRecord(target)
403
411
  }
404
412
 
405
413
  export async function deleteSidebarVariant(
@@ -2,6 +2,7 @@ import { registerCommand } from '@open-mercato/shared/lib/commands'
2
2
  import type { CommandHandler } from '@open-mercato/shared/lib/commands'
3
3
  import { buildChanges, requireId, parseWithCustomFields, setCustomFieldsIfAny, emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'
4
4
  import { loadCustomFieldSnapshot, buildCustomFieldResetMap } from '@open-mercato/shared/lib/commands/customFieldSnapshots'
5
+ import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
5
6
  import type { EntityManager } from '@mikro-orm/postgresql'
6
7
  import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
7
8
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
@@ -160,8 +161,16 @@ const createCategoryCommand: CommandHandler<CategoryCreateInput, { categoryId: s
160
161
  updatedAt: now,
161
162
  })
162
163
  em.persist(record)
163
- await em.flush()
164
- await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)
164
+ await withAtomicFlush(
165
+ em,
166
+ [
167
+ () => em.flush(),
168
+ async () => {
169
+ await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)
170
+ },
171
+ ],
172
+ { transaction: true }
173
+ )
165
174
  await setCustomFieldsIfAny({
166
175
  dataEngine: ctx.container.resolve('dataEngine'),
167
176
  entityId: E.catalog.catalog_product_category,
@@ -215,8 +224,16 @@ const createCategoryCommand: CommandHandler<CategoryCreateInput, { categoryId: s
215
224
  ensureOrganizationScope(ctx, record.organizationId)
216
225
  record.deletedAt = new Date()
217
226
  record.isActive = false
218
- await em.flush()
219
- await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)
227
+ await withAtomicFlush(
228
+ em,
229
+ [
230
+ () => em.flush(),
231
+ async () => {
232
+ await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)
233
+ },
234
+ ],
235
+ { transaction: true }
236
+ )
220
237
  const resetValues = buildCustomFieldResetMap(undefined, after.custom ?? undefined)
221
238
  if (Object.keys(resetValues).length) {
222
239
  await setCustomFieldsIfAny({
@@ -288,8 +305,16 @@ const updateCategoryCommand: CommandHandler<CategoryUpdateInput, { categoryId: s
288
305
  record.isActive = parsed.isActive
289
306
  }
290
307
 
291
- await em.flush()
292
- await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)
308
+ await withAtomicFlush(
309
+ em,
310
+ [
311
+ () => em.flush(),
312
+ async () => {
313
+ await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)
314
+ },
315
+ ],
316
+ { transaction: true }
317
+ )
293
318
  await setCustomFieldsIfAny({
294
319
  dataEngine: ctx.container.resolve('dataEngine'),
295
320
  entityId: E.catalog.catalog_product_category,
@@ -377,8 +402,16 @@ const updateCategoryCommand: CommandHandler<CategoryUpdateInput, { categoryId: s
377
402
  record.isActive = before.isActive
378
403
  record.deletedAt = null
379
404
  }
380
- await em.flush()
381
- await rebuildCategoryHierarchyForOrganization(em, before.organizationId, before.tenantId)
405
+ await withAtomicFlush(
406
+ em,
407
+ [
408
+ () => em.flush(),
409
+ async () => {
410
+ await rebuildCategoryHierarchyForOrganization(em, before.organizationId, before.tenantId)
411
+ },
412
+ ],
413
+ { transaction: true }
414
+ )
382
415
  const resetValues = buildCustomFieldResetMap(payload?.after?.custom ?? undefined, before.custom ?? undefined)
383
416
  if (Object.keys(resetValues).length) {
384
417
  await setCustomFieldsIfAny({
@@ -417,8 +450,16 @@ const deleteCategoryCommand: CommandHandler<{ id?: string }, { categoryId: strin
417
450
 
418
451
  record.deletedAt = new Date()
419
452
  record.isActive = false
420
- await em.flush()
421
- await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)
453
+ await withAtomicFlush(
454
+ em,
455
+ [
456
+ () => em.flush(),
457
+ async () => {
458
+ await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)
459
+ },
460
+ ],
461
+ { transaction: true }
462
+ )
422
463
  if (snapshot?.custom && Object.keys(snapshot.custom).length) {
423
464
  const resetValues = buildCustomFieldResetMap(snapshot.custom, undefined)
424
465
  if (Object.keys(resetValues).length) {
@@ -504,8 +545,16 @@ const deleteCategoryCommand: CommandHandler<{ id?: string }, { categoryId: strin
504
545
  record.childIds = before.childIds
505
546
  record.descendantIds = before.descendantIds
506
547
  }
507
- await em.flush()
508
- await rebuildCategoryHierarchyForOrganization(em, before.organizationId, before.tenantId)
548
+ await withAtomicFlush(
549
+ em,
550
+ [
551
+ () => em.flush(),
552
+ async () => {
553
+ await rebuildCategoryHierarchyForOrganization(em, before.organizationId, before.tenantId)
554
+ },
555
+ ],
556
+ { transaction: true }
557
+ )
509
558
  if (before.custom && Object.keys(before.custom).length) {
510
559
  await setCustomFieldsIfAny({
511
560
  dataEngine: ctx.container.resolve('dataEngine'),