@open-mercato/core 0.6.4-develop.4217.1.c9aa050183 → 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
@@ -53,6 +53,7 @@ import { E } from '#generated/entities.ids.generated'
53
53
  import { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
54
54
  import { CUSTOMER_ENTITY_ID, resolveCompanyCustomFieldRouting } from '../lib/customFieldRouting'
55
55
  import { CustomFieldValue } from '@open-mercato/core/modules/entities/data/entities'
56
+ import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
56
57
 
57
58
  const COMPANY_ENTITY_ID = 'customers:customer_company_profile'
58
59
  const INTERACTION_ENTITY_ID = 'customers:customer_interaction'
@@ -513,12 +514,13 @@ const createCompanyCommand: CommandHandler<CompanyCreateInput, { entityId: strin
513
514
  annualRevenue: parsed.annualRevenue !== undefined ? String(parsed.annualRevenue) : null,
514
515
  })
515
516
 
516
- em.persist(entity)
517
- em.persist(profile)
518
- await em.flush()
519
-
520
- await syncEntityTags(em, entity, parsed.tags)
521
- await em.flush()
517
+ await withAtomicFlush(em, [
518
+ () => {
519
+ em.persist(entity)
520
+ em.persist(profile)
521
+ },
522
+ () => syncEntityTags(em, entity, parsed.tags),
523
+ ], { transaction: true })
522
524
  await setCompanyCustomFields(ctx, entity.id, profile.id, entity.organizationId, entity.tenantId, custom)
523
525
 
524
526
  const de = (ctx.container.resolve('dataEngine') as DataEngine)
@@ -572,10 +574,13 @@ const createCompanyCommand: CommandHandler<CompanyCreateInput, { entityId: strin
572
574
  organizationId: entity.organizationId,
573
575
  tenantId: entity.tenantId,
574
576
  }
