@open-mercato/core 0.4.2-canary-e6bf6a353e → 0.4.2-canary-c84cff7ed5

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 (397) 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/profile/route.js +157 -0
  18. package/dist/modules/auth/api/profile/route.js.map +7 -0
  19. package/dist/modules/auth/api/reset/confirm.js +25 -2
  20. package/dist/modules/auth/api/reset/confirm.js.map +2 -2
  21. package/dist/modules/auth/api/reset.js +23 -0
  22. package/dist/modules/auth/api/reset.js.map +2 -2
  23. package/dist/modules/auth/api/sidebar/preferences/route.js +14 -9
  24. package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
  25. package/dist/modules/auth/api/users/route.js +4 -2
  26. package/dist/modules/auth/api/users/route.js.map +2 -2
  27. package/dist/modules/auth/backend/auth/profile/page.js +141 -0
  28. package/dist/modules/auth/backend/auth/profile/page.js.map +7 -0
  29. package/dist/modules/auth/backend/auth/profile/page.meta.js +13 -0
  30. package/dist/modules/auth/backend/auth/profile/page.meta.js.map +7 -0
  31. package/dist/modules/auth/backend/roles/page.js +3 -3
  32. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  33. package/dist/modules/auth/backend/users/[id]/edit/page.js +14 -2
  34. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  35. package/dist/modules/auth/backend/users/create/page.js +15 -2
  36. package/dist/modules/auth/backend/users/create/page.js.map +2 -2
  37. package/dist/modules/auth/backend/users/page.js +3 -3
  38. package/dist/modules/auth/backend/users/page.js.map +2 -2
  39. package/dist/modules/auth/cli.js +13 -0
  40. package/dist/modules/auth/cli.js.map +2 -2
  41. package/dist/modules/auth/commands/users.js +59 -2
  42. package/dist/modules/auth/commands/users.js.map +2 -2
  43. package/dist/modules/auth/data/validators.js +4 -2
  44. package/dist/modules/auth/data/validators.js.map +2 -2
  45. package/dist/modules/auth/frontend/reset/[token]/page.js +20 -10
  46. package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
  47. package/dist/modules/auth/lib/setup-app.js +1 -0
  48. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  49. package/dist/modules/auth/notifications.js +112 -0
  50. package/dist/modules/auth/notifications.js.map +7 -0
  51. package/dist/modules/auth/services/authService.js +3 -3
  52. package/dist/modules/auth/services/authService.js.map +2 -2
  53. package/dist/modules/business_rules/backend/rules/page.js +4 -0
  54. package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
  55. package/dist/modules/business_rules/backend/sets/page.js +3 -0
  56. package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
  57. package/dist/modules/business_rules/notifications.js +28 -0
  58. package/dist/modules/business_rules/notifications.js.map +7 -0
  59. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +37 -0
  60. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +7 -0
  61. package/dist/modules/catalog/components/PriceKindSettings.js +2 -0
  62. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  63. package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -2
  64. package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
  65. package/dist/modules/catalog/components/products/ProductsDataTable.js +2 -0
  66. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  67. package/dist/modules/catalog/notifications.js +28 -0
  68. package/dist/modules/catalog/notifications.js.map +7 -0
  69. package/dist/modules/catalog/subscribers/low-stock-notification.js +38 -0
  70. package/dist/modules/catalog/subscribers/low-stock-notification.js.map +7 -0
  71. package/dist/modules/configs/cli.js +6 -0
  72. package/dist/modules/configs/cli.js.map +2 -2
  73. package/dist/modules/configs/lib/upgrade-actions.js +18 -0
  74. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  75. package/dist/modules/currencies/backend/currencies/page.js +3 -0
  76. package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
  77. package/dist/modules/currencies/backend/exchange-rates/page.js +2 -0
  78. package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
  79. package/dist/modules/customers/backend/customers/companies/page.js +3 -0
  80. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  81. package/dist/modules/customers/backend/customers/deals/page.js +3 -0
  82. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  83. package/dist/modules/customers/backend/customers/people/page.js +3 -0
  84. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  85. package/dist/modules/customers/commands/deals.js +31 -0
  86. package/dist/modules/customers/commands/deals.js.map +2 -2
  87. package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
  88. package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
  89. package/dist/modules/customers/notifications.js +48 -0
  90. package/dist/modules/customers/notifications.js.map +7 -0
  91. package/dist/modules/dashboards/cli.js +32 -1
  92. package/dist/modules/dashboards/cli.js.map +2 -2
  93. package/dist/modules/dashboards/lib/role-widgets.js +58 -0
  94. package/dist/modules/dashboards/lib/role-widgets.js.map +7 -0
  95. package/dist/modules/dictionaries/components/DictionaryTable.js +2 -0
  96. package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
  97. package/dist/modules/directory/backend/directory/organizations/page.js +2 -2
  98. package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
  99. package/dist/modules/directory/backend/directory/tenants/page.js +2 -2
  100. package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
  101. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +2 -2
  102. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  103. package/dist/modules/entities/components/SystemEntitiesTable.js +1 -1
  104. package/dist/modules/entities/components/SystemEntitiesTable.js.map +2 -2
  105. package/dist/modules/entities/components/UserEntitiesTable.js +2 -2
  106. package/dist/modules/entities/components/UserEntitiesTable.js.map +2 -2
  107. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +3 -3
  108. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
  109. package/dist/modules/feature_toggles/components/OverridesTable.js +1 -1
  110. package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
  111. package/dist/modules/notifications/acl.js +11 -0
  112. package/dist/modules/notifications/acl.js.map +7 -0
  113. package/dist/modules/notifications/api/[id]/action/route.js +74 -0
  114. package/dist/modules/notifications/api/[id]/action/route.js.map +7 -0
  115. package/dist/modules/notifications/api/[id]/dismiss/route.js +15 -0
  116. package/dist/modules/notifications/api/[id]/dismiss/route.js.map +7 -0
  117. package/dist/modules/notifications/api/[id]/read/route.js +15 -0
  118. package/dist/modules/notifications/api/[id]/read/route.js.map +7 -0
  119. package/dist/modules/notifications/api/[id]/restore/route.js +53 -0
  120. package/dist/modules/notifications/api/[id]/restore/route.js.map +7 -0
  121. package/dist/modules/notifications/api/batch/route.js +17 -0
  122. package/dist/modules/notifications/api/batch/route.js.map +7 -0
  123. package/dist/modules/notifications/api/feature/route.js +17 -0
  124. package/dist/modules/notifications/api/feature/route.js.map +7 -0
  125. package/dist/modules/notifications/api/mark-all-read/route.js +35 -0
  126. package/dist/modules/notifications/api/mark-all-read/route.js.map +7 -0
  127. package/dist/modules/notifications/api/openapi.js +76 -0
  128. package/dist/modules/notifications/api/openapi.js.map +7 -0
  129. package/dist/modules/notifications/api/role/route.js +17 -0
  130. package/dist/modules/notifications/api/role/route.js.map +7 -0
  131. package/dist/modules/notifications/api/route.js +85 -0
  132. package/dist/modules/notifications/api/route.js.map +7 -0
  133. package/dist/modules/notifications/api/settings/route.js +155 -0
  134. package/dist/modules/notifications/api/settings/route.js.map +7 -0
  135. package/dist/modules/notifications/api/unread-count/route.js +38 -0
  136. package/dist/modules/notifications/api/unread-count/route.js.map +7 -0
  137. package/dist/modules/notifications/backend/config/notifications/page.js +10 -0
  138. package/dist/modules/notifications/backend/config/notifications/page.js.map +7 -0
  139. package/dist/modules/notifications/backend/config/notifications/page.meta.js +24 -0
  140. package/dist/modules/notifications/backend/config/notifications/page.meta.js.map +7 -0
  141. package/dist/modules/notifications/cli.js +16 -0
  142. package/dist/modules/notifications/cli.js.map +7 -0
  143. package/dist/modules/notifications/data/entities.js +112 -0
  144. package/dist/modules/notifications/data/entities.js.map +7 -0
  145. package/dist/modules/notifications/data/validators.js +94 -0
  146. package/dist/modules/notifications/data/validators.js.map +7 -0
  147. package/dist/modules/notifications/di.js +13 -0
  148. package/dist/modules/notifications/di.js.map +7 -0
  149. package/dist/modules/notifications/emails/NotificationEmail.js +58 -0
  150. package/dist/modules/notifications/emails/NotificationEmail.js.map +7 -0
  151. package/dist/modules/notifications/frontend/NotificationInboxPageClient.js +44 -0
  152. package/dist/modules/notifications/frontend/NotificationInboxPageClient.js.map +7 -0
  153. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +219 -0
  154. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +7 -0
  155. package/dist/modules/notifications/index.js +14 -0
  156. package/dist/modules/notifications/index.js.map +7 -0
  157. package/dist/modules/notifications/lib/deliveryConfig.js +105 -0
  158. package/dist/modules/notifications/lib/deliveryConfig.js.map +7 -0
  159. package/dist/modules/notifications/lib/events.js +12 -0
  160. package/dist/modules/notifications/lib/events.js.map +7 -0
  161. package/dist/modules/notifications/lib/notificationBuilder.js +66 -0
  162. package/dist/modules/notifications/lib/notificationBuilder.js.map +7 -0
  163. package/dist/modules/notifications/lib/notificationFactory.js +54 -0
  164. package/dist/modules/notifications/lib/notificationFactory.js.map +7 -0
  165. package/dist/modules/notifications/lib/notificationMapper.js +34 -0
  166. package/dist/modules/notifications/lib/notificationMapper.js.map +7 -0
  167. package/dist/modules/notifications/lib/notificationRecipients.js +35 -0
  168. package/dist/modules/notifications/lib/notificationRecipients.js.map +7 -0
  169. package/dist/modules/notifications/lib/notificationService.js +279 -0
  170. package/dist/modules/notifications/lib/notificationService.js.map +7 -0
  171. package/dist/modules/notifications/lib/routeHelpers.js +101 -0
  172. package/dist/modules/notifications/lib/routeHelpers.js.map +7 -0
  173. package/dist/modules/notifications/lib/safeHref.js +24 -0
  174. package/dist/modules/notifications/lib/safeHref.js.map +7 -0
  175. package/dist/modules/notifications/migrations/Migration20260123000001.js +70 -0
  176. package/dist/modules/notifications/migrations/Migration20260123000001.js.map +7 -0
  177. package/dist/modules/notifications/migrations/Migration20260126150000.js +37 -0
  178. package/dist/modules/notifications/migrations/Migration20260126150000.js.map +7 -0
  179. package/dist/modules/notifications/subscribers/deliver-notification.js +139 -0
  180. package/dist/modules/notifications/subscribers/deliver-notification.js.map +7 -0
  181. package/dist/modules/notifications/workers/create-notification.worker.js +70 -0
  182. package/dist/modules/notifications/workers/create-notification.worker.js.map +7 -0
  183. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +2 -2
  184. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  185. package/dist/modules/query_index/components/QueryIndexesTable.js +7 -1
  186. package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
  187. package/dist/modules/resources/backend/resources/resource-types/page.js +2 -2
  188. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  189. package/dist/modules/resources/backend/resources/resources/page.js +2 -2
  190. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  191. package/dist/modules/sales/backend/sales/channels/offers/page.js +2 -0
  192. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  193. package/dist/modules/sales/backend/sales/channels/page.js +2 -0
  194. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  195. package/dist/modules/sales/commands/documents.js +53 -0
  196. package/dist/modules/sales/commands/documents.js.map +2 -2
  197. package/dist/modules/sales/commands/payments.js +26 -0
  198. package/dist/modules/sales/commands/payments.js.map +2 -2
  199. package/dist/modules/sales/components/AdjustmentKindSettings.js +2 -2
  200. package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
  201. package/dist/modules/sales/components/PaymentMethodsSettings.js +2 -2
  202. package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
  203. package/dist/modules/sales/components/ShippingMethodsSettings.js +2 -2
  204. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
  205. package/dist/modules/sales/components/TaxRatesSettings.js +2 -2
  206. package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
  207. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +2 -0
  208. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  209. package/dist/modules/sales/components/documents/AdjustmentsSection.js +2 -0
  210. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  211. package/dist/modules/sales/components/documents/PaymentsSection.js +2 -1
  212. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  213. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +2 -0
  214. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  215. package/dist/modules/sales/notifications.client.js +51 -0
  216. package/dist/modules/sales/notifications.client.js.map +7 -0
  217. package/dist/modules/sales/notifications.js +88 -0
  218. package/dist/modules/sales/notifications.js.map +7 -0
  219. package/dist/modules/sales/subscribers/quote-expiring-notification.js +38 -0
  220. package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +7 -0
  221. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +137 -0
  222. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +7 -0
  223. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +137 -0
  224. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +7 -0
  225. package/dist/modules/sales/widgets/notifications/index.js +7 -0
  226. package/dist/modules/sales/widgets/notifications/index.js.map +7 -0
  227. package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js +60 -0
  228. package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js.map +7 -0
  229. package/dist/modules/staff/backend/staff/team-members/page.js +1 -1
  230. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  231. package/dist/modules/staff/backend/staff/team-roles/page.js +2 -2
  232. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  233. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +2 -2
  234. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  235. package/dist/modules/staff/backend/staff/teams/page.js +2 -2
  236. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  237. package/dist/modules/staff/commands/leave-requests.js +79 -0
  238. package/dist/modules/staff/commands/leave-requests.js.map +2 -2
  239. package/dist/modules/staff/notifications.js +75 -0
  240. package/dist/modules/staff/notifications.js.map +7 -0
  241. package/dist/modules/workflows/backend/definitions/page.js +5 -0
  242. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  243. package/dist/modules/workflows/backend/instances/page.js +3 -0
  244. package/dist/modules/workflows/backend/instances/page.js.map +2 -2
  245. package/dist/modules/workflows/backend/tasks/page.js +3 -0
  246. package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
  247. package/dist/modules/workflows/notifications.js +28 -0
  248. package/dist/modules/workflows/notifications.js.map +7 -0
  249. package/dist/modules/workflows/subscribers/task-assigned-notification.js +38 -0
  250. package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +7 -0
  251. package/generated/entities/notification/index.ts +27 -0
  252. package/generated/entities.ids.generated.ts +5 -1
  253. package/generated/entity-fields-registry.ts +2 -0
  254. package/package.json +2 -2
  255. package/src/modules/api_docs/frontend/docs/api/page.tsx +3 -2
  256. package/src/modules/api_keys/backend/api-keys/page.tsx +1 -1
  257. package/src/modules/attachments/components/AttachmentLibrary.tsx +4 -0
  258. package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +2 -0
  259. package/src/modules/auth/api/admin/nav.ts +10 -6
  260. package/src/modules/auth/api/profile/route.ts +163 -0
  261. package/src/modules/auth/api/reset/confirm.ts +25 -2
  262. package/src/modules/auth/api/reset.ts +23 -0
  263. package/src/modules/auth/api/sidebar/preferences/route.ts +21 -12
  264. package/src/modules/auth/api/users/route.ts +5 -2
  265. package/src/modules/auth/backend/auth/profile/page.meta.ts +9 -0
  266. package/src/modules/auth/backend/auth/profile/page.tsx +174 -0
  267. package/src/modules/auth/backend/roles/page.tsx +3 -3
  268. package/src/modules/auth/backend/users/[id]/edit/page.tsx +18 -2
  269. package/src/modules/auth/backend/users/create/page.tsx +19 -2
  270. package/src/modules/auth/backend/users/page.tsx +3 -3
  271. package/src/modules/auth/cli.ts +14 -0
  272. package/src/modules/auth/commands/users.ts +73 -2
  273. package/src/modules/auth/data/validators.ts +5 -2
  274. package/src/modules/auth/frontend/reset/[token]/page.tsx +24 -11
  275. package/src/modules/auth/i18n/de.json +43 -1
  276. package/src/modules/auth/i18n/en.json +43 -1
  277. package/src/modules/auth/i18n/es.json +43 -1
  278. package/src/modules/auth/i18n/pl.json +43 -1
  279. package/src/modules/auth/lib/setup-app.ts +1 -0
  280. package/src/modules/auth/notifications.ts +109 -0
  281. package/src/modules/auth/services/authService.ts +4 -4
  282. package/src/modules/business_rules/backend/rules/page.tsx +4 -0
  283. package/src/modules/business_rules/backend/sets/page.tsx +3 -0
  284. package/src/modules/business_rules/i18n/en.json +3 -1
  285. package/src/modules/business_rules/notifications.ts +25 -0
  286. package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +50 -0
  287. package/src/modules/catalog/components/PriceKindSettings.tsx +2 -0
  288. package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +2 -2
  289. package/src/modules/catalog/components/products/ProductsDataTable.tsx +2 -0
  290. package/src/modules/catalog/i18n/en.json +3 -1
  291. package/src/modules/catalog/notifications.ts +25 -0
  292. package/src/modules/catalog/subscribers/low-stock-notification.ts +52 -0
  293. package/src/modules/configs/cli.ts +6 -0
  294. package/src/modules/configs/lib/upgrade-actions.ts +18 -0
  295. package/src/modules/currencies/backend/currencies/page.tsx +3 -0
  296. package/src/modules/currencies/backend/exchange-rates/page.tsx +2 -0
  297. package/src/modules/customers/backend/customers/companies/page.tsx +3 -0
  298. package/src/modules/customers/backend/customers/deals/page.tsx +3 -0
  299. package/src/modules/customers/backend/customers/people/page.tsx +3 -0
  300. package/src/modules/customers/commands/deals.ts +39 -0
  301. package/src/modules/customers/components/CustomerTodosTable.tsx +1 -0
  302. package/src/modules/customers/i18n/en.json +5 -1
  303. package/src/modules/customers/notifications.ts +44 -0
  304. package/src/modules/dashboards/cli.ts +41 -1
  305. package/src/modules/dashboards/lib/role-widgets.ts +80 -0
  306. package/src/modules/dictionaries/components/DictionaryTable.tsx +2 -0
  307. package/src/modules/directory/backend/directory/organizations/page.tsx +2 -2
  308. package/src/modules/directory/backend/directory/tenants/page.tsx +2 -2
  309. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +2 -2
  310. package/src/modules/entities/components/SystemEntitiesTable.tsx +1 -1
  311. package/src/modules/entities/components/UserEntitiesTable.tsx +2 -2
  312. package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +3 -4
  313. package/src/modules/feature_toggles/components/OverridesTable.tsx +1 -1
  314. package/src/modules/notifications/acl.ts +7 -0
  315. package/src/modules/notifications/api/[id]/action/route.ts +75 -0
  316. package/src/modules/notifications/api/[id]/dismiss/route.ts +12 -0
  317. package/src/modules/notifications/api/[id]/read/route.ts +12 -0
  318. package/src/modules/notifications/api/[id]/restore/route.ts +53 -0
  319. package/src/modules/notifications/api/batch/route.ts +14 -0
  320. package/src/modules/notifications/api/feature/route.ts +14 -0
  321. package/src/modules/notifications/api/mark-all-read/route.ts +34 -0
  322. package/src/modules/notifications/api/openapi.ts +76 -0
  323. package/src/modules/notifications/api/role/route.ts +14 -0
  324. package/src/modules/notifications/api/route.ts +92 -0
  325. package/src/modules/notifications/api/settings/route.ts +157 -0
  326. package/src/modules/notifications/api/unread-count/route.ts +38 -0
  327. package/src/modules/notifications/backend/config/notifications/page.meta.ts +22 -0
  328. package/src/modules/notifications/backend/config/notifications/page.tsx +12 -0
  329. package/src/modules/notifications/cli.ts +18 -0
  330. package/src/modules/notifications/data/entities.ts +99 -0
  331. package/src/modules/notifications/data/validators.ts +110 -0
  332. package/src/modules/notifications/di.ts +11 -0
  333. package/src/modules/notifications/emails/NotificationEmail.tsx +98 -0
  334. package/src/modules/notifications/frontend/NotificationInboxPageClient.tsx +42 -0
  335. package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +231 -0
  336. package/src/modules/notifications/i18n/de.json +50 -0
  337. package/src/modules/notifications/i18n/en.json +50 -0
  338. package/src/modules/notifications/i18n/es.json +50 -0
  339. package/src/modules/notifications/i18n/pl.json +50 -0
  340. package/src/modules/notifications/index.ts +12 -0
  341. package/src/modules/notifications/lib/deliveryConfig.ts +145 -0
  342. package/src/modules/notifications/lib/events.ts +48 -0
  343. package/src/modules/notifications/lib/notificationBuilder.ts +121 -0
  344. package/src/modules/notifications/lib/notificationFactory.ts +76 -0
  345. package/src/modules/notifications/lib/notificationMapper.ts +33 -0
  346. package/src/modules/notifications/lib/notificationRecipients.ts +83 -0
  347. package/src/modules/notifications/lib/notificationService.ts +414 -0
  348. package/src/modules/notifications/lib/routeHelpers.ts +151 -0
  349. package/src/modules/notifications/lib/safeHref.ts +29 -0
  350. package/src/modules/notifications/migrations/.snapshot-open-mercato.json +300 -0
  351. package/src/modules/notifications/migrations/Migration20260123000001.ts +73 -0
  352. package/src/modules/notifications/migrations/Migration20260126150000.ts +39 -0
  353. package/src/modules/notifications/subscribers/deliver-notification.ts +175 -0
  354. package/src/modules/notifications/workers/create-notification.worker.ts +122 -0
  355. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +2 -2
  356. package/src/modules/query_index/components/QueryIndexesTable.tsx +8 -2
  357. package/src/modules/resources/backend/resources/resource-types/page.tsx +2 -2
  358. package/src/modules/resources/backend/resources/resources/page.tsx +2 -2
  359. package/src/modules/sales/backend/sales/channels/offers/page.tsx +2 -0
  360. package/src/modules/sales/backend/sales/channels/page.tsx +2 -0
  361. package/src/modules/sales/commands/documents.ts +65 -0
  362. package/src/modules/sales/commands/payments.ts +33 -0
  363. package/src/modules/sales/components/AdjustmentKindSettings.tsx +2 -2
  364. package/src/modules/sales/components/PaymentMethodsSettings.tsx +2 -2
  365. package/src/modules/sales/components/ShippingMethodsSettings.tsx +2 -2
  366. package/src/modules/sales/components/TaxRatesSettings.tsx +2 -2
  367. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +2 -0
  368. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +2 -0
  369. package/src/modules/sales/components/documents/PaymentsSection.tsx +2 -1
  370. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +2 -0
  371. package/src/modules/sales/i18n/de.json +20 -0
  372. package/src/modules/sales/i18n/en.json +25 -1
  373. package/src/modules/sales/i18n/es.json +20 -0
  374. package/src/modules/sales/i18n/pl.json +20 -0
  375. package/src/modules/sales/notifications.client.ts +65 -0
  376. package/src/modules/sales/notifications.ts +82 -0
  377. package/src/modules/sales/subscribers/quote-expiring-notification.ts +53 -0
  378. package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +156 -0
  379. package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +156 -0
  380. package/src/modules/sales/widgets/notifications/index.ts +2 -0
  381. package/src/modules/sales/widgets/notifications/useSalesDocumentTotals.ts +81 -0
  382. package/src/modules/staff/backend/staff/team-members/page.tsx +1 -1
  383. package/src/modules/staff/backend/staff/team-roles/page.tsx +2 -2
  384. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +2 -2
  385. package/src/modules/staff/backend/staff/teams/page.tsx +2 -2
  386. package/src/modules/staff/commands/leave-requests.ts +94 -0
  387. package/src/modules/staff/i18n/de.json +4 -0
  388. package/src/modules/staff/i18n/en.json +9 -1
  389. package/src/modules/staff/i18n/es.json +4 -0
  390. package/src/modules/staff/i18n/pl.json +4 -0
  391. package/src/modules/staff/notifications.ts +71 -0
  392. package/src/modules/workflows/backend/definitions/page.tsx +5 -0
  393. package/src/modules/workflows/backend/instances/page.tsx +4 -1
  394. package/src/modules/workflows/backend/tasks/page.tsx +4 -1
  395. package/src/modules/workflows/i18n/en.json +3 -1
  396. package/src/modules/workflows/notifications.ts +25 -0
  397. package/src/modules/workflows/subscribers/task-assigned-notification.ts +53 -0
