@open-mercato/core 0.4.2-canary-bdaa640a68 → 0.4.2-canary-3b5064ce72

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 (497) hide show
  1. package/dist/generated/entities/notification/index.js +57 -0
  2. package/dist/generated/entities/notification/index.js.map +7 -0
  3. package/dist/generated/entities.ids.generated.js +5 -1
  4. package/dist/generated/entities.ids.generated.js.map +2 -2
  5. package/dist/generated/entity-fields-registry.js +2 -0
  6. package/dist/generated/entity-fields-registry.js.map +2 -2
  7. package/dist/modules/api_docs/frontend/docs/api/page.js +3 -2
  8. package/dist/modules/api_docs/frontend/docs/api/page.js.map +2 -2
  9. package/dist/modules/api_keys/backend/api-keys/page.js +1 -1
  10. package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
  11. package/dist/modules/attachments/components/AttachmentLibrary.js +4 -0
  12. package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
  13. package/dist/modules/attachments/components/AttachmentPartitionSettings.js +2 -0
  14. package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
  15. package/dist/modules/auth/api/admin/nav.js +4 -3
  16. package/dist/modules/auth/api/admin/nav.js.map +2 -2
  17. package/dist/modules/auth/api/login.js +25 -6
  18. package/dist/modules/auth/api/login.js.map +2 -2
  19. package/dist/modules/auth/api/profile/route.js +157 -0
  20. package/dist/modules/auth/api/profile/route.js.map +7 -0
  21. package/dist/modules/auth/api/reset/confirm.js +25 -2
  22. package/dist/modules/auth/api/reset/confirm.js.map +2 -2
  23. package/dist/modules/auth/api/reset.js +23 -0
  24. package/dist/modules/auth/api/reset.js.map +2 -2
  25. package/dist/modules/auth/api/sidebar/preferences/route.js +14 -9
  26. package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
  27. package/dist/modules/auth/api/users/route.js +4 -2
  28. package/dist/modules/auth/api/users/route.js.map +2 -2
  29. package/dist/modules/auth/backend/auth/profile/page.js +141 -0
  30. package/dist/modules/auth/backend/auth/profile/page.js.map +7 -0
  31. package/dist/modules/auth/backend/auth/profile/page.meta.js +13 -0
  32. package/dist/modules/auth/backend/auth/profile/page.meta.js.map +7 -0
  33. package/dist/modules/auth/backend/roles/[id]/edit/page.js +4 -1
  34. package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
  35. package/dist/modules/auth/backend/roles/page.js +3 -3
  36. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  37. package/dist/modules/auth/backend/users/[id]/edit/page.js +18 -3
  38. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  39. package/dist/modules/auth/backend/users/create/page.js +15 -2
  40. package/dist/modules/auth/backend/users/create/page.js.map +2 -2
  41. package/dist/modules/auth/backend/users/page.js +3 -3
  42. package/dist/modules/auth/backend/users/page.js.map +2 -2
  43. package/dist/modules/auth/cli.js +25 -11
  44. package/dist/modules/auth/cli.js.map +2 -2
  45. package/dist/modules/auth/commands/users.js +59 -2
  46. package/dist/modules/auth/commands/users.js.map +2 -2
  47. package/dist/modules/auth/data/validators.js +6 -3
  48. package/dist/modules/auth/data/validators.js.map +2 -2
  49. package/dist/modules/auth/frontend/login.js +112 -3
  50. package/dist/modules/auth/frontend/login.js.map +2 -2
  51. package/dist/modules/auth/frontend/reset/[token]/page.js +20 -10
  52. package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
  53. package/dist/modules/auth/lib/setup-app.js +42 -8
  54. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  55. package/dist/modules/auth/notifications.js +112 -0
  56. package/dist/modules/auth/notifications.js.map +7 -0
  57. package/dist/modules/auth/services/authService.js +24 -3
  58. package/dist/modules/auth/services/authService.js.map +2 -2
  59. package/dist/modules/business_rules/api/execute/route.js +7 -1
  60. package/dist/modules/business_rules/api/execute/route.js.map +2 -2
  61. package/dist/modules/business_rules/backend/rules/page.js +4 -0
  62. package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
  63. package/dist/modules/business_rules/backend/sets/page.js +3 -0
  64. package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
  65. package/dist/modules/business_rules/cli.js +2 -1
  66. package/dist/modules/business_rules/cli.js.map +2 -2
  67. package/dist/modules/business_rules/lib/rule-engine.js +33 -3
  68. package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
  69. package/dist/modules/business_rules/notifications.js +28 -0
  70. package/dist/modules/business_rules/notifications.js.map +7 -0
  71. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +37 -0
  72. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +7 -0
  73. package/dist/modules/catalog/components/PriceKindSettings.js +2 -0
  74. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  75. package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -2
  76. package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
  77. package/dist/modules/catalog/components/products/ProductsDataTable.js +2 -0
  78. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  79. package/dist/modules/catalog/notifications.js +28 -0
  80. package/dist/modules/catalog/notifications.js.map +7 -0
  81. package/dist/modules/catalog/subscribers/low-stock-notification.js +38 -0
  82. package/dist/modules/catalog/subscribers/low-stock-notification.js.map +7 -0
  83. package/dist/modules/configs/cli.js +6 -0
  84. package/dist/modules/configs/cli.js.map +2 -2
  85. package/dist/modules/configs/components/CachePanel.js +4 -4
  86. package/dist/modules/configs/components/CachePanel.js.map +2 -2
  87. package/dist/modules/configs/lib/system-status.js +48 -1
  88. package/dist/modules/configs/lib/system-status.js.map +2 -2
  89. package/dist/modules/configs/lib/upgrade-actions.js +18 -0
  90. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  91. package/dist/modules/currencies/backend/currencies/page.js +3 -0
  92. package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
  93. package/dist/modules/currencies/backend/exchange-rates/page.js +2 -0
  94. package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
  95. package/dist/modules/customers/backend/customers/companies/page.js +3 -0
  96. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  97. package/dist/modules/customers/backend/customers/deals/page.js +3 -0
  98. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  99. package/dist/modules/customers/backend/customers/people/page.js +3 -0
  100. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  101. package/dist/modules/customers/commands/deals.js +31 -0
  102. package/dist/modules/customers/commands/deals.js.map +2 -2
  103. package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
  104. package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
  105. package/dist/modules/customers/notifications.js +48 -0
  106. package/dist/modules/customers/notifications.js.map +7 -0
  107. package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js +2 -1
  108. package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js.map +2 -2
  109. package/dist/modules/customers/widgets/dashboard/new-customers/widget.js +2 -1
  110. package/dist/modules/customers/widgets/dashboard/new-customers/widget.js.map +2 -2
  111. package/dist/modules/customers/widgets/dashboard/new-deals/widget.js +2 -1
  112. package/dist/modules/customers/widgets/dashboard/new-deals/widget.js.map +2 -2
  113. package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js +2 -1
  114. package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js.map +2 -2
  115. package/dist/modules/dashboards/cli.js +44 -5
  116. package/dist/modules/dashboards/cli.js.map +2 -2
  117. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +16 -11
  118. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +3 -3
  119. package/dist/modules/dashboards/lib/role-widgets.js +58 -0
  120. package/dist/modules/dashboards/lib/role-widgets.js.map +7 -0
  121. package/dist/modules/dashboards/services/widgetDataService.js +139 -3
  122. package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
  123. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js +2 -1
  124. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js.map +2 -2
  125. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js +2 -1
  126. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js.map +2 -2
  127. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js +2 -1
  128. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js.map +2 -2
  129. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js +2 -1
  130. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js.map +2 -2
  131. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js +2 -1
  132. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js.map +2 -2
  133. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js +2 -1
  134. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js.map +2 -2
  135. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js +2 -1
  136. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js.map +2 -2
  137. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js +2 -1
  138. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js.map +2 -2
  139. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js +2 -1
  140. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js.map +2 -2
  141. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js +2 -1
  142. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js.map +2 -2
  143. package/dist/modules/dictionaries/components/DictionaryTable.js +2 -0
  144. package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
  145. package/dist/modules/directory/api/get/tenants/lookup.js +70 -0
  146. package/dist/modules/directory/api/get/tenants/lookup.js.map +7 -0
  147. package/dist/modules/directory/backend/directory/organizations/page.js +2 -2
  148. package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
  149. package/dist/modules/directory/backend/directory/tenants/page.js +2 -2
  150. package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
  151. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +2 -2
  152. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  153. package/dist/modules/entities/components/SystemEntitiesTable.js +1 -1
  154. package/dist/modules/entities/components/SystemEntitiesTable.js.map +2 -2
  155. package/dist/modules/entities/components/UserEntitiesTable.js +2 -2
  156. package/dist/modules/entities/components/UserEntitiesTable.js.map +2 -2
  157. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +3 -3
  158. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
  159. package/dist/modules/feature_toggles/components/OverridesTable.js +1 -1
  160. package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
  161. package/dist/modules/notifications/acl.js +11 -0
  162. package/dist/modules/notifications/acl.js.map +7 -0
  163. package/dist/modules/notifications/api/[id]/action/route.js +74 -0
  164. package/dist/modules/notifications/api/[id]/action/route.js.map +7 -0
  165. package/dist/modules/notifications/api/[id]/dismiss/route.js +15 -0
  166. package/dist/modules/notifications/api/[id]/dismiss/route.js.map +7 -0
  167. package/dist/modules/notifications/api/[id]/read/route.js +15 -0
  168. package/dist/modules/notifications/api/[id]/read/route.js.map +7 -0
  169. package/dist/modules/notifications/api/[id]/restore/route.js +53 -0
  170. package/dist/modules/notifications/api/[id]/restore/route.js.map +7 -0
  171. package/dist/modules/notifications/api/batch/route.js +17 -0
  172. package/dist/modules/notifications/api/batch/route.js.map +7 -0
  173. package/dist/modules/notifications/api/feature/route.js +17 -0
  174. package/dist/modules/notifications/api/feature/route.js.map +7 -0
  175. package/dist/modules/notifications/api/mark-all-read/route.js +35 -0
  176. package/dist/modules/notifications/api/mark-all-read/route.js.map +7 -0
  177. package/dist/modules/notifications/api/openapi.js +76 -0
  178. package/dist/modules/notifications/api/openapi.js.map +7 -0
  179. package/dist/modules/notifications/api/role/route.js +17 -0
  180. package/dist/modules/notifications/api/role/route.js.map +7 -0
  181. package/dist/modules/notifications/api/route.js +85 -0
  182. package/dist/modules/notifications/api/route.js.map +7 -0
  183. package/dist/modules/notifications/api/settings/route.js +155 -0
  184. package/dist/modules/notifications/api/settings/route.js.map +7 -0
  185. package/dist/modules/notifications/api/unread-count/route.js +38 -0
  186. package/dist/modules/notifications/api/unread-count/route.js.map +7 -0
  187. package/dist/modules/notifications/backend/config/notifications/page.js +10 -0
  188. package/dist/modules/notifications/backend/config/notifications/page.js.map +7 -0
  189. package/dist/modules/notifications/backend/config/notifications/page.meta.js +24 -0
  190. package/dist/modules/notifications/backend/config/notifications/page.meta.js.map +7 -0
  191. package/dist/modules/notifications/cli.js +16 -0
  192. package/dist/modules/notifications/cli.js.map +7 -0
  193. package/dist/modules/notifications/data/entities.js +112 -0
  194. package/dist/modules/notifications/data/entities.js.map +7 -0
  195. package/dist/modules/notifications/data/validators.js +98 -0
  196. package/dist/modules/notifications/data/validators.js.map +7 -0
  197. package/dist/modules/notifications/di.js +13 -0
  198. package/dist/modules/notifications/di.js.map +7 -0
  199. package/dist/modules/notifications/emails/NotificationEmail.js +58 -0
  200. package/dist/modules/notifications/emails/NotificationEmail.js.map +7 -0
  201. package/dist/modules/notifications/frontend/NotificationInboxPageClient.js +44 -0
  202. package/dist/modules/notifications/frontend/NotificationInboxPageClient.js.map +7 -0
  203. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +220 -0
  204. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +7 -0
  205. package/dist/modules/notifications/index.js +14 -0
  206. package/dist/modules/notifications/index.js.map +7 -0
  207. package/dist/modules/notifications/lib/deliveryConfig.js +107 -0
  208. package/dist/modules/notifications/lib/deliveryConfig.js.map +7 -0
  209. package/dist/modules/notifications/lib/deliveryStrategies.js +14 -0
  210. package/dist/modules/notifications/lib/deliveryStrategies.js.map +7 -0
  211. package/dist/modules/notifications/lib/events.js +12 -0
  212. package/dist/modules/notifications/lib/events.js.map +7 -0
  213. package/dist/modules/notifications/lib/notificationBuilder.js +66 -0
  214. package/dist/modules/notifications/lib/notificationBuilder.js.map +7 -0
  215. package/dist/modules/notifications/lib/notificationFactory.js +54 -0
  216. package/dist/modules/notifications/lib/notificationFactory.js.map +7 -0
  217. package/dist/modules/notifications/lib/notificationMapper.js +34 -0
  218. package/dist/modules/notifications/lib/notificationMapper.js.map +7 -0
  219. package/dist/modules/notifications/lib/notificationRecipients.js +35 -0
  220. package/dist/modules/notifications/lib/notificationRecipients.js.map +7 -0
  221. package/dist/modules/notifications/lib/notificationService.js +279 -0
  222. package/dist/modules/notifications/lib/notificationService.js.map +7 -0
  223. package/dist/modules/notifications/lib/routeHelpers.js +101 -0
  224. package/dist/modules/notifications/lib/routeHelpers.js.map +7 -0
  225. package/dist/modules/notifications/lib/safeHref.js +24 -0
  226. package/dist/modules/notifications/lib/safeHref.js.map +7 -0
  227. package/dist/modules/notifications/migrations/Migration20260123000001.js +70 -0
  228. package/dist/modules/notifications/migrations/Migration20260123000001.js.map +7 -0
  229. package/dist/modules/notifications/migrations/Migration20260126150000.js +37 -0
  230. package/dist/modules/notifications/migrations/Migration20260126150000.js.map +7 -0
  231. package/dist/modules/notifications/migrations/Migration20260129082610.js +13 -0
  232. package/dist/modules/notifications/migrations/Migration20260129082610.js.map +7 -0
  233. package/dist/modules/notifications/subscribers/deliver-notification.js +165 -0
  234. package/dist/modules/notifications/subscribers/deliver-notification.js.map +7 -0
  235. package/dist/modules/notifications/workers/create-notification.worker.js +70 -0
  236. package/dist/modules/notifications/workers/create-notification.worker.js.map +7 -0
  237. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +2 -2
  238. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  239. package/dist/modules/query_index/cli.js +63 -7
  240. package/dist/modules/query_index/cli.js.map +2 -2
  241. package/dist/modules/query_index/components/QueryIndexesTable.js +7 -1
  242. package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
  243. package/dist/modules/resources/backend/resources/resource-types/page.js +2 -2
  244. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  245. package/dist/modules/resources/backend/resources/resources/page.js +2 -2
  246. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  247. package/dist/modules/sales/backend/sales/channels/offers/page.js +2 -0
  248. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  249. package/dist/modules/sales/backend/sales/channels/page.js +2 -0
  250. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  251. package/dist/modules/sales/commands/documents.js +53 -0
  252. package/dist/modules/sales/commands/documents.js.map +2 -2
  253. package/dist/modules/sales/commands/payments.js +26 -0
  254. package/dist/modules/sales/commands/payments.js.map +2 -2
  255. package/dist/modules/sales/components/AdjustmentKindSettings.js +2 -2
  256. package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
  257. package/dist/modules/sales/components/PaymentMethodsSettings.js +2 -2
  258. package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
  259. package/dist/modules/sales/components/ShippingMethodsSettings.js +2 -2
  260. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
  261. package/dist/modules/sales/components/TaxRatesSettings.js +2 -2
  262. package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
  263. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +2 -0
  264. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  265. package/dist/modules/sales/components/documents/AdjustmentsSection.js +2 -0
  266. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  267. package/dist/modules/sales/components/documents/PaymentsSection.js +2 -1
  268. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  269. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +2 -0
  270. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  271. package/dist/modules/sales/notifications.client.js +51 -0
  272. package/dist/modules/sales/notifications.client.js.map +7 -0
  273. package/dist/modules/sales/notifications.js +88 -0
  274. package/dist/modules/sales/notifications.js.map +7 -0
  275. package/dist/modules/sales/subscribers/quote-expiring-notification.js +38 -0
  276. package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +7 -0
  277. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +137 -0
  278. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +7 -0
  279. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +137 -0
  280. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +7 -0
  281. package/dist/modules/sales/widgets/notifications/index.js +7 -0
  282. package/dist/modules/sales/widgets/notifications/index.js.map +7 -0
  283. package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js +60 -0
  284. package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js.map +7 -0
  285. package/dist/modules/staff/backend/staff/team-members/page.js +1 -1
  286. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  287. package/dist/modules/staff/backend/staff/team-roles/page.js +2 -2
  288. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  289. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +2 -2
  290. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  291. package/dist/modules/staff/backend/staff/teams/page.js +2 -2
  292. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  293. package/dist/modules/staff/commands/leave-requests.js +79 -0
  294. package/dist/modules/staff/commands/leave-requests.js.map +2 -2
  295. package/dist/modules/staff/notifications.js +75 -0
  296. package/dist/modules/staff/notifications.js.map +7 -0
  297. package/dist/modules/workflows/backend/definitions/page.js +5 -0
  298. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  299. package/dist/modules/workflows/backend/instances/page.js +3 -0
  300. package/dist/modules/workflows/backend/instances/page.js.map +2 -2
  301. package/dist/modules/workflows/backend/tasks/page.js +3 -0
  302. package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
  303. package/dist/modules/workflows/cli.js +12 -12
  304. package/dist/modules/workflows/cli.js.map +2 -2
  305. package/dist/modules/workflows/lib/transition-handler.js +14 -6
  306. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  307. package/dist/modules/workflows/notifications.js +28 -0
  308. package/dist/modules/workflows/notifications.js.map +7 -0
  309. package/dist/modules/workflows/subscribers/task-assigned-notification.js +38 -0
  310. package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +7 -0
  311. package/generated/entities/notification/index.ts +27 -0
  312. package/generated/entities.ids.generated.ts +5 -1
  313. package/generated/entity-fields-registry.ts +2 -0
  314. package/package.json +2 -2
  315. package/src/modules/api_docs/frontend/docs/api/page.tsx +3 -2
  316. package/src/modules/api_keys/backend/api-keys/page.tsx +1 -1
  317. package/src/modules/attachments/components/AttachmentLibrary.tsx +4 -0
  318. package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +2 -0
  319. package/src/modules/auth/README.md +1 -1
  320. package/src/modules/auth/__tests__/cli-setup-acl.test.ts +1 -1
  321. package/src/modules/auth/api/__tests__/login.test.ts +2 -0
  322. package/src/modules/auth/api/admin/nav.ts +10 -6
  323. package/src/modules/auth/api/login.ts +26 -7
  324. package/src/modules/auth/api/profile/route.ts +163 -0
  325. package/src/modules/auth/api/reset/confirm.ts +25 -2
  326. package/src/modules/auth/api/reset.ts +23 -0
  327. package/src/modules/auth/api/sidebar/preferences/route.ts +21 -12
  328. package/src/modules/auth/api/users/route.ts +5 -2
  329. package/src/modules/auth/backend/auth/profile/page.meta.ts +9 -0
  330. package/src/modules/auth/backend/auth/profile/page.tsx +174 -0
  331. package/src/modules/auth/backend/roles/[id]/edit/page.tsx +4 -1
  332. package/src/modules/auth/backend/roles/page.tsx +3 -3
  333. package/src/modules/auth/backend/users/[id]/edit/page.tsx +22 -3
  334. package/src/modules/auth/backend/users/create/page.tsx +19 -2
  335. package/src/modules/auth/backend/users/page.tsx +3 -3
  336. package/src/modules/auth/cli.ts +38 -11
  337. package/src/modules/auth/commands/users.ts +73 -2
  338. package/src/modules/auth/data/validators.ts +6 -2
  339. package/src/modules/auth/frontend/login.tsx +134 -5
  340. package/src/modules/auth/frontend/reset/[token]/page.tsx +24 -11
  341. package/src/modules/auth/i18n/de.json +48 -1
  342. package/src/modules/auth/i18n/en.json +48 -1
  343. package/src/modules/auth/i18n/es.json +48 -1
  344. package/src/modules/auth/i18n/pl.json +48 -1
  345. package/src/modules/auth/lib/setup-app.ts +58 -9
  346. package/src/modules/auth/notifications.ts +109 -0
  347. package/src/modules/auth/services/authService.ts +27 -4
  348. package/src/modules/business_rules/api/execute/route.ts +8 -1
  349. package/src/modules/business_rules/backend/rules/page.tsx +4 -0
  350. package/src/modules/business_rules/backend/sets/page.tsx +3 -0
  351. package/src/modules/business_rules/cli.ts +2 -1
  352. package/src/modules/business_rules/i18n/en.json +3 -1
  353. package/src/modules/business_rules/lib/__tests__/rule-engine.test.ts +51 -0
  354. package/src/modules/business_rules/lib/rule-engine.ts +57 -3
  355. package/src/modules/business_rules/notifications.ts +25 -0
  356. package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +50 -0
  357. package/src/modules/catalog/components/PriceKindSettings.tsx +2 -0
  358. package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +2 -2
  359. package/src/modules/catalog/components/products/ProductsDataTable.tsx +2 -0
  360. package/src/modules/catalog/i18n/en.json +3 -1
  361. package/src/modules/catalog/notifications.ts +25 -0
  362. package/src/modules/catalog/subscribers/low-stock-notification.ts +52 -0
  363. package/src/modules/configs/cli.ts +6 -0
  364. package/src/modules/configs/components/CachePanel.tsx +4 -4
  365. package/src/modules/configs/i18n/en.json +12 -2
  366. package/src/modules/configs/i18n/pl.json +12 -2
  367. package/src/modules/configs/lib/system-status.ts +48 -1
  368. package/src/modules/configs/lib/system-status.types.ts +1 -0
  369. package/src/modules/configs/lib/upgrade-actions.ts +18 -0
  370. package/src/modules/currencies/backend/currencies/page.tsx +3 -0
  371. package/src/modules/currencies/backend/exchange-rates/page.tsx +2 -0
  372. package/src/modules/customers/backend/customers/companies/page.tsx +3 -0
  373. package/src/modules/customers/backend/customers/deals/page.tsx +3 -0
  374. package/src/modules/customers/backend/customers/people/page.tsx +3 -0
  375. package/src/modules/customers/commands/deals.ts +39 -0
  376. package/src/modules/customers/components/CustomerTodosTable.tsx +1 -0
  377. package/src/modules/customers/i18n/en.json +5 -1
  378. package/src/modules/customers/notifications.ts +44 -0
  379. package/src/modules/customers/widgets/dashboard/customer-todos/widget.ts +2 -2
  380. package/src/modules/customers/widgets/dashboard/new-customers/widget.ts +2 -2
  381. package/src/modules/customers/widgets/dashboard/new-deals/widget.ts +2 -2
  382. package/src/modules/customers/widgets/dashboard/next-interactions/widget.ts +2 -2
  383. package/src/modules/dashboards/cli.ts +55 -5
  384. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +22 -11
  385. package/src/modules/dashboards/lib/role-widgets.ts +80 -0
  386. package/src/modules/dashboards/services/widgetDataService.ts +164 -4
  387. package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.ts +2 -2
  388. package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.ts +2 -2
  389. package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.ts +2 -2
  390. package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.ts +2 -2
  391. package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.ts +2 -2
  392. package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.ts +2 -2
  393. package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.ts +2 -2
  394. package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.ts +2 -2
  395. package/src/modules/dashboards/widgets/dashboard/top-customers/widget.ts +2 -2
  396. package/src/modules/dashboards/widgets/dashboard/top-products/widget.ts +2 -2
  397. package/src/modules/dictionaries/components/DictionaryTable.tsx +2 -0
  398. package/src/modules/directory/api/get/tenants/lookup.ts +75 -0
  399. package/src/modules/directory/backend/directory/organizations/page.tsx +2 -2
  400. package/src/modules/directory/backend/directory/tenants/page.tsx +2 -2
  401. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +2 -2
  402. package/src/modules/entities/components/SystemEntitiesTable.tsx +1 -1
  403. package/src/modules/entities/components/UserEntitiesTable.tsx +2 -2
  404. package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +3 -4
  405. package/src/modules/feature_toggles/components/OverridesTable.tsx +1 -1
  406. package/src/modules/notifications/__tests__/deliver-notification.test.ts +195 -0
  407. package/src/modules/notifications/__tests__/deliveryStrategies.test.ts +19 -0
  408. package/src/modules/notifications/__tests__/notificationService.test.ts +208 -0
  409. package/src/modules/notifications/acl.ts +7 -0
  410. package/src/modules/notifications/api/[id]/action/route.ts +75 -0
  411. package/src/modules/notifications/api/[id]/dismiss/route.ts +12 -0
  412. package/src/modules/notifications/api/[id]/read/route.ts +12 -0
  413. package/src/modules/notifications/api/[id]/restore/route.ts +53 -0
  414. package/src/modules/notifications/api/batch/route.ts +14 -0
  415. package/src/modules/notifications/api/feature/route.ts +14 -0
  416. package/src/modules/notifications/api/mark-all-read/route.ts +34 -0
  417. package/src/modules/notifications/api/openapi.ts +76 -0
  418. package/src/modules/notifications/api/role/route.ts +14 -0
  419. package/src/modules/notifications/api/route.ts +92 -0
  420. package/src/modules/notifications/api/settings/route.ts +157 -0
  421. package/src/modules/notifications/api/unread-count/route.ts +38 -0
  422. package/src/modules/notifications/backend/config/notifications/page.meta.ts +22 -0
  423. package/src/modules/notifications/backend/config/notifications/page.tsx +12 -0
  424. package/src/modules/notifications/cli.ts +18 -0
  425. package/src/modules/notifications/data/entities.ts +99 -0
  426. package/src/modules/notifications/data/validators.ts +115 -0
  427. package/src/modules/notifications/di.ts +11 -0
  428. package/src/modules/notifications/emails/NotificationEmail.tsx +98 -0
  429. package/src/modules/notifications/frontend/NotificationInboxPageClient.tsx +42 -0
  430. package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +233 -0
  431. package/src/modules/notifications/i18n/de.json +50 -0
  432. package/src/modules/notifications/i18n/en.json +50 -0
  433. package/src/modules/notifications/i18n/es.json +50 -0
  434. package/src/modules/notifications/i18n/pl.json +50 -0
  435. package/src/modules/notifications/index.ts +12 -0
  436. package/src/modules/notifications/lib/deliveryConfig.ts +153 -0
  437. package/src/modules/notifications/lib/deliveryStrategies.ts +50 -0
  438. package/src/modules/notifications/lib/events.ts +48 -0
  439. package/src/modules/notifications/lib/notificationBuilder.ts +121 -0
  440. package/src/modules/notifications/lib/notificationFactory.ts +76 -0
  441. package/src/modules/notifications/lib/notificationMapper.ts +33 -0
  442. package/src/modules/notifications/lib/notificationRecipients.ts +83 -0
  443. package/src/modules/notifications/lib/notificationService.ts +414 -0
  444. package/src/modules/notifications/lib/routeHelpers.ts +151 -0
  445. package/src/modules/notifications/lib/safeHref.ts +29 -0
  446. package/src/modules/notifications/migrations/.snapshot-open-mercato.json +336 -0
  447. package/src/modules/notifications/migrations/Migration20260123000001.ts +73 -0
  448. package/src/modules/notifications/migrations/Migration20260126150000.ts +39 -0
  449. package/src/modules/notifications/migrations/Migration20260129082610.ts +13 -0
  450. package/src/modules/notifications/subscribers/deliver-notification.ts +204 -0
  451. package/src/modules/notifications/workers/create-notification.worker.ts +122 -0
  452. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +2 -2
  453. package/src/modules/query_index/cli.ts +82 -13
  454. package/src/modules/query_index/components/QueryIndexesTable.tsx +8 -2
  455. package/src/modules/resources/backend/resources/resource-types/page.tsx +2 -2
  456. package/src/modules/resources/backend/resources/resources/page.tsx +2 -2
  457. package/src/modules/sales/backend/sales/channels/offers/page.tsx +2 -0
  458. package/src/modules/sales/backend/sales/channels/page.tsx +2 -0
  459. package/src/modules/sales/commands/documents.ts +65 -0
  460. package/src/modules/sales/commands/payments.ts +33 -0
  461. package/src/modules/sales/components/AdjustmentKindSettings.tsx +2 -2
  462. package/src/modules/sales/components/PaymentMethodsSettings.tsx +2 -2
  463. package/src/modules/sales/components/ShippingMethodsSettings.tsx +2 -2
  464. package/src/modules/sales/components/TaxRatesSettings.tsx +2 -2
  465. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +2 -0
  466. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +2 -0
  467. package/src/modules/sales/components/documents/PaymentsSection.tsx +2 -1
  468. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +2 -0
  469. package/src/modules/sales/i18n/de.json +20 -0
  470. package/src/modules/sales/i18n/en.json +25 -1
  471. package/src/modules/sales/i18n/es.json +20 -0
  472. package/src/modules/sales/i18n/pl.json +20 -0
  473. package/src/modules/sales/notifications.client.ts +65 -0
  474. package/src/modules/sales/notifications.ts +82 -0
  475. package/src/modules/sales/subscribers/quote-expiring-notification.ts +53 -0
  476. package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +156 -0
  477. package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +156 -0
  478. package/src/modules/sales/widgets/notifications/index.ts +2 -0
  479. package/src/modules/sales/widgets/notifications/useSalesDocumentTotals.ts +81 -0
  480. package/src/modules/staff/backend/staff/team-members/page.tsx +1 -1
  481. package/src/modules/staff/backend/staff/team-roles/page.tsx +2 -2
  482. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +2 -2
  483. package/src/modules/staff/backend/staff/teams/page.tsx +2 -2
  484. package/src/modules/staff/commands/leave-requests.ts +94 -0
  485. package/src/modules/staff/i18n/de.json +4 -0
  486. package/src/modules/staff/i18n/en.json +9 -1
  487. package/src/modules/staff/i18n/es.json +4 -0
  488. package/src/modules/staff/i18n/pl.json +4 -0
  489. package/src/modules/staff/notifications.ts +71 -0
  490. package/src/modules/workflows/backend/definitions/page.tsx +5 -0
  491. package/src/modules/workflows/backend/instances/page.tsx +4 -1
  492. package/src/modules/workflows/backend/tasks/page.tsx +4 -1
  493. package/src/modules/workflows/cli.ts +12 -12
  494. package/src/modules/workflows/i18n/en.json +3 -1
  495. package/src/modules/workflows/lib/transition-handler.ts +18 -6
  496. package/src/modules/workflows/notifications.ts +25 -0
  497. package/src/modules/workflows/subscribers/task-assigned-notification.ts +53 -0