575
- await em.nativeDelete(CustomerCompanyProfile, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
576
- await em.nativeDelete(CustomerTagAssignment, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
577
- em.remove(entity)
578
- await em.flush()
577
+ await withAtomicFlush(em, [
578
+ async () => {
579
+ await em.nativeDelete(CustomerCompanyProfile, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
580
+ await em.nativeDelete(CustomerTagAssignment, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
581
+ em.remove(entity)
582
+ },
583
+ ], { transaction: true })
579
584
 
580
585
  const de = (ctx.container.resolve('dataEngine') as DataEngine)
581
586
  await emitCrudUndoSideEffects({
@@ -642,9 +647,9 @@ const updateCompanyCommand: CommandHandler<CompanyUpdateInput, { entityId: strin
642
647
  profile.annualRevenue = parsed.annualRevenue !== null && parsed.annualRevenue !== undefined ? String(parsed.annualRevenue) : null
643
648
  }
644
649
 
645
- await em.flush()
646
- await syncEntityTags(em, record, parsed.tags)
647
- await em.flush()
650
+ await withAtomicFlush(em, [
651
+ () => syncEntityTags(em, record, parsed.tags),
652
+ ], { transaction: true })
648
653
 
649
654
  await setCompanyCustomFields(ctx, record.id, profile.id, record.organizationId, record.tenantId, custom)
650
655
 
@@ -1092,10 +1097,6 @@ const deleteCompanyCommand: CommandHandler<{ body?: Record<string, unknown>; que
1092
1097
  profile.annualRevenue = before.profile.annualRevenue
1093
1098
  }
1094
1099
 
1095
- await em.flush()
1096
- await syncEntityTags(em, entity, before.tagIds)
1097
- await em.flush()
1098
-
1099
1100
  const beforeDeals = before.deals ?? []
1100
1101
  const beforeMembers = before.members ?? []
1101
1102
  const beforeActivities = (before as { activities?: CompanyActivitySnapshot[] }).activities ?? []
@@ -1104,163 +1105,163 @@ const deleteCompanyCommand: CommandHandler<{ body?: Record<string, unknown>; que
1104
1105
  const beforeTodos = (before as { todos?: CompanyTodoSnapshot[] }).todos ?? []
1105
1106
  const beforeInteractions = (before as { interactions?: CompanyInteractionSnapshot[] }).interactions ?? []
1106
1107
 
1107
- const relatedDealIds = new Set<string>()
1108
- for (const link of beforeDeals) relatedDealIds.add(link.dealId)
1109
- for (const activity of beforeActivities) {
1110
- if (activity.dealId) relatedDealIds.add(activity.dealId)
1111
- }
1112
- for (const comment of beforeComments) {
1113
- if (comment.dealId) relatedDealIds.add(comment.dealId)
1114
- }
1115
1108
  let dealMap = new Map<string, CustomerDeal>()
1116
- if (relatedDealIds.size) {
1117
- const deals = await em.find(CustomerDeal, {
1118
- id: { $in: Array.from(relatedDealIds) },
1119
- organizationId: entity.organizationId,
1120
- tenantId: entity.tenantId,
1121
- })
1122
- dealMap = new Map(deals.map((deal) => [deal.id, deal]))
1123
- }
1124
1109
 
1125
- await em.nativeDelete(CustomerDealCompanyLink, { company: entity })
1126
- for (const link of beforeDeals) {
1127
- const deal = dealMap.get(link.dealId)
1128
- if (!deal) continue
1129
- const restoredLink = em.create(CustomerDealCompanyLink, {
1130
- id: link.id,
1131
- deal,
1132
- company: entity,
1133
- createdAt: link.createdAt,
1134
- })
1135
- em.persist(restoredLink)
1136
- }
1137
- await em.flush()
1110
+ await withAtomicFlush(em, [
1111
+ () => syncEntityTags(em, entity, before.tagIds),
1112
+ async () => {
1113
+ const relatedDealIds = new Set<string>()
1114
+ for (const link of beforeDeals) relatedDealIds.add(link.dealId)
1115
+ for (const activity of beforeActivities) {
1116
+ if (activity.dealId) relatedDealIds.add(activity.dealId)
1117
+ }
1118
+ for (const comment of beforeComments) {
1119
+ if (comment.dealId) relatedDealIds.add(comment.dealId)
1120
+ }
1121
+ if (relatedDealIds.size) {
1122
+ const deals = await em.find(CustomerDeal, {
1123
+ id: { $in: Array.from(relatedDealIds) },
1124
+ organizationId: entity.organizationId,
1125
+ tenantId: entity.tenantId,
1126
+ })
1127
+ dealMap = new Map(deals.map((deal) => [deal.id, deal]))
1128
+ }
1138
1129
 
1139
- if (beforeMembers.length) {
1140
- const memberIds = beforeMembers.map((member) => member.profileId)
1141
- const profiles = await em.find(CustomerPersonProfile, {
1142
- id: { $in: memberIds },
1143
- organizationId: entity.organizationId,
1144
- tenantId: entity.tenantId,
1145
- })
1146
- const profileMap = new Map(profiles.map((profile) => [profile.id, profile]))
1147
- for (const member of beforeMembers) {
1148
- const memberProfile = profileMap.get(member.profileId)
1149
- if (!memberProfile) continue
1150
- memberProfile.company = entity
1151
- }
1152
- await em.flush()
1153
- }
1130
+ await em.nativeDelete(CustomerDealCompanyLink, { company: entity })
1131
+ for (const link of beforeDeals) {
1132
+ const deal = dealMap.get(link.dealId)
1133
+ if (!deal) continue
1134
+ const restoredLink = em.create(CustomerDealCompanyLink, {
1135
+ id: link.id,
1136
+ deal,
1137
+ company: entity,
1138
+ createdAt: link.createdAt,
1139
+ })
1140
+ em.persist(restoredLink)
1141
+ }
1154
1142
 
1155
- await em.nativeDelete(CustomerActivity, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
1156
- for (const activity of beforeActivities) {
1157
- const restoredActivity = em.create(CustomerActivity, {
1158
- id: activity.id,
1159
- organizationId: entity.organizationId,
1160
- tenantId: entity.tenantId,
1161
- entity,
1162
- activityType: activity.activityType,
1163
- subject: activity.subject,
1164
- body: activity.body,
1165
- occurredAt: activity.occurredAt,
1166
- authorUserId: activity.authorUserId,
1167
- appearanceIcon: activity.appearanceIcon,
1168
- appearanceColor: activity.appearanceColor,
1169
- deal: activity.dealId ? dealMap.get(activity.dealId) ?? null : null,
1170
- createdAt: activity.createdAt,
1171
- updatedAt: activity.updatedAt,
1172
- })
1173
- em.persist(restoredActivity)
1174
- }
1175
- await em.flush()
1143
+ if (beforeMembers.length) {
1144
+ const memberIds = beforeMembers.map((member) => member.profileId)
1145
+ const profiles = await em.find(CustomerPersonProfile, {
1146
+ id: { $in: memberIds },
1147
+ organizationId: entity.organizationId,
1148
+ tenantId: entity.tenantId,
1149
+ })
1150
+ const profileMap = new Map(profiles.map((profile) => [profile.id, profile]))
1151
+ for (const member of beforeMembers) {
1152
+ const memberProfile = profileMap.get(member.profileId)
1153
+ if (!memberProfile) continue
1154
+ memberProfile.company = entity
1155
+ }
1156
+ }
1176
1157
 
1177
- await em.nativeDelete(CustomerComment, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
1178
- for (const comment of beforeComments) {
1179
- const restoredComment = em.create(CustomerComment, {
1180
- id: comment.id,
1181
- organizationId: entity.organizationId,
1182
- tenantId: entity.tenantId,
1183
- entity,
1184
- body: comment.body,
1185
- authorUserId: comment.authorUserId,
1186
- appearanceIcon: comment.appearanceIcon,
1187
- appearanceColor: comment.appearanceColor,
1188
- deal: comment.dealId ? dealMap.get(comment.dealId) ?? null : null,
1189
- createdAt: comment.createdAt,
1190
- updatedAt: comment.updatedAt,
1191
- deletedAt: comment.deletedAt,
1192
- })
1193
- em.persist(restoredComment)
1194
- }
1195
- await em.flush()
1158
+ await em.nativeDelete(CustomerActivity, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
1159
+ for (const activity of beforeActivities) {
1160
+ const restoredActivity = em.create(CustomerActivity, {
1161
+ id: activity.id,
1162
+ organizationId: entity.organizationId,
1163
+ tenantId: entity.tenantId,
1164
+ entity,
1165
+ activityType: activity.activityType,
1166
+ subject: activity.subject,
1167
+ body: activity.body,
1168
+ occurredAt: activity.occurredAt,
1169
+ authorUserId: activity.authorUserId,
1170
+ appearanceIcon: activity.appearanceIcon,
1171
+ appearanceColor: activity.appearanceColor,
1172
+ deal: activity.dealId ? dealMap.get(activity.dealId) ?? null : null,
1173
+ createdAt: activity.createdAt,
1174
+ updatedAt: activity.updatedAt,
1175
+ })
1176
+ em.persist(restoredActivity)
1177
+ }
1196
1178
 
1197
- await em.nativeDelete(CustomerAddress, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
1198
- for (const address of beforeAddresses) {
1199
- const restoredAddress = em.create(CustomerAddress, {
1200
- id: address.id,
1201
- organizationId: entity.organizationId,
1202
- tenantId: entity.tenantId,
1203
- entity,
1204
- name: address.name,
1205
- purpose: address.purpose,
1206
- addressLine1: address.addressLine1,
1207
- addressLine2: address.addressLine2,
1208
- city: address.city,
1209
- region: address.region,
1210
- postalCode: address.postalCode,
1211
- country: address.country,
1212
- latitude: address.latitude,
1213
- longitude: address.longitude,
1214
- isPrimary: address.isPrimary,
1215
- })
1216
- em.persist(restoredAddress)
1217
- }
1218
- await em.flush()
1179
+ await em.nativeDelete(CustomerComment, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
1180
+ for (const comment of beforeComments) {
1181
+ const restoredComment = em.create(CustomerComment, {
1182
+ id: comment.id,
1183
+ organizationId: entity.organizationId,
1184
+ tenantId: entity.tenantId,
1185
+ entity,
1186
+ body: comment.body,
1187
+ authorUserId: comment.authorUserId,
1188
+ appearanceIcon: comment.appearanceIcon,
1189
+ appearanceColor: comment.appearanceColor,
1190
+ deal: comment.dealId ? dealMap.get(comment.dealId) ?? null : null,
1191
+ createdAt: comment.createdAt,
1192
+ updatedAt: comment.updatedAt,
1193
+ deletedAt: comment.deletedAt,
1194
+ })
1195
+ em.persist(restoredComment)
1196
+ }
1219
1197
 
1220
- await em.nativeDelete(CustomerTodoLink, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
1221
- for (const todo of beforeTodos) {
1222
- const restoredTodo = em.create(CustomerTodoLink, {
1223
- id: todo.id,
1224
- organizationId: entity.organizationId,
1225
- tenantId: entity.tenantId,
1226
- entity,
1227
- todoId: todo.todoId,
1228
- todoSource: todo.todoSource,
1229
- createdAt: todo.createdAt,
1230
- createdByUserId: todo.createdByUserId,
1231
- })
1232
- em.persist(restoredTodo)
1233
- }
1234
- await em.flush()
1198
+ await em.nativeDelete(CustomerAddress, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
1199
+ for (const address of beforeAddresses) {
1200
+ const restoredAddress = em.create(CustomerAddress, {
1201
+ id: address.id,
1202
+ organizationId: entity.organizationId,
1203
+ tenantId: entity.tenantId,
1204
+ entity,
1205
+ name: address.name,
1206
+ purpose: address.purpose,
1207
+ addressLine1: address.addressLine1,
1208
+ addressLine2: address.addressLine2,
1209
+ city: address.city,
1210
+ region: address.region,
1211
+ postalCode: address.postalCode,
1212
+ country: address.country,
1213
+ latitude: address.latitude,
1214
+ longitude: address.longitude,
1215
+ isPrimary: address.isPrimary,
1216
+ })
1217
+ em.persist(restoredAddress)
1218
+ }
1219
+
1220
+ await em.nativeDelete(CustomerTodoLink, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
1221
+ for (const todo of beforeTodos) {
1222
+ const restoredTodo = em.create(CustomerTodoLink, {
1223
+ id: todo.id,
1224
+ organizationId: entity.organizationId,
1225
+ tenantId: entity.tenantId,
1226
+ entity,
1227
+ todoId: todo.todoId,
1228
+ todoSource: todo.todoSource,
1229
+ createdAt: todo.createdAt,
1230
+ createdByUserId: todo.createdByUserId,
1231
+ })
1232
+ em.persist(restoredTodo)
1233
+ }
1234
+
1235
+ await em.nativeDelete(CustomerInteraction, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
1236
+ for (const interaction of beforeInteractions) {
1237
+ const restoredInteraction = em.create(CustomerInteraction, {
1238
+ id: interaction.id,
1239
+ organizationId: entity.organizationId,
1240
+ tenantId: entity.tenantId,
1241
+ entity,
1242
+ interactionType: interaction.interactionType,
1243
+ title: interaction.title,
1244
+ body: interaction.body,
1245
+ status: interaction.status,
1246
+ scheduledAt: interaction.scheduledAt,
1247
+ occurredAt: interaction.occurredAt,
1248
+ priority: interaction.priority,
1249
+ authorUserId: interaction.authorUserId,
1250
+ ownerUserId: interaction.ownerUserId,
1251
+ dealId: interaction.dealId,
1252
+ source: interaction.source,
1253
+ appearanceIcon: interaction.appearanceIcon,
1254
+ appearanceColor: interaction.appearanceColor,
1255
+ createdAt: interaction.createdAt,
1256
+ updatedAt: interaction.updatedAt,
1257
+ deletedAt: interaction.deletedAt,
1258
+ })
1259
+ em.persist(restoredInteraction)
1260
+ }
1261
+ },
1262
+ ], { transaction: true })
1235
1263
 
1236
1264
  const de = (ctx.container.resolve('dataEngine') as DataEngine)
1237
- await em.nativeDelete(CustomerInteraction, { entity, organizationId: entity.organizationId, tenantId: entity.tenantId })
1238
- for (const interaction of beforeInteractions) {
1239
- const restoredInteraction = em.create(CustomerInteraction, {
1240
- id: interaction.id,
1241
- organizationId: entity.organizationId,
1242
- tenantId: entity.tenantId,
1243
- entity,
1244
- interactionType: interaction.interactionType,
1245
- title: interaction.title,
1246
- body: interaction.body,
1247
- status: interaction.status,
1248
- scheduledAt: interaction.scheduledAt,
1249
- occurredAt: interaction.occurredAt,
1250
- priority: interaction.priority,
1251
- authorUserId: interaction.authorUserId,
1252
- ownerUserId: interaction.ownerUserId,
1253
- dealId: interaction.dealId,
1254
- source: interaction.source,
1255
- appearanceIcon: interaction.appearanceIcon,
1256
- appearanceColor: interaction.appearanceColor,
1257
- createdAt: interaction.createdAt,
1258
- updatedAt: interaction.updatedAt,
1259
- deletedAt: interaction.deletedAt,
1260
- })
1261
- em.persist(restoredInteraction)
1262
- }
1263
- await em.flush()
1264
1265
  for (const interaction of beforeInteractions) {
1265
1266
  if (!interaction.custom || !Object.keys(interaction.custom).length) continue
1266
1267
  await setCustomFieldsIfAny({
@@ -384,7 +384,7 @@ const createDealCommand: CommandHandler<DealCreateInput, { dealId: string }> = {
384
384
  }))?.value ?? stageSnapshot.label
385
385
  : parsed.pipelineStage ?? null
386
386
  },
387
- () => {
387
+ async () => {
388
388
  deal = em.create(CustomerDeal, {
389
389
  organizationId: parsed.organizationId,
390
390
  tenantId: parsed.tenantId,
@@ -405,10 +405,8 @@ const createDealCommand: CommandHandler<DealCreateInput, { dealId: string }> = {
405
405
  lossNotes: parsed.lossNotes ?? null,
406
406
  })
407
407
  em.persist(deal)
408
+ await em.flush()
408
409
  },
409
- ], { transaction: true })
410
-
411
- await withAtomicFlush(em, [
412
410
  async () => {
413
411
  const snapshot = stageSnapshot
414
412
  if (!snapshot) return
@@ -301,7 +301,7 @@ const createInteractionCommand: CommandHandler<InteractionCreateInput, { interac
301
301
 
302
302
  const em = (ctx.container.resolve('em') as EntityManager).fork()
303
303
  const normalizedAuthor = normalizeAuthorUserId(parsed.authorUserId ?? null, ctx.auth)
304
- const { interaction, entityId } = await runInTransaction(em, async (trx) => {
304
+ const { interaction, entityId, nextInteractionId } = await runInTransaction(em, async (trx) => {
305
305
  const entity = await requireTimelineParentEntity(trx, parsed.entityId)
306
306
  ensureTenantScope(ctx, entity.tenantId)
307
307
  ensureOrganizationScope(ctx, entity.organizationId)
@@ -352,15 +352,15 @@ const createInteractionCommand: CommandHandler<InteractionCreateInput, { interac
352
352
  custom,
353
353
  )
354
354
 
355
+ const projection = await recomputeNextInteraction(trx, entity.id)
356
+
355
357
  return {
356
358
  interaction,
357
359
  entityId: entity.id,
360
+ nextInteractionId: projection.nextInteractionId,
358
361
  }
359
362
  })
360
363
 
361
- const projection = await recomputeNextInteraction(em, entityId)
362
- const nextInteractionId = projection.nextInteractionId
363
-
364
364
  const de = (ctx.container.resolve('dataEngine') as DataEngine)
365
365
  await emitCrudSideEffects({
366
366
  dataEngine: de,
@@ -416,8 +416,10 @@ const createInteractionCommand: CommandHandler<InteractionCreateInput, { interac
416
416
  const entityId = typeof record.entity === 'string' ? record.entity : record.entity.id
417
417
  trx.remove(record)
418
418
  await trx.flush()
419
+ const projection = await recomputeNextInteraction(trx, entityId)
419
420
  return {
420
421
  entityId,
422
+ nextInteractionId: projection.nextInteractionId,
421
423
  identifiers: {
422
424
  id: record.id,
423
425
  organizationId: record.organizationId,
@@ -426,10 +428,9 @@ const createInteractionCommand: CommandHandler<InteractionCreateInput, { interac
426
428
  }
427
429
  })
428
430
  if (!result) return
429
- const projection = await recomputeNextInteraction(em, result.entityId)
430
431
  await emitNextInteractionUpdatedEvent(ctx, {
431
432
  entityId: result.entityId,
432
- nextInteractionId: projection.nextInteractionId,
433
+ nextInteractionId: result.nextInteractionId,
433
434
  }, result.identifiers)
434
435
  },
435
436
  }
@@ -447,7 +448,7 @@ const updateInteractionCommand: CommandHandler<InteractionUpdateInput, { interac
447
448
  async execute(rawInput, ctx) {
448
449
  const { parsed, custom } = parseWithCustomFields(interactionUpdateSchema, rawInput)
449
450
  const em = (ctx.container.resolve('em') as EntityManager).fork()
450
- const { interaction, entityId } = await runInTransaction(em, async (trx) => {
451
+ const { interaction, entityId, nextInteractionId } = await runInTransaction(em, async (trx) => {
451
452
  const interaction = await findOneWithDecryption(trx, CustomerInteraction, { id: parsed.id, deletedAt: null })
452
453
  if (!interaction) throw new CrudHttpError(404, { error: 'Interaction not found' })
453
454
  ensureTenantScope(ctx, interaction.tenantId)
@@ -493,11 +494,10 @@ const updateInteractionCommand: CommandHandler<InteractionUpdateInput, { interac
493
494
  custom,
494
495
  )
495
496
 
496
- return { interaction, entityId }
497
- })
497
+ const projection = await recomputeNextInteraction(trx, entityId)
498
498
 
499
- const projection = await recomputeNextInteraction(em, entityId)
500
- const nextInteractionId = projection.nextInteractionId
499
+ return { interaction, entityId, nextInteractionId: projection.nextInteractionId }
500
+ })
501
501
 
502
502
  const de = (ctx.container.resolve('dataEngine') as DataEngine)
503
503
  await emitCrudSideEffects({
@@ -677,7 +677,7 @@ const completeInteractionCommand: CommandHandler<InteractionCompleteInput, { int
677
677
  async execute(rawInput, ctx) {
678
678
  const parsed = interactionCompleteSchema.parse(rawInput)
679
679
  const em = (ctx.container.resolve('em') as EntityManager).fork()
680
- const { interaction, entityId } = await runInTransaction(em, async (trx) => {
680
+ const { interaction, entityId, nextInteractionId } = await runInTransaction(em, async (trx) => {
681
681
  const interaction = await findOneWithDecryption(trx, CustomerInteraction, { id: parsed.id, deletedAt: null })
682
682
  if (!interaction) throw new CrudHttpError(404, { error: 'Interaction not found' })
683
683
  ensureTenantScope(ctx, interaction.tenantId)
@@ -688,12 +688,10 @@ const completeInteractionCommand: CommandHandler<InteractionCompleteInput, { int
688
688
  await trx.flush()
689
689
 
690
690
  const entityId = typeof interaction.entity === 'string' ? interaction.entity : interaction.entity.id
691
- return { interaction, entityId }
691
+ const projection = await recomputeNextInteraction(trx, entityId)
692
+ return { interaction, entityId, nextInteractionId: projection.nextInteractionId }
692
693
  })
693
694
 
694
- const projection = await recomputeNextInteraction(em, entityId)
695
- const nextInteractionId = projection.nextInteractionId
696
-
697
695
  const identifiers = {
698
696
  id: interaction.id,
699
697
  organizationId: interaction.organizationId,
@@ -809,7 +807,7 @@ const cancelInteractionCommand: CommandHandler<InteractionCancelInput, { interac
809
807
  async execute(rawInput, ctx) {
810
808
  const parsed = interactionCancelSchema.parse(rawInput)
811
809
  const em = (ctx.container.resolve('em') as EntityManager).fork()
812
- const { interaction, entityId } = await runInTransaction(em, async (trx) => {
810
+ const { interaction, entityId, nextInteractionId } = await runInTransaction(em, async (trx) => {
813
811
  const interaction = await findOneWithDecryption(trx, CustomerInteraction, { id: parsed.id, deletedAt: null })
814
812
  if (!interaction) throw new CrudHttpError(404, { error: 'Interaction not found' })
815
813
  ensureTenantScope(ctx, interaction.tenantId)
@@ -819,12 +817,10 @@ const cancelInteractionCommand: CommandHandler<InteractionCancelInput, { interac
819
817
  await trx.flush()
820
818
 
821
819
  const entityId = typeof interaction.entity === 'string' ? interaction.entity : interaction.entity.id
822
- return { interaction, entityId }
820
+ const projection = await recomputeNextInteraction(trx, entityId)
821
+ return { interaction, entityId, nextInteractionId: projection.nextInteractionId }
823
822
  })
824
823
 
825
- const projection = await recomputeNextInteraction(em, entityId)
826
- const nextInteractionId = projection.nextInteractionId
827
-
828
824
  const identifiers = {
829
825
  id: interaction.id,
830
826
  organizationId: interaction.organizationId,
@@ -939,7 +935,7 @@ const deleteInteractionCommand: CommandHandler<{ body?: Record<string, unknown>;
939
935
  async execute(input, ctx) {
940
936
  const id = requireId(input, 'Interaction id required')
941
937
  const em = (ctx.container.resolve('em') as EntityManager).fork()
942
- const { interaction, entityId } = await runInTransaction(em, async (trx) => {
938
+ const { interaction, entityId, nextInteractionId } = await runInTransaction(em, async (trx) => {
943
939
  const interaction = await findOneWithDecryption(trx, CustomerInteraction, { id, deletedAt: null })
944
940
  if (!interaction) throw new CrudHttpError(404, { error: 'Interaction not found' })
945
941
  ensureTenantScope(ctx, interaction.tenantId)
@@ -949,12 +945,10 @@ const deleteInteractionCommand: CommandHandler<{ body?: Record<string, unknown>;
949
945
  interaction.deletedAt = new Date()
950
946
  await trx.flush()
951
947
 
952
- return { interaction, entityId }
948
+ const projection = await recomputeNextInteraction(trx, entityId)
949
+ return { interaction, entityId, nextInteractionId: projection.nextInteractionId }
953
950
  })
954
951
 
955
- const projection = await recomputeNextInteraction(em, entityId)
956
- const nextInteractionId = projection.nextInteractionId
957
-
958
952
  const de = (ctx.container.resolve('dataEngine') as DataEngine)
959
953
  await emitCrudSideEffects({
960
954
  dataEngine: de,
@@ -1041,21 +1041,24 @@ const deletePersonCommand: CommandHandler<{ body?: Record<string, unknown>; quer
1041
1041
  }
1042
1042
 
1043
1043
  const profile = await em.findOne(CustomerPersonProfile, { entity: record })
1044
- if (profile) em.remove(profile)
1045
- await em.nativeDelete(CustomerAddress, { entity: record, organizationId: record.organizationId, tenantId: record.tenantId })
1046
- await em.nativeDelete(CustomerComment, { entity: record, organizationId: record.organizationId, tenantId: record.tenantId })
1047
- await em.nativeDelete(CustomerActivity, { entity: record, organizationId: record.organizationId, tenantId: record.tenantId })
1048
- await em.nativeDelete(CustomerInteraction, { entity: record, organizationId: record.organizationId, tenantId: record.tenantId })
1049
- await em.nativeDelete(CustomerTodoLink, { entity: record, organizationId: record.organizationId, tenantId: record.tenantId })
1050
- await em.nativeDelete(CustomerTagAssignment, { entity: record, organizationId: record.organizationId, tenantId: record.tenantId })
1051
- await em.nativeDelete(CustomerDealPersonLink, { person: record })
1052
- await em.nativeDelete(CustomerPersonCompanyLink, { person: record })
1053
- if (profile) {
1054
- await em.nativeDelete(CustomFieldValue, { entityId: PERSON_ENTITY_ID, recordId: profile.id })
1055
- }
1056
- await em.nativeDelete(CustomFieldValue, { entityId: CUSTOMER_ENTITY_ID, recordId: record.id })
1057
- em.remove(record)
1058
- await em.flush()
1044
+ await withAtomicFlush(em, [
1045
+ async () => {
1046
+ if (profile) em.remove(profile)
1047
+ await em.nativeDelete(CustomerAddress, { entity: record, organizationId: record.organizationId, tenantId: record.tenantId })
1048
+ await em.nativeDelete(CustomerComment, { entity: record, organizationId: record.organizationId, tenantId: record.tenantId })
1049
+ await em.nativeDelete(CustomerActivity, { entity: record, organizationId: record.organizationId, tenantId: record.tenantId })
1050
+ await em.nativeDelete(CustomerInteraction, { entity: record, organizationId: record.organizationId, tenantId: record.tenantId })
1051
+ await em.nativeDelete(CustomerTodoLink, { entity: record, organizationId: record.organizationId, tenantId: record.tenantId })
1052
+ await em.nativeDelete(CustomerTagAssignment, { entity: record, organizationId: record.organizationId, tenantId: record.tenantId })
1053
+ await em.nativeDelete(CustomerDealPersonLink, { person: record })
1054
+ await em.nativeDelete(CustomerPersonCompanyLink, { person: record })
1055
+ if (profile) {
1056
+ await em.nativeDelete(CustomFieldValue, { entityId: PERSON_ENTITY_ID, recordId: profile.id })
1057
+ }
1058
+ await em.nativeDelete(CustomFieldValue, { entityId: CUSTOMER_ENTITY_ID, recordId: record.id })
1059
+ em.remove(record)
1060
+ },
1061
+ ], { transaction: true })
1059
1062
 
1060
1063
  const indexDeletes: QueryIndexEventEntry[] = []
1061
1064
  const dealUpserts: QueryIndexEventEntry[] = []