@open-mercato/core 0.6.4-develop.4217.1.c9aa050183 → 0.6.4-develop.4239.1.4a264a5828

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 (408) 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/business_rules/backend/logs/[id]/page.js +24 -5
  31. package/dist/modules/business_rules/backend/logs/[id]/page.js.map +2 -2
  32. package/dist/modules/catalog/api/offers/route.js +15 -5
  33. package/dist/modules/catalog/api/offers/route.js.map +2 -2
  34. package/dist/modules/catalog/commands/categories.js +61 -12
  35. package/dist/modules/catalog/commands/categories.js.map +2 -2
  36. package/dist/modules/catalog/commands/products.js +79 -54
  37. package/dist/modules/catalog/commands/products.js.map +2 -2
  38. package/dist/modules/catalog/commands/variants.js +29 -16
  39. package/dist/modules/catalog/commands/variants.js.map +2 -2
  40. package/dist/modules/currencies/backend/currencies/[id]/page.js +19 -2
  41. package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
  42. package/dist/modules/currencies/commands/currencies.js +15 -8
  43. package/dist/modules/currencies/commands/currencies.js.map +2 -2
  44. package/dist/modules/customer_accounts/api/admin/users.js +27 -26
  45. package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
  46. package/dist/modules/customer_accounts/api/password/reset-confirm.js +5 -5
  47. package/dist/modules/customer_accounts/api/password/reset-confirm.js.map +2 -2
  48. package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js +11 -10
  49. package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js.map +2 -2
  50. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +27 -7
  51. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
  52. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +27 -7
  53. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
  54. package/dist/modules/customers/backend/customers/people/[id]/page.js +29 -8
  55. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  56. package/dist/modules/customers/commands/addresses.js +35 -21
  57. package/dist/modules/customers/commands/addresses.js.map +2 -2
  58. package/dist/modules/customers/commands/companies.js +163 -162
  59. package/dist/modules/customers/commands/companies.js.map +2 -2
  60. package/dist/modules/customers/commands/deals.js +3 -4
  61. package/dist/modules/customers/commands/deals.js.map +2 -2
  62. package/dist/modules/customers/commands/interactions.js +19 -22
  63. package/dist/modules/customers/commands/interactions.js.map +2 -2
  64. package/dist/modules/customers/commands/people.js +18 -15
  65. package/dist/modules/customers/commands/people.js.map +2 -2
  66. package/dist/modules/customers/commands/personCompanyLinks.js +105 -94
  67. package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
  68. package/dist/modules/customers/commands/pipeline-stages.js +30 -23
  69. package/dist/modules/customers/commands/pipeline-stages.js.map +2 -2
  70. package/dist/modules/customers/commands/pipelines.js +27 -20
  71. package/dist/modules/customers/commands/pipelines.js.map +2 -2
  72. package/dist/modules/customers/commands/tags.js +13 -5
  73. package/dist/modules/customers/commands/tags.js.map +2 -2
  74. package/dist/modules/dashboards/api/users/widgets/route.js +0 -1
  75. package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
  76. package/dist/modules/dashboards/api/widgets/data/route.js +29 -1
  77. package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
  78. package/dist/modules/data_sync/lib/sync-engine.js +4 -4
  79. package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
  80. package/dist/modules/data_sync/lib/sync-run-service.js +51 -27
  81. package/dist/modules/data_sync/lib/sync-run-service.js.map +2 -2
  82. package/dist/modules/directory/commands/organizations.js +192 -158
  83. package/dist/modules/directory/commands/organizations.js.map +3 -3
  84. package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js +22 -16
  85. package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js.map +2 -2
  86. package/dist/modules/messages/commands/messages.js +77 -75
  87. package/dist/modules/messages/commands/messages.js.map +2 -2
  88. package/dist/modules/messages/commands/shared.js +132 -132
  89. package/dist/modules/messages/commands/shared.js.map +2 -2
  90. package/dist/modules/perspectives/api/[tableId]/route.js +37 -26
  91. package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
  92. package/dist/modules/progress/acl.js +8 -4
  93. package/dist/modules/progress/acl.js.map +2 -2
  94. package/dist/modules/resources/commands/resources.js +125 -117
  95. package/dist/modules/resources/commands/resources.js.map +2 -2
  96. package/dist/modules/resources/commands/tags.js +7 -3
  97. package/dist/modules/resources/commands/tags.js.map +2 -2
  98. package/dist/modules/sales/api/quotes/send/route.js +12 -11
  99. package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
  100. package/dist/modules/sales/commands/documents.js +629 -478
  101. package/dist/modules/sales/commands/documents.js.map +2 -2
  102. package/dist/modules/sales/commands/payments.js +146 -146
  103. package/dist/modules/sales/commands/payments.js.map +2 -2
  104. package/dist/modules/sales/commands/returns.js +68 -60
  105. package/dist/modules/sales/commands/returns.js.map +2 -2
  106. package/dist/modules/staff/acl.js +10 -1
  107. package/dist/modules/staff/acl.js.map +2 -2
  108. package/dist/modules/staff/analytics.js +33 -0
  109. package/dist/modules/staff/analytics.js.map +7 -0
  110. package/dist/modules/staff/api/guards.js +31 -0
  111. package/dist/modules/staff/api/guards.js.map +7 -0
  112. package/dist/modules/staff/api/interceptors.js +96 -0
  113. package/dist/modules/staff/api/interceptors.js.map +7 -0
  114. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +170 -0
  115. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +7 -0
  116. package/dist/modules/staff/api/timesheets/my-projects/route.js +103 -0
  117. package/dist/modules/staff/api/timesheets/my-projects/route.js.map +7 -0
  118. package/dist/modules/staff/api/timesheets/projects/kpis/route.js +147 -0
  119. package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +7 -0
  120. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js +171 -0
  121. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js.map +7 -0
  122. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +180 -0
  123. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +7 -0
  124. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +155 -0
  125. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +7 -0
  126. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +173 -0
  127. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +7 -0
  128. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +260 -0
  129. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +7 -0
  130. package/dist/modules/staff/api/timesheets/time-entries/route.js +188 -0
  131. package/dist/modules/staff/api/timesheets/time-entries/route.js.map +7 -0
  132. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js +159 -0
  133. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js.map +7 -0
  134. package/dist/modules/staff/api/timesheets/time-projects/route.js +230 -0
  135. package/dist/modules/staff/api/timesheets/time-projects/route.js.map +7 -0
  136. package/dist/modules/staff/backend/staff/timesheets/page.js +710 -0
  137. package/dist/modules/staff/backend/staff/timesheets/page.js.map +7 -0
  138. package/dist/modules/staff/backend/staff/timesheets/page.meta.js +22 -0
  139. package/dist/modules/staff/backend/staff/timesheets/page.meta.js.map +7 -0
  140. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js +125 -0
  141. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js.map +7 -0
  142. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js +16 -0
  143. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js.map +7 -0
  144. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js +418 -0
  145. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +7 -0
  146. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js +16 -0
  147. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js.map +7 -0
  148. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js +79 -0
  149. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js.map +7 -0
  150. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js +16 -0
  151. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js.map +7 -0
  152. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +602 -0
  153. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +7 -0
  154. package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js +25 -0
  155. package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js.map +7 -0
  156. package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js +123 -0
  157. package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js.map +7 -0
  158. package/dist/modules/staff/cli.js +38 -1
  159. package/dist/modules/staff/cli.js.map +2 -2
  160. package/dist/modules/staff/commands/index.js +2 -0
  161. package/dist/modules/staff/commands/index.js.map +2 -2
  162. package/dist/modules/staff/commands/leave-requests.js +30 -28
  163. package/dist/modules/staff/commands/leave-requests.js.map +3 -3
  164. package/dist/modules/staff/commands/team-members.js +21 -20
  165. package/dist/modules/staff/commands/team-members.js.map +2 -2
  166. package/dist/modules/staff/commands/timesheets-entries.js +409 -0
  167. package/dist/modules/staff/commands/timesheets-entries.js.map +7 -0
  168. package/dist/modules/staff/commands/timesheets-projects.js +618 -0
  169. package/dist/modules/staff/commands/timesheets-projects.js.map +7 -0
  170. package/dist/modules/staff/data/enrichers.js +104 -0
  171. package/dist/modules/staff/data/enrichers.js.map +7 -0
  172. package/dist/modules/staff/data/entities.js +226 -1
  173. package/dist/modules/staff/data/entities.js.map +2 -2
  174. package/dist/modules/staff/data/validators.js +113 -1
  175. package/dist/modules/staff/data/validators.js.map +2 -2
  176. package/dist/modules/staff/events.js +13 -1
  177. package/dist/modules/staff/events.js.map +2 -2
  178. package/dist/modules/staff/lib/crud.js +7 -1
  179. package/dist/modules/staff/lib/crud.js.map +2 -2
  180. package/dist/modules/staff/lib/staffMemberResolver.js +15 -0
  181. package/dist/modules/staff/lib/staffMemberResolver.js.map +7 -0
  182. package/dist/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.js +60 -0
  183. package/dist/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.js.map +7 -0
  184. package/dist/modules/staff/lib/timesheets-projects/computeProjectsKpis.js +260 -0
  185. package/dist/modules/staff/lib/timesheets-projects/computeProjectsKpis.js.map +7 -0
  186. package/dist/modules/staff/lib/timesheets-projects/dateBuckets.js +41 -0
  187. package/dist/modules/staff/lib/timesheets-projects/dateBuckets.js.map +7 -0
  188. package/dist/modules/staff/lib/timesheets-projects/initials.js +10 -0
  189. package/dist/modules/staff/lib/timesheets-projects/initials.js.map +7 -0
  190. package/dist/modules/staff/lib/timesheets-projects/kpiMath.js +12 -0
  191. package/dist/modules/staff/lib/timesheets-projects/kpiMath.js.map +7 -0
  192. package/dist/modules/staff/lib/timesheets-projects/listProjectMembersPreview.js +55 -0
  193. package/dist/modules/staff/lib/timesheets-projects/listProjectMembersPreview.js.map +7 -0
  194. package/dist/modules/staff/lib/timesheets-projects-ui/HoursSparkline.js +66 -0
  195. package/dist/modules/staff/lib/timesheets-projects-ui/HoursSparkline.js.map +7 -0
  196. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js +81 -0
  197. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js.map +7 -0
  198. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.js +58 -0
  199. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.js.map +7 -0
  200. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.js +152 -0
  201. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.js.map +7 -0
  202. package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js +37 -0
  203. package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js.map +7 -0
  204. package/dist/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.js +57 -0
  205. package/dist/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.js.map +7 -0
  206. package/dist/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.js +50 -0
  207. package/dist/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.js.map +7 -0
  208. package/dist/modules/staff/lib/timesheets-ui/AddRowDropdown.js +163 -0
  209. package/dist/modules/staff/lib/timesheets-ui/AddRowDropdown.js.map +7 -0
  210. package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js +209 -0
  211. package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js.map +7 -0
  212. package/dist/modules/staff/lib/timesheets-ui/ColorPicker.js +52 -0
  213. package/dist/modules/staff/lib/timesheets-ui/ColorPicker.js.map +7 -0
  214. package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js +77 -0
  215. package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js.map +7 -0
  216. package/dist/modules/staff/lib/timesheets-ui/ListView.js +173 -0
  217. package/dist/modules/staff/lib/timesheets-ui/ListView.js.map +7 -0
  218. package/dist/modules/staff/lib/timesheets-ui/ProjectColorDot.js +32 -0
  219. package/dist/modules/staff/lib/timesheets-ui/ProjectColorDot.js.map +7 -0
  220. package/dist/modules/staff/lib/timesheets-ui/TimerBar.js +270 -0
  221. package/dist/modules/staff/lib/timesheets-ui/TimerBar.js.map +7 -0
  222. package/dist/modules/staff/lib/timesheets-ui/ViewSwitcher.js +57 -0
  223. package/dist/modules/staff/lib/timesheets-ui/ViewSwitcher.js.map +7 -0
  224. package/dist/modules/staff/lib/timesheets-ui/colors.js +43 -0
  225. package/dist/modules/staff/lib/timesheets-ui/colors.js.map +7 -0
  226. package/dist/modules/staff/migrations/Migration20260326135612.js +24 -0
  227. package/dist/modules/staff/migrations/Migration20260326135612.js.map +7 -0
  228. package/dist/modules/staff/migrations/Migration20260413102715.js +23 -0
  229. package/dist/modules/staff/migrations/Migration20260413102715.js.map +7 -0
  230. package/dist/modules/staff/migrations/Migration20260413111602.js +13 -0
  231. package/dist/modules/staff/migrations/Migration20260413111602.js.map +7 -0
  232. package/dist/modules/staff/migrations/Migration20260511112759.js +19 -0
  233. package/dist/modules/staff/migrations/Migration20260511112759.js.map +7 -0
  234. package/dist/modules/staff/search.js +35 -0
  235. package/dist/modules/staff/search.js.map +2 -2
  236. package/dist/modules/staff/setup.js +15 -1
  237. package/dist/modules/staff/setup.js.map +2 -2
  238. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.js +16 -0
  239. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.js.map +7 -0
  240. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js +126 -0
  241. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js.map +7 -0
  242. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.js +26 -0
  243. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.js.map +7 -0
  244. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/config.js +15 -0
  245. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/config.js.map +7 -0
  246. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js +238 -0
  247. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js.map +7 -0
  248. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.js +26 -0
  249. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.js.map +7 -0
  250. package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js +145 -0
  251. package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js.map +7 -0
  252. package/dist/modules/staff/widgets/injection-table.js +12 -0
  253. package/dist/modules/staff/widgets/injection-table.js.map +7 -0
  254. package/dist/modules/sync_excel/api/import/route.js +19 -17
  255. package/dist/modules/sync_excel/api/import/route.js.map +2 -2
  256. package/dist/modules/translations/commands/translations.js +22 -19
  257. package/dist/modules/translations/commands/translations.js.map +2 -2
  258. package/dist/modules/workflows/backend/events/[id]/page.js +24 -6
  259. package/dist/modules/workflows/backend/events/[id]/page.js.map +2 -2
  260. package/dist/modules/workflows/backend/instances/[id]/page.js +27 -5
  261. package/dist/modules/workflows/backend/instances/[id]/page.js.map +2 -2
  262. package/dist/modules/workflows/backend/tasks/[id]/page.js +25 -6
  263. package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
  264. package/generated/entities/staff_time_entry/index.ts +17 -0
  265. package/generated/entities/staff_time_entry_segment/index.ts +10 -0
  266. package/generated/entities/staff_time_project/index.ts +16 -0
  267. package/generated/entities/staff_time_project_member/index.ts +13 -0
  268. package/generated/entities.ids.generated.ts +5 -1
  269. package/generated/entity-fields-registry.ts +64 -0
  270. package/package.json +7 -7
  271. package/src/helpers/integration/timesheetFixtures.ts +61 -0
  272. package/src/modules/attachments/api/library/[id]/route.ts +24 -17
  273. package/src/modules/attachments/api/route.ts +20 -14
  274. package/src/modules/auth/api/roles/acl/route.ts +11 -5
  275. package/src/modules/auth/api/sidebar/preferences/route.ts +33 -24
  276. package/src/modules/auth/api/users/acl/route.ts +17 -12
  277. package/src/modules/auth/commands/users.ts +96 -80
  278. package/src/modules/auth/services/sidebarPreferencesService.ts +40 -32
  279. package/src/modules/business_rules/backend/logs/[id]/page.tsx +32 -7
  280. package/src/modules/catalog/api/offers/route.ts +20 -5
  281. package/src/modules/catalog/commands/categories.ts +61 -12
  282. package/src/modules/catalog/commands/products.ts +93 -60
  283. package/src/modules/catalog/commands/variants.ts +29 -16
  284. package/src/modules/currencies/backend/currencies/[id]/page.tsx +21 -2
  285. package/src/modules/currencies/commands/currencies.ts +27 -14
  286. package/src/modules/currencies/i18n/de.json +1 -0
  287. package/src/modules/currencies/i18n/en.json +1 -0
  288. package/src/modules/currencies/i18n/es.json +1 -0
  289. package/src/modules/currencies/i18n/pl.json +1 -0
  290. package/src/modules/customer_accounts/api/admin/users.ts +31 -26
  291. package/src/modules/customer_accounts/api/password/reset-confirm.ts +5 -6
  292. package/src/modules/customer_accounts/api/portal/users/[id]/roles.ts +14 -13
  293. package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +34 -11
  294. package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +34 -11
  295. package/src/modules/customers/backend/customers/people/[id]/page.tsx +35 -11
  296. package/src/modules/customers/commands/addresses.ts +35 -23
  297. package/src/modules/customers/commands/companies.ts +166 -165
  298. package/src/modules/customers/commands/deals.ts +2 -4
  299. package/src/modules/customers/commands/interactions.ts +20 -26
  300. package/src/modules/customers/commands/people.ts +18 -15
  301. package/src/modules/customers/commands/personCompanyLinks.ts +109 -100
  302. package/src/modules/customers/commands/pipeline-stages.ts +31 -27
  303. package/src/modules/customers/commands/pipelines.ts +29 -23
  304. package/src/modules/customers/commands/tags.ts +13 -5
  305. package/src/modules/dashboards/api/users/widgets/route.ts +0 -1
  306. package/src/modules/dashboards/api/widgets/data/route.ts +36 -1
  307. package/src/modules/data_sync/lib/sync-engine.ts +4 -5
  308. package/src/modules/data_sync/lib/sync-run-service.ts +57 -28
  309. package/src/modules/directory/commands/organizations.ts +203 -166
  310. package/src/modules/inbox_ops/api/emails/[id]/reprocess/route.ts +26 -18
  311. package/src/modules/messages/commands/messages.ts +82 -80
  312. package/src/modules/messages/commands/shared.ts +138 -133
  313. package/src/modules/perspectives/api/[tableId]/route.ts +38 -27
  314. package/src/modules/progress/acl.ts +4 -0
  315. package/src/modules/resources/commands/resources.ts +127 -117
  316. package/src/modules/resources/commands/tags.ts +7 -3
  317. package/src/modules/sales/api/quotes/send/route.ts +17 -12
  318. package/src/modules/sales/commands/documents.ts +673 -481
  319. package/src/modules/sales/commands/payments.ts +158 -152
  320. package/src/modules/sales/commands/returns.ts +74 -63
  321. package/src/modules/staff/acl.ts +11 -0
  322. package/src/modules/staff/analytics.ts +30 -0
  323. package/src/modules/staff/api/guards.ts +59 -0
  324. package/src/modules/staff/api/interceptors.ts +122 -0
  325. package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +191 -0
  326. package/src/modules/staff/api/timesheets/my-projects/route.ts +115 -0
  327. package/src/modules/staff/api/timesheets/projects/kpis/route.ts +159 -0
  328. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.ts +187 -0
  329. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +191 -0
  330. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +168 -0
  331. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +191 -0
  332. package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +292 -0
  333. package/src/modules/staff/api/timesheets/time-entries/route.ts +193 -0
  334. package/src/modules/staff/api/timesheets/time-projects/[id]/employees/route.ts +167 -0
  335. package/src/modules/staff/api/timesheets/time-projects/route.ts +244 -0
  336. package/src/modules/staff/backend/staff/timesheets/page.meta.ts +20 -0
  337. package/src/modules/staff/backend/staff/timesheets/page.tsx +899 -0
  338. package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.ts +12 -0
  339. package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.tsx +141 -0
  340. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.ts +12 -0
  341. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +579 -0
  342. package/src/modules/staff/backend/staff/timesheets/projects/create/page.meta.ts +12 -0
  343. package/src/modules/staff/backend/staff/timesheets/projects/create/page.tsx +90 -0
  344. package/src/modules/staff/backend/staff/timesheets/projects/page.meta.ts +23 -0
  345. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +765 -0
  346. package/src/modules/staff/backend/staff/timesheets/projects/projectFormConfig.ts +138 -0
  347. package/src/modules/staff/cli.ts +40 -1
  348. package/src/modules/staff/commands/index.ts +2 -0
  349. package/src/modules/staff/commands/leave-requests.ts +37 -29
  350. package/src/modules/staff/commands/team-members.ts +25 -20
  351. package/src/modules/staff/commands/timesheets-entries.ts +504 -0
  352. package/src/modules/staff/commands/timesheets-projects.ts +699 -0
  353. package/src/modules/staff/data/enrichers.ts +134 -0
  354. package/src/modules/staff/data/entities.ts +198 -0
  355. package/src/modules/staff/data/validators.ts +129 -0
  356. package/src/modules/staff/events.ts +13 -0
  357. package/src/modules/staff/i18n/de.json +209 -1
  358. package/src/modules/staff/i18n/en.json +209 -1
  359. package/src/modules/staff/i18n/es.json +209 -1
  360. package/src/modules/staff/i18n/pl.json +209 -1
  361. package/src/modules/staff/lib/crud.ts +8 -0
  362. package/src/modules/staff/lib/staffMemberResolver.ts +22 -0
  363. package/src/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.ts +89 -0
  364. package/src/modules/staff/lib/timesheets-projects/computeProjectsKpis.ts +311 -0
  365. package/src/modules/staff/lib/timesheets-projects/dateBuckets.ts +37 -0
  366. package/src/modules/staff/lib/timesheets-projects/initials.ts +6 -0
  367. package/src/modules/staff/lib/timesheets-projects/kpiMath.ts +8 -0
  368. package/src/modules/staff/lib/timesheets-projects/listProjectMembersPreview.ts +83 -0
  369. package/src/modules/staff/lib/timesheets-projects-ui/HoursSparkline.tsx +75 -0
  370. package/src/modules/staff/lib/timesheets-projects-ui/ProjectCard.tsx +110 -0
  371. package/src/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.tsx +73 -0
  372. package/src/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.tsx +185 -0
  373. package/src/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.tsx +53 -0
  374. package/src/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.tsx +63 -0
  375. package/src/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.ts +63 -0
  376. package/src/modules/staff/lib/timesheets-ui/AddRowDropdown.tsx +188 -0
  377. package/src/modules/staff/lib/timesheets-ui/CalendarPicker.tsx +229 -0
  378. package/src/modules/staff/lib/timesheets-ui/ColorPicker.tsx +65 -0
  379. package/src/modules/staff/lib/timesheets-ui/CreateProjectDialog.tsx +99 -0
  380. package/src/modules/staff/lib/timesheets-ui/ListView.tsx +230 -0
  381. package/src/modules/staff/lib/timesheets-ui/ProjectColorDot.tsx +40 -0
  382. package/src/modules/staff/lib/timesheets-ui/TimerBar.tsx +327 -0
  383. package/src/modules/staff/lib/timesheets-ui/ViewSwitcher.tsx +60 -0
  384. package/src/modules/staff/lib/timesheets-ui/colors.ts +58 -0
  385. package/src/modules/staff/migrations/.snapshot-open-mercato.json +1148 -0
  386. package/src/modules/staff/migrations/Migration20260326135612.ts +26 -0
  387. package/src/modules/staff/migrations/Migration20260413102715.ts +25 -0
  388. package/src/modules/staff/migrations/Migration20260413111602.ts +13 -0
  389. package/src/modules/staff/migrations/Migration20260511112759.ts +21 -0
  390. package/src/modules/staff/search.ts +35 -0
  391. package/src/modules/staff/setup.ts +15 -0
  392. package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.ts +17 -0
  393. package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.tsx +158 -0
  394. package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.ts +25 -0
  395. package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/config.ts +15 -0
  396. package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.tsx +297 -0
  397. package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.ts +25 -0
  398. package/src/modules/staff/widgets/injection/timer-sidebar-indicator/widget.tsx +161 -0
  399. package/src/modules/staff/widgets/injection-table.ts +10 -0
  400. package/src/modules/sync_excel/api/import/route.ts +23 -18
  401. package/src/modules/translations/commands/translations.ts +49 -41
  402. package/src/modules/workflows/backend/events/[id]/page.tsx +32 -10
  403. package/src/modules/workflows/backend/instances/[id]/page.tsx +33 -9
  404. package/src/modules/workflows/backend/tasks/[id]/page.tsx +33 -10
  405. package/src/modules/workflows/i18n/de.json +1 -0
  406. package/src/modules/workflows/i18n/en.json +1 -0
  407. package/src/modules/workflows/i18n/es.json +1 -0
  408. package/src/modules/workflows/i18n/pl.json +1 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/business_rules/backend/logs/%5Bid%5D/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useParams, useRouter } from 'next/navigation'\nimport { useQuery } from '@tanstack/react-query'\nimport { apiFetch } from '@open-mercato/ui/backend/utils/api'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\n\ntype RuleExecutionLog = {\n id: string\n ruleId: string\n rule?: {\n id: string\n ruleId: string\n ruleName: string\n ruleType: string\n } | null\n entityType: string\n entityId: string | null\n eventType: string | null\n executedAt: string\n executionTimeMs: number\n executionResult: 'SUCCESS' | 'FAILURE' | 'ERROR'\n resultValue: any | null\n errorMessage: string | null\n inputContext: any | null\n outputContext: any | null\n executedBy: string | null\n tenantId: string | null\n organizationId: string | null\n}\n\nexport default function ExecutionLogDetailPage() {\n const router = useRouter()\n const params = useParams()\n\n // Handle catch-all route: params.slug = ['logs', 'id']\n let logId: string | undefined\n if (params?.slug && Array.isArray(params.slug)) {\n logId = params.slug[1] // Second element is the ID\n } else if (params?.id) {\n logId = Array.isArray(params.id) ? params.id[0] : params.id\n }\n\n const t = useT()\n\n const { data: log, isLoading, error } = useQuery({\n queryKey: ['business-rules', 'logs', logId],\n queryFn: async () => {\n const response = await apiFetch(`/api/business_rules/logs/${logId}`)\n if (!response.ok) {\n throw new Error(t('business_rules.logs.errors.fetchFailed'))\n }\n const result = await response.json()\n return result as RuleExecutionLog\n },\n enabled: !!logId,\n })\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-6 w-6\" />\n <span>{t('business_rules.logs.detail.loading')}</span>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n if (error || !log) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <p>{error ? t('business_rules.logs.errors.loadFailed') : t('business_rules.logs.errors.notFound')}</p>\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/logs\">{t('business_rules.logs.backToList')}</Link>\n </Button>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n const getResultBadgeClass = (result: string) => {\n switch (result) {\n case 'SUCCESS':\n return 'bg-green-100 text-green-800'\n case 'FAILURE':\n return 'bg-yellow-100 text-yellow-800'\n case 'ERROR':\n return 'bg-red-100 text-red-800'\n default:\n return 'bg-muted text-foreground'\n }\n }\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold text-foreground\">\n {t('business_rules.logs.detail.title')}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {t('business_rules.logs.detail.logId')}: {log.id}\n </p>\n </div>\n <Button onClick={() => router.push('/backend/logs')} variant=\"outline\">\n {t('business_rules.logs.backToList')}\n </Button>\n </div>\n\n {/* Execution Summary */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('business_rules.logs.detail.summary')}\n </h2>\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.executedAt')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {new Date(log.executedAt).toLocaleString()}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.result')}\n </dt>\n <dd className=\"mt-1\">\n <span\n className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getResultBadgeClass(\n log.executionResult\n )}`}\n >\n {t(`business_rules.logs.result.${log.executionResult.toLowerCase()}`)}\n </span>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.executionTime')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">{log.executionTimeMs}ms</dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.executedBy')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {log.executedBy || t('common.unknown')}\n </dd>\n </div>\n </dl>\n </div>\n\n {/* Rule Information */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('business_rules.logs.detail.ruleInfo')}\n </h2>\n {log.rule ? (\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.ruleName')}\n </dt>\n <dd className=\"mt-1\">\n <Link\n href={`/backend/rules/${log.rule.id}`}\n className=\"text-sm text-primary hover:underline\"\n >\n {log.rule.ruleName}\n </Link>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.ruleType')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">{log.rule.ruleType}</dd>\n </div>\n <div className=\"md:col-span-2\">\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.ruleId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">{log.rule.ruleId}</dd>\n </div>\n </dl>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('business_rules.logs.ruleDeleted')}</p>\n )}\n </div>\n\n {/* Entity Information */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('business_rules.logs.detail.entityInfo')}\n </h2>\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.entityType')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">{log.entityType}</dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.eventType')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {log.eventType || t('common.none')}\n </dd>\n </div>\n {log.entityId && (\n <div className=\"md:col-span-2\">\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.entityId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono break-all\">\n {log.entityId}\n </dd>\n </div>\n )}\n </dl>\n </div>\n\n {/* Error Message (if present) */}\n {log.errorMessage && (\n <div className=\"rounded-lg border border-destructive bg-destructive/5 p-6\">\n <h2 className=\"text-lg font-semibold mb-4 text-destructive\">\n {t('business_rules.logs.detail.errorMessage')}\n </h2>\n <pre className=\"text-sm text-destructive whitespace-pre-wrap font-mono\">\n {log.errorMessage}\n </pre>\n </div>\n )}\n\n {/* Input Context */}\n {log.inputContext && (\n <JsonDisplay\n data={log.inputContext}\n title={t('business_rules.logs.detail.inputContext')}\n />\n )}\n\n {/* Output Context */}\n {log.outputContext && (\n <JsonDisplay\n data={log.outputContext}\n title={t('business_rules.logs.detail.outputContext')}\n />\n )}\n\n {/* Result Value */}\n {log.resultValue && (\n <JsonDisplay\n data={log.resultValue}\n title={t('business_rules.logs.detail.resultValue')}\n />\n )}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useParams, useRouter } from 'next/navigation'\nimport { useQuery } from '@tanstack/react-query'\nimport { apiFetch } from '@open-mercato/ui/backend/utils/api'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\nimport { RecordNotFoundState, ErrorMessage } from '@open-mercato/ui/backend/detail'\n\ntype RuleExecutionLog = {\n id: string\n ruleId: string\n rule?: {\n id: string\n ruleId: string\n ruleName: string\n ruleType: string\n } | null\n entityType: string\n entityId: string | null\n eventType: string | null\n executedAt: string\n executionTimeMs: number\n executionResult: 'SUCCESS' | 'FAILURE' | 'ERROR'\n resultValue: any | null\n errorMessage: string | null\n inputContext: any | null\n outputContext: any | null\n executedBy: string | null\n tenantId: string | null\n organizationId: string | null\n}\n\nexport default function ExecutionLogDetailPage() {\n const router = useRouter()\n const params = useParams()\n\n // Handle catch-all route: params.slug = ['logs', 'id']\n let logId: string | undefined\n if (params?.slug && Array.isArray(params.slug)) {\n logId = params.slug[1] // Second element is the ID\n } else if (params?.id) {\n logId = Array.isArray(params.id) ? params.id[0] : params.id\n }\n\n const t = useT()\n\n const { data: log, isLoading, error } = useQuery({\n queryKey: ['business-rules', 'logs', logId],\n queryFn: async () => {\n const response = await apiFetch(`/api/business_rules/logs/${logId}`)\n if (!response.ok) {\n const httpErr = new Error(\n response.status === 404\n ? t('business_rules.logs.errors.notFound', 'Execution log not found.')\n : t('business_rules.logs.errors.fetchFailed')\n ) as Error & { status: number }\n httpErr.status = response.status\n throw httpErr\n }\n const result = await response.json()\n return result as RuleExecutionLog\n },\n enabled: !!logId,\n })\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-6 w-6\" />\n <span>{t('business_rules.logs.detail.loading')}</span>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n const isNotFound = !isLoading && (error as (Error & { status?: number }) | null)?.status === 404\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('business_rules.logs.errors.notFound', 'Execution log not found.')}\n backHref=\"/backend/logs\"\n backLabel={t('business_rules.logs.backToList', 'Back to logs')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !log) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={(error as Error | null)?.message ?? t('business_rules.logs.errors.loadFailed')}\n action={\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/backend/logs\">{t('business_rules.logs.backToList', 'Back to logs')}</Link>\n </Button>\n }\n />\n </PageBody>\n </Page>\n )\n }\n\n const getResultBadgeClass = (result: string) => {\n switch (result) {\n case 'SUCCESS':\n return 'bg-green-100 text-green-800'\n case 'FAILURE':\n return 'bg-yellow-100 text-yellow-800'\n case 'ERROR':\n return 'bg-red-100 text-red-800'\n default:\n return 'bg-muted text-foreground'\n }\n }\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold text-foreground\">\n {t('business_rules.logs.detail.title')}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {t('business_rules.logs.detail.logId')}: {log.id}\n </p>\n </div>\n <Button onClick={() => router.push('/backend/logs')} variant=\"outline\">\n {t('business_rules.logs.backToList')}\n </Button>\n </div>\n\n {/* Execution Summary */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('business_rules.logs.detail.summary')}\n </h2>\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.executedAt')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {new Date(log.executedAt).toLocaleString()}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.result')}\n </dt>\n <dd className=\"mt-1\">\n <span\n className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getResultBadgeClass(\n log.executionResult\n )}`}\n >\n {t(`business_rules.logs.result.${log.executionResult.toLowerCase()}`)}\n </span>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.executionTime')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">{log.executionTimeMs}ms</dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.executedBy')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {log.executedBy || t('common.unknown')}\n </dd>\n </div>\n </dl>\n </div>\n\n {/* Rule Information */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('business_rules.logs.detail.ruleInfo')}\n </h2>\n {log.rule ? (\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.ruleName')}\n </dt>\n <dd className=\"mt-1\">\n <Link\n href={`/backend/rules/${log.rule.id}`}\n className=\"text-sm text-primary hover:underline\"\n >\n {log.rule.ruleName}\n </Link>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.ruleType')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">{log.rule.ruleType}</dd>\n </div>\n <div className=\"md:col-span-2\">\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.ruleId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">{log.rule.ruleId}</dd>\n </div>\n </dl>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('business_rules.logs.ruleDeleted')}</p>\n )}\n </div>\n\n {/* Entity Information */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('business_rules.logs.detail.entityInfo')}\n </h2>\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.entityType')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">{log.entityType}</dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.eventType')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {log.eventType || t('common.none')}\n </dd>\n </div>\n {log.entityId && (\n <div className=\"md:col-span-2\">\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('business_rules.logs.fields.entityId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono break-all\">\n {log.entityId}\n </dd>\n </div>\n )}\n </dl>\n </div>\n\n {/* Error Message (if present) */}\n {log.errorMessage && (\n <div className=\"rounded-lg border border-destructive bg-destructive/5 p-6\">\n <h2 className=\"text-lg font-semibold mb-4 text-destructive\">\n {t('business_rules.logs.detail.errorMessage')}\n </h2>\n <pre className=\"text-sm text-destructive whitespace-pre-wrap font-mono\">\n {log.errorMessage}\n </pre>\n </div>\n )}\n\n {/* Input Context */}\n {log.inputContext && (\n <JsonDisplay\n data={log.inputContext}\n title={t('business_rules.logs.detail.inputContext')}\n />\n )}\n\n {/* Output Context */}\n {log.outputContext && (\n <JsonDisplay\n data={log.outputContext}\n title={t('business_rules.logs.detail.outputContext')}\n />\n )}\n\n {/* Result Value */}\n {log.resultValue && (\n <JsonDisplay\n data={log.resultValue}\n title={t('business_rules.logs.detail.resultValue')}\n />\n )}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -75,10 +75,19 @@ async function decorateOffersWithDetails(items, ctx) {
75
75
  const productIds = items.map((item) => item?.productId ? String(item.productId) : null).filter((value) => !!value);
76
76
  if (!offerIds.length && !productIds.length) return;
77
77
  const em = ctx.container.resolve("em");
78
+ const scopeTenantId = ctx.auth?.tenantId ?? null;
79
+ if (!scopeTenantId) {
80
+ throw new CrudHttpError(403, "[internal] Missing tenant scope for offer decoration");
81
+ }
82
+ const scopeOrgIds = Array.isArray(ctx.organizationIds) && ctx.organizationIds.length ? Array.from(new Set(ctx.organizationIds)) : ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null ? [ctx.selectedOrganizationId ?? ctx.auth?.orgId] : [];
83
+ const scopeWhere = { tenantId: scopeTenantId };
84
+ if (scopeOrgIds.length === 1) scopeWhere.organizationId = scopeOrgIds[0];
85
+ else if (scopeOrgIds.length > 1) scopeWhere.organizationId = { $in: scopeOrgIds };
86
+ const scope = { tenantId: scopeTenantId, organizationId: scopeOrgIds.length === 1 ? scopeOrgIds[0] : null };
78
87
  const [products, prices, defaultVariants] = await Promise.all([
79
88
  productIds.length ? em.find(
80
89
  CatalogProduct,
81
- { id: { $in: productIds } },
90
+ { id: { $in: productIds }, ...scopeWhere },
82
91
  {
83
92
  fields: ["id", "title", "description", "defaultMediaId", "defaultMediaUrl", "sku"]
84
93
  }
@@ -86,13 +95,13 @@ async function decorateOffersWithDetails(items, ctx) {
86
95
  offerIds.length ? findWithDecryption(
87
96
  em,
88
97
  CatalogProductPrice,
89
- { offer: { $in: offerIds } },
98
+ { offer: { $in: offerIds }, ...scopeWhere },
90
99
  { populate: ["priceKind"] },
91
- { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null }
100
+ scope
92
101
  ) : [],
93
102
  productIds.length ? em.find(
94
103
  CatalogProductVariant,
95
- { product: { $in: productIds }, isDefault: true },
104
+ { product: { $in: productIds }, isDefault: true, ...scopeWhere },
96
105
  { fields: ["id", "product"] }
97
106
  ) : []
98
107
  ]);
@@ -174,6 +183,7 @@ async function decorateOffersWithDetails(items, ctx) {
174
183
  CatalogProductPrice,
175
184
  {
176
185
  offer: null,
186
+ ...scopeWhere,
177
187
  $and: [
178
188
  { $or: fallbackTargets },
179
189
  channelFilterValues.includes(null) ? {
@@ -185,7 +195,7 @@ async function decorateOffersWithDetails(items, ctx) {
185
195
  ]
186
196
  },
187
197
  { populate: ["priceKind"] },
188
- { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null }
198
+ scope
189
199
  ) : [];
190
200
  fallbackEntries.forEach((entry) => {
191
201
  const entryChannelId = typeof entry.channelId === "string" && entry.channelId.length ? entry.channelId : null;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/catalog/api/offers/route.ts"],
4
- "sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { makeCrudRoute, type CrudCtx } from '@open-mercato/shared/lib/crud/factory'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { CatalogOffer, CatalogProduct, CatalogProductPrice, CatalogProductVariant } from '../../data/entities'\nimport { offerCreateSchema, offerUpdateSchema } from '../../data/validators'\nimport { parseScopedCommandInput, resolveCrudRecordId } from '../utils'\nimport { E } from '#generated/entities.ids.generated'\nimport * as F from '#generated/entities/catalog_offer'\nimport { parseIdList } from '../products/route'\nimport { extractAllCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport {\n createCatalogCrudOpenApi,\n createPagedListResponseSchema,\n defaultOkResponseSchema,\n} from '../openapi'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst listSchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n productId: z.string().uuid().optional(),\n channelId: z.string().uuid().optional(),\n channelIds: z.string().optional(),\n id: z.string().uuid().optional(),\n search: z.string().optional(),\n isActive: z.string().optional(),\n withDeleted: z.coerce.boolean().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n })\n .passthrough()\n\ntype OfferListQuery = z.infer<typeof listSchema>\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['sales.channels.manage'] },\n POST: { requireAuth: true, requireFeatures: ['sales.channels.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['sales.channels.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['sales.channels.manage'] },\n}\n\nexport const metadata = routeMetadata\n\nexport function normalizeSearch(term?: string | null): string | null {\n if (!term) return null\n const trimmed = term.trim()\n if (!trimmed.length) return null\n return trimmed\n}\n\nexport function buildOfferFilters(query: OfferListQuery): Record<string, unknown> {\n const filters: Record<string, unknown> = {}\n const searchTerm = normalizeSearch(query.search)\n if (query.id) {\n filters.id = { $eq: query.id }\n }\n if (query.productId) {\n filters.product_id = { $eq: query.productId }\n }\n if (query.channelId) {\n filters.channel_id = { $eq: query.channelId }\n } else {\n const channelIds = parseIdList(query.channelIds)\n if (channelIds.length) {\n filters.channel_id = { $in: channelIds }\n }\n }\n if (searchTerm) {\n const like = `%${escapeLikePattern(searchTerm)}%`\n filters.$or = [{ [F.title]: { $ilike: like } }, { [F.description]: { $ilike: like } }]\n }\n const isActive = parseBooleanToken(query.isActive)\n if (isActive !== null) filters[F.is_active] = isActive\n return filters\n}\n\nexport async function decorateOffersWithDetails(\n items: Record<string, unknown>[],\n ctx: CrudCtx,\n): Promise<void> {\n if (!items.length) return\n const offerIds = items\n .map((item) => (item?.id ? String(item.id) : null))\n .filter((value): value is string => !!value)\n const productIds = items\n .map((item) => (item?.productId ? String(item.productId) : null))\n .filter((value): value is string => !!value)\n if (!offerIds.length && !productIds.length) return\n const em = ctx.container.resolve('em') as EntityManager\n const [products, prices, defaultVariants] = await Promise.all([\n productIds.length\n ? em.find(\n CatalogProduct,\n { id: { $in: productIds } },\n {\n fields: ['id', 'title', 'description', 'defaultMediaId', 'defaultMediaUrl', 'sku'],\n },\n )\n : [],\n offerIds.length\n ? findWithDecryption(\n em,\n CatalogProductPrice,\n { offer: { $in: offerIds } },\n { populate: ['priceKind'] },\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n : [],\n productIds.length\n ? em.find(\n CatalogProductVariant,\n { product: { $in: productIds }, isDefault: true },\n { fields: ['id', 'product'] },\n )\n : [],\n ])\n const productMap = new Map(\n products.map((product) => [\n product.id,\n {\n id: product.id,\n title: product.title,\n defaultMediaId: product.defaultMediaId ?? null,\n defaultMediaUrl: product.defaultMediaUrl ?? null,\n sku: product.sku ?? null,\n },\n ]),\n )\n const priceMap = new Map<string, Array<Record<string, unknown>>>()\n prices.forEach((price) => {\n const offerRef = price.offer\n const offerId =\n typeof offerRef === 'string'\n ? offerRef\n : offerRef && typeof offerRef === 'object' && 'id' in offerRef\n ? (offerRef as { id?: string }).id ?? null\n : null\n if (!offerId) return\n const priceKind = price.priceKind\n const priceKindId =\n typeof priceKind === 'string'\n ? priceKind\n : priceKind && typeof priceKind === 'object'\n ? (priceKind as { id?: string }).id ?? null\n : null\n const priceKindCode =\n priceKind && typeof priceKind === 'object' && 'code' in priceKind\n ? (priceKind as { code?: string }).code ?? null\n : null\n const priceKindTitle =\n priceKind && typeof priceKind === 'object' && 'title' in priceKind\n ? (priceKind as { title?: string }).title ?? null\n : null\n const displayMode =\n priceKind && typeof priceKind === 'object' && 'displayMode' in priceKind\n ? (priceKind as { displayMode?: string }).displayMode ?? 'excluding-tax'\n : 'excluding-tax'\n const bucket = priceMap.get(offerId) ?? []\n bucket.push({\n id: price.id,\n priceKindId,\n priceKindCode,\n priceKindTitle,\n currencyCode: price.currencyCode ?? null,\n unitPriceNet: price.unitPriceNet ?? null,\n unitPriceGross: price.unitPriceGross ?? null,\n displayMode,\n minQuantity: price.minQuantity ?? null,\n maxQuantity: price.maxQuantity ?? null,\n })\n priceMap.set(offerId, bucket)\n })\n const variantToProductMap = new Map<string, string>()\n defaultVariants.forEach((variant) => {\n const variantId = typeof variant.id === 'string' ? variant.id : null\n const productRef =\n typeof variant.product === 'string'\n ? variant.product\n : variant.product && typeof variant.product === 'object' && 'id' in variant.product\n ? (variant.product as { id?: string }).id ?? null\n : null\n if (variantId && productRef) {\n variantToProductMap.set(variantId, productRef)\n }\n })\n const DEFAULT_CHANNEL_KEY = '__default__'\n type ProductFallbackPrice = { prices: Record<string, unknown>[]; priority: number }\n const productChannelPriceMap = new Map<string, Map<string, ProductFallbackPrice>>()\n const assignFallbackPrice = (productRef: string | null, channelRef: string | null, payload: Record<string, unknown>, priority: number) => {\n if (!productRef) return\n const bucket = productChannelPriceMap.get(productRef) ?? new Map()\n const effectiveChannel = channelRef ?? DEFAULT_CHANNEL_KEY\n const existing = bucket.get(effectiveChannel)\n if (existing && existing.priority > priority) return\n if (existing && existing.priority === priority) {\n bucket.set(effectiveChannel, { prices: [...existing.prices, payload], priority })\n productChannelPriceMap.set(productRef, bucket)\n return\n }\n bucket.set(effectiveChannel, { prices: [payload], priority })\n productChannelPriceMap.set(productRef, bucket)\n }\n const channelIds = Array.from(new Set(\n items\n .map((item) => {\n if (typeof item?.channelId === 'string') return item.channelId\n if (typeof item?.channel_id === 'string') return item.channel_id\n return null\n })\n .filter((value): value is string => !!value),\n ))\n const channelFilterValues = channelIds.length ? [...channelIds, null] : [null]\n const fallbackTargets: Array<Record<string, unknown>> = []\n if (productIds.length) fallbackTargets.push({ product: { $in: productIds } })\n const defaultVariantIds = Array.from(variantToProductMap.keys())\n if (defaultVariantIds.length) fallbackTargets.push({ variant: { $in: defaultVariantIds } })\n const fallbackEntries = fallbackTargets.length\n ? await findWithDecryption(\n em,\n CatalogProductPrice,\n {\n offer: null,\n $and: [\n { $or: fallbackTargets },\n channelFilterValues.includes(null)\n ? {\n $or: [\n { channelId: { $in: channelFilterValues.filter((id): id is string => typeof id === 'string') } },\n { channelId: null },\n ],\n }\n : { channelId: { $in: channelFilterValues } },\n ],\n },\n { populate: ['priceKind'] },\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n : []\n fallbackEntries.forEach((entry) => {\n const entryChannelId = typeof entry.channelId === 'string' && entry.channelId.length\n ? entry.channelId\n : null\n const priceKind = entry.priceKind ?? null\n const priceKindId =\n typeof priceKind?.id === 'string'\n ? priceKind.id\n : null\n const priceKindCode =\n typeof priceKind?.code === 'string'\n ? priceKind.code\n : null\n const priceKindTitle =\n typeof priceKind?.title === 'string'\n ? priceKind.title\n : null\n const displayMode = typeof priceKind?.displayMode === 'string'\n ? priceKind.displayMode\n : typeof (priceKind as any)?.display_mode === 'string'\n ? (priceKind as any).display_mode\n : 'excluding-tax'\n const payload = {\n priceKindId,\n priceKindCode,\n priceKindTitle,\n currencyCode: entry.currencyCode ?? null,\n unitPriceNet: entry.unitPriceNet ?? null,\n unitPriceGross: entry.unitPriceGross ?? null,\n displayMode,\n }\n const variantRef =\n typeof entry.variant === 'string'\n ? entry.variant\n : entry.variant && typeof entry.variant === 'object' && 'id' in entry.variant\n ? (entry.variant as { id?: string }).id ?? null\n : null\n if (variantRef) {\n const variantProduct = variantToProductMap.get(variantRef)\n const productRef =\n variantProduct\n ?? (typeof entry.product === 'string'\n ? entry.product\n : entry.product && typeof entry.product === 'object' && 'id' in entry.product\n ? (entry.product as { id?: string }).id ?? null\n : null)\n const priority = entryChannelId ? 4 : 3\n assignFallbackPrice(productRef, entryChannelId, payload, priority)\n return\n }\n const productRef =\n typeof entry.product === 'string'\n ? entry.product\n : entry.product && typeof entry.product === 'object' && 'id' in entry.product\n ? (entry.product as { id?: string }).id ?? null\n : null\n const priority = entryChannelId ? 2 : 1\n assignFallbackPrice(productRef, entryChannelId, payload, priority)\n })\n items.forEach((item) => {\n const productId = String(item?.productId ?? '')\n item.product = productId ? productMap.get(productId) ?? null : null\n item.prices = priceMap.get(String(item?.id ?? '')) ?? []\n const rowChannelId = typeof item?.channelId === 'string'\n ? item.channelId\n : typeof item?.channel_id === 'string'\n ? item.channel_id\n : null\n const bucket = productChannelPriceMap.get(productId)\n const channelKey = rowChannelId ?? DEFAULT_CHANNEL_KEY\n const channelPrice = bucket?.get(channelKey) ?? null\n const defaultPrice = bucket?.get(DEFAULT_CHANNEL_KEY) ?? null\n const effectivePrice = channelPrice ?? defaultPrice ?? null\n item.productChannelPrice = effectivePrice?.prices?.[0] ?? null\n item.productDefaultPrices = effectivePrice?.prices ?? []\n })\n}\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: CatalogOffer,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n indexer: { entityType: E.catalog.catalog_offer },\n list: {\n schema: listSchema,\n entityId: E.catalog.catalog_offer,\n fields: [\n F.id,\n 'product_id',\n F.organization_id,\n F.tenant_id,\n F.channel_id,\n F.title,\n F.description,\n 'default_media_id',\n 'default_media_url',\n F.metadata,\n F.is_active,\n F.created_at,\n F.updated_at,\n ],\n sortFieldMap: {\n title: F.title,\n createdAt: F.created_at,\n updatedAt: F.updated_at,\n },\n buildFilters: async (query) => buildOfferFilters(query),\n transformItem: (item: Record<string, unknown>) => {\n if (!item) return item\n const cfEntries = extractAllCustomFieldEntries(item)\n const base = {\n id: item.id,\n productId: item.product_id ?? null,\n organizationId: item.organization_id ?? null,\n tenantId: item.tenant_id ?? null,\n channelId: item.channel_id ?? null,\n title: item.title ?? '',\n description: item.description ?? null,\n defaultMediaId: item.default_media_id ?? null,\n defaultMediaUrl: item.default_media_url ?? null,\n metadata: item.metadata ?? null,\n isActive: item.is_active ?? false,\n createdAt: item.created_at,\n updatedAt: item.updated_at,\n }\n return Object.keys(cfEntries).length ? { ...base, ...cfEntries } : base\n },\n },\n actions: {\n create: {\n commandId: 'catalog.offers.create',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n return parseScopedCommandInput(offerCreateSchema, raw ?? {}, ctx, translate)\n },\n response: ({ result }) => ({ id: result?.offerId ?? null }),\n status: 201,\n },\n update: {\n commandId: 'catalog.offers.update',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n return parseScopedCommandInput(offerUpdateSchema, raw ?? {}, ctx, translate)\n },\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'catalog.offers.delete',\n schema: rawBodySchema,\n mapInput: async ({ parsed, ctx }) => {\n const { translate } = await resolveTranslations()\n const id = resolveCrudRecordId(parsed, ctx, translate)\n if (!id) {\n throw new CrudHttpError(400, { error: translate('catalog.errors.id_required', 'Offer id is required.') })\n }\n return { id }\n },\n response: () => ({ ok: true }),\n },\n },\n hooks: {\n afterList: async (payload, ctx) => {\n const items = Array.isArray(payload.items) ? payload.items : []\n if (!items.length) return\n await decorateOffersWithDetails(items, ctx)\n },\n },\n})\n\nexport const GET = crud.GET\nexport const POST = crud.POST\nexport const PUT = crud.PUT\nexport const DELETE = crud.DELETE\n\nconst offerListItemSchema = z.object({\n id: z.string().uuid(),\n productId: z.string().uuid().nullable().optional(),\n organizationId: z.string().uuid().nullable().optional(),\n tenantId: z.string().uuid().nullable().optional(),\n channelId: z.string().uuid().nullable().optional(),\n title: z.string(),\n description: z.string().nullable().optional(),\n defaultMediaId: z.string().uuid().nullable().optional(),\n defaultMediaUrl: z.string().nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n isActive: z.boolean().nullable().optional(),\n createdAt: z.string().nullable().optional(),\n updatedAt: z.string().nullable().optional(),\n product: z.record(z.string(), z.unknown()).nullable().optional(),\n prices: z.array(z.record(z.string(), z.unknown())).optional(),\n productChannelPrice: z.record(z.string(), z.unknown()).nullable().optional(),\n productDefaultPrices: z.array(z.record(z.string(), z.unknown())).optional(),\n})\n\nexport const openApi = createCatalogCrudOpenApi({\n resourceName: 'Offer',\n pluralName: 'Offers',\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(offerListItemSchema),\n create: {\n schema: offerCreateSchema,\n description: 'Creates a new offer linking a product to a sales channel.',\n },\n update: {\n schema: offerUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Updates an existing offer by id.',\n },\n del: {\n schema: z.object({ id: z.string().uuid() }),\n responseSchema: defaultOkResponseSchema,\n description: 'Deletes an offer by id.',\n },\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { makeCrudRoute, type CrudCtx } from '@open-mercato/shared/lib/crud/factory'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { CatalogOffer, CatalogProduct, CatalogProductPrice, CatalogProductVariant } from '../../data/entities'\nimport { offerCreateSchema, offerUpdateSchema } from '../../data/validators'\nimport { parseScopedCommandInput, resolveCrudRecordId } from '../utils'\nimport { E } from '#generated/entities.ids.generated'\nimport * as F from '#generated/entities/catalog_offer'\nimport { parseIdList } from '../products/route'\nimport { extractAllCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport {\n createCatalogCrudOpenApi,\n createPagedListResponseSchema,\n defaultOkResponseSchema,\n} from '../openapi'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst listSchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n productId: z.string().uuid().optional(),\n channelId: z.string().uuid().optional(),\n channelIds: z.string().optional(),\n id: z.string().uuid().optional(),\n search: z.string().optional(),\n isActive: z.string().optional(),\n withDeleted: z.coerce.boolean().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n })\n .passthrough()\n\ntype OfferListQuery = z.infer<typeof listSchema>\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['sales.channels.manage'] },\n POST: { requireAuth: true, requireFeatures: ['sales.channels.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['sales.channels.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['sales.channels.manage'] },\n}\n\nexport const metadata = routeMetadata\n\nexport function normalizeSearch(term?: string | null): string | null {\n if (!term) return null\n const trimmed = term.trim()\n if (!trimmed.length) return null\n return trimmed\n}\n\nexport function buildOfferFilters(query: OfferListQuery): Record<string, unknown> {\n const filters: Record<string, unknown> = {}\n const searchTerm = normalizeSearch(query.search)\n if (query.id) {\n filters.id = { $eq: query.id }\n }\n if (query.productId) {\n filters.product_id = { $eq: query.productId }\n }\n if (query.channelId) {\n filters.channel_id = { $eq: query.channelId }\n } else {\n const channelIds = parseIdList(query.channelIds)\n if (channelIds.length) {\n filters.channel_id = { $in: channelIds }\n }\n }\n if (searchTerm) {\n const like = `%${escapeLikePattern(searchTerm)}%`\n filters.$or = [{ [F.title]: { $ilike: like } }, { [F.description]: { $ilike: like } }]\n }\n const isActive = parseBooleanToken(query.isActive)\n if (isActive !== null) filters[F.is_active] = isActive\n return filters\n}\n\nexport async function decorateOffersWithDetails(\n items: Record<string, unknown>[],\n ctx: CrudCtx,\n): Promise<void> {\n if (!items.length) return\n const offerIds = items\n .map((item) => (item?.id ? String(item.id) : null))\n .filter((value): value is string => !!value)\n const productIds = items\n .map((item) => (item?.productId ? String(item.productId) : null))\n .filter((value): value is string => !!value)\n if (!offerIds.length && !productIds.length) return\n const em = ctx.container.resolve('em') as EntityManager\n const scopeTenantId = ctx.auth?.tenantId ?? null\n if (!scopeTenantId) {\n throw new CrudHttpError(403, '[internal] Missing tenant scope for offer decoration')\n }\n const scopeOrgIds =\n Array.isArray(ctx.organizationIds) && ctx.organizationIds.length\n ? Array.from(new Set(ctx.organizationIds))\n : (ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null)\n ? [(ctx.selectedOrganizationId ?? ctx.auth?.orgId) as string]\n : []\n const scopeWhere: Record<string, unknown> = { tenantId: scopeTenantId }\n if (scopeOrgIds.length === 1) scopeWhere.organizationId = scopeOrgIds[0]\n else if (scopeOrgIds.length > 1) scopeWhere.organizationId = { $in: scopeOrgIds }\n const scope = { tenantId: scopeTenantId, organizationId: scopeOrgIds.length === 1 ? scopeOrgIds[0] : null }\n const [products, prices, defaultVariants] = await Promise.all([\n productIds.length\n ? em.find(\n CatalogProduct,\n { id: { $in: productIds }, ...scopeWhere },\n {\n fields: ['id', 'title', 'description', 'defaultMediaId', 'defaultMediaUrl', 'sku'],\n },\n )\n : [],\n offerIds.length\n ? findWithDecryption(\n em,\n CatalogProductPrice,\n { offer: { $in: offerIds }, ...scopeWhere },\n { populate: ['priceKind'] },\n scope,\n )\n : [],\n productIds.length\n ? em.find(\n CatalogProductVariant,\n { product: { $in: productIds }, isDefault: true, ...scopeWhere },\n { fields: ['id', 'product'] },\n )\n : [],\n ])\n const productMap = new Map(\n products.map((product) => [\n product.id,\n {\n id: product.id,\n title: product.title,\n defaultMediaId: product.defaultMediaId ?? null,\n defaultMediaUrl: product.defaultMediaUrl ?? null,\n sku: product.sku ?? null,\n },\n ]),\n )\n const priceMap = new Map<string, Array<Record<string, unknown>>>()\n prices.forEach((price) => {\n const offerRef = price.offer\n const offerId =\n typeof offerRef === 'string'\n ? offerRef\n : offerRef && typeof offerRef === 'object' && 'id' in offerRef\n ? (offerRef as { id?: string }).id ?? null\n : null\n if (!offerId) return\n const priceKind = price.priceKind\n const priceKindId =\n typeof priceKind === 'string'\n ? priceKind\n : priceKind && typeof priceKind === 'object'\n ? (priceKind as { id?: string }).id ?? null\n : null\n const priceKindCode =\n priceKind && typeof priceKind === 'object' && 'code' in priceKind\n ? (priceKind as { code?: string }).code ?? null\n : null\n const priceKindTitle =\n priceKind && typeof priceKind === 'object' && 'title' in priceKind\n ? (priceKind as { title?: string }).title ?? null\n : null\n const displayMode =\n priceKind && typeof priceKind === 'object' && 'displayMode' in priceKind\n ? (priceKind as { displayMode?: string }).displayMode ?? 'excluding-tax'\n : 'excluding-tax'\n const bucket = priceMap.get(offerId) ?? []\n bucket.push({\n id: price.id,\n priceKindId,\n priceKindCode,\n priceKindTitle,\n currencyCode: price.currencyCode ?? null,\n unitPriceNet: price.unitPriceNet ?? null,\n unitPriceGross: price.unitPriceGross ?? null,\n displayMode,\n minQuantity: price.minQuantity ?? null,\n maxQuantity: price.maxQuantity ?? null,\n })\n priceMap.set(offerId, bucket)\n })\n const variantToProductMap = new Map<string, string>()\n defaultVariants.forEach((variant) => {\n const variantId = typeof variant.id === 'string' ? variant.id : null\n const productRef =\n typeof variant.product === 'string'\n ? variant.product\n : variant.product && typeof variant.product === 'object' && 'id' in variant.product\n ? (variant.product as { id?: string }).id ?? null\n : null\n if (variantId && productRef) {\n variantToProductMap.set(variantId, productRef)\n }\n })\n const DEFAULT_CHANNEL_KEY = '__default__'\n type ProductFallbackPrice = { prices: Record<string, unknown>[]; priority: number }\n const productChannelPriceMap = new Map<string, Map<string, ProductFallbackPrice>>()\n const assignFallbackPrice = (productRef: string | null, channelRef: string | null, payload: Record<string, unknown>, priority: number) => {\n if (!productRef) return\n const bucket = productChannelPriceMap.get(productRef) ?? new Map()\n const effectiveChannel = channelRef ?? DEFAULT_CHANNEL_KEY\n const existing = bucket.get(effectiveChannel)\n if (existing && existing.priority > priority) return\n if (existing && existing.priority === priority) {\n bucket.set(effectiveChannel, { prices: [...existing.prices, payload], priority })\n productChannelPriceMap.set(productRef, bucket)\n return\n }\n bucket.set(effectiveChannel, { prices: [payload], priority })\n productChannelPriceMap.set(productRef, bucket)\n }\n const channelIds = Array.from(new Set(\n items\n .map((item) => {\n if (typeof item?.channelId === 'string') return item.channelId\n if (typeof item?.channel_id === 'string') return item.channel_id\n return null\n })\n .filter((value): value is string => !!value),\n ))\n const channelFilterValues = channelIds.length ? [...channelIds, null] : [null]\n const fallbackTargets: Array<Record<string, unknown>> = []\n if (productIds.length) fallbackTargets.push({ product: { $in: productIds } })\n const defaultVariantIds = Array.from(variantToProductMap.keys())\n if (defaultVariantIds.length) fallbackTargets.push({ variant: { $in: defaultVariantIds } })\n const fallbackEntries = fallbackTargets.length\n ? await findWithDecryption(\n em,\n CatalogProductPrice,\n {\n offer: null,\n ...scopeWhere,\n $and: [\n { $or: fallbackTargets },\n channelFilterValues.includes(null)\n ? {\n $or: [\n { channelId: { $in: channelFilterValues.filter((id): id is string => typeof id === 'string') } },\n { channelId: null },\n ],\n }\n : { channelId: { $in: channelFilterValues } },\n ],\n },\n { populate: ['priceKind'] },\n scope,\n )\n : []\n fallbackEntries.forEach((entry) => {\n const entryChannelId = typeof entry.channelId === 'string' && entry.channelId.length\n ? entry.channelId\n : null\n const priceKind = entry.priceKind ?? null\n const priceKindId =\n typeof priceKind?.id === 'string'\n ? priceKind.id\n : null\n const priceKindCode =\n typeof priceKind?.code === 'string'\n ? priceKind.code\n : null\n const priceKindTitle =\n typeof priceKind?.title === 'string'\n ? priceKind.title\n : null\n const displayMode = typeof priceKind?.displayMode === 'string'\n ? priceKind.displayMode\n : typeof (priceKind as any)?.display_mode === 'string'\n ? (priceKind as any).display_mode\n : 'excluding-tax'\n const payload = {\n priceKindId,\n priceKindCode,\n priceKindTitle,\n currencyCode: entry.currencyCode ?? null,\n unitPriceNet: entry.unitPriceNet ?? null,\n unitPriceGross: entry.unitPriceGross ?? null,\n displayMode,\n }\n const variantRef =\n typeof entry.variant === 'string'\n ? entry.variant\n : entry.variant && typeof entry.variant === 'object' && 'id' in entry.variant\n ? (entry.variant as { id?: string }).id ?? null\n : null\n if (variantRef) {\n const variantProduct = variantToProductMap.get(variantRef)\n const productRef =\n variantProduct\n ?? (typeof entry.product === 'string'\n ? entry.product\n : entry.product && typeof entry.product === 'object' && 'id' in entry.product\n ? (entry.product as { id?: string }).id ?? null\n : null)\n const priority = entryChannelId ? 4 : 3\n assignFallbackPrice(productRef, entryChannelId, payload, priority)\n return\n }\n const productRef =\n typeof entry.product === 'string'\n ? entry.product\n : entry.product && typeof entry.product === 'object' && 'id' in entry.product\n ? (entry.product as { id?: string }).id ?? null\n : null\n const priority = entryChannelId ? 2 : 1\n assignFallbackPrice(productRef, entryChannelId, payload, priority)\n })\n items.forEach((item) => {\n const productId = String(item?.productId ?? '')\n item.product = productId ? productMap.get(productId) ?? null : null\n item.prices = priceMap.get(String(item?.id ?? '')) ?? []\n const rowChannelId = typeof item?.channelId === 'string'\n ? item.channelId\n : typeof item?.channel_id === 'string'\n ? item.channel_id\n : null\n const bucket = productChannelPriceMap.get(productId)\n const channelKey = rowChannelId ?? DEFAULT_CHANNEL_KEY\n const channelPrice = bucket?.get(channelKey) ?? null\n const defaultPrice = bucket?.get(DEFAULT_CHANNEL_KEY) ?? null\n const effectivePrice = channelPrice ?? defaultPrice ?? null\n item.productChannelPrice = effectivePrice?.prices?.[0] ?? null\n item.productDefaultPrices = effectivePrice?.prices ?? []\n })\n}\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: CatalogOffer,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n indexer: { entityType: E.catalog.catalog_offer },\n list: {\n schema: listSchema,\n entityId: E.catalog.catalog_offer,\n fields: [\n F.id,\n 'product_id',\n F.organization_id,\n F.tenant_id,\n F.channel_id,\n F.title,\n F.description,\n 'default_media_id',\n 'default_media_url',\n F.metadata,\n F.is_active,\n F.created_at,\n F.updated_at,\n ],\n sortFieldMap: {\n title: F.title,\n createdAt: F.created_at,\n updatedAt: F.updated_at,\n },\n buildFilters: async (query) => buildOfferFilters(query),\n transformItem: (item: Record<string, unknown>) => {\n if (!item) return item\n const cfEntries = extractAllCustomFieldEntries(item)\n const base = {\n id: item.id,\n productId: item.product_id ?? null,\n organizationId: item.organization_id ?? null,\n tenantId: item.tenant_id ?? null,\n channelId: item.channel_id ?? null,\n title: item.title ?? '',\n description: item.description ?? null,\n defaultMediaId: item.default_media_id ?? null,\n defaultMediaUrl: item.default_media_url ?? null,\n metadata: item.metadata ?? null,\n isActive: item.is_active ?? false,\n createdAt: item.created_at,\n updatedAt: item.updated_at,\n }\n return Object.keys(cfEntries).length ? { ...base, ...cfEntries } : base\n },\n },\n actions: {\n create: {\n commandId: 'catalog.offers.create',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n return parseScopedCommandInput(offerCreateSchema, raw ?? {}, ctx, translate)\n },\n response: ({ result }) => ({ id: result?.offerId ?? null }),\n status: 201,\n },\n update: {\n commandId: 'catalog.offers.update',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n return parseScopedCommandInput(offerUpdateSchema, raw ?? {}, ctx, translate)\n },\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'catalog.offers.delete',\n schema: rawBodySchema,\n mapInput: async ({ parsed, ctx }) => {\n const { translate } = await resolveTranslations()\n const id = resolveCrudRecordId(parsed, ctx, translate)\n if (!id) {\n throw new CrudHttpError(400, { error: translate('catalog.errors.id_required', 'Offer id is required.') })\n }\n return { id }\n },\n response: () => ({ ok: true }),\n },\n },\n hooks: {\n afterList: async (payload, ctx) => {\n const items = Array.isArray(payload.items) ? payload.items : []\n if (!items.length) return\n await decorateOffersWithDetails(items, ctx)\n },\n },\n})\n\nexport const GET = crud.GET\nexport const POST = crud.POST\nexport const PUT = crud.PUT\nexport const DELETE = crud.DELETE\n\nconst offerListItemSchema = z.object({\n id: z.string().uuid(),\n productId: z.string().uuid().nullable().optional(),\n organizationId: z.string().uuid().nullable().optional(),\n tenantId: z.string().uuid().nullable().optional(),\n channelId: z.string().uuid().nullable().optional(),\n title: z.string(),\n description: z.string().nullable().optional(),\n defaultMediaId: z.string().uuid().nullable().optional(),\n defaultMediaUrl: z.string().nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n isActive: z.boolean().nullable().optional(),\n createdAt: z.string().nullable().optional(),\n updatedAt: z.string().nullable().optional(),\n product: z.record(z.string(), z.unknown()).nullable().optional(),\n prices: z.array(z.record(z.string(), z.unknown())).optional(),\n productChannelPrice: z.record(z.string(), z.unknown()).nullable().optional(),\n productDefaultPrices: z.array(z.record(z.string(), z.unknown())).optional(),\n})\n\nexport const openApi = createCatalogCrudOpenApi({\n resourceName: 'Offer',\n pluralName: 'Offers',\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(offerListItemSchema),\n create: {\n schema: offerCreateSchema,\n description: 'Creates a new offer linking a product to a sales channel.',\n },\n update: {\n schema: offerUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Updates an existing offer by id.',\n },\n del: {\n schema: z.object({ id: z.string().uuid() }),\n responseSchema: defaultOkResponseSchema,\n description: 'Deletes an offer by id.',\n },\n})\n"],
5
+ "mappings": "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",
6
6
  "names": ["productRef", "priority"]
7
7
  }
@@ -1,6 +1,7 @@
1
1
  import { registerCommand } from "@open-mercato/shared/lib/commands";
2
2
  import { buildChanges, requireId, parseWithCustomFields, setCustomFieldsIfAny, emitCrudSideEffects } from "@open-mercato/shared/lib/commands/helpers";
3
3
  import { loadCustomFieldSnapshot, buildCustomFieldResetMap } from "@open-mercato/shared/lib/commands/customFieldSnapshots";
4
+ import { withAtomicFlush } from "@open-mercato/shared/lib/commands/flush";
4
5
  import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
5
6
  import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
6
7
  import { CatalogProductCategory } from "../data/entities.js";
@@ -116,8 +117,16 @@ const createCategoryCommand = {
116
117
  updatedAt: now
117
118
  });
118
119
  em.persist(record);
119
- await em.flush();
120
- await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId);
120
+ await withAtomicFlush(
121
+ em,
122
+ [
123
+ () => em.flush(),
124
+ async () => {
125
+ await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId);
126
+ }
127
+ ],
128
+ { transaction: true }
129
+ );
121
130
  await setCustomFieldsIfAny({
122
131
  dataEngine: ctx.container.resolve("dataEngine"),
123
132
  entityId: E.catalog.catalog_product_category,
@@ -171,8 +180,16 @@ const createCategoryCommand = {
171
180
  ensureOrganizationScope(ctx, record.organizationId);
172
181
  record.deletedAt = /* @__PURE__ */ new Date();
173
182
  record.isActive = false;
174
- await em.flush();
175
- await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId);
183
+ await withAtomicFlush(
184
+ em,
185
+ [
186
+ () => em.flush(),
187
+ async () => {
188
+ await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId);
189
+ }
190
+ ],
191
+ { transaction: true }
192
+ );
176
193
  const resetValues = buildCustomFieldResetMap(void 0, after.custom ?? void 0);
177
194
  if (Object.keys(resetValues).length) {
178
195
  await setCustomFieldsIfAny({
@@ -237,8 +254,16 @@ const updateCategoryCommand = {
237
254
  if (parsed.isActive !== void 0) {
238
255
  record.isActive = parsed.isActive;
239
256
  }
240
- await em.flush();
241
- await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId);
257
+ await withAtomicFlush(
258
+ em,
259
+ [
260
+ () => em.flush(),
261
+ async () => {
262
+ await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId);
263
+ }
264
+ ],
265
+ { transaction: true }
266
+ );
242
267
  await setCustomFieldsIfAny({
243
268
  dataEngine: ctx.container.resolve("dataEngine"),
244
269
  entityId: E.catalog.catalog_product_category,
@@ -326,8 +351,16 @@ const updateCategoryCommand = {
326
351
  record.isActive = before.isActive;
327
352
  record.deletedAt = null;
328
353
  }
329
- await em.flush();
330
- await rebuildCategoryHierarchyForOrganization(em, before.organizationId, before.tenantId);
354
+ await withAtomicFlush(
355
+ em,
356
+ [
357
+ () => em.flush(),
358
+ async () => {
359
+ await rebuildCategoryHierarchyForOrganization(em, before.organizationId, before.tenantId);
360
+ }
361
+ ],
362
+ { transaction: true }
363
+ );
331
364
  const resetValues = buildCustomFieldResetMap(payload?.after?.custom ?? void 0, before.custom ?? void 0);
332
365
  if (Object.keys(resetValues).length) {
333
366
  await setCustomFieldsIfAny({
@@ -364,8 +397,16 @@ const deleteCategoryCommand = {
364
397
  const snapshot = await loadCategorySnapshot(baseEm, id);
365
398
  record.deletedAt = /* @__PURE__ */ new Date();
366
399
  record.isActive = false;
367
- await em.flush();
368
- await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId);
400
+ await withAtomicFlush(
401
+ em,
402
+ [
403
+ () => em.flush(),
404
+ async () => {
405
+ await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId);
406
+ }
407
+ ],
408
+ { transaction: true }
409
+ );
369
410
  if (snapshot?.custom && Object.keys(snapshot.custom).length) {
370
411
  const resetValues = buildCustomFieldResetMap(snapshot.custom, void 0);
371
412
  if (Object.keys(resetValues).length) {
@@ -451,8 +492,16 @@ const deleteCategoryCommand = {
451
492
  record.childIds = before.childIds;
452
493
  record.descendantIds = before.descendantIds;
453
494
  }
454
- await em.flush();
455
- await rebuildCategoryHierarchyForOrganization(em, before.organizationId, before.tenantId);
495
+ await withAtomicFlush(
496
+ em,
497
+ [
498
+ () => em.flush(),
499
+ async () => {
500
+ await rebuildCategoryHierarchyForOrganization(em, before.organizationId, before.tenantId);
501
+ }
502
+ ],
503
+ { transaction: true }
504
+ );
456
505
  if (before.custom && Object.keys(before.custom).length) {
457
506
  await setCustomFieldsIfAny({
458
507
  dataEngine: ctx.container.resolve("dataEngine"),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/catalog/commands/categories.ts"],
4
- "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { buildChanges, requireId, parseWithCustomFields, setCustomFieldsIfAny, emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { loadCustomFieldSnapshot, buildCustomFieldResetMap } from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CatalogProductCategory } from '../data/entities'\nimport {\n categoryCreateSchema,\n categoryUpdateSchema,\n type CategoryCreateInput,\n type CategoryUpdateInput,\n} from '../data/validators'\nimport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload } from './shared'\nimport { rebuildCategoryHierarchyForOrganization } from '../lib/categoryHierarchy'\nimport type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { E } from '#generated/entities.ids.generated'\n\nconst categoryCrudEvents: CrudEventsConfig = {\n module: 'catalog',\n entity: 'category',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\ntype CategorySnapshot = {\n id: string\n organizationId: string\n tenantId: string\n name: string\n slug: string | null\n description: string | null\n parentId: string | null\n rootId: string | null\n treePath: string | null\n depth: number\n ancestorIds: string[]\n childIds: string[]\n descendantIds: string[]\n isActive: boolean\n createdAt: string\n updatedAt: string\n custom?: Record<string, unknown> | null\n}\n\ntype CategoryUndoPayload = {\n before?: CategorySnapshot | null\n after?: CategorySnapshot | null\n}\n\nconst CATEGORY_CHANGE_KEYS = [\n 'name',\n 'slug',\n 'description',\n 'parentId',\n 'rootId',\n 'treePath',\n 'isActive',\n] as const satisfies readonly string[]\n\nasync function loadCategorySnapshot(em: EntityManager, id: string): Promise<CategorySnapshot | null> {\n const record = await em.findOne(CatalogProductCategory, { id })\n if (!record) return null\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.catalog.catalog_product_category,\n recordId: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n return {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n name: record.name,\n slug: record.slug ?? null,\n description: record.description ?? null,\n parentId: record.parentId ?? null,\n rootId: record.rootId ?? null,\n treePath: record.treePath ?? null,\n depth: record.depth ?? 0,\n ancestorIds: Array.isArray(record.ancestorIds) ? [...record.ancestorIds] : [],\n childIds: Array.isArray(record.childIds) ? [...record.childIds] : [],\n descendantIds: Array.isArray(record.descendantIds) ? [...record.descendantIds] : [],\n isActive: !!record.isActive,\n createdAt: record.createdAt.toISOString(),\n updatedAt: record.updatedAt.toISOString(),\n custom: custom && Object.keys(custom).length ? custom : null,\n }\n}\n\nasync function assertParentScope(\n em: EntityManager,\n parentId: string | null,\n organizationId: string,\n tenantId: string\n): Promise<string | null> {\n if (!parentId) return null\n const parent = await em.findOne(CatalogProductCategory, {\n id: parentId,\n organizationId,\n tenantId,\n deletedAt: null,\n })\n if (!parent) {\n throw new CrudHttpError(400, { error: 'Parent category not found or inaccessible.' })\n }\n if (parent.id === parentId) return parent.id\n return String(parent.id)\n}\n\nfunction normalizeSlug(slug?: string | null): string | null {\n if (typeof slug !== 'string') return null\n const trimmed = slug.trim().toLowerCase()\n return trimmed.length ? trimmed : null\n}\n\nconst createCategoryCommand: CommandHandler<CategoryCreateInput, { categoryId: string }> = {\n id: 'catalog.categories.create',\n async execute(input, ctx) {\n const { parsed, custom } = parseWithCustomFields(categoryCreateSchema, input)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const slug = normalizeSlug(parsed.slug ?? null)\n if (slug) {\n const conflict = await em.findOne(CatalogProductCategory, {\n slug,\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n deletedAt: null,\n })\n if (conflict) {\n throw new CrudHttpError(400, { error: 'Category slug already exists for this organization.' })\n }\n }\n const parentId = parsed.parentId ? String(parsed.parentId) : null\n const resolvedParent = await assertParentScope(em, parentId, parsed.organizationId, parsed.tenantId)\n\n const now = new Date()\n const record = em.create(CatalogProductCategory, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n name: parsed.name,\n slug,\n description: parsed.description?.trim()?.length ? parsed.description.trim() : null,\n parentId: resolvedParent,\n depth: 0,\n ancestorIds: [],\n childIds: [],\n descendantIds: [],\n isActive: parsed.isActive !== false,\n createdAt: now,\n updatedAt: now,\n })\n em.persist(record)\n await em.flush()\n await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_category,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n })\n const de = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n events: categoryCrudEvents,\n })\n return { categoryId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadCategorySnapshot(em, result.categoryId)\n },\n buildLog: async ({ snapshots }) => {\n const after = snapshots.after as CategorySnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.categories.create', 'Create catalog category'),\n resourceKind: 'catalog.category',\n resourceId: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies CategoryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CategoryUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogProductCategory, { id: after.id })\n if (!record) return\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n record.deletedAt = new Date()\n record.isActive = false\n await em.flush()\n await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)\n const resetValues = buildCustomFieldResetMap(undefined, after.custom ?? undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_category,\n recordId: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n values: resetValues,\n })\n }\n },\n}\n\nconst updateCategoryCommand: CommandHandler<CategoryUpdateInput, { categoryId: string }> = {\n id: 'catalog.categories.update',\n async prepare(input, ctx) {\n const id = requireId(input, 'Category id is required')\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadCategorySnapshot(em, id)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const { parsed, custom } = parseWithCustomFields(categoryUpdateSchema, input)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogProductCategory, { id: parsed.id, deletedAt: null })\n if (!record) throw new CrudHttpError(404, { error: 'Catalog category not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n\n if (parsed.name !== undefined) {\n record.name = parsed.name\n }\n\n if (parsed.slug !== undefined) {\n const slug = normalizeSlug(parsed.slug ?? null)\n if (slug !== record.slug) {\n if (slug) {\n const conflict = await em.findOne(CatalogProductCategory, {\n slug,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n deletedAt: null,\n id: { $ne: record.id },\n })\n if (conflict) {\n throw new CrudHttpError(400, { error: 'Category slug already exists.' })\n }\n }\n record.slug = slug\n }\n }\n\n if (parsed.description !== undefined) {\n record.description = parsed.description?.trim()?.length ? parsed.description.trim() : null\n }\n\n if (parsed.parentId !== undefined) {\n const requestedParent = parsed.parentId ? String(parsed.parentId) : null\n const safeParent = requestedParent && requestedParent !== record.id ? requestedParent : null\n record.parentId = await assertParentScope(em, safeParent, record.organizationId, record.tenantId)\n }\n\n if (parsed.isActive !== undefined) {\n record.isActive = parsed.isActive\n }\n\n await em.flush()\n await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_category,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n })\n const de = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n events: categoryCrudEvents,\n })\n return { categoryId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadCategorySnapshot(em, result.categoryId)\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as CategorySnapshot | undefined\n const after = snapshots.after as CategorySnapshot | undefined\n if (!before || !after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.categories.update', 'Update catalog category'),\n resourceKind: 'catalog.category',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(before as Record<string, unknown>, after as Record<string, unknown>, CATEGORY_CHANGE_KEYS),\n payload: {\n undo: { before, after } satisfies CategoryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CategoryUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let record = await em.findOne(CatalogProductCategory, { id: before.id })\n if (!record) {\n record = em.create(CatalogProductCategory, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n name: before.name,\n slug: before.slug,\n description: before.description,\n parentId: before.parentId,\n rootId: before.rootId,\n treePath: before.treePath,\n depth: before.depth,\n ancestorIds: before.ancestorIds,\n childIds: before.childIds,\n descendantIds: before.descendantIds,\n isActive: before.isActive,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(record)\n } else {\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n record.name = before.name\n record.slug = before.slug\n record.description = before.description\n record.parentId = before.parentId\n record.rootId = before.rootId\n record.treePath = before.treePath\n record.depth = before.depth\n record.ancestorIds = before.ancestorIds\n record.childIds = before.childIds\n record.descendantIds = before.descendantIds\n record.isActive = before.isActive\n record.deletedAt = null\n }\n await em.flush()\n await rebuildCategoryHierarchyForOrganization(em, before.organizationId, before.tenantId)\n const resetValues = buildCustomFieldResetMap(payload?.after?.custom ?? undefined, before.custom ?? undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_category,\n recordId: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n values: resetValues,\n })\n }\n },\n}\n\nconst deleteCategoryCommand: CommandHandler<{ id?: string }, { categoryId: string }> = {\n id: 'catalog.categories.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Category id is required')\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadCategorySnapshot(em, id)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Category id is required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogProductCategory, { id, deletedAt: null })\n if (!record) throw new CrudHttpError(404, { error: 'Catalog category not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n const baseEm = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadCategorySnapshot(baseEm, id)\n\n record.deletedAt = new Date()\n record.isActive = false\n await em.flush()\n await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)\n if (snapshot?.custom && Object.keys(snapshot.custom).length) {\n const resetValues = buildCustomFieldResetMap(snapshot.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_category,\n recordId: snapshot.id,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n values: resetValues,\n })\n }\n }\n const de = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n events: categoryCrudEvents,\n })\n return { categoryId: record.id }\n },\n buildLog: async ({ ctx, snapshots }) => {\n const before = snapshots.before as CategorySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.categories.delete', 'Delete catalog category'),\n resourceKind: 'catalog.category',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies CategoryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CategoryUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let record = await em.findOne(CatalogProductCategory, { id: before.id })\n if (!record) {\n record = em.create(CatalogProductCategory, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n name: before.name,\n slug: before.slug,\n description: before.description,\n parentId: before.parentId,\n rootId: before.rootId,\n treePath: before.treePath,\n depth: before.depth,\n ancestorIds: before.ancestorIds,\n childIds: before.childIds,\n descendantIds: before.descendantIds,\n isActive: before.isActive,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(record)\n } else {\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n record.deletedAt = null\n record.isActive = before.isActive\n record.name = before.name\n record.slug = before.slug\n record.description = before.description\n record.parentId = before.parentId\n record.rootId = before.rootId\n record.treePath = before.treePath\n record.depth = before.depth\n record.ancestorIds = before.ancestorIds\n record.childIds = before.childIds\n record.descendantIds = before.descendantIds\n }\n await em.flush()\n await rebuildCategoryHierarchyForOrganization(em, before.organizationId, before.tenantId)\n if (before.custom && Object.keys(before.custom).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_category,\n recordId: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n values: before.custom,\n })\n }\n },\n}\n\nregisterCommand(createCategoryCommand)\nregisterCommand(updateCategoryCommand)\nregisterCommand(deleteCategoryCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { buildChanges, requireId, parseWithCustomFields, setCustomFieldsIfAny, emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { loadCustomFieldSnapshot, buildCustomFieldResetMap } from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CatalogProductCategory } from '../data/entities'\nimport {\n categoryCreateSchema,\n categoryUpdateSchema,\n type CategoryCreateInput,\n type CategoryUpdateInput,\n} from '../data/validators'\nimport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload } from './shared'\nimport { rebuildCategoryHierarchyForOrganization } from '../lib/categoryHierarchy'\nimport type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { E } from '#generated/entities.ids.generated'\n\nconst categoryCrudEvents: CrudEventsConfig = {\n module: 'catalog',\n entity: 'category',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\ntype CategorySnapshot = {\n id: string\n organizationId: string\n tenantId: string\n name: string\n slug: string | null\n description: string | null\n parentId: string | null\n rootId: string | null\n treePath: string | null\n depth: number\n ancestorIds: string[]\n childIds: string[]\n descendantIds: string[]\n isActive: boolean\n createdAt: string\n updatedAt: string\n custom?: Record<string, unknown> | null\n}\n\ntype CategoryUndoPayload = {\n before?: CategorySnapshot | null\n after?: CategorySnapshot | null\n}\n\nconst CATEGORY_CHANGE_KEYS = [\n 'name',\n 'slug',\n 'description',\n 'parentId',\n 'rootId',\n 'treePath',\n 'isActive',\n] as const satisfies readonly string[]\n\nasync function loadCategorySnapshot(em: EntityManager, id: string): Promise<CategorySnapshot | null> {\n const record = await em.findOne(CatalogProductCategory, { id })\n if (!record) return null\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.catalog.catalog_product_category,\n recordId: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n return {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n name: record.name,\n slug: record.slug ?? null,\n description: record.description ?? null,\n parentId: record.parentId ?? null,\n rootId: record.rootId ?? null,\n treePath: record.treePath ?? null,\n depth: record.depth ?? 0,\n ancestorIds: Array.isArray(record.ancestorIds) ? [...record.ancestorIds] : [],\n childIds: Array.isArray(record.childIds) ? [...record.childIds] : [],\n descendantIds: Array.isArray(record.descendantIds) ? [...record.descendantIds] : [],\n isActive: !!record.isActive,\n createdAt: record.createdAt.toISOString(),\n updatedAt: record.updatedAt.toISOString(),\n custom: custom && Object.keys(custom).length ? custom : null,\n }\n}\n\nasync function assertParentScope(\n em: EntityManager,\n parentId: string | null,\n organizationId: string,\n tenantId: string\n): Promise<string | null> {\n if (!parentId) return null\n const parent = await em.findOne(CatalogProductCategory, {\n id: parentId,\n organizationId,\n tenantId,\n deletedAt: null,\n })\n if (!parent) {\n throw new CrudHttpError(400, { error: 'Parent category not found or inaccessible.' })\n }\n if (parent.id === parentId) return parent.id\n return String(parent.id)\n}\n\nfunction normalizeSlug(slug?: string | null): string | null {\n if (typeof slug !== 'string') return null\n const trimmed = slug.trim().toLowerCase()\n return trimmed.length ? trimmed : null\n}\n\nconst createCategoryCommand: CommandHandler<CategoryCreateInput, { categoryId: string }> = {\n id: 'catalog.categories.create',\n async execute(input, ctx) {\n const { parsed, custom } = parseWithCustomFields(categoryCreateSchema, input)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const slug = normalizeSlug(parsed.slug ?? null)\n if (slug) {\n const conflict = await em.findOne(CatalogProductCategory, {\n slug,\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n deletedAt: null,\n })\n if (conflict) {\n throw new CrudHttpError(400, { error: 'Category slug already exists for this organization.' })\n }\n }\n const parentId = parsed.parentId ? String(parsed.parentId) : null\n const resolvedParent = await assertParentScope(em, parentId, parsed.organizationId, parsed.tenantId)\n\n const now = new Date()\n const record = em.create(CatalogProductCategory, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n name: parsed.name,\n slug,\n description: parsed.description?.trim()?.length ? parsed.description.trim() : null,\n parentId: resolvedParent,\n depth: 0,\n ancestorIds: [],\n childIds: [],\n descendantIds: [],\n isActive: parsed.isActive !== false,\n createdAt: now,\n updatedAt: now,\n })\n em.persist(record)\n await withAtomicFlush(\n em,\n [\n () => em.flush(),\n async () => {\n await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)\n },\n ],\n { transaction: true }\n )\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_category,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n })\n const de = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n events: categoryCrudEvents,\n })\n return { categoryId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadCategorySnapshot(em, result.categoryId)\n },\n buildLog: async ({ snapshots }) => {\n const after = snapshots.after as CategorySnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.categories.create', 'Create catalog category'),\n resourceKind: 'catalog.category',\n resourceId: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies CategoryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CategoryUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogProductCategory, { id: after.id })\n if (!record) return\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n record.deletedAt = new Date()\n record.isActive = false\n await withAtomicFlush(\n em,\n [\n () => em.flush(),\n async () => {\n await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)\n },\n ],\n { transaction: true }\n )\n const resetValues = buildCustomFieldResetMap(undefined, after.custom ?? undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_category,\n recordId: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n values: resetValues,\n })\n }\n },\n}\n\nconst updateCategoryCommand: CommandHandler<CategoryUpdateInput, { categoryId: string }> = {\n id: 'catalog.categories.update',\n async prepare(input, ctx) {\n const id = requireId(input, 'Category id is required')\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadCategorySnapshot(em, id)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const { parsed, custom } = parseWithCustomFields(categoryUpdateSchema, input)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogProductCategory, { id: parsed.id, deletedAt: null })\n if (!record) throw new CrudHttpError(404, { error: 'Catalog category not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n\n if (parsed.name !== undefined) {\n record.name = parsed.name\n }\n\n if (parsed.slug !== undefined) {\n const slug = normalizeSlug(parsed.slug ?? null)\n if (slug !== record.slug) {\n if (slug) {\n const conflict = await em.findOne(CatalogProductCategory, {\n slug,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n deletedAt: null,\n id: { $ne: record.id },\n })\n if (conflict) {\n throw new CrudHttpError(400, { error: 'Category slug already exists.' })\n }\n }\n record.slug = slug\n }\n }\n\n if (parsed.description !== undefined) {\n record.description = parsed.description?.trim()?.length ? parsed.description.trim() : null\n }\n\n if (parsed.parentId !== undefined) {\n const requestedParent = parsed.parentId ? String(parsed.parentId) : null\n const safeParent = requestedParent && requestedParent !== record.id ? requestedParent : null\n record.parentId = await assertParentScope(em, safeParent, record.organizationId, record.tenantId)\n }\n\n if (parsed.isActive !== undefined) {\n record.isActive = parsed.isActive\n }\n\n await withAtomicFlush(\n em,\n [\n () => em.flush(),\n async () => {\n await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)\n },\n ],\n { transaction: true }\n )\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_category,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n })\n const de = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n events: categoryCrudEvents,\n })\n return { categoryId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadCategorySnapshot(em, result.categoryId)\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as CategorySnapshot | undefined\n const after = snapshots.after as CategorySnapshot | undefined\n if (!before || !after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.categories.update', 'Update catalog category'),\n resourceKind: 'catalog.category',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(before as Record<string, unknown>, after as Record<string, unknown>, CATEGORY_CHANGE_KEYS),\n payload: {\n undo: { before, after } satisfies CategoryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CategoryUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let record = await em.findOne(CatalogProductCategory, { id: before.id })\n if (!record) {\n record = em.create(CatalogProductCategory, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n name: before.name,\n slug: before.slug,\n description: before.description,\n parentId: before.parentId,\n rootId: before.rootId,\n treePath: before.treePath,\n depth: before.depth,\n ancestorIds: before.ancestorIds,\n childIds: before.childIds,\n descendantIds: before.descendantIds,\n isActive: before.isActive,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(record)\n } else {\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n record.name = before.name\n record.slug = before.slug\n record.description = before.description\n record.parentId = before.parentId\n record.rootId = before.rootId\n record.treePath = before.treePath\n record.depth = before.depth\n record.ancestorIds = before.ancestorIds\n record.childIds = before.childIds\n record.descendantIds = before.descendantIds\n record.isActive = before.isActive\n record.deletedAt = null\n }\n await withAtomicFlush(\n em,\n [\n () => em.flush(),\n async () => {\n await rebuildCategoryHierarchyForOrganization(em, before.organizationId, before.tenantId)\n },\n ],\n { transaction: true }\n )\n const resetValues = buildCustomFieldResetMap(payload?.after?.custom ?? undefined, before.custom ?? undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_category,\n recordId: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n values: resetValues,\n })\n }\n },\n}\n\nconst deleteCategoryCommand: CommandHandler<{ id?: string }, { categoryId: string }> = {\n id: 'catalog.categories.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Category id is required')\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadCategorySnapshot(em, id)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Category id is required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogProductCategory, { id, deletedAt: null })\n if (!record) throw new CrudHttpError(404, { error: 'Catalog category not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n const baseEm = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadCategorySnapshot(baseEm, id)\n\n record.deletedAt = new Date()\n record.isActive = false\n await withAtomicFlush(\n em,\n [\n () => em.flush(),\n async () => {\n await rebuildCategoryHierarchyForOrganization(em, record.organizationId, record.tenantId)\n },\n ],\n { transaction: true }\n )\n if (snapshot?.custom && Object.keys(snapshot.custom).length) {\n const resetValues = buildCustomFieldResetMap(snapshot.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_category,\n recordId: snapshot.id,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n values: resetValues,\n })\n }\n }\n const de = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n events: categoryCrudEvents,\n })\n return { categoryId: record.id }\n },\n buildLog: async ({ ctx, snapshots }) => {\n const before = snapshots.before as CategorySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.categories.delete', 'Delete catalog category'),\n resourceKind: 'catalog.category',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies CategoryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CategoryUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let record = await em.findOne(CatalogProductCategory, { id: before.id })\n if (!record) {\n record = em.create(CatalogProductCategory, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n name: before.name,\n slug: before.slug,\n description: before.description,\n parentId: before.parentId,\n rootId: before.rootId,\n treePath: before.treePath,\n depth: before.depth,\n ancestorIds: before.ancestorIds,\n childIds: before.childIds,\n descendantIds: before.descendantIds,\n isActive: before.isActive,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(record)\n } else {\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n record.deletedAt = null\n record.isActive = before.isActive\n record.name = before.name\n record.slug = before.slug\n record.description = before.description\n record.parentId = before.parentId\n record.rootId = before.rootId\n record.treePath = before.treePath\n record.depth = before.depth\n record.ancestorIds = before.ancestorIds\n record.childIds = before.childIds\n record.descendantIds = before.descendantIds\n }\n await withAtomicFlush(\n em,\n [\n () => em.flush(),\n async () => {\n await rebuildCategoryHierarchyForOrganization(em, before.organizationId, before.tenantId)\n },\n ],\n { transaction: true }\n )\n if (before.custom && Object.keys(before.custom).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_product_category,\n recordId: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n values: before.custom,\n })\n }\n },\n}\n\nregisterCommand(createCategoryCommand)\nregisterCommand(updateCategoryCommand)\nregisterCommand(deleteCategoryCommand)\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }