@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
@@ -1,6 +1,7 @@
1
1
  import { randomUUID } from "crypto";
2
2
  import { z } from "zod";
3
3
  import { registerCommand } from "@open-mercato/shared/lib/commands";
4
+ import { withAtomicFlush } from "@open-mercato/shared/lib/commands/flush";
4
5
  import {
5
6
  buildChanges,
6
7
  emitCrudSideEffects,
@@ -3161,7 +3162,6 @@ const createQuoteCommand = {
3161
3162
  createdAt: /* @__PURE__ */ new Date(),
3162
3163
  updatedAt: /* @__PURE__ */ new Date()
3163
3164
  });
3164
- em.persist(quote);
3165
3165
  const lineInputs = (parsed.lines ?? []).map(
3166
3166
  (line, index) => quoteLineCreateSchema.parse({
3167
3167
  ...line,
@@ -3221,32 +3221,45 @@ const createQuoteCommand = {
3221
3221
  adjustments: adjustmentDrafts,
3222
3222
  context: calculationContext
3223
3223
  });
3224
- await replaceQuoteLines(em, quote, calculation, normalizedLineInputs);
3225
- await replaceQuoteAdjustments(em, quote, calculation, adjustmentInputs);
3226
- applyQuoteTotals(quote, calculation.totals, calculation.lines.length);
3227
3224
  let eventBus = null;
3228
3225
  try {
3229
3226
  eventBus = ctx.container.resolve("eventBus");
3230
3227
  } catch {
3231
3228
  eventBus = null;
3232
3229
  }
3233
- await emitTotalsCalculated(eventBus, {
3234
- documentKind: "quote",
3235
- documentId: quote.id,
3236
- organizationId: quote.organizationId,
3237
- tenantId: quote.tenantId,
3238
- customerId: quote.customerEntityId ?? null,
3239
- totals: calculation.totals,
3240
- lineCount: calculation.lines.length
3241
- });
3242
- await syncSalesDocumentTags(em, {
3243
- documentId: quote.id,
3244
- kind: "quote",
3245
- organizationId: quote.organizationId,
3246
- tenantId: quote.tenantId,
3247
- tagIds: parsed.tags
3248
- });
3249
- await em.flush();
3230
+ await withAtomicFlush(
3231
+ em,
3232
+ [
3233
+ async () => {
3234
+ em.persist(quote);
3235
+ await replaceQuoteLines(em, quote, calculation, normalizedLineInputs);
3236
+ await replaceQuoteAdjustments(
3237
+ em,
3238
+ quote,
3239
+ calculation,
3240
+ adjustmentInputs
3241
+ );
3242
+ applyQuoteTotals(quote, calculation.totals, calculation.lines.length);
3243
+ await emitTotalsCalculated(eventBus, {
3244
+ documentKind: "quote",
3245
+ documentId: quote.id,
3246
+ organizationId: quote.organizationId,
3247
+ tenantId: quote.tenantId,
3248
+ customerId: quote.customerEntityId ?? null,
3249
+ totals: calculation.totals,
3250
+ lineCount: calculation.lines.length
3251
+ });
3252
+ await syncSalesDocumentTags(em, {
3253
+ documentId: quote.id,
3254
+ kind: "quote",
3255
+ organizationId: quote.organizationId,
3256
+ tenantId: quote.tenantId,
3257
+ tagIds: parsed.tags
3258
+ });
3259
+ }
3260
+ ],
3261
+ { transaction: true }
3262
+ );
3250
3263
  try {
3251
3264
  const notificationService = resolveNotificationService(ctx.container);
3252
3265
  const typeDef = notificationTypes.find(
@@ -3387,22 +3400,29 @@ const deleteQuoteCommand = {
3387
3400
  em.find(SalesQuoteAdjustment, { quote: quote.id }),
3388
3401
  em.find(SalesQuoteLine, { quote: quote.id })
3389
3402
  ]);
3390
- await em.nativeDelete(SalesDocumentAddress, {
3391
- documentId: quote.id,
3392
- documentKind: "quote"
3393
- });
3394
- await em.nativeDelete(SalesNote, {
3395
- contextType: "quote",
3396
- contextId: quote.id
3397
- });
3398
- await em.nativeDelete(SalesDocumentTagAssignment, {
3399
- documentId: quote.id,
3400
- documentKind: "quote"
3401
- });
3402
- await em.nativeDelete(SalesQuoteAdjustment, { quote: quote.id });
3403
- await em.nativeDelete(SalesQuoteLine, { quote: quote.id });
3404
- em.remove(quote);
3405
- await em.flush();
3403
+ await withAtomicFlush(
3404
+ em,
3405
+ [
3406
+ async () => {
3407
+ await em.nativeDelete(SalesDocumentAddress, {
3408
+ documentId: quote.id,
3409
+ documentKind: "quote"
3410
+ });
3411
+ await em.nativeDelete(SalesNote, {
3412
+ contextType: "quote",
3413
+ contextId: quote.id
3414
+ });
3415
+ await em.nativeDelete(SalesDocumentTagAssignment, {
3416
+ documentId: quote.id,
3417
+ documentKind: "quote"
3418
+ });
3419
+ await em.nativeDelete(SalesQuoteAdjustment, { quote: quote.id });
3420
+ await em.nativeDelete(SalesQuoteLine, { quote: quote.id });
3421
+ em.remove(quote);
3422
+ }
3423
+ ],
3424
+ { transaction: true }
3425
+ );
3406
3426
  const dataEngine = ctx.container.resolve("dataEngine");
3407
3427
  await Promise.all([
3408
3428
  queueDeletionSideEffects(dataEngine, quote, E.sales.sales_quote),
@@ -3485,106 +3505,119 @@ const updateQuoteCommand = {
3485
3505
  quote.sentAt = null;
3486
3506
  }
3487
3507
  const shouldRecalculateTotals = parsed.shippingMethodId !== void 0 || parsed.shippingMethodSnapshot !== void 0 || parsed.shippingMethodCode !== void 0 || parsed.paymentMethodId !== void 0 || parsed.paymentMethodSnapshot !== void 0 || parsed.paymentMethodCode !== void 0 || parsed.currencyCode !== void 0;
3488
- await applyDocumentUpdate({
3489
- kind: "quote",
3490
- entity: quote,
3491
- input: parsed,
3492
- em
3493
- });
3494
- await em.flush();
3495
- if (shouldInvalidateSentToken) {
3496
- quote.status = "draft";
3497
- quote.statusEntryId = await resolveStatusEntryIdByValue(em, {
3498
- tenantId: quote.tenantId,
3499
- organizationId: quote.organizationId,
3500
- value: "draft"
3501
- });
3502
- }
3503
- if (shouldRecalculateTotals) {
3504
- const [existingLines, adjustments] = await Promise.all([
3505
- em.find(SalesQuoteLine, { quote }, { orderBy: { lineNumber: "asc" } }),
3506
- em.find(
3507
- SalesQuoteAdjustment,
3508
- { quote },
3509
- { orderBy: { position: "asc" } }
3510
- )
3511
- ]);
3512
- const lineSnapshots = existingLines.map(mapQuoteLineEntityToSnapshot);
3513
- const calcLines = lineSnapshots.map(
3514
- (line, index) => createLineSnapshotFromInput(
3515
- {
3516
- ...line,
3517
- organizationId: quote.organizationId,
3518
- tenantId: quote.tenantId,
3519
- quoteId: quote.id,
3520
- lineNumber: line.lineNumber ?? index + 1,
3521
- statusEntryId: line.statusEntryId ?? null,
3522
- catalogSnapshot: line.catalogSnapshot ?? null,
3523
- promotionSnapshot: line.promotionSnapshot ?? null
3524
- },
3525
- line.lineNumber ?? index + 1
3526
- )
3527
- );
3528
- const adjustmentDrafts = adjustments.map(mapQuoteAdjustmentToDraft);
3529
- const salesCalculationService = ctx.container.resolve(
3530
- "salesCalculationService"
3531
- );
3532
- const calculationContext = buildCalculationContext({
3533
- tenantId: quote.tenantId,
3534
- organizationId: quote.organizationId,
3535
- currencyCode: quote.currencyCode,
3536
- shippingSnapshot: quote.shippingMethodSnapshot,
3537
- paymentSnapshot: quote.paymentMethodSnapshot,
3538
- shippingMethodId: quote.shippingMethodId ?? null,
3539
- paymentMethodId: quote.paymentMethodId ?? null,
3540
- shippingMethodCode: quote.shippingMethodCode ?? null,
3541
- paymentMethodCode: quote.paymentMethodCode ?? null
3542
- });
3543
- const calculation = await salesCalculationService.calculateDocumentTotals(
3544
- {
3545
- documentKind: "quote",
3546
- lines: calcLines,
3547
- adjustments: adjustmentDrafts,
3548
- context: calculationContext
3508
+ await withAtomicFlush(
3509
+ em,
3510
+ [
3511
+ async () => {
3512
+ await applyDocumentUpdate({
3513
+ kind: "quote",
3514
+ entity: quote,
3515
+ input: parsed,
3516
+ em
3517
+ });
3518
+ if (shouldInvalidateSentToken) {
3519
+ quote.status = "draft";
3520
+ quote.statusEntryId = await resolveStatusEntryIdByValue(em, {
3521
+ tenantId: quote.tenantId,
3522
+ organizationId: quote.organizationId,
3523
+ value: "draft"
3524
+ });
3525
+ }
3526
+ if (shouldRecalculateTotals) {
3527
+ const [existingLines, adjustments] = await Promise.all([
3528
+ em.find(
3529
+ SalesQuoteLine,
3530
+ { quote },
3531
+ { orderBy: { lineNumber: "asc" } }
3532
+ ),
3533
+ em.find(
3534
+ SalesQuoteAdjustment,
3535
+ { quote },
3536
+ { orderBy: { position: "asc" } }
3537
+ )
3538
+ ]);
3539
+ const lineSnapshots = existingLines.map(mapQuoteLineEntityToSnapshot);
3540
+ const calcLines = lineSnapshots.map(
3541
+ (line, index) => createLineSnapshotFromInput(
3542
+ {
3543
+ ...line,
3544
+ organizationId: quote.organizationId,
3545
+ tenantId: quote.tenantId,
3546
+ quoteId: quote.id,
3547
+ lineNumber: line.lineNumber ?? index + 1,
3548
+ statusEntryId: line.statusEntryId ?? null,
3549
+ catalogSnapshot: line.catalogSnapshot ?? null,
3550
+ promotionSnapshot: line.promotionSnapshot ?? null
3551
+ },
3552
+ line.lineNumber ?? index + 1
3553
+ )
3554
+ );
3555
+ const adjustmentDrafts = adjustments.map(mapQuoteAdjustmentToDraft);
3556
+ const salesCalculationService = ctx.container.resolve(
3557
+ "salesCalculationService"
3558
+ );
3559
+ const calculationContext = buildCalculationContext({
3560
+ tenantId: quote.tenantId,
3561
+ organizationId: quote.organizationId,
3562
+ currencyCode: quote.currencyCode,
3563
+ shippingSnapshot: quote.shippingMethodSnapshot,
3564
+ paymentSnapshot: quote.paymentMethodSnapshot,
3565
+ shippingMethodId: quote.shippingMethodId ?? null,
3566
+ paymentMethodId: quote.paymentMethodId ?? null,
3567
+ shippingMethodCode: quote.shippingMethodCode ?? null,
3568
+ paymentMethodCode: quote.paymentMethodCode ?? null
3569
+ });
3570
+ const calculation = await salesCalculationService.calculateDocumentTotals({
3571
+ documentKind: "quote",
3572
+ lines: calcLines,
3573
+ adjustments: adjustmentDrafts,
3574
+ context: calculationContext
3575
+ });
3576
+ const adjustmentInputs = adjustmentDrafts.map((adj, index) => ({
3577
+ organizationId: quote.organizationId,
3578
+ tenantId: quote.tenantId,
3579
+ quoteId: quote.id,
3580
+ scope: adj.scope ?? "order",
3581
+ kind: adj.kind ?? "custom",
3582
+ code: adj.code ?? void 0,
3583
+ label: adj.label ?? void 0,
3584
+ calculatorKey: adj.calculatorKey ?? void 0,
3585
+ promotionId: adj.promotionId ?? void 0,
3586
+ rate: adj.rate ?? void 0,
3587
+ amountNet: adj.amountNet ?? void 0,
3588
+ amountGross: adj.amountGross ?? void 0,
3589
+ currencyCode: adj.currencyCode ?? quote.currencyCode,
3590
+ metadata: adj.metadata ?? void 0,
3591
+ position: adj.position ?? index
3592
+ }));
3593
+ await replaceQuoteAdjustments(
3594
+ em,
3595
+ quote,
3596
+ calculation,
3597
+ adjustmentInputs
3598
+ );
3599
+ applyQuoteTotals(quote, calculation.totals, calculation.lines.length);
3600
+ let eventBus = null;
3601
+ try {
3602
+ eventBus = ctx.container.resolve("eventBus");
3603
+ } catch {
3604
+ eventBus = null;
3605
+ }
3606
+ await emitTotalsCalculated(eventBus, {
3607
+ documentKind: "quote",
3608
+ documentId: quote.id,
3609
+ organizationId: quote.organizationId,
3610
+ tenantId: quote.tenantId,
3611
+ customerId: quote.customerEntityId ?? null,
3612
+ totals: calculation.totals,
3613
+ lineCount: calculation.lines.length
3614
+ });
3615
+ }
3616
+ quote.updatedAt = /* @__PURE__ */ new Date();
3549
3617
  }
3550
- );
3551
- const adjustmentInputs = adjustmentDrafts.map((adj, index) => ({
3552
- organizationId: quote.organizationId,
3553
- tenantId: quote.tenantId,
3554
- quoteId: quote.id,
3555
- scope: adj.scope ?? "order",
3556
- kind: adj.kind ?? "custom",
3557
- code: adj.code ?? void 0,
3558
- label: adj.label ?? void 0,
3559
- calculatorKey: adj.calculatorKey ?? void 0,
3560
- promotionId: adj.promotionId ?? void 0,
3561
- rate: adj.rate ?? void 0,
3562
- amountNet: adj.amountNet ?? void 0,
3563
- amountGross: adj.amountGross ?? void 0,
3564
- currencyCode: adj.currencyCode ?? quote.currencyCode,
3565
- metadata: adj.metadata ?? void 0,
3566
- position: adj.position ?? index
3567
- }));
3568
- await replaceQuoteAdjustments(em, quote, calculation, adjustmentInputs);
3569
- applyQuoteTotals(quote, calculation.totals, calculation.lines.length);
3570
- let eventBus = null;
3571
- try {
3572
- eventBus = ctx.container.resolve("eventBus");
3573
- } catch {
3574
- eventBus = null;
3575
- }
3576
- await emitTotalsCalculated(eventBus, {
3577
- documentKind: "quote",
3578
- documentId: quote.id,
3579
- organizationId: quote.organizationId,
3580
- tenantId: quote.tenantId,
3581
- customerId: quote.customerEntityId ?? null,
3582
- totals: calculation.totals,
3583
- lineCount: calculation.lines.length
3584
- });
3585
- }
3586
- quote.updatedAt = /* @__PURE__ */ new Date();
3587
- await em.flush();
3618
+ ],
3619
+ { transaction: true }
3620
+ );
3588
3621
  const resourceKind = deriveResourceFromCommandId(updateQuoteCommand.id) ?? "sales.quote";
3589
3622
  await invalidateCrudCache(
3590
3623
  ctx.container,
@@ -3673,105 +3706,118 @@ const updateOrderCommand = {
3673
3706
  const previousStatus = normalizeStatusValue(order.status);
3674
3707
  let statusChangeNote = null;
3675
3708
  const shouldRecalculateTotals = parsed.shippingMethodId !== void 0 || parsed.shippingMethodSnapshot !== void 0 || parsed.shippingMethodCode !== void 0 || parsed.paymentMethodId !== void 0 || parsed.paymentMethodSnapshot !== void 0 || parsed.paymentMethodCode !== void 0 || parsed.currencyCode !== void 0;
3676
- await applyDocumentUpdate({
3677
- kind: "order",
3678
- entity: order,
3679
- input: parsed,
3680
- em
3681
- });
3682
- await em.flush();
3683
- if (shouldRecalculateTotals) {
3684
- const [existingLines, adjustments] = await Promise.all([
3685
- em.find(SalesOrderLine, { order }, { orderBy: { lineNumber: "asc" } }),
3686
- em.find(
3687
- SalesOrderAdjustment,
3688
- { order },
3689
- { orderBy: { position: "asc" } }
3690
- )
3691
- ]);
3692
- const lineSnapshots = existingLines.map(mapOrderLineEntityToSnapshot);
3693
- const calcLines = lineSnapshots.map(
3694
- (line, index) => createLineSnapshotFromInput(
3695
- {
3696
- ...line,
3697
- organizationId: order.organizationId,
3698
- tenantId: order.tenantId,
3699
- orderId: order.id,
3700
- lineNumber: line.lineNumber ?? index + 1,
3701
- statusEntryId: line.statusEntryId ?? null,
3702
- catalogSnapshot: line.catalogSnapshot ?? null,
3703
- promotionSnapshot: line.promotionSnapshot ?? null
3704
- },
3705
- line.lineNumber ?? index + 1
3706
- )
3707
- );
3708
- const adjustmentDrafts = adjustments.map(mapOrderAdjustmentToDraft);
3709
- const salesCalculationService = ctx.container.resolve(
3710
- "salesCalculationService"
3711
- );
3712
- const calculationContext = buildCalculationContext({
3713
- tenantId: order.tenantId,
3714
- organizationId: order.organizationId,
3715
- currencyCode: order.currencyCode,
3716
- shippingSnapshot: order.shippingMethodSnapshot,
3717
- paymentSnapshot: order.paymentMethodSnapshot,
3718
- shippingMethodId: order.shippingMethodId ?? null,
3719
- paymentMethodId: order.paymentMethodId ?? null,
3720
- shippingMethodCode: order.shippingMethodCode ?? null,
3721
- paymentMethodCode: order.paymentMethodCode ?? null
3722
- });
3723
- const calculation = await salesCalculationService.calculateDocumentTotals(
3724
- {
3725
- documentKind: "order",
3726
- lines: calcLines,
3727
- adjustments: adjustmentDrafts,
3728
- context: calculationContext,
3729
- existingTotals: resolveExistingPaymentTotals(order)
3730
- }
3731
- );
3732
- const adjustmentInputs = adjustmentDrafts.map((adj, index) => ({
3733
- organizationId: order.organizationId,
3734
- tenantId: order.tenantId,
3735
- orderId: order.id,
3736
- scope: adj.scope ?? "order",
3737
- kind: adj.kind ?? "custom",
3738
- code: adj.code ?? void 0,
3739
- label: adj.label ?? void 0,
3740
- calculatorKey: adj.calculatorKey ?? void 0,
3741
- promotionId: adj.promotionId ?? void 0,
3742
- rate: adj.rate ?? void 0,
3743
- amountNet: adj.amountNet ?? void 0,
3744
- amountGross: adj.amountGross ?? void 0,
3745
- currencyCode: adj.currencyCode ?? order.currencyCode,
3746
- metadata: adj.metadata ?? void 0,
3747
- position: adj.position ?? index
3748
- }));
3749
- await replaceOrderAdjustments(em, order, calculation, adjustmentInputs);
3750
- applyOrderTotals(order, calculation.totals, calculation.lines.length);
3751
- let eventBus = null;
3752
- try {
3753
- eventBus = ctx.container.resolve("eventBus");
3754
- } catch {
3755
- eventBus = null;
3756
- }
3757
- await emitTotalsCalculated(eventBus, {
3758
- documentKind: "order",
3759
- documentId: order.id,
3760
- organizationId: order.organizationId,
3761
- tenantId: order.tenantId,
3762
- customerId: order.customerEntityId ?? null,
3763
- totals: calculation.totals,
3764
- lineCount: calculation.lines.length
3765
- });
3766
- }
3767
- statusChangeNote = await appendOrderStatusChangeNote({
3709
+ await withAtomicFlush(
3768
3710
  em,
3769
- order,
3770
- previousStatus,
3771
- auth: ctx.auth ?? null
3772
- });
3773
- order.updatedAt = /* @__PURE__ */ new Date();
3774
- await em.flush();
3711
+ [
3712
+ async () => {
3713
+ await applyDocumentUpdate({
3714
+ kind: "order",
3715
+ entity: order,
3716
+ input: parsed,
3717
+ em
3718
+ });
3719
+ if (shouldRecalculateTotals) {
3720
+ const [existingLines, adjustments] = await Promise.all([
3721
+ em.find(
3722
+ SalesOrderLine,
3723
+ { order },
3724
+ { orderBy: { lineNumber: "asc" } }
3725
+ ),
3726
+ em.find(
3727
+ SalesOrderAdjustment,
3728
+ { order },
3729
+ { orderBy: { position: "asc" } }
3730
+ )
3731
+ ]);
3732
+ const lineSnapshots = existingLines.map(mapOrderLineEntityToSnapshot);
3733
+ const calcLines = lineSnapshots.map(
3734
+ (line, index) => createLineSnapshotFromInput(
3735
+ {
3736
+ ...line,
3737
+ organizationId: order.organizationId,
3738
+ tenantId: order.tenantId,
3739
+ orderId: order.id,
3740
+ lineNumber: line.lineNumber ?? index + 1,
3741
+ statusEntryId: line.statusEntryId ?? null,
3742
+ catalogSnapshot: line.catalogSnapshot ?? null,
3743
+ promotionSnapshot: line.promotionSnapshot ?? null
3744
+ },
3745
+ line.lineNumber ?? index + 1
3746
+ )
3747
+ );
3748
+ const adjustmentDrafts = adjustments.map(mapOrderAdjustmentToDraft);
3749
+ const salesCalculationService = ctx.container.resolve(
3750
+ "salesCalculationService"
3751
+ );
3752
+ const calculationContext = buildCalculationContext({
3753
+ tenantId: order.tenantId,
3754
+ organizationId: order.organizationId,
3755
+ currencyCode: order.currencyCode,
3756
+ shippingSnapshot: order.shippingMethodSnapshot,
3757
+ paymentSnapshot: order.paymentMethodSnapshot,
3758
+ shippingMethodId: order.shippingMethodId ?? null,
3759
+ paymentMethodId: order.paymentMethodId ?? null,
3760
+ shippingMethodCode: order.shippingMethodCode ?? null,
3761
+ paymentMethodCode: order.paymentMethodCode ?? null
3762
+ });
3763
+ const calculation = await salesCalculationService.calculateDocumentTotals({
3764
+ documentKind: "order",
3765
+ lines: calcLines,
3766
+ adjustments: adjustmentDrafts,
3767
+ context: calculationContext,
3768
+ existingTotals: resolveExistingPaymentTotals(order)
3769
+ });
3770
+ const adjustmentInputs = adjustmentDrafts.map((adj, index) => ({
3771
+ organizationId: order.organizationId,
3772
+ tenantId: order.tenantId,
3773
+ orderId: order.id,
3774
+ scope: adj.scope ?? "order",
3775
+ kind: adj.kind ?? "custom",
3776
+ code: adj.code ?? void 0,
3777
+ label: adj.label ?? void 0,
3778
+ calculatorKey: adj.calculatorKey ?? void 0,
3779
+ promotionId: adj.promotionId ?? void 0,
3780
+ rate: adj.rate ?? void 0,
3781
+ amountNet: adj.amountNet ?? void 0,
3782
+ amountGross: adj.amountGross ?? void 0,
3783
+ currencyCode: adj.currencyCode ?? order.currencyCode,
3784
+ metadata: adj.metadata ?? void 0,
3785
+ position: adj.position ?? index
3786
+ }));
3787
+ await replaceOrderAdjustments(
3788
+ em,
3789
+ order,
3790
+ calculation,
3791
+ adjustmentInputs
3792
+ );
3793
+ applyOrderTotals(order, calculation.totals, calculation.lines.length);
3794
+ let eventBus = null;
3795
+ try {
3796
+ eventBus = ctx.container.resolve("eventBus");
3797
+ } catch {
3798
+ eventBus = null;
3799
+ }
3800
+ await emitTotalsCalculated(eventBus, {
3801
+ documentKind: "order",
3802
+ documentId: order.id,
3803
+ organizationId: order.organizationId,
3804
+ tenantId: order.tenantId,
3805
+ customerId: order.customerEntityId ?? null,
3806
+ totals: calculation.totals,
3807
+ lineCount: calculation.lines.length
3808
+ });
3809
+ }
3810
+ statusChangeNote = await appendOrderStatusChangeNote({
3811
+ em,
3812
+ order,
3813
+ previousStatus,
3814
+ auth: ctx.auth ?? null
3815
+ });
3816
+ order.updatedAt = /* @__PURE__ */ new Date();
3817
+ }
3818
+ ],
3819
+ { transaction: true }
3820
+ );
3775
3821
  if (statusChangeNote) {
3776
3822
  const dataEngine = ctx.container.resolve("dataEngine");
3777
3823
  await emitCrudSideEffects({
@@ -3975,7 +4021,6 @@ const createOrderCommand = {
3975
4021
  createdAt: /* @__PURE__ */ new Date(),
3976
4022
  updatedAt: /* @__PURE__ */ new Date()
3977
4023
  });
3978
- em.persist(order);
3979
4024
  const lineInputs = (parsed.lines ?? []).map(
3980
4025
  (line, index) => orderLineCreateSchema.parse({
3981
4026
  ...line,
@@ -4036,32 +4081,45 @@ const createOrderCommand = {
4036
4081
  context: calculationContext,
4037
4082
  existingTotals: resolveExistingPaymentTotals(order)
4038
4083
  });
4039
- await replaceOrderLines(em, order, calculation, normalizedLineInputs);
4040
- await replaceOrderAdjustments(em, order, calculation, adjustmentInputs);
4041
- applyOrderTotals(order, calculation.totals, calculation.lines.length);
4042
4084
  let eventBus = null;
4043
4085
  try {
4044
4086
  eventBus = ctx.container.resolve("eventBus");
4045
4087
  } catch {
4046
4088
  eventBus = null;
4047
4089
  }
4048
- await emitTotalsCalculated(eventBus, {
4049
- documentKind: "order",
4050
- documentId: order.id,
4051
- organizationId: order.organizationId,
4052
- tenantId: order.tenantId,
4053
- customerId: order.customerEntityId ?? null,
4054
- totals: calculation.totals,
4055
- lineCount: calculation.lines.length
4056
- });
4057
- await syncSalesDocumentTags(em, {
4058
- documentId: order.id,
4059
- kind: "order",
4060
- organizationId: order.organizationId,
4061
- tenantId: order.tenantId,
4062
- tagIds: parsed.tags
4063
- });
4064
- await em.flush();
4090
+ await withAtomicFlush(
4091
+ em,
4092
+ [
4093
+ async () => {
4094
+ em.persist(order);
4095
+ await replaceOrderLines(em, order, calculation, normalizedLineInputs);
4096
+ await replaceOrderAdjustments(
4097
+ em,
4098
+ order,
4099
+ calculation,
4100
+ adjustmentInputs
4101
+ );
4102
+ applyOrderTotals(order, calculation.totals, calculation.lines.length);
4103
+ await emitTotalsCalculated(eventBus, {
4104
+ documentKind: "order",
4105
+ documentId: order.id,
4106
+ organizationId: order.organizationId,
4107
+ tenantId: order.tenantId,
4108
+ customerId: order.customerEntityId ?? null,
4109
+ totals: calculation.totals,
4110
+ lineCount: calculation.lines.length
4111
+ });
4112
+ await syncSalesDocumentTags(em, {
4113
+ documentId: order.id,
4114
+ kind: "order",
4115
+ organizationId: order.organizationId,
4116
+ tenantId: order.tenantId,
4117
+ tagIds: parsed.tags
4118
+ });
4119
+ }
4120
+ ],
4121
+ { transaction: true }
4122
+ );
4065
4123
  try {
4066
4124
  const notificationService = resolveNotificationService(ctx.container);
4067
4125
  const typeDef = notificationTypes.find(
@@ -4216,30 +4274,37 @@ const deleteOrderCommand = {
4216
4274
  em.find(SalesOrderAdjustment, { order: order.id }),
4217
4275
  em.find(SalesOrderLine, { order: order.id })
4218
4276
  ]);
4219
- if (shipmentIds.length) {
4220
- await em.nativeDelete(SalesShipmentItem, {
4221
- shipment: { $in: shipmentIds }
4222
- });
4223
- await em.nativeDelete(SalesShipment, { id: { $in: shipmentIds } });
4224
- }
4225
- await em.nativeDelete(SalesPaymentAllocation, { order: order.id });
4226
- await em.nativeDelete(SalesPayment, { order: order.id });
4227
- await em.nativeDelete(SalesDocumentAddress, {
4228
- documentId: order.id,
4229
- documentKind: "order"
4230
- });
4231
- await em.nativeDelete(SalesNote, {
4232
- contextType: "order",
4233
- contextId: order.id
4234
- });
4235
- await em.nativeDelete(SalesDocumentTagAssignment, {
4236
- documentId: order.id,
4237
- documentKind: "order"
4238
- });
4239
- await em.nativeDelete(SalesOrderAdjustment, { order: order.id });
4240
- await em.nativeDelete(SalesOrderLine, { order: order.id });
4241
- em.remove(order);
4242
- await em.flush();
4277
+ await withAtomicFlush(
4278
+ em,
4279
+ [
4280
+ async () => {
4281
+ if (shipmentIds.length) {
4282
+ await em.nativeDelete(SalesShipmentItem, {
4283
+ shipment: { $in: shipmentIds }
4284
+ });
4285
+ await em.nativeDelete(SalesShipment, { id: { $in: shipmentIds } });
4286
+ }
4287
+ await em.nativeDelete(SalesPaymentAllocation, { order: order.id });
4288
+ await em.nativeDelete(SalesPayment, { order: order.id });
4289
+ await em.nativeDelete(SalesDocumentAddress, {
4290
+ documentId: order.id,
4291
+ documentKind: "order"
4292
+ });
4293
+ await em.nativeDelete(SalesNote, {
4294
+ contextType: "order",
4295
+ contextId: order.id
4296
+ });
4297
+ await em.nativeDelete(SalesDocumentTagAssignment, {
4298
+ documentId: order.id,
4299
+ documentKind: "order"
4300
+ });
4301
+ await em.nativeDelete(SalesOrderAdjustment, { order: order.id });
4302
+ await em.nativeDelete(SalesOrderLine, { order: order.id });
4303
+ em.remove(order);
4304
+ }
4305
+ ],
4306
+ { transaction: true }
4307
+ );
4243
4308
  const dataEngine = ctx.container.resolve("dataEngine");
4244
4309
  await Promise.all([
4245
4310
  queueDeletionSideEffects(dataEngine, order, E.sales.sales_order),
@@ -4897,30 +4962,37 @@ const orderLineUpsertCommand = {
4897
4962
  context: calculationContext,
4898
4963
  existingTotals: resolveExistingPaymentTotals(order)
4899
4964
  });
4900
- await applyOrderLineResults({
4901
- em,
4902
- order,
4903
- calculation,
4904
- sourceLines: sourceInputs,
4905
- existingLines
4906
- });
4907
- applyOrderTotals(order, calculation.totals, calculation.lines.length);
4908
4965
  let eventBus = null;
4909
4966
  try {
4910
4967
  eventBus = ctx.container.resolve("eventBus");
4911
4968
  } catch {
4912
4969
  eventBus = null;
4913
4970
  }
4914
- await emitTotalsCalculated(eventBus, {
4915
- documentKind: "order",
4916
- documentId: order.id,
4917
- organizationId: order.organizationId,
4918
- tenantId: order.tenantId,
4919
- customerId: order.customerEntityId ?? null,
4920
- totals: calculation.totals,
4921
- lineCount: calculation.lines.length
4922
- });
4923
- await em.flush();
4971
+ await withAtomicFlush(
4972
+ em,
4973
+ [
4974
+ async () => {
4975
+ await applyOrderLineResults({
4976
+ em,
4977
+ order,
4978
+ calculation,
4979
+ sourceLines: sourceInputs,
4980
+ existingLines
4981
+ });
4982
+ applyOrderTotals(order, calculation.totals, calculation.lines.length);
4983
+ await emitTotalsCalculated(eventBus, {
4984
+ documentKind: "order",
4985
+ documentId: order.id,
4986
+ organizationId: order.organizationId,
4987
+ tenantId: order.tenantId,
4988
+ customerId: order.customerEntityId ?? null,
4989
+ totals: calculation.totals,
4990
+ lineCount: calculation.lines.length
4991
+ });
4992
+ }
4993
+ ],
4994
+ { transaction: true }
4995
+ );
4924
4996
  return { orderId: order.id, lineId };
4925
4997
  },
4926
4998
  captureAfter: async (_input, result, ctx) => {
@@ -5056,30 +5128,37 @@ const orderLineDeleteCommand = {
5056
5128
  context: calculationContext,
5057
5129
  existingTotals: resolveExistingPaymentTotals(order)
5058
5130
  });
5059
- await applyOrderLineResults({
5060
- em,
5061
- order,
5062
- calculation,
5063
- sourceLines: sourceInputs,
5064
- existingLines
5065
- });
5066
- applyOrderTotals(order, calculation.totals, calculation.lines.length);
5067
5131
  let eventBus = null;
5068
5132
  try {
5069
5133
  eventBus = ctx.container.resolve("eventBus");
5070
5134
  } catch {
5071
5135
  eventBus = null;
5072
5136
  }
5073
- await emitTotalsCalculated(eventBus, {
5074
- documentKind: "order",
5075
- documentId: order.id,
5076
- organizationId: order.organizationId,
5077
- tenantId: order.tenantId,
5078
- customerId: order.customerEntityId ?? null,
5079
- totals: calculation.totals,
5080
- lineCount: calculation.lines.length
5081
- });
5082
- await em.flush();
5137
+ await withAtomicFlush(
5138
+ em,
5139
+ [
5140
+ async () => {
5141
+ await applyOrderLineResults({
5142
+ em,
5143
+ order,
5144
+ calculation,
5145
+ sourceLines: sourceInputs,
5146
+ existingLines
5147
+ });
5148
+ applyOrderTotals(order, calculation.totals, calculation.lines.length);
5149
+ await emitTotalsCalculated(eventBus, {
5150
+ documentKind: "order",
5151
+ documentId: order.id,
5152
+ organizationId: order.organizationId,
5153
+ tenantId: order.tenantId,
5154
+ customerId: order.customerEntityId ?? null,
5155
+ totals: calculation.totals,
5156
+ lineCount: calculation.lines.length
5157
+ });
5158
+ }
5159
+ ],
5160
+ { transaction: true }
5161
+ );
5083
5162
  return { orderId: order.id, lineId: parsed.id };
5084
5163
  },
5085
5164
  captureAfter: async (_input, result, ctx) => {
@@ -5297,30 +5376,37 @@ const quoteLineUpsertCommand = {
5297
5376
  adjustments: adjustmentDrafts,
5298
5377
  context: calculationContext
5299
5378
  });
5300
- await applyQuoteLineResults({
5301
- em,
5302
- quote,
5303
- calculation,
5304
- sourceLines: sourceInputs,
5305
- existingLines
5306
- });
5307
- applyQuoteTotals(quote, calculation.totals, calculation.lines.length);
5308
5379
  let eventBus = null;
5309
5380
  try {
5310
5381
  eventBus = ctx.container.resolve("eventBus");
5311
5382
  } catch {
5312
5383
  eventBus = null;
5313
5384
  }
5314
- await emitTotalsCalculated(eventBus, {
5315
- documentKind: "quote",
5316
- documentId: quote.id,
5317
- organizationId: quote.organizationId,
5318
- tenantId: quote.tenantId,
5319
- customerId: quote.customerEntityId ?? null,
5320
- totals: calculation.totals,
5321
- lineCount: calculation.lines.length
5322
- });
5323
- await em.flush();
5385
+ await withAtomicFlush(
5386
+ em,
5387
+ [
5388
+ async () => {
5389
+ await applyQuoteLineResults({
5390
+ em,
5391
+ quote,
5392
+ calculation,
5393
+ sourceLines: sourceInputs,
5394
+ existingLines
5395
+ });
5396
+ applyQuoteTotals(quote, calculation.totals, calculation.lines.length);
5397
+ await emitTotalsCalculated(eventBus, {
5398
+ documentKind: "quote",
5399
+ documentId: quote.id,
5400
+ organizationId: quote.organizationId,
5401
+ tenantId: quote.tenantId,
5402
+ customerId: quote.customerEntityId ?? null,
5403
+ totals: calculation.totals,
5404
+ lineCount: calculation.lines.length
5405
+ });
5406
+ }
5407
+ ],
5408
+ { transaction: true }
5409
+ );
5324
5410
  return { quoteId: quote.id, lineId };
5325
5411
  },
5326
5412
  captureAfter: async (_input, result, ctx) => {
@@ -5432,30 +5518,37 @@ const quoteLineDeleteCommand = {
5432
5518
  adjustments: adjustmentDrafts,
5433
5519
  context: calculationContext
5434
5520
  });
5435
- await applyQuoteLineResults({
5436
- em,
5437
- quote,
5438
- calculation,
5439
- sourceLines: sourceInputs,
5440
- existingLines
5441
- });
5442
- applyQuoteTotals(quote, calculation.totals, calculation.lines.length);
5443
5521
  let eventBus = null;
5444
5522
  try {
5445
5523
  eventBus = ctx.container.resolve("eventBus");
5446
5524
  } catch {
5447
5525
  eventBus = null;
5448
5526
  }
5449
- await emitTotalsCalculated(eventBus, {
5450
- documentKind: "quote",
5451
- documentId: quote.id,
5452
- organizationId: quote.organizationId,
5453
- tenantId: quote.tenantId,
5454
- customerId: quote.customerEntityId ?? null,
5455
- totals: calculation.totals,
5456
- lineCount: calculation.lines.length
5457
- });
5458
- await em.flush();
5527
+ await withAtomicFlush(
5528
+ em,
5529
+ [
5530
+ async () => {
5531
+ await applyQuoteLineResults({
5532
+ em,
5533
+ quote,
5534
+ calculation,
5535
+ sourceLines: sourceInputs,
5536
+ existingLines
5537
+ });
5538
+ applyQuoteTotals(quote, calculation.totals, calculation.lines.length);
5539
+ await emitTotalsCalculated(eventBus, {
5540
+ documentKind: "quote",
5541
+ documentId: quote.id,
5542
+ organizationId: quote.organizationId,
5543
+ tenantId: quote.tenantId,
5544
+ customerId: quote.customerEntityId ?? null,
5545
+ totals: calculation.totals,
5546
+ lineCount: calculation.lines.length
5547
+ });
5548
+ }
5549
+ ],
5550
+ { transaction: true }
5551
+ );
5459
5552
  return { quoteId: quote.id, lineId: parsed.id };
5460
5553
  },
5461
5554
  captureAfter: async (_input, result, ctx) => {
@@ -5682,25 +5775,32 @@ const orderAdjustmentUpsertCommand = {
5682
5775
  customFields: adj.customFields ?? void 0,
5683
5776
  position: adj.position ?? index
5684
5777
  }));
5685
- await replaceOrderAdjustments(em, order, calculation, adjustmentInputs);
5686
- applyOrderTotals(order, calculation.totals, calculation.lines.length);
5687
- order.updatedAt = /* @__PURE__ */ new Date();
5688
5778
  let eventBus = null;
5689
5779
  try {
5690
5780
  eventBus = ctx.container.resolve("eventBus");
5691
5781
  } catch {
5692
5782
  eventBus = null;
5693
5783
  }
5694
- await emitTotalsCalculated(eventBus, {
5695
- documentKind: "order",
5696
- documentId: order.id,
5697
- organizationId: order.organizationId,
5698
- tenantId: order.tenantId,
5699
- customerId: order.customerEntityId ?? null,
5700
- totals: calculation.totals,
5701
- lineCount: calculation.lines.length
5702
- });
5703
- await em.flush();
5784
+ await withAtomicFlush(
5785
+ em,
5786
+ [
5787
+ async () => {
5788
+ await replaceOrderAdjustments(em, order, calculation, adjustmentInputs);
5789
+ applyOrderTotals(order, calculation.totals, calculation.lines.length);
5790
+ order.updatedAt = /* @__PURE__ */ new Date();
5791
+ await emitTotalsCalculated(eventBus, {
5792
+ documentKind: "order",
5793
+ documentId: order.id,
5794
+ organizationId: order.organizationId,
5795
+ tenantId: order.tenantId,
5796
+ customerId: order.customerEntityId ?? null,
5797
+ totals: calculation.totals,
5798
+ lineCount: calculation.lines.length
5799
+ });
5800
+ }
5801
+ ],
5802
+ { transaction: true }
5803
+ );
5704
5804
  return { orderId: order.id, adjustmentId };
5705
5805
  },
5706
5806
  captureAfter: async (_input, result, ctx) => {
@@ -5831,25 +5931,32 @@ const orderAdjustmentDeleteCommand = {
5831
5931
  metadata: adj.metadata ?? void 0,
5832
5932
  position: adj.position ?? index
5833
5933
  }));
5834
- await replaceOrderAdjustments(em, order, calculation, adjustmentInputs);
5835
- applyOrderTotals(order, calculation.totals, calculation.lines.length);
5836
- order.updatedAt = /* @__PURE__ */ new Date();
5837
5934
  let eventBus = null;
5838
5935
  try {
5839
5936
  eventBus = ctx.container.resolve("eventBus");
5840
5937
  } catch {
5841
5938
  eventBus = null;
5842
5939
  }
5843
- await emitTotalsCalculated(eventBus, {
5844
- documentKind: "order",
5845
- documentId: order.id,
5846
- organizationId: order.organizationId,
5847
- tenantId: order.tenantId,
5848
- customerId: order.customerEntityId ?? null,
5849
- totals: calculation.totals,
5850
- lineCount: calculation.lines.length
5851
- });
5852
- await em.flush();
5940
+ await withAtomicFlush(
5941
+ em,
5942
+ [
5943
+ async () => {
5944
+ await replaceOrderAdjustments(em, order, calculation, adjustmentInputs);
5945
+ applyOrderTotals(order, calculation.totals, calculation.lines.length);
5946
+ order.updatedAt = /* @__PURE__ */ new Date();
5947
+ await emitTotalsCalculated(eventBus, {
5948
+ documentKind: "order",
5949
+ documentId: order.id,
5950
+ organizationId: order.organizationId,
5951
+ tenantId: order.tenantId,
5952
+ customerId: order.customerEntityId ?? null,
5953
+ totals: calculation.totals,
5954
+ lineCount: calculation.lines.length
5955
+ });
5956
+ }
5957
+ ],
5958
+ { transaction: true }
5959
+ );
5853
5960
  return { orderId: order.id, adjustmentId: parsed.id };
5854
5961
  },
5855
5962
  captureAfter: async (_input, result, ctx) => {
@@ -6074,25 +6181,32 @@ const quoteAdjustmentUpsertCommand = {
6074
6181
  customFields: adj.customFields ?? void 0,
6075
6182
  position: adj.position ?? index
6076
6183
  }));
6077
- await replaceQuoteAdjustments(em, quote, calculation, adjustmentInputs);
6078
- applyQuoteTotals(quote, calculation.totals, calculation.lines.length);
6079
- quote.updatedAt = /* @__PURE__ */ new Date();
6080
6184
  let eventBus = null;
6081
6185
  try {
6082
6186
  eventBus = ctx.container.resolve("eventBus");
6083
6187
  } catch {
6084
6188
  eventBus = null;
6085
6189
  }
6086
- await emitTotalsCalculated(eventBus, {
6087
- documentKind: "quote",
6088
- documentId: quote.id,
6089
- organizationId: quote.organizationId,
6090
- tenantId: quote.tenantId,
6091
- customerId: quote.customerEntityId ?? null,
6092
- totals: calculation.totals,
6093
- lineCount: calculation.lines.length
6094
- });
6095
- await em.flush();
6190
+ await withAtomicFlush(
6191
+ em,
6192
+ [
6193
+ async () => {
6194
+ await replaceQuoteAdjustments(em, quote, calculation, adjustmentInputs);
6195
+ applyQuoteTotals(quote, calculation.totals, calculation.lines.length);
6196
+ quote.updatedAt = /* @__PURE__ */ new Date();
6197
+ await emitTotalsCalculated(eventBus, {
6198
+ documentKind: "quote",
6199
+ documentId: quote.id,
6200
+ organizationId: quote.organizationId,
6201
+ tenantId: quote.tenantId,
6202
+ customerId: quote.customerEntityId ?? null,
6203
+ totals: calculation.totals,
6204
+ lineCount: calculation.lines.length
6205
+ });
6206
+ }
6207
+ ],
6208
+ { transaction: true }
6209
+ );
6096
6210
  return { quoteId: quote.id, adjustmentId };
6097
6211
  },
6098
6212
  captureAfter: async (_input, result, ctx) => {
@@ -6222,25 +6336,32 @@ const quoteAdjustmentDeleteCommand = {
6222
6336
  metadata: adj.metadata ?? void 0,
6223
6337
  position: adj.position ?? index
6224
6338
  }));
6225
- await replaceQuoteAdjustments(em, quote, calculation, adjustmentInputs);
6226
- applyQuoteTotals(quote, calculation.totals, calculation.lines.length);
6227
- quote.updatedAt = /* @__PURE__ */ new Date();
6228
6339
  let eventBus = null;
6229
6340
  try {
6230
6341
  eventBus = ctx.container.resolve("eventBus");
6231
6342
  } catch {
6232
6343
  eventBus = null;
6233
6344
  }
6234
- await emitTotalsCalculated(eventBus, {
6235
- documentKind: "quote",
6236
- documentId: quote.id,
6237
- organizationId: quote.organizationId,
6238
- tenantId: quote.tenantId,
6239
- customerId: quote.customerEntityId ?? null,
6240
- totals: calculation.totals,
6241
- lineCount: calculation.lines.length
6242
- });
6243
- await em.flush();
6345
+ await withAtomicFlush(
6346
+ em,
6347
+ [
6348
+ async () => {
6349
+ await replaceQuoteAdjustments(em, quote, calculation, adjustmentInputs);
6350
+ applyQuoteTotals(quote, calculation.totals, calculation.lines.length);
6351
+ quote.updatedAt = /* @__PURE__ */ new Date();
6352
+ await emitTotalsCalculated(eventBus, {
6353
+ documentKind: "quote",
6354
+ documentId: quote.id,
6355
+ organizationId: quote.organizationId,
6356
+ tenantId: quote.tenantId,
6357
+ customerId: quote.customerEntityId ?? null,
6358
+ totals: calculation.totals,
6359
+ lineCount: calculation.lines.length
6360
+ });
6361
+ }
6362
+ ],
6363
+ { transaction: true }
6364
+ );
6244
6365
  return { quoteId: quote.id, adjustmentId: parsed.id };
6245
6366
  },
6246
6367
  captureAfter: async (_input, result, ctx) => {
@@ -6348,45 +6469,60 @@ const createInvoiceCommand = {
6348
6469
  createdAt: /* @__PURE__ */ new Date(),
6349
6470
  updatedAt: /* @__PURE__ */ new Date()
6350
6471
  });
6351
- em.persist(invoice);
6352
- if (parsed.lines?.length) {
6353
- for (let i = 0; i < parsed.lines.length; i++) {
6354
- const line = parsed.lines[i];
6355
- em.persist(
6356
- em.create(SalesInvoiceLine, {
6357
- id: randomUUID(),
6358
- invoice,
6359
- orderLineId: line.orderLineId ?? null,
6360
- organizationId: parsed.organizationId,
6361
- tenantId: parsed.tenantId,
6362
- lineNumber: line.lineNumber ?? i + 1,
6363
- kind: line.kind ?? "product",
6364
- name: line.name ?? null,
6365
- sku: line.sku ?? null,
6366
- description: line.description ?? null,
6367
- quantity: toNumericString(line.quantity ?? 0),
6368
- quantityUnit: line.quantityUnit ?? null,
6369
- normalizedQuantity: toNumericString(line.normalizedQuantity ?? 0),
6370
- normalizedUnit: line.normalizedUnit ?? null,
6371
- uomSnapshot: line.uomSnapshot ?? null,
6372
- currencyCode: line.currencyCode ?? parsed.currencyCode,
6373
- unitPriceNet: toNumericString(line.unitPriceNet ?? 0),
6374
- unitPriceGross: toNumericString(line.unitPriceGross ?? 0),
6375
- discountAmount: toNumericString(line.discountAmount ?? 0),
6376
- discountPercent: toNumericString(line.discountPercent ?? 0),
6377
- taxRate: toNumericString(line.taxRate ?? 0),
6378
- taxAmount: toNumericString(line.taxAmount ?? 0),
6379
- totalNetAmount: toNumericString(line.totalNetAmount ?? 0),
6380
- totalGrossAmount: toNumericString(line.totalGrossAmount ?? 0),
6381
- metadata: line.metadata ?? null
6382
- })
6383
- );
6384
- }
6385
- }
6386
- if (parsed.customFieldSetId) {
6387
- await setRecordCustomFields(em, invoiceId, parsed.customFieldSetId, parsed);
6388
- }
6389
- await em.flush();
6472
+ await withAtomicFlush(
6473
+ em,
6474
+ [
6475
+ async () => {
6476
+ em.persist(invoice);
6477
+ if (parsed.lines?.length) {
6478
+ for (let i = 0; i < parsed.lines.length; i++) {
6479
+ const line = parsed.lines[i];
6480
+ em.persist(
6481
+ em.create(SalesInvoiceLine, {
6482
+ id: randomUUID(),
6483
+ invoice,
6484
+ orderLineId: line.orderLineId ?? null,
6485
+ organizationId: parsed.organizationId,
6486
+ tenantId: parsed.tenantId,
6487
+ lineNumber: line.lineNumber ?? i + 1,
6488
+ kind: line.kind ?? "product",
6489
+ name: line.name ?? null,
6490
+ sku: line.sku ?? null,
6491
+ description: line.description ?? null,
6492
+ quantity: toNumericString(line.quantity ?? 0),
6493
+ quantityUnit: line.quantityUnit ?? null,
6494
+ normalizedQuantity: toNumericString(line.normalizedQuantity ?? 0),
6495
+ normalizedUnit: line.normalizedUnit ?? null,
6496
+ uomSnapshot: line.uomSnapshot ?? null,
6497
+ currencyCode: line.currencyCode ?? parsed.currencyCode,
6498
+ unitPriceNet: toNumericString(line.unitPriceNet ?? 0),
6499
+ unitPriceGross: toNumericString(line.unitPriceGross ?? 0),
6500
+ discountAmount: toNumericString(line.discountAmount ?? 0),
6501
+ discountPercent: toNumericString(line.discountPercent ?? 0),
6502
+ taxRate: toNumericString(line.taxRate ?? 0),
6503
+ taxAmount: toNumericString(line.taxAmount ?? 0),
6504
+ totalNetAmount: toNumericString(line.totalNetAmount ?? 0),
6505
+ totalGrossAmount: toNumericString(line.totalGrossAmount ?? 0),
6506
+ metadata: line.metadata ?? null
6507
+ })
6508
+ );
6509
+ }
6510
+ }
6511
+ if (parsed.customFieldSetId) {
6512
+ await setRecordCustomFields(em, {
6513
+ entityId: E.sales.sales_invoice,
6514
+ recordId: invoiceId,
6515
+ organizationId: parsed.organizationId,
6516
+ tenantId: parsed.tenantId,
6517
+ values: normalizeCustomFieldValues(
6518
+ parsed.customFields ?? {}
6519
+ )
6520
+ });
6521
+ }
6522
+ }
6523
+ ],
6524
+ { transaction: true }
6525
+ );
6390
6526
  const dataEngine = ctx.container.resolve("dataEngine");
6391
6527
  await emitCrudSideEffects({
6392
6528
  dataEngine,
@@ -6783,42 +6919,57 @@ const createCreditMemoCommand = {
6783
6919
  createdAt: /* @__PURE__ */ new Date(),
6784
6920
  updatedAt: /* @__PURE__ */ new Date()
6785
6921
  });
6786
- em.persist(creditMemo);
6787
- if (parsed.lines?.length) {
6788
- for (let i = 0; i < parsed.lines.length; i++) {
6789
- const line = parsed.lines[i];
6790
- em.persist(
6791
- em.create(SalesCreditMemoLine, {
6792
- id: randomUUID(),
6793
- creditMemo,
6794
- orderLineId: line.orderLineId ?? null,
6795
- organizationId: parsed.organizationId,
6796
- tenantId: parsed.tenantId,
6797
- lineNumber: line.lineNumber ?? i + 1,
6798
- name: line.name ?? null,
6799
- sku: line.sku ?? null,
6800
- description: line.description ?? null,
6801
- quantity: toNumericString(line.quantity ?? 0),
6802
- quantityUnit: line.quantityUnit ?? null,
6803
- normalizedQuantity: toNumericString(line.normalizedQuantity ?? 0),
6804
- normalizedUnit: line.normalizedUnit ?? null,
6805
- uomSnapshot: line.uomSnapshot ?? null,
6806
- currencyCode: line.currencyCode ?? parsed.currencyCode,
6807
- unitPriceNet: toNumericString(line.unitPriceNet ?? 0),
6808
- unitPriceGross: toNumericString(line.unitPriceGross ?? 0),
6809
- taxRate: toNumericString(line.taxRate ?? 0),
6810
- taxAmount: toNumericString(line.taxAmount ?? 0),
6811
- totalNetAmount: toNumericString(line.totalNetAmount ?? 0),
6812
- totalGrossAmount: toNumericString(line.totalGrossAmount ?? 0),
6813
- metadata: line.metadata ?? null
6814
- })
6815
- );
6816
- }
6817
- }
6818
- if (parsed.customFieldSetId) {
6819
- await setRecordCustomFields(em, creditMemoId, parsed.customFieldSetId, parsed);
6820
- }
6821
- await em.flush();
6922
+ await withAtomicFlush(
6923
+ em,
6924
+ [
6925
+ async () => {
6926
+ em.persist(creditMemo);
6927
+ if (parsed.lines?.length) {
6928
+ for (let i = 0; i < parsed.lines.length; i++) {
6929
+ const line = parsed.lines[i];
6930
+ em.persist(
6931
+ em.create(SalesCreditMemoLine, {
6932
+ id: randomUUID(),
6933
+ creditMemo,
6934
+ orderLineId: line.orderLineId ?? null,
6935
+ organizationId: parsed.organizationId,
6936
+ tenantId: parsed.tenantId,
6937
+ lineNumber: line.lineNumber ?? i + 1,
6938
+ name: line.name ?? null,
6939
+ sku: line.sku ?? null,
6940
+ description: line.description ?? null,
6941
+ quantity: toNumericString(line.quantity ?? 0),
6942
+ quantityUnit: line.quantityUnit ?? null,
6943
+ normalizedQuantity: toNumericString(line.normalizedQuantity ?? 0),
6944
+ normalizedUnit: line.normalizedUnit ?? null,
6945
+ uomSnapshot: line.uomSnapshot ?? null,
6946
+ currencyCode: line.currencyCode ?? parsed.currencyCode,
6947
+ unitPriceNet: toNumericString(line.unitPriceNet ?? 0),
6948
+ unitPriceGross: toNumericString(line.unitPriceGross ?? 0),
6949
+ taxRate: toNumericString(line.taxRate ?? 0),
6950
+ taxAmount: toNumericString(line.taxAmount ?? 0),
6951
+ totalNetAmount: toNumericString(line.totalNetAmount ?? 0),
6952
+ totalGrossAmount: toNumericString(line.totalGrossAmount ?? 0),
6953
+ metadata: line.metadata ?? null
6954
+ })
6955
+ );
6956
+ }
6957
+ }
6958
+ if (parsed.customFieldSetId) {
6959
+ await setRecordCustomFields(em, {
6960
+ entityId: E.sales.sales_credit_memo,
6961
+ recordId: creditMemoId,
6962
+ organizationId: parsed.organizationId,
6963
+ tenantId: parsed.tenantId,
6964
+ values: normalizeCustomFieldValues(
6965
+ parsed.customFields ?? {}
6966
+ )
6967
+ });
6968
+ }
6969
+ }
6970
+ ],
6971
+ { transaction: true }
6972
+ );
6822
6973
  const dataEngine = ctx.container.resolve("dataEngine");
6823
6974
  await emitCrudSideEffects({
6824
6975
  dataEngine,