@@ -4,11 +4,20 @@ import { Input } from '@open-mercato/ui/primitives/input'
4
4
  import { Label } from '@open-mercato/ui/primitives/label'
5
5
  import { useState } from 'react'
6
6
  import { useRouter } from 'next/navigation'
7
+ import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
8
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
9
+ import { formatPasswordRequirements, getPasswordPolicy } from '@open-mercato/shared/lib/auth/passwordPolicy'
7
10
 
8
11
  export default function ResetWithTokenPage({ params }: { params: { token: string } }) {
9
12
  const router = useRouter()
13
+ const t = useT()
10
14
  const [error, setError] = useState<string | null>(null)
11
15
  const [submitting, setSubmitting] = useState(false)
16
+ const passwordPolicy = getPasswordPolicy()
17
+ const passwordRequirements = formatPasswordRequirements(passwordPolicy, t)
18
+ const passwordDescription = passwordRequirements
19
+ ? t('auth.password.requirements.help', 'Password requirements: {requirements}', { requirements: passwordRequirements })
20
+ : ''
12
21
 
13
22
  async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
14
23
  e.preventDefault()
@@ -17,13 +26,15 @@ export default function ResetWithTokenPage({ params }: { params: { token: string
17
26
  try {
18
27
  const form = new FormData(e.currentTarget)
19
28
  form.set('token', params.token)
20
- const res = await fetch('/api/auth/reset/confirm', { method: 'POST', body: form })
21
- const data = await res.json().catch(() => null)
22
- if (!res.ok) {
23
- setError(data?.error || 'Unable to reset password')
29
+ const { ok, result } = await apiCall<{ ok?: boolean; error?: string; redirect?: string }>(
30
+ '/api/auth/reset/confirm',
31
+ { method: 'POST', body: form },
32
+ )
33
+ if (!ok || result?.ok === false) {
34
+ setError(result?.error || t('auth.reset.errors.failed', 'Unable to reset password'))
24
35
  return
25
36
  }
26
- router.replace(data?.redirect || '/login')
37
+ router.replace(result?.redirect || '/login')
27
38
  } finally {
28
39
  setSubmitting(false)
29
40
  }
@@ -33,18 +44,21 @@ export default function ResetWithTokenPage({ params }: { params: { token: string
33
44
  <div className="min-h-svh flex items-center justify-center p-4">
34
45
  <Card className="w-full max-w-sm">
35
46
  <CardHeader>
36
- <CardTitle>Set a new password</CardTitle>
37
- <CardDescription>Choose a strong password for your account.</CardDescription>
47
+ <CardTitle>{t('auth.reset.title', 'Set a new password')}</CardTitle>
48
+ <CardDescription>{t('auth.reset.subtitle', 'Choose a strong password for your account.')}</CardDescription>
38
49
  </CardHeader>
39
50
  <CardContent>
40
51
  <form className="grid gap-3" onSubmit={onSubmit}>
41
52
  {error && <div className="text-sm text-red-600">{error}</div>}
42
53
  <div className="grid gap-1">
43
- <Label htmlFor="password">New password</Label>
44
- <Input id="password" name="password" type="password" required minLength={6} />
54
+ <Label htmlFor="password">{t('auth.reset.form.password', 'New password')}</Label>
55
+ <Input id="password" name="password" type="password" required minLength={passwordPolicy.minLength} />
56
+ {passwordDescription ? (
57
+ <p className="text-xs text-muted-foreground">{passwordDescription}</p>
58
+ ) : null}
45
59
  </div>
46
60
  <button disabled={submitting} className="h-10 rounded-md bg-foreground text-background mt-2 hover:opacity-90 transition disabled:opacity-60">
47
- {submitting ? '...' : 'Update password'}
61
+ {submitting ? t('auth.reset.form.loading', '...') : t('auth.reset.form.submit', 'Update password')}
48
62
  </button>
49
63
  </form>
50
64
  </CardContent>
@@ -52,4 +66,3 @@ export default function ResetWithTokenPage({ params }: { params: { token: string
52
66
  </div>
53
67
  )
54
68
  }
55
-
@@ -2,8 +2,20 @@
2
2
  "auth.signIn": "Anmelden",
3
3
  "auth.email": "E-Mail",
4
4
  "auth.password": "Passwort",
5
+ "auth.password.requirements.help": "Passwortanforderungen: {requirements}",
6
+ "auth.password.requirements.minLength": "Mindestens {min} Zeichen",
7
+ "auth.password.requirements.digit": "Eine Zahl",
8
+ "auth.password.requirements.uppercase": "Ein Großbuchstabe",
9
+ "auth.password.requirements.special": "Ein Sonderzeichen",
10
+ "auth.password.requirements.separator": ", ",
5
11
  "auth.sendResetLink": "Link zum Zurücksetzen senden",
6
12
  "auth.resetPassword": "Passwort zurücksetzen",
13
+ "auth.reset.title": "Neues Passwort festlegen",
14
+ "auth.reset.subtitle": "Wähle ein sicheres Passwort für dein Konto.",
15
+ "auth.reset.form.password": "Neues Passwort",
16
+ "auth.reset.form.loading": "...",
17
+ "auth.reset.form.submit": "Passwort aktualisieren",
18
+ "auth.reset.errors.failed": "Passwort konnte nicht zurückgesetzt werden",
7
19
  "auth.usersRoles": "Benutzer und Rollen",
8
20
  "auth.manageAuthSettings": "Verwalte die Authentifizierungseinstellungen.",
9
21
  "auth.login.errors.permissionDenied": "Du hast keine Berechtigung, auf diesen Bereich zuzugreifen. Bitte wende dich an deine Administration.",
@@ -80,6 +92,21 @@
80
92
  "auth.users.form.errors.load": "Benutzerdaten konnten nicht geladen werden",
81
93
  "auth.users.form.errors.aclUpdate": "Aktualisierung der Benutzerberechtigungen fehlgeschlagen",
82
94
  "auth.users.form.errors.delete": "Benutzer konnte nicht gelöscht werden",
95
+ "auth.profile.title": "Profil",
96
+ "auth.profile.subtitle": "Passwort ändern",
97
+ "auth.profile.form.email": "E-Mail",
98
+ "auth.profile.form.password": "Neues Passwort",
99
+ "auth.profile.form.confirmPassword": "Neues Passwort bestätigen",
100
+ "auth.profile.form.save": "Änderungen speichern",
101
+ "auth.profile.form.loading": "Profil wird geladen...",
102
+ "auth.profile.form.errors.load": "Profil konnte nicht geladen werden.",
103
+ "auth.profile.form.errors.save": "Profil konnte nicht aktualisiert werden.",
104
+ "auth.profile.form.errors.invalid": "Ungültige Profilaktualisierung.",
105
+ "auth.profile.form.errors.passwordMismatch": "Die Passwörter stimmen nicht überein.",
106
+ "auth.profile.form.errors.passwordRequirements": "Das Passwort muss die Anforderungen erfüllen.",
107
+ "auth.profile.form.errors.noChanges": "Keine Änderungen zu speichern.",
108
+ "auth.profile.form.errors.emailRequired": "E-Mail ist erforderlich.",
109
+ "auth.profile.form.success": "Profil aktualisiert.",
83
110
  "auth.users.list.error.load": "Benutzer konnten nicht geladen werden",
84
111
  "auth.users.list.error.delete": "Benutzer konnte nicht gelöscht werden",
85
112
  "auth.users.flash.created": "Benutzer erstellt",
@@ -95,5 +122,20 @@
95
122
  "auth.email.resetPassword.title": "Passwort zurücksetzen",
96
123
  "auth.email.resetPassword.body": "Klicken Sie auf den Link unten, um ein neues Passwort festzulegen. Dieser Link läuft in 60 Minuten ab.",
97
124
  "auth.email.resetPassword.cta": "Neues Passwort festlegen",
98
- "auth.email.resetPassword.hint": "Wenn Sie dies nicht angefordert haben, können Sie diese E-Mail ignorieren."
125
+ "auth.email.resetPassword.hint": "Wenn Sie dies nicht angefordert haben, können Sie diese E-Mail ignorieren.",
126
+ "auth.notifications.passwordReset.requested.title": "Passwort-Zurücksetzung angefordert",
127
+ "auth.notifications.passwordReset.requested.body": "Ein Link zum Zurücksetzen des Passworts wurde an Ihre E-Mail gesendet",
128
+ "auth.notifications.passwordReset.completed.title": "Passwort erfolgreich geändert",
129
+ "auth.notifications.passwordReset.completed.body": "Ihr Passwort wurde erfolgreich aktualisiert",
130
+ "auth.notifications.account.locked.title": "Konto gesperrt",
131
+ "auth.notifications.account.locked.body": "Ihr Konto wurde aus Sicherheitsgründen gesperrt. Bitte wenden Sie sich an den Support.",
132
+ "auth.notifications.login.newDevice.title": "Neues Gerät erkannt",
133
+ "auth.notifications.login.newDevice.body": "Es wurde eine Anmeldung von einem unbekannten Gerät für Ihr Konto erkannt",
134
+ "auth.notifications.role.assigned.title": "Neue Rolle zugewiesen",
135
+ "auth.notifications.role.assigned.body": "Ihnen wurde eine neue Rolle mit zusätzlichen Berechtigungen zugewiesen",
136
+ "auth.notifications.role.revoked.title": "Rolle entfernt",
137
+ "auth.notifications.role.revoked.body": "Eine Rolle wurde von Ihrem Konto entfernt",
138
+ "auth.actions.contactSupport": "Support kontaktieren",
139
+ "auth.actions.viewSessions": "Sitzungen anzeigen",
140
+ "auth.actions.viewPermissions": "Berechtigungen anzeigen"
99
141
  }
@@ -2,8 +2,20 @@
2
2
  "auth.signIn": "Sign in",
3
3
  "auth.email": "Email",
4
4
  "auth.password": "Password",
5
+ "auth.password.requirements.help": "Password requirements: {requirements}",
6
+ "auth.password.requirements.minLength": "At least {min} characters",
7
+ "auth.password.requirements.digit": "One number",
8
+ "auth.password.requirements.uppercase": "One uppercase letter",
9
+ "auth.password.requirements.special": "One special character",
10
+ "auth.password.requirements.separator": ", ",
5
11
  "auth.sendResetLink": "Send reset link",
6
12
  "auth.resetPassword": "Reset password",
13
+ "auth.reset.title": "Set a new password",
14
+ "auth.reset.subtitle": "Choose a strong password for your account.",
15
+ "auth.reset.form.password": "New password",
16
+ "auth.reset.form.loading": "...",
17
+ "auth.reset.form.submit": "Update password",
18
+ "auth.reset.errors.failed": "Unable to reset password",
7
19
  "auth.usersRoles": "Users & Roles",
8
20
  "auth.manageAuthSettings": "Manage authentication settings.",
9
21
  "auth.login.errors.permissionDenied": "You do not have permission to access this area. Please contact your administrator.",
@@ -80,6 +92,21 @@
80
92
  "auth.users.form.errors.load": "Failed to load user data",
81
93
  "auth.users.form.errors.aclUpdate": "Failed to update user access control",
82
94
  "auth.users.form.errors.delete": "Failed to delete user",
95
+ "auth.profile.title": "Profile",
96
+ "auth.profile.subtitle": "Change password",
97
+ "auth.profile.form.email": "Email",
98
+ "auth.profile.form.password": "New password",
99
+ "auth.profile.form.confirmPassword": "Confirm new password",
100
+ "auth.profile.form.save": "Save changes",
101
+ "auth.profile.form.loading": "Loading profile...",
102
+ "auth.profile.form.errors.load": "Failed to load profile.",
103
+ "auth.profile.form.errors.save": "Failed to update profile.",
104
+ "auth.profile.form.errors.invalid": "Invalid profile update.",
105
+ "auth.profile.form.errors.passwordMismatch": "Passwords do not match.",
106
+ "auth.profile.form.errors.passwordRequirements": "Password must meet the requirements.",
107
+ "auth.profile.form.errors.noChanges": "No changes to save.",
108
+ "auth.profile.form.errors.emailRequired": "Email is required.",
109
+ "auth.profile.form.success": "Profile updated.",
83
110
  "auth.users.list.error.load": "Failed to load users",
84
111
  "auth.users.list.error.delete": "Failed to delete user",
85
112
  "auth.users.flash.created": "User created",
@@ -95,5 +122,20 @@
95
122
  "auth.email.resetPassword.title": "Reset your password",
96
123
  "auth.email.resetPassword.body": "Click the link below to set a new password. This link will expire in 60 minutes.",
97
124
  "auth.email.resetPassword.cta": "Set a new password",
98
- "auth.email.resetPassword.hint": "If you didn't request this, you can safely ignore this email."
125
+ "auth.email.resetPassword.hint": "If you didn't request this, you can safely ignore this email.",
126
+ "auth.notifications.passwordReset.requested.title": "Password reset requested",
127
+ "auth.notifications.passwordReset.requested.body": "A password reset link has been sent to your email",
128
+ "auth.notifications.passwordReset.completed.title": "Password successfully changed",
129
+ "auth.notifications.passwordReset.completed.body": "Your password has been updated successfully",
130
+ "auth.notifications.account.locked.title": "Account locked",
131
+ "auth.notifications.account.locked.body": "Your account has been locked due to security reasons. Please contact support.",
132
+ "auth.notifications.login.newDevice.title": "New device login detected",
133
+ "auth.notifications.login.newDevice.body": "A new login from an unrecognized device was detected on your account",
134
+ "auth.notifications.role.assigned.title": "New role assigned",
135
+ "auth.notifications.role.assigned.body": "You have been assigned a new role with additional permissions",
136
+ "auth.notifications.role.revoked.title": "Role removed",
137
+ "auth.notifications.role.revoked.body": "A role has been removed from your account",
138
+ "auth.actions.contactSupport": "Contact Support",
139
+ "auth.actions.viewSessions": "View Sessions",
140
+ "auth.actions.viewPermissions": "View Permissions"
99
141
  }
@@ -2,8 +2,20 @@
2
2
  "auth.signIn": "Iniciar sesión",
3
3
  "auth.email": "Correo electrónico",
4
4
  "auth.password": "Contraseña",
5
+ "auth.password.requirements.help": "Requisitos de la contraseña: {requirements}",
6
+ "auth.password.requirements.minLength": "Al menos {min} caracteres",
7
+ "auth.password.requirements.digit": "Un número",
8
+ "auth.password.requirements.uppercase": "Una letra mayúscula",
9
+ "auth.password.requirements.special": "Un carácter especial",
10
+ "auth.password.requirements.separator": ", ",
5
11
  "auth.sendResetLink": "Enviar enlace de restablecimiento",
6
12
  "auth.resetPassword": "Restablecer contraseña",
13
+ "auth.reset.title": "Establecer una nueva contraseña",
14
+ "auth.reset.subtitle": "Elige una contraseña segura para tu cuenta.",
15
+ "auth.reset.form.password": "Nueva contraseña",
16
+ "auth.reset.form.loading": "...",
17
+ "auth.reset.form.submit": "Actualizar contraseña",
18
+ "auth.reset.errors.failed": "No se pudo restablecer la contraseña",
7
19
  "auth.usersRoles": "Usuarios y roles",
8
20
  "auth.manageAuthSettings": "Administra la configuración de autenticación.",
9
21
  "auth.login.errors.permissionDenied": "No tienes permiso para acceder a esta área. Ponte en contacto con tu administrador.",
@@ -80,6 +92,21 @@
80
92
  "auth.users.form.errors.load": "No se pudieron cargar los datos del usuario",
81
93
  "auth.users.form.errors.aclUpdate": "No se pudo actualizar el control de acceso del usuario",
82
94
  "auth.users.form.errors.delete": "No se pudo eliminar el usuario",
95
+ "auth.profile.title": "Perfil",
96
+ "auth.profile.subtitle": "Cambiar contraseña",
97
+ "auth.profile.form.email": "Correo electrónico",
98
+ "auth.profile.form.password": "Nueva contraseña",
99
+ "auth.profile.form.confirmPassword": "Confirmar nueva contraseña",
100
+ "auth.profile.form.save": "Guardar cambios",
101
+ "auth.profile.form.loading": "Cargando perfil...",
102
+ "auth.profile.form.errors.load": "No se pudo cargar el perfil.",
103
+ "auth.profile.form.errors.save": "No se pudo actualizar el perfil.",
104
+ "auth.profile.form.errors.invalid": "Actualización de perfil inválida.",
105
+ "auth.profile.form.errors.passwordMismatch": "Las contraseñas no coinciden.",
106
+ "auth.profile.form.errors.passwordRequirements": "La contraseña debe cumplir los requisitos.",
107
+ "auth.profile.form.errors.noChanges": "No hay cambios para guardar.",
108
+ "auth.profile.form.errors.emailRequired": "El correo electrónico es obligatorio.",
109
+ "auth.profile.form.success": "Perfil actualizado.",
83
110
  "auth.users.list.error.load": "No se pudieron cargar los usuarios",
84
111
  "auth.users.list.error.delete": "No se pudo eliminar el usuario",
85
112
  "auth.users.flash.created": "Usuario creado",
@@ -95,5 +122,20 @@
95
122
  "auth.email.resetPassword.title": "Restablecer tu contraseña",
96
123
  "auth.email.resetPassword.body": "Haz clic en el siguiente enlace para establecer una nueva contraseña. Este enlace caducará en 60 minutos.",
97
124
  "auth.email.resetPassword.cta": "Establecer nueva contraseña",
98
- "auth.email.resetPassword.hint": "Si no solicitaste esto, puedes ignorar este correo de forma segura."
125
+ "auth.email.resetPassword.hint": "Si no solicitaste esto, puedes ignorar este correo de forma segura.",
126
+ "auth.notifications.passwordReset.requested.title": "Solicitud de restablecimiento de contraseña",
127
+ "auth.notifications.passwordReset.requested.body": "Se ha enviado un enlace de restablecimiento de contraseña a tu correo electrónico",
128
+ "auth.notifications.passwordReset.completed.title": "Contraseña cambiada correctamente",
129
+ "auth.notifications.passwordReset.completed.body": "Tu contraseña se actualizó correctamente",
130
+ "auth.notifications.account.locked.title": "Cuenta bloqueada",
131
+ "auth.notifications.account.locked.body": "Tu cuenta ha sido bloqueada por razones de seguridad. Ponte en contacto con soporte.",
132
+ "auth.notifications.login.newDevice.title": "Nuevo inicio de sesión detectado",
133
+ "auth.notifications.login.newDevice.body": "Se detectó un inicio de sesión desde un dispositivo no reconocido en tu cuenta",
134
+ "auth.notifications.role.assigned.title": "Nuevo rol asignado",
135
+ "auth.notifications.role.assigned.body": "Se te ha asignado un nuevo rol con permisos adicionales",
136
+ "auth.notifications.role.revoked.title": "Rol eliminado",
137
+ "auth.notifications.role.revoked.body": "Se ha eliminado un rol de tu cuenta",
138
+ "auth.actions.contactSupport": "Contactar soporte",
139
+ "auth.actions.viewSessions": "Ver sesiones",
140
+ "auth.actions.viewPermissions": "Ver permisos"
99
141
  }
@@ -2,8 +2,20 @@
2
2
  "auth.signIn": "Zaloguj się",
3
3
  "auth.email": "Email",
4
4
  "auth.password": "Hasło",
5
+ "auth.password.requirements.help": "Wymagania hasła: {requirements}",
6
+ "auth.password.requirements.minLength": "Co najmniej {min} znaków",
7
+ "auth.password.requirements.digit": "Jedna cyfra",
8
+ "auth.password.requirements.uppercase": "Jedna wielka litera",
9
+ "auth.password.requirements.special": "Jeden znak specjalny",
10
+ "auth.password.requirements.separator": ", ",
5
11
  "auth.sendResetLink": "Wyślij link resetujący",
6
12
  "auth.resetPassword": "Resetuj hasło",
13
+ "auth.reset.title": "Ustaw nowe hasło",
14
+ "auth.reset.subtitle": "Wybierz silne hasło dla swojego konta.",
15
+ "auth.reset.form.password": "Nowe hasło",
16
+ "auth.reset.form.loading": "...",
17
+ "auth.reset.form.submit": "Zaktualizuj hasło",
18
+ "auth.reset.errors.failed": "Nie udało się zresetować hasła",
7
19
  "auth.usersRoles": "Użytkownicy i role",
8
20
  "auth.manageAuthSettings": "Zarządzaj ustawieniami uwierzytelniania.",
9
21
  "auth.login.errors.permissionDenied": "Nie masz uprawnień do tego obszaru. Skontaktuj się z administratorem.",
@@ -80,6 +92,21 @@
80
92
  "auth.users.form.errors.load": "Nie udało się wczytać danych użytkownika",
81
93
  "auth.users.form.errors.aclUpdate": "Nie udało się zaktualizować uprawnień użytkownika",
82
94
  "auth.users.form.errors.delete": "Nie udało się usunąć użytkownika",
95
+ "auth.profile.title": "Profil",
96
+ "auth.profile.subtitle": "Zmiana hasła",
97
+ "auth.profile.form.email": "Email",
98
+ "auth.profile.form.password": "Nowe hasło",
99
+ "auth.profile.form.confirmPassword": "Potwierdź nowe hasło",
100
+ "auth.profile.form.save": "Zapisz zmiany",
101
+ "auth.profile.form.loading": "Ładowanie profilu...",
102
+ "auth.profile.form.errors.load": "Nie udało się wczytać profilu.",
103
+ "auth.profile.form.errors.save": "Nie udało się zaktualizować profilu.",
104
+ "auth.profile.form.errors.invalid": "Nieprawidłowa aktualizacja profilu.",
105
+ "auth.profile.form.errors.passwordMismatch": "Hasła nie są zgodne.",
106
+ "auth.profile.form.errors.passwordRequirements": "Hasło musi spełniać wymagania.",
107
+ "auth.profile.form.errors.noChanges": "Brak zmian do zapisania.",
108
+ "auth.profile.form.errors.emailRequired": "Email jest wymagany.",
109
+ "auth.profile.form.success": "Profil zaktualizowany.",
83
110
  "auth.users.list.error.load": "Nie udało się wczytać użytkowników",
84
111
  "auth.users.list.error.delete": "Nie udało się usunąć użytkownika",
85
112
  "auth.users.flash.created": "Użytkownik utworzony",
@@ -95,5 +122,20 @@
95
122
  "auth.email.resetPassword.title": "Zresetuj swoje hasło",
96
123
  "auth.email.resetPassword.body": "Kliknij poniższy link, aby ustawić nowe hasło. Link wygaśnie za 60 minut.",
97
124
  "auth.email.resetPassword.cta": "Ustaw nowe hasło",
98
- "auth.email.resetPassword.hint": "Jeśli nie prosiłeś o tę wiadomość, możesz ją bezpiecznie zignorować."
125
+ "auth.email.resetPassword.hint": "Jeśli nie prosiłeś o tę wiadomość, możesz ją bezpiecznie zignorować.",
126
+ "auth.notifications.passwordReset.requested.title": "Żądanie resetu hasła",
127
+ "auth.notifications.passwordReset.requested.body": "Link do resetu hasła został wysłany na Twój adres e-mail",
128
+ "auth.notifications.passwordReset.completed.title": "Hasło zmienione pomyślnie",
129
+ "auth.notifications.passwordReset.completed.body": "Twoje hasło zostało pomyślnie zaktualizowane",
130
+ "auth.notifications.account.locked.title": "Konto zablokowane",
131
+ "auth.notifications.account.locked.body": "Twoje konto zostało zablokowane z powodów bezpieczeństwa. Skontaktuj się z pomocą techniczną.",
132
+ "auth.notifications.login.newDevice.title": "Wykryto logowanie z nowego urządzenia",
133
+ "auth.notifications.login.newDevice.body": "Wykryto logowanie z nieznanego urządzenia na Twoim koncie",
134
+ "auth.notifications.role.assigned.title": "Przypisano nową rolę",
135
+ "auth.notifications.role.assigned.body": "Przypisano Ci nową rolę z dodatkowymi uprawnieniami",
136
+ "auth.notifications.role.revoked.title": "Rola usunięta",
137
+ "auth.notifications.role.revoked.body": "Z Twojego konta usunięto rolę",
138
+ "auth.actions.contactSupport": "Skontaktuj się z pomocą",
139
+ "auth.actions.viewSessions": "Zobacz sesje",
140
+ "auth.actions.viewPermissions": "Zobacz uprawnienia"
99
141
  }
@@ -396,6 +396,7 @@ async function ensureDefaultRoleAcls(
396
396
  'dashboards.admin.assign-widgets',
397
397
  'analytics.view',
398
398
  'api_keys.*',
399
+ 'notifications.manage',
399
400
  'perspectives.use',
400
401
  'perspectives.role_defaults',
401
402
  'business_rules.*',
@@ -0,0 +1,109 @@
1
+ import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'
2
+
3
+ export const notificationTypes: NotificationTypeDefinition[] = [
4
+ {
5
+ type: 'auth.password_reset.requested',
6
+ module: 'auth',
7
+ titleKey: 'auth.notifications.passwordReset.requested.title',
8
+ bodyKey: 'auth.notifications.passwordReset.requested.body',
9
+ icon: 'key',
10
+ severity: 'info',
11
+ actions: [
12
+ {
13
+ id: 'view',
14
+ labelKey: 'common.view',
15
+ variant: 'outline',
16
+ href: '/backend/auth/profile',
17
+ icon: 'external-link',
18
+ },
19
+ ],
20
+ linkHref: '/backend/auth/profile',
21
+ expiresAfterHours: 24,
22
+ },
23
+ {
24
+ type: 'auth.password_reset.completed',
25
+ module: 'auth',
26
+ titleKey: 'auth.notifications.passwordReset.completed.title',
27
+ bodyKey: 'auth.notifications.passwordReset.completed.body',
28
+ icon: 'check-circle',
29
+ severity: 'success',
30
+ actions: [],
31
+ expiresAfterHours: 72,
32
+ },
33
+ {
34
+ type: 'auth.account.locked',
35
+ module: 'auth',
36
+ titleKey: 'auth.notifications.account.locked.title',
37
+ bodyKey: 'auth.notifications.account.locked.body',
38
+ icon: 'lock',
39
+ severity: 'warning',
40
+ actions: [
41
+ {
42
+ id: 'contact_support',
43
+ labelKey: 'auth.actions.contactSupport',
44
+ variant: 'default',
45
+ href: '/backend/support',
46
+ icon: 'mail',
47
+ },
48
+ ],
49
+ linkHref: '/backend/support',
50
+ },
51
+ {
52
+ type: 'auth.login.new_device',
53
+ module: 'auth',
54
+ titleKey: 'auth.notifications.login.newDevice.title',
55
+ bodyKey: 'auth.notifications.login.newDevice.body',
56
+ icon: 'smartphone',
57
+ severity: 'info',
58
+ actions: [
59
+ {
60
+ id: 'view_sessions',
61
+ labelKey: 'auth.actions.viewSessions',
62
+ variant: 'outline',
63
+ href: '/backend/auth/sessions',
64
+ icon: 'list',
65
+ },
66
+ ],
67
+ linkHref: '/backend/auth/sessions',
68
+ expiresAfterHours: 168, // 7 days
69
+ },
70
+ {
71
+ type: 'auth.role.assigned',
72
+ module: 'auth',
73
+ titleKey: 'auth.notifications.role.assigned.title',
74
+ bodyKey: 'auth.notifications.role.assigned.body',
75
+ icon: 'user-plus',
76
+ severity: 'success',
77
+ actions: [
78
+ {
79
+ id: 'view_permissions',
80
+ labelKey: 'auth.actions.viewPermissions',
81
+ variant: 'outline',
82
+ href: '/backend/auth/profile',
83
+ icon: 'shield',
84
+ },
85
+ ],
86
+ linkHref: '/backend/auth/profile',
87
+ expiresAfterHours: 168,
88
+ },
89
+ {
90
+ type: 'auth.role.revoked',
91
+ module: 'auth',
92
+ titleKey: 'auth.notifications.role.revoked.title',
93
+ bodyKey: 'auth.notifications.role.revoked.body',
94
+ icon: 'user-minus',
95
+ severity: 'warning',
96
+ actions: [
97
+ {
98
+ id: 'view_profile',
99
+ labelKey: 'common.view',
100
+ variant: 'outline',
101
+ href: '/backend/auth/profile',
102
+ },
103
+ ],
104
+ linkHref: '/backend/auth/profile',
105
+ expiresAfterHours: 168,
106
+ },
107
+ ]
108
+
109
+ export default notificationTypes
@@ -75,15 +75,15 @@ export class AuthService {
75
75
  return { user, token }
76
76
  }
77
77
 
78
- async confirmPasswordReset(token: string, newPassword: string) {
78
+ async confirmPasswordReset(token: string, newPassword: string): Promise<User | null> {
79
79
  const now = new Date()
80
80
  const row = await this.em.findOne(PasswordReset, { token })
81
- if (!row || (row.usedAt && row.usedAt <= now) || row.expiresAt <= now) return false
81
+ if (!row || (row.usedAt && row.usedAt <= now) || row.expiresAt <= now) return null
82
82
  const user = await this.em.findOne(User, { id: row.user.id })
83
- if (!user) return false
83
+ if (!user) return null
84
84
  user.passwordHash = await hash(newPassword, 10)
85
85
  row.usedAt = new Date()
86
86
  await this.em.flush()
87
- return true
87
+ return user
88
88
  }
89
89
  }
@@ -264,14 +264,17 @@ export default function RulesListPage() {
264
264
  <RowActions
265
265
  items={[
266
266
  {
267
+ id: 'edit',
267
268
  label: t('common.edit'),
268
269
  href: `/backend/rules/${row.original.id}`,
269
270
  },
270
271
  {
272
+ id: row.original.enabled ? 'disable' : 'enable',
271
273
  label: row.original.enabled ? t('common.disable') : t('common.enable'),
272
274
  onSelect: () => handleToggleEnabled(row.original.id, row.original.enabled),
273
275
  },
274
276
  {
277
+ id: 'duplicate',
275
278
  label: t('common.duplicate'),
276
279
  onSelect: () => {
277
280
  // TODO: Implement duplicate functionality in Step 5.2
@@ -279,6 +282,7 @@ export default function RulesListPage() {
279
282
  },
280
283
  },
281
284
  {
285
+ id: 'delete',
282
286
  label: t('common.delete'),
283
287
  onSelect: () => handleDelete(row.original.id, row.original.ruleName),
284
288
  destructive: true,
@@ -196,14 +196,17 @@ export default function RuleSetsListPage() {
196
196
  <RowActions
197
197
  items={[
198
198
  {
199
+ id: 'edit',
199
200
  label: t('common.edit'),
200
201
  href: `/backend/sets/${row.original.id}`,
201
202
  },
202
203
  {
204
+ id: row.original.enabled ? 'disable' : 'enable',
203
205
  label: row.original.enabled ? t('common.disable') : t('common.enable'),
204
206
  onSelect: () => handleToggleEnabled(row.original.id, row.original.enabled),
205
207
  },
206
208
  {
209
+ id: 'delete',
207
210
  label: t('common.delete'),
208
211
  onSelect: () => handleDelete(row.original.id, row.original.setName),
209
212
  destructive: true,
@@ -367,5 +367,7 @@
367
367
  "business_rules.components.conditionRow.field.comparisonPlaceholder": "e.g., user.role",
368
368
  "business_rules.components.conditionRow.value.help": "Use JSON for arrays: [\"a\",\"b\"]",
369
369
  "business_rules.components.conditionRow.field.comparisonHelp": "Field path to compare with",
370
- "business_rules.components.conditionRow.deleteCondition": "Delete condition"
370
+ "business_rules.components.conditionRow.deleteCondition": "Delete condition",
371
+ "businessRules.notifications.rule.executionFailed.title": "Business Rule Failed",
372
+ "businessRules.notifications.rule.executionFailed.body": "Rule \"{ruleName}\" failed to execute{entityType, select, other { on {entityType}}}: {errorMessage}"
371
373
  }
@@ -0,0 +1,25 @@
1
+ import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'
2
+
3
+ export const notificationTypes: NotificationTypeDefinition[] = [
4
+ {
5
+ type: 'business_rules.rule.execution_failed',
6
+ module: 'business_rules',
7
+ titleKey: 'businessRules.notifications.rule.executionFailed.title',
8
+ bodyKey: 'businessRules.notifications.rule.executionFailed.body',
9
+ icon: 'alert-triangle',
10
+ severity: 'error',
11
+ actions: [
12
+ {
13
+ id: 'view',
14
+ labelKey: 'common.view',
15
+ variant: 'outline',
16
+ href: '/backend/business-rules/{sourceEntityId}',
17
+ icon: 'external-link',
18
+ },
19
+ ],
20
+ linkHref: '/backend/business-rules/{sourceEntityId}',
21
+ expiresAfterHours: 168, // 7 days
22
+ },
23
+ ]
24
+
25
+ export default notificationTypes
@@ -0,0 +1,50 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql'
2
+ import { resolveNotificationService } from '../../notifications/lib/notificationService'
3
+ import { buildFeatureNotificationFromType } from '../../notifications/lib/notificationBuilder'
4
+ import { notificationTypes } from '../notifications'
5
+
6
+ export const metadata = {
7
+ event: 'business_rules.rule.execution_failed',
8
+ persistent: true,
9
+ id: 'business_rules:rule-execution-failed-notification',
10
+ }
11
+
12
+ type RuleExecutionFailedPayload = {
13
+ ruleId: string
14
+ ruleName: string
15
+ entityType?: string | null
16
+ errorMessage?: string | null
17
+ tenantId: string
18
+ organizationId?: string | null
19
+ }
20
+
21
+ type ResolverContext = {
22
+ resolve: <T = unknown>(name: string) => T
23
+ }
24
+
25
+ export default async function handle(payload: RuleExecutionFailedPayload, ctx: ResolverContext) {
26
+ try {
27
+ const notificationService = resolveNotificationService(ctx)
28
+ const typeDef = notificationTypes.find((type) => type.type === 'business_rules.rule.execution_failed')
29
+ if (!typeDef) return
30
+
31
+ const notificationInput = buildFeatureNotificationFromType(typeDef, {
32
+ requiredFeature: 'business_rules.manage',
33
+ bodyVariables: {
34
+ ruleName: payload.ruleName,
35
+ entityType: payload.entityType ?? '',
36
+ errorMessage: payload.errorMessage ?? 'Unknown error',
37
+ },
38
+ sourceEntityType: 'business_rules:rule',
39
+ sourceEntityId: payload.ruleId,
40
+ linkHref: `/backend/business-rules/${payload.ruleId}`,
41
+ })
42
+
43
+ await notificationService.createForFeature(notificationInput, {
44
+ tenantId: payload.tenantId,
45
+ organizationId: payload.organizationId ?? null,
46
+ })
47
+ } catch (err) {
48
+ console.error('[business_rules:rule-execution-failed-notification] Failed to create notification:', err)
49
+ }
50
+ }
@@ -420,10 +420,12 @@ export function PriceKindSettings() {
420
420
  <RowActions
421
421
  items={[
422
422
  {
423
+ id: 'edit',
423
424
  label: t('catalog.priceKinds.actions.edit', 'Edit'),
424
425
  onSelect: () => openDialog({ mode: 'edit', entry }),
425
426
  },
426
427
  {
428
+ id: 'delete',
427
429
  label: t('catalog.priceKinds.actions.delete', 'Delete'),
428
430
  destructive: true,
429
431
  onSelect: () => { void handleDelete(entry) },
@@ -221,8 +221,8 @@ export default function CategoriesDataTable() {
221
221
  canManage ? (
222
222
  <RowActions
223
223
  items={[
224
- { label: t('catalog.categories.list.actions.edit', 'Edit'), href: `/backend/catalog/categories/${row.id}/edit` },
225
- { label: t('catalog.categories.list.actions.delete', 'Delete'), destructive: true, onSelect: () => handleDelete(row) },
224
+ { id: 'edit', label: t('catalog.categories.list.actions.edit', 'Edit'), href: `/backend/catalog/categories/${row.id}/edit` },
225
+ { id: 'delete', label: t('catalog.categories.list.actions.delete', 'Delete'), destructive: true, onSelect: () => handleDelete(row) },
226
226
  ]}
227
227
  />
228
228
  ) : null