@@ -0,0 +1,122 @@
1
+ import type { EntityManager } from '@mikro-orm/core'
2
+ import type { Knex } from 'knex'
3
+ import { Notification } from '../data/entities'
4
+ import type { CreateNotificationInput, CreateRoleNotificationInput, CreateFeatureNotificationInput } from '../data/validators'
5
+ import { buildNotificationEntity, emitNotificationCreated, emitNotificationCreatedBatch } from '../lib/notificationFactory'
6
+ import { getRecipientUserIdsForFeature, getRecipientUserIdsForRole } from '../lib/notificationRecipients'
7
+
8
+ function getKnex(em: EntityManager): Knex {
9
+ return (em.getConnection() as unknown as { getKnex: () => Knex }).getKnex()
10
+ }
11
+
12
+ export const NOTIFICATIONS_QUEUE_NAME = 'notifications'
13
+
14
+ export type CreateNotificationJob = {
15
+ type: 'create'
16
+ input: CreateNotificationInput
17
+ tenantId: string
18
+ organizationId?: string | null
19
+ }
20
+
21
+ export type CreateRoleNotificationJob = {
22
+ type: 'create-role'
23
+ input: CreateRoleNotificationInput
24
+ tenantId: string
25
+ organizationId?: string | null
26
+ }
27
+
28
+ export type CreateFeatureNotificationJob = {
29
+ type: 'create-feature'
30
+ input: CreateFeatureNotificationInput
31
+ tenantId: string
32
+ organizationId?: string | null
33
+ }
34
+
35
+ export type CleanupExpiredJob = {
36
+ type: 'cleanup-expired'
37
+ }
38
+
39
+ export type NotificationJob = CreateNotificationJob | CreateRoleNotificationJob | CreateFeatureNotificationJob | CleanupExpiredJob
40
+
41
+ export const metadata = {
42
+ queue: NOTIFICATIONS_QUEUE_NAME,
43
+ id: 'notifications:create',
44
+ concurrency: 5,
45
+ }
46
+
47
+ type HandlerContext = {
48
+ resolve: <T = unknown>(name: string) => T
49
+ }
50
+
51
+ export default async function handle(
52
+ job: { payload: NotificationJob },
53
+ ctx: HandlerContext
54
+ ): Promise<void> {
55
+ const { payload } = job
56
+
57
+ if (payload.type === 'create') {
58
+ const em = (ctx.resolve('em') as EntityManager).fork()
59
+ const eventBus = ctx.resolve('eventBus') as { emit: (event: string, payload: unknown) => Promise<void> }
60
+ const { input, tenantId, organizationId } = payload
61
+ const { recipientUserId, ...content } = input
62
+ const notification = buildNotificationEntity(em, content, recipientUserId, { tenantId, organizationId })
63
+
64
+ await em.persistAndFlush(notification)
65
+
66
+ await emitNotificationCreated(eventBus, notification, { tenantId, organizationId })
67
+ } else if (payload.type === 'create-role') {
68
+ const em = (ctx.resolve('em') as EntityManager).fork()
69
+ const eventBus = ctx.resolve('eventBus') as { emit: (event: string, payload: unknown) => Promise<void> }
70
+ const { input, tenantId, organizationId } = payload
71
+
72
+ const knex = getKnex(em)
73
+ const recipientUserIds = await getRecipientUserIdsForRole(knex, tenantId, input.roleId)
74
+ if (recipientUserIds.length === 0) {
75
+ return
76
+ }
77
+
78
+ const { roleId: _roleId, ...content } = input
79
+ const notifications: Notification[] = []
80
+ for (const recipientUserId of recipientUserIds) {
81
+ const notification = buildNotificationEntity(em, content, recipientUserId, { tenantId, organizationId })
82
+ notifications.push(notification)
83
+ }
84
+
85
+ await em.persistAndFlush(notifications)
86
+
87
+ await emitNotificationCreatedBatch(eventBus, notifications, { tenantId, organizationId })
88
+ } else if (payload.type === 'create-feature') {
89
+ const em = (ctx.resolve('em') as EntityManager).fork()
90
+ const eventBus = ctx.resolve('eventBus') as { emit: (event: string, payload: unknown) => Promise<void> }
91
+ const { input, tenantId, organizationId } = payload
92
+
93
+ const knex = getKnex(em)
94
+ const recipientUserIds = await getRecipientUserIdsForFeature(knex, tenantId, input.requiredFeature)
95
+
96
+ if (recipientUserIds.length === 0) {
97
+ return
98
+ }
99
+
100
+ const notifications: Notification[] = []
101
+ const { requiredFeature: _requiredFeature, ...content } = input
102
+ for (const recipientUserId of recipientUserIds) {
103
+ const notification = buildNotificationEntity(em, content, recipientUserId, { tenantId, organizationId })
104
+ notifications.push(notification)
105
+ }
106
+
107
+ await em.persistAndFlush(notifications)
108
+
109
+ await emitNotificationCreatedBatch(eventBus, notifications, { tenantId, organizationId })
110
+ } else if (payload.type === 'cleanup-expired') {
111
+ const em = (ctx.resolve('em') as EntityManager).fork()
112
+ const knex = getKnex(em)
113
+
114
+ await knex('notifications')
115
+ .where('expires_at', '<', knex.fn.now())
116
+ .whereNotIn('status', ['actioned', 'dismissed'])
117
+ .update({
118
+ status: 'dismissed',
119
+ dismissed_at: knex.fn.now(),
120
+ })
121
+ }
122
+ }
@@ -202,8 +202,8 @@ export default function PlannerAvailabilityRuleSetsPage() {
202
202
  rowActions={(row) => (
203
203
  <RowActions
204
204
  items={[
205
- { label: labels.actions.edit, href: `/backend/planner/availability-rulesets/${row.id}` },
206
- { label: labels.actions.delete, destructive: true, onSelect: () => { void handleDelete(row) } },
205
+ { id: 'edit', label: labels.actions.edit, href: `/backend/planner/availability-rulesets/${row.id}` },
206
+ { id: 'delete', label: labels.actions.delete, destructive: true, onSelect: () => { void handleDelete(row) } },
207
207
  ]}
208
208
  />
209
209
  )}
@@ -22,6 +22,50 @@ import type { VectorIndexService } from '@open-mercato/search/vector'
22
22
 
23
23
  type ParsedArgs = Record<string, string | boolean>
24
24
 
25
+ type PartitionProgressInfo = { processed: number; total: number }
26
+
27
+ function isIndexerVerbose(): boolean {
28
+ const parsed = parseBooleanToken(process.env.OM_INDEXER_VERBOSE ?? '')
29
+ return parsed === true
30
+ }
31
+
32
+ function createGroupedProgress(label: string, partitionTargets: number[]) {
33
+ const totals = new Map<number, number>()
34
+ const processed = new Map<number, number>()
35
+ let bar: ProgressBarHandle | null = null
36
+
37
+ const getTotals = () => {
38
+ let total = 0
39
+ let done = 0
40
+ for (const value of totals.values()) total += value
41
+ for (const value of processed.values()) done += value
42
+ return { total, done }
43
+ }
44
+
45
+ const tryInitBar = () => {
46
+ if (bar) return
47
+ if (totals.size < partitionTargets.length) return
48
+ const { total } = getTotals()
49
+ if (total <= 0) return
50
+ bar = createProgressBar(label, total) as ProgressBarHandle
51
+ }
52
+
53
+ return {
54
+ onProgress(partition: number, info: PartitionProgressInfo) {
55
+ processed.set(partition, info.processed)
56
+ if (!totals.has(partition)) totals.set(partition, info.total)
57
+ tryInitBar()
58
+ if (!bar) return
59
+ const { done } = getTotals()
60
+ bar.update(done)
61
+ },
62
+ complete() {
63
+ if (bar) bar.complete()
64
+ },
65
+ getTotals,
66
+ }
67
+ }
68
+
25
69
  function parseArgs(rest: string[]): ParsedArgs {
26
70
  const args: ParsedArgs = {}
27
71
  for (let i = 0; i < rest.length; i += 1) {
@@ -550,8 +594,14 @@ const reindex: ModuleCli = {
550
594
  await purgeIndexScope(baseEm, { entityType: entity, organizationId: orgId, tenantId })
551
595
  }
552
596
  console.log(`Reindexing ${entity}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`)
553
- const progressState = new Map<number, { last: number }>()
554
- const renderProgress = (part: number, entityId: string, info: { processed: number; total: number }) => {
597
+ const verbose = isIndexerVerbose()
598
+ const progressState = verbose ? new Map<number, { last: number }>() : null
599
+ const groupedProgress =
600
+ !verbose && partitionTargets.length > 1
601
+ ? createGroupedProgress(`Reindexing ${entity}`, partitionTargets)
602
+ : null
603
+ const renderProgress = (part: number, entityId: string, info: PartitionProgressInfo) => {
604
+ if (!progressState) return
555
605
  const state = progressState.get(part) ?? { last: 0 }
556
606
  const now = Date.now()
557
607
  if (now - state.last < 1000 && info.processed < info.total) return
@@ -568,7 +618,7 @@ const reindex: ModuleCli = {
568
618
  const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''
569
619
  if (partitionTargets.length === 1) {
570
620
  console.log(` -> processing${label}`)
571
- } else if (idx === 0) {
621
+ } else if (verbose && idx === 0) {
572
622
  console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)
573
623
  }
574
624
  const partitionContainer = await createRequestContainer()
@@ -596,9 +646,14 @@ const reindex: ModuleCli = {
596
646
  onProgress(info) {
597
647
  if (useBar) {
598
648
  if (info.total > 0 && !progressBar) {
599
- progressBar = createProgressBar(`Reindexing ${entity}${label}`, info.total) as ProgressBarHandle
649
+ progressBar = createProgressBar(
650
+ `Reindexing ${entity}${label}`,
651
+ info.total,
652
+ ) as ProgressBarHandle
600
653
  }
601
654
  progressBar?.update(info.processed)
655
+ } else if (groupedProgress) {
656
+ groupedProgress.onProgress(part, info)
602
657
  } else {
603
658
  renderProgress(part, entity, info)
604
659
  }
@@ -607,7 +662,9 @@ const reindex: ModuleCli = {
607
662
  if (progressBar) {
608
663
  (progressBar as ProgressBarHandle).complete()
609
664
  }
610
- if (!useBar) {
665
+ if (!useBar && groupedProgress) {
666
+ groupedProgress.onProgress(part, { processed: partitionStats.processed, total: partitionStats.total })
667
+ } else if (!useBar) {
611
668
  renderProgress(part, entity, { processed: partitionStats.processed, total: partitionStats.total })
612
669
  } else {
613
670
  console.log(
@@ -622,6 +679,7 @@ const reindex: ModuleCli = {
622
679
  }
623
680
  }),
624
681
  )
682
+ groupedProgress?.complete()
625
683
  const totalProcessed = stats.reduce((acc, value) => acc + value, 0)
626
684
  console.log(`Finished ${entity}: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)
627
685
  await recordIndexerLog(
@@ -677,8 +735,14 @@ const reindex: ModuleCli = {
677
735
  console.log(
678
736
  `[${idx + 1}/${entityIds.length}] Reindexing ${id}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`,
679
737
  )
680
- const progressState = new Map<number, { last: number }>()
681
- const renderProgress = (part: number, entityId: string, info: { processed: number; total: number }) => {
738
+ const verbose = isIndexerVerbose()
739
+ const progressState = verbose ? new Map<number, { last: number }>() : null
740
+ const groupedProgress =
741
+ !verbose && partitionTargets.length > 1
742
+ ? createGroupedProgress(`Reindexing ${id}`, partitionTargets)
743
+ : null
744
+ const renderProgress = (part: number, entityId: string, info: PartitionProgressInfo) => {
745
+ if (!progressState) return
682
746
  const state = progressState.get(part) ?? { last: 0 }
683
747
  const now = Date.now()
684
748
  if (now - state.last < 1000 && info.processed < info.total) return
@@ -695,7 +759,7 @@ const reindex: ModuleCli = {
695
759
  const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''
696
760
  if (partitionTargets.length === 1) {
697
761
  console.log(` -> processing${label}`)
698
- } else if (partitionIdx === 0) {
762
+ } else if (verbose && partitionIdx === 0) {
699
763
  console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)
700
764
  }
701
765
  const partitionContainer = await createRequestContainer()
@@ -723,18 +787,22 @@ const reindex: ModuleCli = {
723
787
  onProgress(info) {
724
788
  if (useBar) {
725
789
  if (info.total > 0 && !progressBar) {
726
- progressBar = createProgressBar(`Reindexing ${id}${label}`, info.total) as ProgressBarHandle
790
+ progressBar = createProgressBar(`Reindexing ${id}${label}`, info.total) as ProgressBarHandle
727
791
  }
728
792
  progressBar?.update(info.processed)
793
+ } else if (groupedProgress) {
794
+ groupedProgress.onProgress(part, info)
729
795
  } else {
730
796
  renderProgress(part, id, info)
731
797
  }
732
798
  },
733
799
  })
734
- if (progressBar) {
735
- (progressBar as ProgressBarHandle).complete()
736
- }
737
- if (!useBar) {
800
+ if (progressBar) {
801
+ (progressBar as ProgressBarHandle).complete()
802
+ }
803
+ if (!useBar && groupedProgress) {
804
+ groupedProgress.onProgress(part, { processed: result.processed, total: result.total })
805
+ } else if (!useBar) {
738
806
  renderProgress(part, id, { processed: result.processed, total: result.total })
739
807
  } else {
740
808
  console.log(
@@ -749,6 +817,7 @@ const reindex: ModuleCli = {
749
817
  }
750
818
  }),
751
819
  )
820
+ groupedProgress?.complete()
752
821
  const totalProcessed = partitionResults.reduce((acc, value) => acc + value, 0)
753
822
  console.log(` -> ${id} complete: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)
754
823
  await recordIndexerLog(
@@ -366,13 +366,15 @@ export default function QueryIndexesTable() {
366
366
  onSortingChange={setSorting}
367
367
  perspective={{ tableId: 'query_index.status.list' }}
368
368
  rowActions={(row) => {
369
- const items: Array<{ label: string; onSelect: () => void; destructive?: boolean }> = [
370
- { label: t('query_index.table.actions.reindex'), onSelect: () => trigger('reindex', row.entityId) },
369
+ const items: Array<{ id: string; label: string; onSelect: () => void; destructive?: boolean }> = [
370
+ { id: 'reindex', label: t('query_index.table.actions.reindex'), onSelect: () => trigger('reindex', row.entityId) },
371
371
  {
372
+ id: 'reindex-force',
372
373
  label: t('query_index.table.actions.reindexForce'),
373
374
  onSelect: () => trigger('reindex', row.entityId, { force: true }),
374
375
  },
375
376
  {
377
+ id: 'purge',
376
378
  label: t('query_index.table.actions.purge'),
377
379
  destructive: true,
378
380
  onSelect: () => trigger('purge', row.entityId),
@@ -382,10 +384,12 @@ export default function QueryIndexesTable() {
382
384
  if (row.vectorEnabled) {
383
385
  items.push(
384
386
  {
387
+ id: 'vector-reindex',
385
388
  label: t('query_index.table.actions.vectorReindex'),
386
389
  onSelect: () => triggerVector('reindex', row.entityId),
387
390
  },
388
391
  {
392
+ id: 'vector-purge',
389
393
  label: t('query_index.table.actions.vectorPurge'),
390
394
  destructive: true,
391
395
  onSelect: () => triggerVector('purge', row.entityId),
@@ -396,10 +400,12 @@ export default function QueryIndexesTable() {
396
400
  if (row.fulltextEnabled) {
397
401
  items.push(
398
402
  {
403
+ id: 'fulltext-reindex',
399
404
  label: t('query_index.table.actions.fulltextReindex'),
400
405
  onSelect: () => triggerFulltext('reindex', row.entityId),
401
406
  },
402
407
  {
408
+ id: 'fulltext-purge',
403
409
  label: t('query_index.table.actions.fulltextPurge'),
404
410
  destructive: true,
405
411
  onSelect: () => triggerFulltext('purge', row.entityId),
@@ -266,10 +266,10 @@ export default function ResourcesResourceTypesPage() {
266
266
  rowActions={(row) => (
267
267
  <RowActions
268
268
  items={[
269
- { label: translations.actions.edit, href: `/backend/resources/resource-types/${row.id}/edit` },
269
+ { id: 'edit', label: translations.actions.edit, href: `/backend/resources/resource-types/${row.id}/edit` },
270
270
  ...(row.resourceCount > 0
271
271
  ? []
272
- : [{ label: translations.actions.delete, destructive: true, onSelect: () => handleDelete(row) }]),
272
+ : [{ id: 'delete', label: translations.actions.delete, destructive: true, onSelect: () => handleDelete(row) }]),
273
273
  ]}
274
274
  />
275
275
  )}
@@ -481,8 +481,8 @@ export default function ResourcesResourcesPage() {
481
481
  if (!canManage || row.rowKind !== 'resource') return null
482
482
  return (
483
483
  <RowActions items={[
484
- { label: t('common.edit', 'Edit'), href: `/backend/resources/resources/${encodeURIComponent(row.id)}` },
485
- { label: t('common.delete', 'Delete'), destructive: true, onSelect: () => { void handleDelete(row) } },
484
+ { id: 'edit', label: t('common.edit', 'Edit'), href: `/backend/resources/resources/${encodeURIComponent(row.id)}` },
485
+ { id: 'delete', label: t('common.delete', 'Delete'), destructive: true, onSelect: () => { void handleDelete(row) } },
486
486
  ]} />
487
487
  )
488
488
  }}
@@ -334,10 +334,12 @@ export default function SalesChannelOffersListPage() {
334
334
  <RowActions
335
335
  items={[
336
336
  {
337
+ id: 'edit',
337
338
  label: t('sales.channels.offers.actions.edit', 'Edit'),
338
339
  href: `/backend/sales/channels/${row.channelId}/offers/${row.id}/edit`,
339
340
  },
340
341
  {
342
+ id: 'delete',
341
343
  label: t('sales.channels.offers.actions.delete', 'Delete'),
342
344
  onSelect: () => handleDelete(row),
343
345
  destructive: true,
@@ -191,10 +191,12 @@ export default function SalesChannelsPage() {
191
191
  <RowActions
192
192
  items={[
193
193
  {
194
+ id: 'edit',
194
195
  label: t('sales.channels.table.actions.edit', 'Edit'),
195
196
  href: `/backend/sales/channels/${row.id}/edit`,
196
197
  },
197
198
  {
199
+ id: 'delete',
198
200
  label: t('sales.channels.table.actions.delete', 'Delete'),
199
201
  onSelect: () => handleDelete(row),
200
202
  },
@@ -11,6 +11,8 @@ import type { DataEngine } from '@open-mercato/shared/lib/data/engine'
11
11
  import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
12
12
  import { deriveResourceFromCommandId, invalidateCrudCache } from '@open-mercato/shared/lib/crud/cache'
13
13
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
14
+ import { resolveNotificationService } from '../../notifications/lib/notificationService'
15
+ import { buildFeatureNotificationFromType } from '../../notifications/lib/notificationBuilder'
14
16
  import { setRecordCustomFields } from '@open-mercato/core/modules/entities/lib/helpers'
15
17
  import { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'
16
18
  import { normalizeCustomFieldValues } from '@open-mercato/shared/lib/custom-fields/normalize'
@@ -88,6 +90,7 @@ import { resolveDictionaryEntryValue } from '../lib/dictionaries'
88
90
  import { resolveStatusEntryIdByValue } from '../lib/statusHelpers'
89
91
  import { SalesDocumentNumberGenerator } from '../services/salesDocumentNumberGenerator'
90
92
  import { loadSalesSettings } from './settings'
93
+ import { notificationTypes } from '../notifications'
91
94
 
92
95
  type DocumentAddressSnapshot = {
93
96
  id: string
@@ -3111,6 +3114,37 @@ const createQuoteCommand: CommandHandler<QuoteCreateInput, { quoteId: string }>
3111
3114
  })
3112
3115
  await em.flush()
3113
3116
 
3117
+ // Create notification for users with sales.quotes.manage feature
3118
+ try {
3119
+ const notificationService = resolveNotificationService(ctx.container)
3120
+ const typeDef = notificationTypes.find((type) => type.type === 'sales.quote.created')
3121
+ if (typeDef) {
3122
+ const totalAmount = quote.grandTotalGrossAmount && quote.currencyCode
3123
+ ? `${quote.grandTotalGrossAmount} ${quote.currencyCode}`
3124
+ : ''
3125
+ const totalDisplay = totalAmount ? ` (${totalAmount})` : ''
3126
+ const notificationInput = buildFeatureNotificationFromType(typeDef, {
3127
+ requiredFeature: 'sales.quotes.manage',
3128
+ bodyVariables: {
3129
+ quoteNumber: quote.quoteNumber,
3130
+ total: totalDisplay,
3131
+ totalAmount,
3132
+ },
3133
+ sourceEntityType: 'sales:quote',
3134
+ sourceEntityId: quote.id,
3135
+ linkHref: `/backend/sales/quotes/${quote.id}`,
3136
+ })
3137
+
3138
+ await notificationService.createForFeature(notificationInput, {
3139
+ tenantId: quote.tenantId,
3140
+ organizationId: quote.organizationId ?? null,
3141
+ })
3142
+ }
3143
+ } catch (err) {
3144
+ // Notification creation is non-critical, don't fail the command
3145
+ console.error('[sales.quotes.create] Failed to create notification:', err)
3146
+ }
3147
+
3114
3148
  return { quoteId: quote.id }
3115
3149
  },
3116
3150
  captureAfter: async (_input, result, ctx) => {
@@ -3782,6 +3816,37 @@ const createOrderCommand: CommandHandler<OrderCreateInput, { orderId: string }>
3782
3816
  })
3783
3817
  await em.flush()
3784
3818
 
3819
+ // Create notification for users with sales.orders.manage feature
3820
+ try {
3821
+ const notificationService = resolveNotificationService(ctx.container)
3822
+ const typeDef = notificationTypes.find((type) => type.type === 'sales.order.created')
3823
+ if (typeDef) {
3824
+ const totalAmount = order.grandTotalGrossAmount && order.currencyCode
3825
+ ? `${order.grandTotalGrossAmount} ${order.currencyCode}`
3826
+ : ''
3827
+ const totalDisplay = totalAmount ? ` (${totalAmount})` : ''
3828
+ const notificationInput = buildFeatureNotificationFromType(typeDef, {
3829
+ requiredFeature: 'sales.orders.manage',
3830
+ bodyVariables: {
3831
+ orderNumber: order.orderNumber,
3832
+ total: totalDisplay,
3833
+ totalAmount,
3834
+ },
3835
+ sourceEntityType: 'sales:order',
3836
+ sourceEntityId: order.id,
3837
+ linkHref: `/backend/sales/orders/${order.id}`,
3838
+ })
3839
+
3840
+ await notificationService.createForFeature(notificationInput, {
3841
+ tenantId: order.tenantId,
3842
+ organizationId: order.organizationId ?? null,
3843
+ })
3844
+ }
3845
+ } catch (err) {
3846
+ // Notification creation is non-critical, don't fail the command
3847
+ console.error('[sales.orders.create] Failed to create notification:', err)
3848
+ }
3849
+
3785
3850
  return { orderId: order.id }
3786
3851
  },
3787
3852
  captureAfter: async (_input, result, ctx) => {
@@ -35,6 +35,9 @@ import { invalidateCrudCache } from '@open-mercato/shared/lib/crud/cache'
35
35
  import { emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'
36
36
  import type { DataEngine } from '@open-mercato/shared/lib/data/engine'
37
37
  import { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
38
+ import { resolveNotificationService } from '../../notifications/lib/notificationService'
39
+ import { buildFeatureNotificationFromType } from '../../notifications/lib/notificationBuilder'
40
+ import { notificationTypes } from '../notifications'
38
41
 
39
42
  export type PaymentAllocationSnapshot = {
40
43
  id: string
@@ -422,6 +425,36 @@ const createPaymentCommand: CommandHandler<
422
425
  const totals = await recomputeOrderPaymentTotals(em, order)
423
426
  await em.flush()
424
427
  await invalidateOrderCache(ctx.container, order, ctx.auth?.tenantId ?? null)
428
+
429
+ // Create notification for payment received
430
+ try {
431
+ const notificationService = resolveNotificationService(ctx.container)
432
+ const typeDef = notificationTypes.find((type) => type.type === 'sales.payment.received')
433
+ if (typeDef) {
434
+ const amountDisplay = payment.amount && payment.currencyCode
435
+ ? `${payment.currencyCode} ${payment.amount}`
436
+ : ''
437
+ const notificationInput = buildFeatureNotificationFromType(typeDef, {
438
+ requiredFeature: 'sales.orders.manage',
439
+ bodyVariables: {
440
+ orderNumber: order.orderNumber ?? '',
441
+ amount: amountDisplay,
442
+ },
443
+ sourceEntityType: 'sales:order',
444
+ sourceEntityId: order.id,
445
+ linkHref: `/backend/sales/orders/${order.id}`,
446
+ })
447
+
448
+ await notificationService.createForFeature(notificationInput, {
449
+ tenantId: payment.tenantId,
450
+ organizationId: payment.organizationId ?? null,
451
+ })
452
+ }
453
+ } catch (err) {
454
+ // Notification creation is non-critical, don't fail the command
455
+ console.error('[sales.payments.create] Failed to create notification:', err)
456
+ }
457
+
425
458
  return { paymentId: payment.id, orderTotals: totals }
426
459
  },
427
460
  captureAfter: async (_input, result, ctx) => {
@@ -333,8 +333,8 @@ export function AdjustmentKindSettings() {
333
333
  rowActions={(entry) => (
334
334
  <RowActions
335
335
  items={[
336
- { label: labels.edit, onSelect: () => openDialog({ mode: 'edit', entry }) },
337
- { label: labels.delete, destructive: true, onSelect: () => { void handleDelete(entry) } },
336
+ { id: 'edit', label: labels.edit, onSelect: () => openDialog({ mode: 'edit', entry }) },
337
+ { id: 'delete', label: labels.delete, destructive: true, onSelect: () => { void handleDelete(entry) } },
338
338
  ]}
339
339
  />
340
340
  )}
@@ -526,8 +526,8 @@ export function PaymentMethodsSettings() {
526
526
  rowActions={(row) => (
527
527
  <RowActions
528
528
  items={[
529
- { label: translations.actions.edit, onSelect: () => openEdit(row) },
530
- { label: translations.actions.delete, destructive: true, onSelect: () => deleteEntry(row) },
529
+ { id: 'edit', label: translations.actions.edit, onSelect: () => openEdit(row) },
530
+ { id: 'delete', label: translations.actions.delete, destructive: true, onSelect: () => deleteEntry(row) },
531
531
  ]}
532
532
  />
533
533
  )}
@@ -820,8 +820,8 @@ export function ShippingMethodsSettings() {
820
820
  rowActions={(row) => (
821
821
  <RowActions
822
822
  items={[
823
- { label: translations.actions.edit, onSelect: () => openEdit(row) },
824
- { label: translations.actions.delete, destructive: true, onSelect: () => deleteEntry(row) },
823
+ { id: 'edit', label: translations.actions.edit, onSelect: () => openEdit(row) },
824
+ { id: 'delete', label: translations.actions.delete, destructive: true, onSelect: () => deleteEntry(row) },
825
825
  ]}
826
826
  />
827
827
  )}
@@ -335,8 +335,8 @@ export function TaxRatesSettings() {
335
335
  rowActions={(row) => (
336
336
  <RowActions
337
337
  items={[
338
- { label: translations.actions.edit, onSelect: () => openEdit(row) },
339
- { label: translations.actions.delete, destructive: true, onSelect: () => deleteEntry(row) },
338
+ { id: 'edit', label: translations.actions.edit, onSelect: () => openEdit(row) },
339
+ { id: 'delete', label: translations.actions.delete, destructive: true, onSelect: () => deleteEntry(row) },
340
340
  ]}
341
341
  />
342
342
  )}
@@ -185,10 +185,12 @@ export function SalesChannelOffersPanel({ channelId, channelName }: { channelId:
185
185
  <RowActions
186
186
  items={[
187
187
  {
188
+ id: 'edit',
188
189
  label: t('sales.channels.offers.actions.edit', 'Edit'),
189
190
  href: `/backend/sales/channels/${channelId}/offers/${row.id}/edit`,
190
191
  },
191
192
  {
193
+ id: 'delete',
192
194
  label: t('sales.channels.offers.actions.delete', 'Delete'),
193
195
  onSelect: () => handleDelete(row),
194
196
  destructive: true,
@@ -427,10 +427,12 @@ export function SalesDocumentAdjustmentsSection({
427
427
  <RowActions
428
428
  items={[
429
429
  {
430
+ id: 'edit',
430
431
  label: t('ui.actions.edit', 'Edit'),
431
432
  onSelect: () => handleEdit(row),
432
433
  },
433
434
  {
435
+ id: 'delete',
434
436
  label: t('ui.actions.delete', 'Delete'),
435
437
  destructive: true,
436
438
  onSelect: () => handleDelete(row),
@@ -295,8 +295,9 @@ export function SalesDocumentPaymentsSection({
295
295
  return (
296
296
  <RowActions
297
297
  items={[
298
- { label: editActionLabel, onSelect: () => openEditPayment(row.original) },
298
+ { id: 'edit', label: editActionLabel, onSelect: () => openEditPayment(row.original) },
299
299
  {
300
+ id: 'delete',
300
301
  label: deleteActionLabel,
301
302
  destructive: true,
302
303
  onSelect: () => void handleDelete(row.original),
@@ -699,10 +699,12 @@ export function SalesDocumentsTable({ kind }: { kind: SalesDocumentKind }) {
699
699
  <RowActions
700
700
  items={[
701
701
  {
702
+ id: 'open',
702
703
  label: t('sales.documents.list.table.open', 'Open'),
703
704
  href: `/backend/sales/${resource}/${row.id}?kind=${kind}`,
704
705
  },
705
706
  {
707
+ id: 'delete',
706
708
  label:
707
709
  kind === 'order'
708
710
  ? t('sales.documents.list.table.deleteOrder', 'Delete order')