@open-mercato/core 0.6.5-develop.4516.1.88e6ab71a9 → 0.6.5-develop.4544.1.71c003c861

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 (726) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/AGENTS.md +5 -0
  3. package/dist/generated/entities/role/index.js +3 -1
  4. package/dist/generated/entities/role/index.js.map +2 -2
  5. package/dist/generated/entities/step_instance/index.js +2 -0
  6. package/dist/generated/entities/step_instance/index.js.map +2 -2
  7. package/dist/generated/entities/user/index.js +3 -1
  8. package/dist/generated/entities/user/index.js.map +2 -2
  9. package/dist/generated/entities/user_task/index.js +2 -0
  10. package/dist/generated/entities/user_task/index.js.map +2 -2
  11. package/dist/generated/entities/workflow_branch_instance/index.js +39 -0
  12. package/dist/generated/entities/workflow_branch_instance/index.js.map +7 -0
  13. package/dist/generated/entities/workflow_event/index.js +2 -0
  14. package/dist/generated/entities/workflow_event/index.js.map +2 -2
  15. package/dist/generated/entities/workflow_instance/index.js +2 -0
  16. package/dist/generated/entities/workflow_instance/index.js.map +2 -2
  17. package/dist/generated/entities.ids.generated.js +1 -0
  18. package/dist/generated/entities.ids.generated.js.map +2 -2
  19. package/dist/generated/entity-fields-registry.js +26 -0
  20. package/dist/generated/entity-fields-registry.js.map +2 -2
  21. package/dist/helpers/integration/optimisticLockUi.js +104 -0
  22. package/dist/helpers/integration/optimisticLockUi.js.map +7 -0
  23. package/dist/helpers/integration/salesFixtures.js +17 -0
  24. package/dist/helpers/integration/salesFixtures.js.map +2 -2
  25. package/dist/modules/api_keys/backend/api-keys/page.js +9 -5
  26. package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
  27. package/dist/modules/attachments/components/AttachmentPartitionSettings.js +17 -9
  28. package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
  29. package/dist/modules/auth/api/roles/acl/route.js +32 -13
  30. package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
  31. package/dist/modules/auth/api/roles/route.js +3 -1
  32. package/dist/modules/auth/api/roles/route.js.map +2 -2
  33. package/dist/modules/auth/api/sidebar/preferences/route.js +71 -3
  34. package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
  35. package/dist/modules/auth/api/users/acl/route.js +42 -19
  36. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  37. package/dist/modules/auth/api/users/route.js +3 -1
  38. package/dist/modules/auth/api/users/route.js.map +2 -2
  39. package/dist/modules/auth/backend/roles/[id]/edit/page.js +24 -4
  40. package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
  41. package/dist/modules/auth/backend/roles/page.js +8 -4
  42. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  43. package/dist/modules/auth/backend/users/[id]/edit/page.js +27 -5
  44. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  45. package/dist/modules/auth/backend/users/page.js +6 -2
  46. package/dist/modules/auth/backend/users/page.js.map +2 -2
  47. package/dist/modules/auth/components/AclEditor.js +3 -1
  48. package/dist/modules/auth/components/AclEditor.js.map +2 -2
  49. package/dist/modules/auth/data/entities.js +6 -0
  50. package/dist/modules/auth/data/entities.js.map +2 -2
  51. package/dist/modules/auth/services/sidebarPreferencesService.js +32 -4
  52. package/dist/modules/auth/services/sidebarPreferencesService.js.map +2 -2
  53. package/dist/modules/business_rules/api/rules/route.js +28 -0
  54. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  55. package/dist/modules/business_rules/api/sets/route.js +28 -0
  56. package/dist/modules/business_rules/api/sets/route.js.map +2 -2
  57. package/dist/modules/business_rules/backend/rules/[id]/page.js +11 -4
  58. package/dist/modules/business_rules/backend/rules/[id]/page.js.map +3 -3
  59. package/dist/modules/business_rules/backend/rules/page.js +20 -11
  60. package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
  61. package/dist/modules/business_rules/backend/sets/[id]/page.js +11 -4
  62. package/dist/modules/business_rules/backend/sets/[id]/page.js.map +2 -2
  63. package/dist/modules/business_rules/backend/sets/page.js +20 -11
  64. package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
  65. package/dist/modules/catalog/api/categories/route.js +2 -0
  66. package/dist/modules/catalog/api/categories/route.js.map +2 -2
  67. package/dist/modules/catalog/api/products/route.js +2 -1
  68. package/dist/modules/catalog/api/products/route.js.map +2 -2
  69. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js +2 -0
  70. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js.map +2 -2
  71. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +94 -40
  72. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  73. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +37 -8
  74. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
  75. package/dist/modules/catalog/backend/catalog/products/optionSchemaClient.js.map +2 -2
  76. package/dist/modules/catalog/commands/variants.js +32 -31
  77. package/dist/modules/catalog/commands/variants.js.map +2 -2
  78. package/dist/modules/catalog/components/PriceKindSettings.js +12 -5
  79. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  80. package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
  81. package/dist/modules/catalog/components/products/ProductMediaManager.js.map +2 -2
  82. package/dist/modules/catalog/components/products/ProductsDataTable.js +5 -3
  83. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  84. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  85. package/dist/modules/catalog/components/products/variantForm.js +2 -1
  86. package/dist/modules/catalog/components/products/variantForm.js.map +2 -2
  87. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +5 -0
  88. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
  89. package/dist/modules/currencies/backend/currencies/[id]/page.js +6 -3
  90. package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
  91. package/dist/modules/currencies/backend/currencies/page.js +18 -11
  92. package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
  93. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js +1 -0
  94. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js.map +2 -2
  95. package/dist/modules/currencies/backend/exchange-rates/page.js +10 -6
  96. package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
  97. package/dist/modules/currencies/commands/currencies.js +7 -5
  98. package/dist/modules/currencies/commands/currencies.js.map +2 -2
  99. package/dist/modules/currencies/components/CurrencyFetchingConfig.js +26 -19
  100. package/dist/modules/currencies/components/CurrencyFetchingConfig.js.map +2 -2
  101. package/dist/modules/customer_accounts/api/admin/roles/[id].js +28 -5
  102. package/dist/modules/customer_accounts/api/admin/roles/[id].js.map +2 -2
  103. package/dist/modules/customer_accounts/api/admin/roles.js +4 -2
  104. package/dist/modules/customer_accounts/api/admin/roles.js.map +2 -2
  105. package/dist/modules/customer_accounts/api/admin/users/[id].js +28 -5
  106. package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
  107. package/dist/modules/customer_accounts/api/admin/users.js +2 -0
  108. package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
  109. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +16 -8
  110. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
  111. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +8 -4
  112. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
  113. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js +8 -4
  114. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js.map +2 -2
  115. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +29 -18
  116. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
  117. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +18 -11
  118. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
  119. package/dist/modules/customers/api/companies/route.js +13 -2
  120. package/dist/modules/customers/api/companies/route.js.map +2 -2
  121. package/dist/modules/customers/api/deals/route.js +2 -0
  122. package/dist/modules/customers/api/deals/route.js.map +2 -2
  123. package/dist/modules/customers/api/people/route.js +11 -2
  124. package/dist/modules/customers/api/people/route.js.map +2 -2
  125. package/dist/modules/customers/api/todos/route.js +1 -0
  126. package/dist/modules/customers/api/todos/route.js.map +2 -2
  127. package/dist/modules/customers/backend/config/customers/deals/page.js.map +2 -2
  128. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +34 -21
  129. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
  130. package/dist/modules/customers/backend/customers/companies/[id]/page.js +45 -27
  131. package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
  132. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  133. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +22 -5
  134. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  135. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js +30 -8
  136. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js.map +2 -2
  137. package/dist/modules/customers/backend/customers/deals/[id]/page.js +1 -0
  138. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  139. package/dist/modules/customers/backend/customers/deals/page.js +16 -6
  140. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  141. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +62 -39
  142. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
  143. package/dist/modules/customers/backend/customers/people/[id]/page.js +41 -26
  144. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  145. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  146. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +50 -23
  147. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  148. package/dist/modules/customers/commands/addresses.js +16 -14
  149. package/dist/modules/customers/commands/addresses.js.map +2 -2
  150. package/dist/modules/customers/commands/companies.js +1 -1
  151. package/dist/modules/customers/commands/companies.js.map +2 -2
  152. package/dist/modules/customers/commands/interactions.js +41 -4
  153. package/dist/modules/customers/commands/interactions.js.map +2 -2
  154. package/dist/modules/customers/commands/people.js +1 -1
  155. package/dist/modules/customers/commands/people.js.map +2 -2
  156. package/dist/modules/customers/commands/personCompanyLinks.js +8 -5
  157. package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
  158. package/dist/modules/customers/commands/pipeline-stages.js +13 -11
  159. package/dist/modules/customers/commands/pipeline-stages.js.map +3 -3
  160. package/dist/modules/customers/components/AddressFormatSettings.js.map +2 -2
  161. package/dist/modules/customers/components/DictionarySettings.js +20 -13
  162. package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
  163. package/dist/modules/customers/components/DictionarySortSettings.js +4 -0
  164. package/dist/modules/customers/components/DictionarySortSettings.js.map +2 -2
  165. package/dist/modules/customers/components/PipelineSettings.js +38 -23
  166. package/dist/modules/customers/components/PipelineSettings.js.map +2 -2
  167. package/dist/modules/customers/components/detail/ActivityTimeline.js +1 -1
  168. package/dist/modules/customers/components/detail/ActivityTimeline.js.map +2 -2
  169. package/dist/modules/customers/components/detail/AddressesSection.js +4 -0
  170. package/dist/modules/customers/components/detail/AddressesSection.js.map +2 -2
  171. package/dist/modules/customers/components/detail/CompanyPeopleSection.js +28 -22
  172. package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
  173. package/dist/modules/customers/components/detail/DealsSection.js +36 -24
  174. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  175. package/dist/modules/customers/components/detail/EmailCardActions.js +5 -0
  176. package/dist/modules/customers/components/detail/EmailCardActions.js.map +2 -2
  177. package/dist/modules/customers/components/detail/EntityTagsDialog.js +7 -0
  178. package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
  179. package/dist/modules/customers/components/detail/ManageTagsDialog.js +34 -22
  180. package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +2 -2
  181. package/dist/modules/customers/components/detail/PersonCompaniesSection.js +41 -29
  182. package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
  183. package/dist/modules/customers/components/detail/RoleAssignmentRow.js +14 -8
  184. package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +2 -2
  185. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +14 -6
  186. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  187. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +29 -13
  188. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +2 -2
  189. package/dist/modules/customers/components/detail/hooks/useInteractions.js +77 -35
  190. package/dist/modules/customers/components/detail/hooks/useInteractions.js.map +2 -2
  191. package/dist/modules/customers/components/detail/hooks/usePersonTasks.js +25 -17
  192. package/dist/modules/customers/components/detail/hooks/usePersonTasks.js.map +2 -2
  193. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
  194. package/dist/modules/customers/components/formConfig.js.map +2 -2
  195. package/dist/modules/customers/data/guards.js +66 -0
  196. package/dist/modules/customers/data/guards.js.map +7 -0
  197. package/dist/modules/customers/di.js +37 -0
  198. package/dist/modules/customers/di.js.map +2 -2
  199. package/dist/modules/customers/lib/todoCompatibility.js +11 -0
  200. package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
  201. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  202. package/dist/modules/data_sync/api/options.js +4 -4
  203. package/dist/modules/data_sync/api/options.js.map +2 -2
  204. package/dist/modules/data_sync/api/schedules/route.js +9 -1
  205. package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
  206. package/dist/modules/data_sync/backend/data-sync/page.js +17 -8
  207. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  208. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +43 -22
  209. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  210. package/dist/modules/data_sync/lib/sync-schedule-service.js +9 -0
  211. package/dist/modules/data_sync/lib/sync-schedule-service.js.map +2 -2
  212. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +8 -1
  213. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
  214. package/dist/modules/dictionaries/api/[dictionaryId]/route.js +17 -1
  215. package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
  216. package/dist/modules/dictionaries/components/DictionariesManager.js +31 -10
  217. package/dist/modules/dictionaries/components/DictionariesManager.js.map +2 -2
  218. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js +28 -15
  219. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js.map +2 -2
  220. package/dist/modules/directory/api/organizations/route.js +3 -0
  221. package/dist/modules/directory/api/organizations/route.js.map +2 -2
  222. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js +2 -0
  223. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js.map +2 -2
  224. package/dist/modules/directory/backend/directory/organizations/page.js +9 -5
  225. package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
  226. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js +7 -3
  227. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js.map +2 -2
  228. package/dist/modules/directory/backend/directory/tenants/page.js +8 -4
  229. package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
  230. package/dist/modules/directory/commands/organizations.js +7 -2
  231. package/dist/modules/directory/commands/organizations.js.map +2 -2
  232. package/dist/modules/entities/api/records.js +66 -0
  233. package/dist/modules/entities/api/records.js.map +2 -2
  234. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js +1 -0
  235. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js.map +2 -2
  236. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +8 -4
  237. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  238. package/dist/modules/entities/lib/helpers.js +17 -0
  239. package/dist/modules/entities/lib/helpers.js.map +2 -2
  240. package/dist/modules/feature_toggles/api/global/[id]/override/route.js +2 -1
  241. package/dist/modules/feature_toggles/api/global/[id]/override/route.js.map +2 -2
  242. package/dist/modules/feature_toggles/api/overrides/route.js +15 -0
  243. package/dist/modules/feature_toggles/api/overrides/route.js.map +2 -2
  244. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js +15 -14
  245. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js.map +2 -2
  246. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js +20 -12
  247. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js.map +2 -2
  248. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +6 -2
  249. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
  250. package/dist/modules/feature_toggles/components/formConfig.js +2 -1
  251. package/dist/modules/feature_toggles/components/formConfig.js.map +2 -2
  252. package/dist/modules/feature_toggles/components/overrideFormConfig.js +5 -1
  253. package/dist/modules/feature_toggles/components/overrideFormConfig.js.map +2 -2
  254. package/dist/modules/feature_toggles/data/validators.js +7 -4
  255. package/dist/modules/feature_toggles/data/validators.js.map +2 -2
  256. package/dist/modules/inbox_ops/api/settings/route.js +17 -2
  257. package/dist/modules/inbox_ops/api/settings/route.js.map +2 -2
  258. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js +13 -8
  259. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js.map +2 -2
  260. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +9 -4
  261. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
  262. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +18 -11
  263. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
  264. package/dist/modules/integrations/backend/integrations/page.js +12 -8
  265. package/dist/modules/integrations/backend/integrations/page.js.map +2 -2
  266. package/dist/modules/messages/commands/messages.js +13 -10
  267. package/dist/modules/messages/commands/messages.js.map +2 -2
  268. package/dist/modules/perspectives/api/[tableId]/route.js +39 -30
  269. package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
  270. package/dist/modules/perspectives/services/perspectiveService.js +7 -0
  271. package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
  272. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +6 -14
  273. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +3 -3
  274. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +4 -2
  275. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  276. package/dist/modules/planner/components/AvailabilityRuleSetForm.js +2 -0
  277. package/dist/modules/planner/components/AvailabilityRuleSetForm.js.map +2 -2
  278. package/dist/modules/planner/components/AvailabilityRulesEditor.js +36 -11
  279. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  280. package/dist/modules/planner/components/AvailabilitySchedule.js +9 -5
  281. package/dist/modules/planner/components/AvailabilitySchedule.js.map +2 -2
  282. package/dist/modules/progress/api/jobs/[id]/route.js +7 -1
  283. package/dist/modules/progress/api/jobs/[id]/route.js.map +2 -2
  284. package/dist/modules/query_index/lib/engine.js +19 -0
  285. package/dist/modules/query_index/lib/engine.js.map +2 -2
  286. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js +1 -0
  287. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js.map +2 -2
  288. package/dist/modules/resources/backend/resources/resource-types/page.js +4 -2
  289. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  290. package/dist/modules/resources/backend/resources/resources/[id]/page.js +14 -3
  291. package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
  292. package/dist/modules/resources/backend/resources/resources/page.js +8 -4
  293. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  294. package/dist/modules/resources/components/ResourceCrudForm.js +2 -0
  295. package/dist/modules/resources/components/ResourceCrudForm.js.map +2 -2
  296. package/dist/modules/resources/components/ResourceTypeCrudForm.js +1 -0
  297. package/dist/modules/resources/components/ResourceTypeCrudForm.js.map +2 -2
  298. package/dist/modules/sales/api/documents/factory.js +7 -2
  299. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  300. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +3 -1
  301. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
  302. package/dist/modules/sales/backend/sales/channels/offers/page.js +13 -4
  303. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  304. package/dist/modules/sales/backend/sales/channels/page.js +16 -4
  305. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  306. package/dist/modules/sales/backend/sales/documents/[id]/page.js +68 -22
  307. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  308. package/dist/modules/sales/backend/sales/documents/create/page.js.map +2 -2
  309. package/dist/modules/sales/commands/documentAddresses.js +181 -2
  310. package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
  311. package/dist/modules/sales/commands/documents.js +29 -1
  312. package/dist/modules/sales/commands/documents.js.map +2 -2
  313. package/dist/modules/sales/commands/returns.js +12 -2
  314. package/dist/modules/sales/commands/returns.js.map +2 -2
  315. package/dist/modules/sales/commands/shared.js +15 -0
  316. package/dist/modules/sales/commands/shared.js.map +2 -2
  317. package/dist/modules/sales/commands/shipments.js +4 -1
  318. package/dist/modules/sales/commands/shipments.js.map +2 -2
  319. package/dist/modules/sales/components/AdjustmentKindSettings.js +19 -11
  320. package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
  321. package/dist/modules/sales/components/DocumentNumberSettings.js.map +2 -2
  322. package/dist/modules/sales/components/OrderEditingSettings.js.map +2 -2
  323. package/dist/modules/sales/components/PaymentMethodsSettings.js +12 -4
  324. package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
  325. package/dist/modules/sales/components/ShippingMethodsSettings.js +12 -4
  326. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
  327. package/dist/modules/sales/components/StatusSettings.js +18 -11
  328. package/dist/modules/sales/components/StatusSettings.js.map +2 -2
  329. package/dist/modules/sales/components/TaxRatesSettings.js +12 -4
  330. package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
  331. package/dist/modules/sales/components/channels/ChannelOfferForm.js +47 -16
  332. package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
  333. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +8 -4
  334. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  335. package/dist/modules/sales/components/documents/AddressesSection.js +44 -25
  336. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  337. package/dist/modules/sales/components/documents/AdjustmentsSection.js +43 -23
  338. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  339. package/dist/modules/sales/components/documents/ItemsSection.js +22 -13
  340. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  341. package/dist/modules/sales/components/documents/LineItemDialog.js +23 -10
  342. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  343. package/dist/modules/sales/components/documents/PaymentDialog.js +29 -14
  344. package/dist/modules/sales/components/documents/PaymentDialog.js.map +2 -2
  345. package/dist/modules/sales/components/documents/PaymentsSection.js +20 -10
  346. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  347. package/dist/modules/sales/components/documents/ReturnDialog.js +26 -17
  348. package/dist/modules/sales/components/documents/ReturnDialog.js.map +2 -2
  349. package/dist/modules/sales/components/documents/ReturnsSection.js +3 -1
  350. package/dist/modules/sales/components/documents/ReturnsSection.js.map +2 -2
  351. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +10 -5
  352. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  353. package/dist/modules/sales/components/documents/ShipmentDialog.js +21 -7
  354. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  355. package/dist/modules/sales/components/documents/ShipmentsSection.js +19 -10
  356. package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
  357. package/dist/modules/sales/components/documents/optimisticLock.js +27 -0
  358. package/dist/modules/sales/components/documents/optimisticLock.js.map +7 -0
  359. package/dist/modules/sales/di.js +18 -0
  360. package/dist/modules/sales/di.js.map +2 -2
  361. package/dist/modules/shipping_carriers/api/cancel/route.js +2 -2
  362. package/dist/modules/shipping_carriers/api/cancel/route.js.map +2 -2
  363. package/dist/modules/shipping_carriers/lib/status-sync.js +8 -1
  364. package/dist/modules/shipping_carriers/lib/status-sync.js.map +2 -2
  365. package/dist/modules/staff/api/job-histories.js +11 -2
  366. package/dist/modules/staff/api/job-histories.js.map +2 -2
  367. package/dist/modules/staff/api/timesheets/time-entries/route.js +11 -4
  368. package/dist/modules/staff/api/timesheets/time-entries/route.js.map +2 -2
  369. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +13 -8
  370. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
  371. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +2 -1
  372. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
  373. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +7 -4
  374. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  375. package/dist/modules/staff/backend/staff/team-members/page.js +4 -2
  376. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  377. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js +1 -0
  378. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js.map +2 -2
  379. package/dist/modules/staff/backend/staff/team-roles/page.js +4 -2
  380. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  381. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +5 -2
  382. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  383. package/dist/modules/staff/backend/staff/teams/page.js +12 -3
  384. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  385. package/dist/modules/staff/backend/staff/timesheets/page.js +4 -1
  386. package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
  387. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +2 -2
  388. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +12 -3
  389. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
  390. package/dist/modules/staff/commands/job-histories.js +40 -3
  391. package/dist/modules/staff/commands/job-histories.js.map +2 -2
  392. package/dist/modules/staff/components/LeaveRequestForm.js +1 -0
  393. package/dist/modules/staff/components/LeaveRequestForm.js.map +2 -2
  394. package/dist/modules/staff/components/TeamForm.js +1 -0
  395. package/dist/modules/staff/components/TeamForm.js.map +2 -2
  396. package/dist/modules/staff/components/TeamMemberForm.js +1 -0
  397. package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
  398. package/dist/modules/staff/components/TeamRoleForm.js +1 -0
  399. package/dist/modules/staff/components/TeamRoleForm.js.map +2 -2
  400. package/dist/modules/staff/components/detail/JobHistorySection.js +20 -7
  401. package/dist/modules/staff/components/detail/JobHistorySection.js.map +2 -2
  402. package/dist/modules/staff/data/validators.js +7 -1
  403. package/dist/modules/staff/data/validators.js.map +2 -2
  404. package/dist/modules/staff/lib/leaveRequestHelpers.js +2 -1
  405. package/dist/modules/staff/lib/leaveRequestHelpers.js.map +2 -2
  406. package/dist/modules/translations/components/TranslationManager.js +12 -8
  407. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  408. package/dist/modules/workflows/api/definitions/[id]/route.js +106 -0
  409. package/dist/modules/workflows/api/definitions/[id]/route.js.map +2 -2
  410. package/dist/modules/workflows/backend/definitions/[id]/page.js +11 -3
  411. package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
  412. package/dist/modules/workflows/backend/definitions/page.js +19 -8
  413. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  414. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +29 -16
  415. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  416. package/dist/modules/workflows/components/NodeEditDialog.js +3 -1
  417. package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
  418. package/dist/modules/workflows/components/WorkflowGraphImpl.js +4 -2
  419. package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +2 -2
  420. package/dist/modules/workflows/components/formConfig.js +4 -1
  421. package/dist/modules/workflows/components/formConfig.js.map +2 -2
  422. package/dist/modules/workflows/components/nodes/ParallelForkNode.js +49 -0
  423. package/dist/modules/workflows/components/nodes/ParallelForkNode.js.map +7 -0
  424. package/dist/modules/workflows/components/nodes/ParallelJoinNode.js +49 -0
  425. package/dist/modules/workflows/components/nodes/ParallelJoinNode.js.map +7 -0
  426. package/dist/modules/workflows/components/nodes/index.js +4 -0
  427. package/dist/modules/workflows/components/nodes/index.js.map +2 -2
  428. package/dist/modules/workflows/data/entities.js +81 -0
  429. package/dist/modules/workflows/data/entities.js.map +2 -2
  430. package/dist/modules/workflows/data/validators.js +146 -1
  431. package/dist/modules/workflows/data/validators.js.map +2 -2
  432. package/dist/modules/workflows/di.js +12 -0
  433. package/dist/modules/workflows/di.js.map +2 -2
  434. package/dist/modules/workflows/events.js +7 -1
  435. package/dist/modules/workflows/events.js.map +2 -2
  436. package/dist/modules/workflows/lib/activity-executor.js +4 -2
  437. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  438. package/dist/modules/workflows/lib/activity-queue-types.js.map +2 -2
  439. package/dist/modules/workflows/lib/event-logger.js +2 -0
  440. package/dist/modules/workflows/lib/event-logger.js.map +2 -2
  441. package/dist/modules/workflows/lib/execution-token.js +98 -0
  442. package/dist/modules/workflows/lib/execution-token.js.map +7 -0
  443. package/dist/modules/workflows/lib/node-type-icons.js +14 -5
  444. package/dist/modules/workflows/lib/node-type-icons.js.map +2 -2
  445. package/dist/modules/workflows/lib/parallel-handler.js +364 -0
  446. package/dist/modules/workflows/lib/parallel-handler.js.map +7 -0
  447. package/dist/modules/workflows/lib/signal-handler.js +63 -1
  448. package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
  449. package/dist/modules/workflows/lib/step-handler.js +74 -30
  450. package/dist/modules/workflows/lib/step-handler.js.map +2 -2
  451. package/dist/modules/workflows/lib/task-handler.js +26 -0
  452. package/dist/modules/workflows/lib/task-handler.js.map +2 -2
  453. package/dist/modules/workflows/lib/timer-handler.js +26 -1
  454. package/dist/modules/workflows/lib/timer-handler.js.map +2 -2
  455. package/dist/modules/workflows/lib/transition-handler.js +33 -21
  456. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  457. package/dist/modules/workflows/lib/workflow-executor.js +39 -1
  458. package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
  459. package/dist/modules/workflows/migrations/Migration20260602120000.js +24 -0
  460. package/dist/modules/workflows/migrations/Migration20260602120000.js.map +7 -0
  461. package/dist/modules/workflows/workers/workflow-activities.worker.js +8 -4
  462. package/dist/modules/workflows/workers/workflow-activities.worker.js.map +2 -2
  463. package/generated/entities/role/index.ts +1 -0
  464. package/generated/entities/step_instance/index.ts +1 -0
  465. package/generated/entities/user/index.ts +1 -0
  466. package/generated/entities/user_task/index.ts +1 -0
  467. package/generated/entities/workflow_branch_instance/index.ts +18 -0
  468. package/generated/entities/workflow_event/index.ts +1 -0
  469. package/generated/entities/workflow_instance/index.ts +1 -0
  470. package/generated/entities.ids.generated.ts +1 -0
  471. package/generated/entity-fields-registry.ts +26 -0
  472. package/jest.setup.ts +17 -0
  473. package/package.json +8 -7
  474. package/src/helpers/integration/optimisticLockUi.ts +172 -0
  475. package/src/helpers/integration/salesFixtures.ts +29 -0
  476. package/src/modules/api_keys/backend/api-keys/page.tsx +10 -5
  477. package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +19 -9
  478. package/src/modules/auth/api/roles/acl/route.ts +37 -11
  479. package/src/modules/auth/api/roles/route.ts +2 -0
  480. package/src/modules/auth/api/sidebar/preferences/route.ts +73 -0
  481. package/src/modules/auth/api/users/acl/route.ts +46 -18
  482. package/src/modules/auth/api/users/route.ts +2 -0
  483. package/src/modules/auth/backend/roles/[id]/edit/page.tsx +29 -4
  484. package/src/modules/auth/backend/roles/page.tsx +9 -4
  485. package/src/modules/auth/backend/users/[id]/edit/page.tsx +37 -4
  486. package/src/modules/auth/backend/users/page.tsx +7 -2
  487. package/src/modules/auth/components/AclEditor.tsx +10 -1
  488. package/src/modules/auth/data/entities.ts +7 -1
  489. package/src/modules/auth/services/sidebarPreferencesService.ts +38 -4
  490. package/src/modules/business_rules/api/rules/route.ts +30 -0
  491. package/src/modules/business_rules/api/sets/route.ts +30 -0
  492. package/src/modules/business_rules/backend/rules/[id]/page.tsx +16 -4
  493. package/src/modules/business_rules/backend/rules/page.tsx +20 -11
  494. package/src/modules/business_rules/backend/sets/[id]/page.tsx +16 -4
  495. package/src/modules/business_rules/backend/sets/page.tsx +20 -11
  496. package/src/modules/catalog/api/categories/route.ts +3 -0
  497. package/src/modules/catalog/api/products/route.ts +4 -0
  498. package/src/modules/catalog/backend/catalog/categories/[id]/edit/page.tsx +5 -0
  499. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +112 -35
  500. package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +56 -7
  501. package/src/modules/catalog/backend/catalog/products/optionSchemaClient.ts +2 -0
  502. package/src/modules/catalog/commands/variants.ts +32 -32
  503. package/src/modules/catalog/components/PriceKindSettings.tsx +20 -7
  504. package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +1 -0
  505. package/src/modules/catalog/components/products/ProductMediaManager.tsx +2 -0
  506. package/src/modules/catalog/components/products/ProductsDataTable.tsx +8 -4
  507. package/src/modules/catalog/components/products/productForm.ts +3 -0
  508. package/src/modules/catalog/components/products/variantForm.ts +9 -0
  509. package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +5 -0
  510. package/src/modules/currencies/backend/currencies/[id]/page.tsx +13 -6
  511. package/src/modules/currencies/backend/currencies/page.tsx +18 -11
  512. package/src/modules/currencies/backend/exchange-rates/[id]/page.tsx +3 -0
  513. package/src/modules/currencies/backend/exchange-rates/page.tsx +10 -6
  514. package/src/modules/currencies/commands/currencies.ts +10 -5
  515. package/src/modules/currencies/components/CurrencyFetchingConfig.tsx +31 -21
  516. package/src/modules/customer_accounts/api/admin/roles/[id].ts +35 -5
  517. package/src/modules/customer_accounts/api/admin/roles.ts +2 -0
  518. package/src/modules/customer_accounts/api/admin/users/[id].ts +38 -5
  519. package/src/modules/customer_accounts/api/admin/users.ts +2 -0
  520. package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +34 -20
  521. package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +9 -4
  522. package/src/modules/customer_accounts/backend/customer_accounts/settings/domain/page.tsx +11 -4
  523. package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +28 -17
  524. package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +19 -11
  525. package/src/modules/customers/AGENTS.md +2 -2
  526. package/src/modules/customers/api/companies/route.ts +14 -1
  527. package/src/modules/customers/api/deals/route.ts +3 -0
  528. package/src/modules/customers/api/people/route.ts +12 -1
  529. package/src/modules/customers/api/todos/route.ts +1 -0
  530. package/src/modules/customers/backend/config/customers/deals/page.tsx +1 -0
  531. package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +36 -21
  532. package/src/modules/customers/backend/customers/companies/[id]/page.tsx +52 -27
  533. package/src/modules/customers/backend/customers/companies/page.tsx +2 -0
  534. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +27 -5
  535. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.ts +39 -7
  536. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +1 -0
  537. package/src/modules/customers/backend/customers/deals/page.tsx +18 -6
  538. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +64 -39
  539. package/src/modules/customers/backend/customers/people/[id]/page.tsx +46 -26
  540. package/src/modules/customers/backend/customers/people/page.tsx +2 -0
  541. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +84 -24
  542. package/src/modules/customers/commands/addresses.ts +16 -14
  543. package/src/modules/customers/commands/companies.ts +3 -1
  544. package/src/modules/customers/commands/interactions.ts +50 -4
  545. package/src/modules/customers/commands/people.ts +2 -1
  546. package/src/modules/customers/commands/personCompanyLinks.ts +8 -5
  547. package/src/modules/customers/commands/pipeline-stages.ts +16 -16
  548. package/src/modules/customers/components/AddressFormatSettings.tsx +1 -0
  549. package/src/modules/customers/components/DictionarySettings.tsx +18 -13
  550. package/src/modules/customers/components/DictionarySortSettings.tsx +4 -0
  551. package/src/modules/customers/components/PipelineSettings.tsx +42 -21
  552. package/src/modules/customers/components/detail/ActivityTimeline.tsx +3 -3
  553. package/src/modules/customers/components/detail/AddressesSection.tsx +4 -0
  554. package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +2 -0
  555. package/src/modules/customers/components/detail/DealsSection.tsx +4 -0
  556. package/src/modules/customers/components/detail/EmailCardActions.tsx +5 -0
  557. package/src/modules/customers/components/detail/EntityTagsDialog.tsx +7 -0
  558. package/src/modules/customers/components/detail/ManageTagsDialog.tsx +4 -0
  559. package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +4 -0
  560. package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +2 -0
  561. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +23 -7
  562. package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +25 -15
  563. package/src/modules/customers/components/detail/hooks/useInteractions.ts +76 -35
  564. package/src/modules/customers/components/detail/hooks/usePersonTasks.ts +30 -17
  565. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +2 -0
  566. package/src/modules/customers/components/detail/types.ts +1 -0
  567. package/src/modules/customers/components/formConfig.tsx +2 -0
  568. package/src/modules/customers/data/guards.ts +67 -0
  569. package/src/modules/customers/di.ts +66 -0
  570. package/src/modules/customers/i18n/de.json +2 -0
  571. package/src/modules/customers/i18n/en.json +2 -0
  572. package/src/modules/customers/i18n/es.json +2 -0
  573. package/src/modules/customers/i18n/pl.json +2 -0
  574. package/src/modules/customers/lib/todoCompatibility.ts +14 -0
  575. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +2 -0
  576. package/src/modules/data_sync/api/options.ts +7 -4
  577. package/src/modules/data_sync/api/schedules/route.ts +9 -1
  578. package/src/modules/data_sync/backend/data-sync/page.tsx +18 -5
  579. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +46 -19
  580. package/src/modules/data_sync/lib/sync-schedule-service.ts +11 -0
  581. package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +8 -1
  582. package/src/modules/dictionaries/api/[dictionaryId]/route.ts +23 -0
  583. package/src/modules/dictionaries/components/DictionariesManager.tsx +32 -9
  584. package/src/modules/dictionaries/components/DictionaryEntriesEditor.tsx +30 -14
  585. package/src/modules/dictionaries/i18n/de.json +1 -0
  586. package/src/modules/dictionaries/i18n/en.json +1 -0
  587. package/src/modules/dictionaries/i18n/es.json +1 -0
  588. package/src/modules/dictionaries/i18n/pl.json +1 -0
  589. package/src/modules/directory/api/organizations/route.ts +3 -0
  590. package/src/modules/directory/backend/directory/organizations/[id]/edit/page.tsx +8 -0
  591. package/src/modules/directory/backend/directory/organizations/page.tsx +10 -5
  592. package/src/modules/directory/backend/directory/tenants/[id]/edit/page.tsx +16 -5
  593. package/src/modules/directory/backend/directory/tenants/page.tsx +8 -4
  594. package/src/modules/directory/commands/organizations.ts +7 -4
  595. package/src/modules/entities/api/records.ts +99 -0
  596. package/src/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.tsx +7 -0
  597. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +8 -4
  598. package/src/modules/entities/lib/helpers.ts +17 -0
  599. package/src/modules/feature_toggles/api/global/[id]/override/route.ts +1 -0
  600. package/src/modules/feature_toggles/api/overrides/route.ts +19 -0
  601. package/src/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.tsx +19 -13
  602. package/src/modules/feature_toggles/components/FeatureToggleOverrideCard.tsx +22 -12
  603. package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +7 -2
  604. package/src/modules/feature_toggles/components/formConfig.tsx +2 -1
  605. package/src/modules/feature_toggles/components/overrideFormConfig.tsx +10 -1
  606. package/src/modules/feature_toggles/data/validators.ts +11 -3
  607. package/src/modules/inbox_ops/api/settings/route.ts +18 -0
  608. package/src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx +15 -10
  609. package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +9 -4
  610. package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +20 -11
  611. package/src/modules/integrations/backend/integrations/page.tsx +13 -8
  612. package/src/modules/messages/commands/messages.ts +27 -15
  613. package/src/modules/perspectives/api/[tableId]/route.ts +11 -2
  614. package/src/modules/perspectives/services/perspectiveService.ts +13 -1
  615. package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +16 -14
  616. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +6 -3
  617. package/src/modules/planner/components/AvailabilityRuleSetForm.tsx +3 -0
  618. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +58 -15
  619. package/src/modules/planner/components/AvailabilitySchedule.tsx +22 -7
  620. package/src/modules/progress/api/jobs/[id]/route.ts +7 -0
  621. package/src/modules/query_index/lib/engine.ts +34 -0
  622. package/src/modules/resources/backend/resources/resource-types/[id]/edit/page.tsx +7 -1
  623. package/src/modules/resources/backend/resources/resource-types/page.tsx +6 -3
  624. package/src/modules/resources/backend/resources/resources/[id]/page.tsx +23 -3
  625. package/src/modules/resources/backend/resources/resources/page.tsx +15 -4
  626. package/src/modules/resources/components/ResourceCrudForm.tsx +3 -0
  627. package/src/modules/resources/components/ResourceTypeCrudForm.tsx +2 -0
  628. package/src/modules/sales/api/documents/factory.ts +13 -1
  629. package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +6 -0
  630. package/src/modules/sales/backend/sales/channels/offers/page.tsx +10 -4
  631. package/src/modules/sales/backend/sales/channels/page.tsx +19 -4
  632. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +73 -20
  633. package/src/modules/sales/backend/sales/documents/create/page.tsx +2 -0
  634. package/src/modules/sales/commands/documentAddresses.ts +226 -4
  635. package/src/modules/sales/commands/documents.ts +28 -0
  636. package/src/modules/sales/commands/returns.ts +12 -3
  637. package/src/modules/sales/commands/shared.ts +36 -0
  638. package/src/modules/sales/commands/shipments.ts +17 -1
  639. package/src/modules/sales/components/AdjustmentKindSettings.tsx +20 -11
  640. package/src/modules/sales/components/DocumentNumberSettings.tsx +1 -0
  641. package/src/modules/sales/components/OrderEditingSettings.tsx +1 -0
  642. package/src/modules/sales/components/PaymentMethodsSettings.tsx +12 -4
  643. package/src/modules/sales/components/ShippingMethodsSettings.tsx +12 -4
  644. package/src/modules/sales/components/StatusSettings.tsx +20 -11
  645. package/src/modules/sales/components/TaxRatesSettings.tsx +12 -5
  646. package/src/modules/sales/components/channels/ChannelOfferForm.tsx +67 -14
  647. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +7 -4
  648. package/src/modules/sales/components/documents/AddressesSection.tsx +35 -25
  649. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +50 -25
  650. package/src/modules/sales/components/documents/ItemsSection.tsx +24 -13
  651. package/src/modules/sales/components/documents/LineItemDialog.tsx +26 -9
  652. package/src/modules/sales/components/documents/PaymentDialog.tsx +33 -14
  653. package/src/modules/sales/components/documents/PaymentsSection.tsx +22 -10
  654. package/src/modules/sales/components/documents/ReturnDialog.tsx +28 -17
  655. package/src/modules/sales/components/documents/ReturnsSection.tsx +4 -1
  656. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +11 -4
  657. package/src/modules/sales/components/documents/ShipmentDialog.tsx +23 -8
  658. package/src/modules/sales/components/documents/ShipmentsSection.tsx +20 -10
  659. package/src/modules/sales/components/documents/optimisticLock.ts +34 -0
  660. package/src/modules/sales/components/documents/shipmentTypes.ts +1 -0
  661. package/src/modules/sales/di.ts +35 -0
  662. package/src/modules/sales/i18n/de.json +3 -0
  663. package/src/modules/sales/i18n/en.json +3 -0
  664. package/src/modules/sales/i18n/es.json +3 -0
  665. package/src/modules/sales/i18n/pl.json +3 -0
  666. package/src/modules/shipping_carriers/api/cancel/route.ts +2 -2
  667. package/src/modules/shipping_carriers/lib/status-sync.ts +19 -0
  668. package/src/modules/staff/api/job-histories.ts +12 -2
  669. package/src/modules/staff/api/timesheets/time-entries/route.ts +16 -4
  670. package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +12 -7
  671. package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +2 -0
  672. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +16 -5
  673. package/src/modules/staff/backend/staff/team-members/page.tsx +6 -2
  674. package/src/modules/staff/backend/staff/team-roles/[id]/edit/page.tsx +8 -0
  675. package/src/modules/staff/backend/staff/team-roles/page.tsx +6 -2
  676. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +13 -3
  677. package/src/modules/staff/backend/staff/teams/page.tsx +9 -3
  678. package/src/modules/staff/backend/staff/timesheets/page.tsx +10 -1
  679. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +4 -0
  680. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +9 -3
  681. package/src/modules/staff/commands/job-histories.ts +42 -3
  682. package/src/modules/staff/components/LeaveRequestForm.tsx +2 -0
  683. package/src/modules/staff/components/TeamForm.tsx +2 -0
  684. package/src/modules/staff/components/TeamMemberForm.tsx +2 -0
  685. package/src/modules/staff/components/TeamRoleForm.tsx +2 -0
  686. package/src/modules/staff/components/detail/JobHistorySection.tsx +28 -6
  687. package/src/modules/staff/data/validators.ts +6 -0
  688. package/src/modules/staff/i18n/de.json +1 -0
  689. package/src/modules/staff/i18n/en.json +1 -0
  690. package/src/modules/staff/i18n/es.json +1 -0
  691. package/src/modules/staff/i18n/pl.json +1 -0
  692. package/src/modules/staff/lib/leaveRequestHelpers.ts +4 -0
  693. package/src/modules/translations/components/TranslationManager.tsx +13 -8
  694. package/src/modules/workflows/api/definitions/[id]/route.ts +112 -0
  695. package/src/modules/workflows/backend/definitions/[id]/page.tsx +20 -4
  696. package/src/modules/workflows/backend/definitions/page.tsx +20 -9
  697. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +29 -16
  698. package/src/modules/workflows/components/NodeEditDialog.tsx +2 -0
  699. package/src/modules/workflows/components/WorkflowGraphImpl.tsx +3 -1
  700. package/src/modules/workflows/components/formConfig.tsx +5 -0
  701. package/src/modules/workflows/components/nodes/ParallelForkNode.tsx +66 -0
  702. package/src/modules/workflows/components/nodes/ParallelJoinNode.tsx +66 -0
  703. package/src/modules/workflows/components/nodes/index.ts +6 -0
  704. package/src/modules/workflows/data/entities.ts +109 -0
  705. package/src/modules/workflows/data/validators.ts +223 -0
  706. package/src/modules/workflows/di.ts +20 -0
  707. package/src/modules/workflows/events.ts +7 -0
  708. package/src/modules/workflows/i18n/de.json +13 -0
  709. package/src/modules/workflows/i18n/en.json +13 -0
  710. package/src/modules/workflows/i18n/es.json +13 -0
  711. package/src/modules/workflows/i18n/pl.json +13 -0
  712. package/src/modules/workflows/lib/activity-executor.ts +8 -2
  713. package/src/modules/workflows/lib/activity-queue-types.ts +3 -0
  714. package/src/modules/workflows/lib/event-logger.ts +3 -0
  715. package/src/modules/workflows/lib/execution-token.ts +166 -0
  716. package/src/modules/workflows/lib/node-type-icons.ts +11 -2
  717. package/src/modules/workflows/lib/parallel-handler.ts +575 -0
  718. package/src/modules/workflows/lib/signal-handler.ts +72 -1
  719. package/src/modules/workflows/lib/step-handler.ts +94 -34
  720. package/src/modules/workflows/lib/task-handler.ts +32 -0
  721. package/src/modules/workflows/lib/timer-handler.ts +30 -1
  722. package/src/modules/workflows/lib/transition-handler.ts +56 -24
  723. package/src/modules/workflows/lib/workflow-executor.ts +53 -1
  724. package/src/modules/workflows/migrations/.snapshot-open-mercato.json +263 -0
  725. package/src/modules/workflows/migrations/Migration20260602120000.ts +25 -0
  726. package/src/modules/workflows/workers/workflow-activities.worker.ts +9 -4
@@ -2,7 +2,8 @@
2
2
  import * as React from 'react'
3
3
  import { Page, PageBody } from '@open-mercato/ui/backend/Page'
4
4
  import { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'
5
- import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
5
+ import { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
6
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
6
7
  import { deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'
7
8
  import { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'
8
9
  import { AclEditor, type AclData } from '@open-mercato/core/modules/auth/components/AclEditor'
@@ -16,6 +17,7 @@ import { extractCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-
16
17
  type EditRoleFormValues = {
17
18
  name?: string
18
19
  tenantId?: string | null
20
+ updatedAt?: string | null
19
21
  } & Record<string, unknown>
20
22
 
21
23
  type RoleRecord = {
@@ -24,6 +26,7 @@ type RoleRecord = {
24
26
  tenantId: string | null
25
27
  tenantName?: string | null
26
28
  usersCount?: number | null
29
+ updatedAt?: string | null
27
30
  } & Record<string, unknown>
28
31
 
29
32
  type RoleListResponse = {
@@ -37,6 +40,7 @@ export default function EditRolePage({ params }: { params?: { id?: string } }) {
37
40
  const [initial, setInitial] = React.useState<RoleRecord | null>(null)
38
41
  const [loading, setLoading] = React.useState(true)
39
42
  const [aclData, setAclData] = React.useState<AclData>({ isSuperAdmin: false, features: [], organizations: null })
43
+ const [aclUpdatedAt, setAclUpdatedAt] = React.useState<string | null>(null)
40
44
  const [actorIsSuperAdmin, setActorIsSuperAdmin] = React.useState(false)
41
45
  const [selectedTenantId, setSelectedTenantId] = React.useState<string | null>(null)
42
46
  const widgetEditorRef = React.useRef<WidgetVisibilityEditorHandle | null>(null)
@@ -158,6 +162,7 @@ export default function EditRolePage({ params }: { params?: { id?: string } }) {
158
162
  canEditOrganizations
159
163
  value={aclData}
160
164
  onChange={setAclData}
165
+ onVersionChange={setAclUpdatedAt}
161
166
  currentUserIsSuperAdmin={actorIsSuperAdmin}
162
167
  tenantId={selectedTenantId ?? null}
163
168
  preserveOnTenantChange
@@ -213,17 +218,37 @@ export default function EditRolePage({ params }: { params?: { id?: string } }) {
213
218
  if (Object.keys(customFields).length) {
214
219
  payload.customFields = customFields
215
220
  }
216
- await updateCrud('auth/roles', payload)
217
- await updateCrud('auth/roles/acl', { roleId: id, tenantId: effectiveTenantId, ...aclData }, {
221
+ const roleOptimisticLockHeader = buildOptimisticLockHeader(initial?.updatedAt)
222
+ if (Object.keys(roleOptimisticLockHeader).length > 0) {
223
+ await withScopedApiRequestHeaders(roleOptimisticLockHeader, () => updateCrud('auth/roles', payload))
224
+ } else {
225
+ await updateCrud('auth/roles', payload)
226
+ }
227
+ // Optimistic lock the ACL save against the loaded RoleAcl version so a
228
+ // concurrent permission edit cannot silently overwrite (#2055). CrudForm
229
+ // surfaces the 409 as the unified conflict bar.
230
+ const aclLockHeader = buildOptimisticLockHeader(aclUpdatedAt)
231
+ const saveRoleAcl = () => updateCrud('auth/roles/acl', { roleId: id, tenantId: effectiveTenantId, ...aclData }, {
218
232
  errorMessage: t('auth.roles.form.errors.aclUpdate', 'Failed to update role access control'),
219
233
  })
234
+ if (Object.keys(aclLockHeader).length > 0) {
235
+ await withScopedApiRequestHeaders(aclLockHeader, saveRoleAcl)
236
+ } else {
237
+ await saveRoleAcl()
238
+ }
220
239
  await widgetEditorRef.current?.save()
221
240
  try { window.dispatchEvent(new Event('om:refresh-sidebar')) } catch {}
222
241
  }}
223
242
  onDelete={async () => {
224
- await deleteCrud('auth/roles', String(id), {
243
+ const roleOptimisticLockHeader = buildOptimisticLockHeader(initial?.updatedAt)
244
+ const deleteRole = () => deleteCrud('auth/roles', String(id), {
225
245
  errorMessage: t('auth.roles.form.errors.delete', 'Failed to delete role'),
226
246
  })
247
+ if (Object.keys(roleOptimisticLockHeader).length > 0) {
248
+ await withScopedApiRequestHeaders(roleOptimisticLockHeader, deleteRole)
249
+ } else {
250
+ await deleteRole()
251
+ }
227
252
  }}
228
253
  deleteRedirect={`/backend/roles?flash=${encodeURIComponent(t('auth.roles.flash.deleted', 'Role deleted'))}&type=success`}
229
254
  />
@@ -6,7 +6,8 @@ import { DataTable } from '@open-mercato/ui/backend/DataTable'
6
6
  import type { ColumnDef, SortingState } from '@tanstack/react-table'
7
7
  import { Button } from '@open-mercato/ui/primitives/button'
8
8
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
9
- import { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
9
+ import { apiCall, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
10
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
10
11
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
11
12
  import { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'
12
13
  import { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
@@ -20,6 +21,7 @@ type Row = {
20
21
  tenantId?: string | null
21
22
  tenantIds?: string[]
22
23
  tenantName?: string | null
24
+ updatedAt?: string | null
23
25
  }
24
26
 
25
27
  export default function RolesListPage() {
@@ -77,9 +79,12 @@ export default function RolesListPage() {
77
79
  })
78
80
  if (!confirmed) return
79
81
  try {
80
- const call = await apiCall(
81
- `/api/auth/roles?id=${encodeURIComponent(row.id)}`,
82
- { method: 'DELETE' },
82
+ const call = await withScopedApiRequestHeaders(
83
+ buildOptimisticLockHeader(row.updatedAt),
84
+ () => apiCall(
85
+ `/api/auth/roles?id=${encodeURIComponent(row.id)}`,
86
+ { method: 'DELETE' },
87
+ ),
83
88
  )
84
89
  if (!call.ok) {
85
90
  await raiseCrudError(call.response, t('auth.roles.list.error.delete', 'Failed to delete role'))
@@ -3,7 +3,8 @@ import * as React from 'react'
3
3
  import { E } from '#generated/entities.ids.generated'
4
4
  import { Page, PageBody } from '@open-mercato/ui/backend/Page'
5
5
  import { CrudForm, type CrudField, type CrudFormGroup, type CrudFieldOption } from '@open-mercato/ui/backend/CrudForm'
6
- import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
6
+ import { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
7
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
7
8
  import { deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'
8
9
  import { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'
9
10
  import { AclEditor, type AclData } from '@open-mercato/core/modules/auth/components/AclEditor'
@@ -27,6 +28,7 @@ type EditUserFormValues = {
27
28
  tenantId: string | null
28
29
  organizationId: string | null
29
30
  roles: string[]
31
+ updatedAt?: string | null
30
32
  } & Record<string, unknown>
31
33
 
32
34
  type LoadedUser = {
@@ -40,6 +42,7 @@ type LoadedUser = {
40
42
  roles: string[]
41
43
  roleIds: string[]
42
44
  hasPassword: boolean
45
+ updatedAt: string | null
43
46
  }
44
47
 
45
48
  type UserApiItem = {
@@ -53,6 +56,8 @@ type UserApiItem = {
53
56
  roles?: unknown
54
57
  roleIds?: unknown
55
58
  hasPassword?: boolean
59
+ updatedAt?: string | null
60
+ updated_at?: string | null
56
61
  }
57
62
 
58
63
  type UserListResponse = {
@@ -123,6 +128,7 @@ export default function EditUserPage({ params }: { params?: { id?: string } }) {
123
128
  const [isNotFound, setIsNotFound] = React.useState(false)
124
129
  const [canEditOrgs, setCanEditOrgs] = React.useState(false)
125
130
  const [aclData, setAclData] = React.useState<AclData>({ isSuperAdmin: false, features: [], organizations: null })
131
+ const [aclUpdatedAt, setAclUpdatedAt] = React.useState<string | null>(null)
126
132
  const [customFieldValues, setCustomFieldValues] = React.useState<Record<string, unknown>>({})
127
133
  const [actorIsSuperAdmin, setActorIsSuperAdmin] = React.useState(false)
128
134
  const [actorResolved, setActorResolved] = React.useState(false)
@@ -209,6 +215,11 @@ export default function EditUserPage({ params }: { params?: { id?: string } }) {
209
215
  roles: roleNames,
210
216
  roleIds: roleIds.length > 0 ? roleIds : roleNames,
211
217
  hasPassword: item.hasPassword !== false,
218
+ updatedAt: typeof item.updatedAt === 'string'
219
+ ? item.updatedAt
220
+ : typeof item.updated_at === 'string'
221
+ ? item.updated_at
222
+ : null,
212
223
  })
213
224
  setSelectedTenantId(item.tenantId ? String(item.tenantId) : null)
214
225
  const custom = extractCustomFieldEntries(item as Record<string, unknown>)
@@ -353,6 +364,7 @@ export default function EditUserPage({ params }: { params?: { id?: string } }) {
353
364
  canEditOrganizations={canEditOrgs}
354
365
  value={aclData}
355
366
  onChange={setAclData}
367
+ onVersionChange={setAclUpdatedAt}
356
368
  userRoles={initialUser?.roles || []}
357
369
  currentUserIsSuperAdmin={actorIsSuperAdmin}
358
370
  tenantId={selectedTenantId ?? null}
@@ -393,6 +405,7 @@ export default function EditUserPage({ params }: { params?: { id?: string } }) {
393
405
  tenantId: initialUser.tenantId,
394
406
  organizationId: initialUser.organizationId,
395
407
  roles: initialUser.roleIds,
408
+ updatedAt: initialUser.updatedAt,
396
409
  ...customFieldValues,
397
410
  }
398
411
  }
@@ -471,17 +484,37 @@ export default function EditUserPage({ params }: { params?: { id?: string } }) {
471
484
  roles: Array.isArray(values.roles) ? values.roles : [],
472
485
  ...(Object.keys(customFields).length ? { customFields } : {}),
473
486
  }
474
- await updateCrud('auth/users', payload)
475
- await updateCrud('auth/users/acl', { userId: id, ...aclData }, {
487
+ const userOptimisticLockHeader = buildOptimisticLockHeader(initialUser?.updatedAt)
488
+ if (Object.keys(userOptimisticLockHeader).length > 0) {
489
+ await withScopedApiRequestHeaders(userOptimisticLockHeader, () => updateCrud('auth/users', payload))
490
+ } else {
491
+ await updateCrud('auth/users', payload)
492
+ }
493
+ // Optimistic lock the ACL save against the loaded UserAcl version so a
494
+ // concurrent permission edit cannot silently overwrite (#2055). CrudForm
495
+ // surfaces the 409 as the unified conflict bar.
496
+ const aclLockHeader = buildOptimisticLockHeader(aclUpdatedAt)
497
+ const saveUserAcl = () => updateCrud('auth/users/acl', { userId: id, ...aclData }, {
476
498
  errorMessage: t('auth.users.form.errors.aclUpdate', 'Failed to update user access control'),
477
499
  })
500
+ if (Object.keys(aclLockHeader).length > 0) {
501
+ await withScopedApiRequestHeaders(aclLockHeader, saveUserAcl)
502
+ } else {
503
+ await saveUserAcl()
504
+ }
478
505
  await widgetEditorRef.current?.save()
479
506
  try { window.dispatchEvent(new Event('om:refresh-sidebar')) } catch {}
480
507
  }}
481
508
  onDelete={async () => {
482
- await deleteCrud('auth/users', String(id), {
509
+ const userOptimisticLockHeader = buildOptimisticLockHeader(initialUser?.updatedAt)
510
+ const deleteUser = () => deleteCrud('auth/users', String(id), {
483
511
  errorMessage: t('auth.users.form.errors.delete', 'Failed to delete user'),
484
512
  })
513
+ if (Object.keys(userOptimisticLockHeader).length > 0) {
514
+ await withScopedApiRequestHeaders(userOptimisticLockHeader, deleteUser)
515
+ } else {
516
+ await deleteUser()
517
+ }
485
518
  }}
486
519
  deleteRedirect={`/backend/users?flash=${encodeURIComponent(t('auth.users.flash.deleted', 'User deleted'))}&type=success`}
487
520
  />
@@ -8,7 +8,8 @@ import type { ColumnDef, SortingState } from '@tanstack/react-table'
8
8
  import type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'
9
9
  import { Button } from '@open-mercato/ui/primitives/button'
10
10
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
11
- import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
11
+ import { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
12
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
12
13
  import { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'
13
14
  import { useQuery, useQueryClient } from '@tanstack/react-query'
14
15
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
@@ -26,6 +27,7 @@ type Row = {
26
27
  tenantId: string | null
27
28
  tenantName?: string | null
28
29
  roles: string[]
30
+ updatedAt?: string | null
29
31
  }
30
32
 
31
33
  type FilterOption = { value: string; label: string }
@@ -388,7 +390,10 @@ export default function UsersListPage() {
388
390
  if (!confirmed) return
389
391
  const deleteErrorMessage = t('auth.users.list.error.delete', 'Failed to delete user')
390
392
  try {
391
- const call = await apiCall(`/api/auth/users?id=${encodeURIComponent(row.id)}`, { method: 'DELETE' })
393
+ const call = await withScopedApiRequestHeaders(
394
+ buildOptimisticLockHeader(row.updatedAt),
395
+ () => apiCall(`/api/auth/users?id=${encodeURIComponent(row.id)}`, { method: 'DELETE' }),
396
+ )
392
397
  if (!call.ok) {
393
398
  await raiseCrudError(call.response, deleteErrorMessage)
394
399
  }
@@ -68,6 +68,7 @@ type AclPayload = {
68
68
  isSuperAdmin?: boolean
69
69
  features?: unknown
70
70
  organizations?: unknown
71
+ updatedAt?: string | null
71
72
  }
72
73
  type OrganizationListResponse = { items?: Array<{ id?: string; name?: string }> }
73
74
 
@@ -99,6 +100,7 @@ export function AclEditor({
99
100
  canEditOrganizations,
100
101
  value,
101
102
  onChange,
103
+ onVersionChange,
102
104
  userRoles,
103
105
  currentUserIsSuperAdmin,
104
106
  tenantId,
@@ -109,6 +111,12 @@ export function AclEditor({
109
111
  canEditOrganizations: boolean
110
112
  value?: AclData
111
113
  onChange?: (data: AclData) => void
114
+ /**
115
+ * Reports the loaded ACL row's `updatedAt` (or null when none exists) so the
116
+ * parent can send the optimistic-lock header on save and reject stale ACL
117
+ * overwrites (#2055).
118
+ */
119
+ onVersionChange?: (updatedAt: string | null) => void
112
120
  userRoles?: string[]
113
121
  currentUserIsSuperAdmin?: boolean
114
122
  tenantId?: string | null
@@ -168,8 +176,9 @@ export function AclEditor({
168
176
  setIsSuperAdmin(!!aclJson.isSuperAdmin)
169
177
  setGranted(actorSanitizeFeatures(aclJson.features))
170
178
  setOrganizations(aclJson.organizations == null ? null : Array.isArray(aclJson.organizations) ? aclJson.organizations : [])
179
+ onVersionChange?.(typeof aclJson.updatedAt === 'string' ? aclJson.updatedAt : null)
171
180
  } catch {}
172
- }, [kind, targetId, actorSanitizeFeatures])
181
+ }, [kind, targetId, actorSanitizeFeatures, onVersionChange])
173
182
 
174
183
  React.useEffect(() => {
175
184
  const cancelled = { current: false }
@@ -33,7 +33,10 @@ export class User {
33
33
  @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })
34
34
  createdAt: Date = new Date()
35
35
 
36
- @Property({ name: 'deleted_at', type: Date, nullable: true })
36
+ @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date(), nullable: true })
37
+ updatedAt?: Date | null
38
+
39
+ @Property({ name: 'deleted_at', type: Date, nullable: true })
37
40
  deletedAt?: Date | null
38
41
  }
39
42
 
@@ -52,6 +55,9 @@ export class Role {
52
55
  @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })
53
56
  createdAt: Date = new Date()
54
57
 
58
+ @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date(), nullable: true })
59
+ updatedAt?: Date | null
60
+
55
61
  @Property({ name: 'deleted_at', type: Date, nullable: true })
56
62
  deletedAt?: Date | null
57
63
  }
@@ -54,6 +54,38 @@ export async function loadSidebarPreference(
54
54
  return normalizeSidebarSettings(existing?.settingsJson as SidebarPreferencesSettings | undefined)
55
55
  }
56
56
 
57
+ export async function loadSidebarPreferenceUpdatedAt(
58
+ em: EntityManager,
59
+ scope: SidebarPreferenceScope,
60
+ ): Promise<{ id: string; updatedAt: Date | null } | null> {
61
+ const { userId, tenantId, organizationId } = normalizeScope(scope)
62
+ const existing = await findOneWithDecryption(
63
+ em,
64
+ UserSidebarPreference,
65
+ { user: userId, tenantId, organizationId },
66
+ undefined,
67
+ { tenantId, organizationId },
68
+ )
69
+ if (!existing) return null
70
+ return { id: existing.id, updatedAt: existing.updatedAt ?? null }
71
+ }
72
+
73
+ export async function loadRoleSidebarPreferenceUpdatedAt(
74
+ em: EntityManager,
75
+ scope: RoleSidebarPreferenceScope,
76
+ ): Promise<{ id: string; updatedAt: Date | null } | null> {
77
+ const { roleId, tenantId } = normalizeRoleScope(scope)
78
+ const existing = await findOneWithDecryption(
79
+ em,
80
+ RoleSidebarPreference,
81
+ { role: roleId, tenantId },
82
+ undefined,
83
+ { tenantId, organizationId: null },
84
+ )
85
+ if (!existing) return null
86
+ return { id: existing.id, updatedAt: existing.updatedAt ?? null }
87
+ }
88
+
57
89
  export async function saveSidebarPreference(
58
90
  em: EntityManager,
59
91
  scope: SidebarPreferenceScope,
@@ -389,7 +421,7 @@ export async function updateSidebarVariant(
389
421
  if (!variant) return null
390
422
  const target = variant
391
423
  await withAtomicFlush(em, [
392
- async () => {
424
+ () => {
393
425
  if (typeof input.name === 'string' && input.name.trim().length > 0) {
394
426
  target.name = input.name.trim()
395
427
  }
@@ -400,12 +432,14 @@ export async function updateSidebarVariant(
400
432
  })
401
433
  }
402
434
  if (typeof input.isActive === 'boolean') {
403
- if (input.isActive) {
404
- await deactivateAllVariants(em, scope, variantId)
405
- }
406
435
  target.isActive = input.isActive
407
436
  }
408
437
  },
438
+ async () => {
439
+ if (input.isActive === true) {
440
+ await deactivateAllVariants(em, scope, variantId)
441
+ }
442
+ },
409
443
  ], { transaction: true })
410
444
  return toVariantRecord(target)
411
445
  }
@@ -4,6 +4,8 @@ import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
4
4
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
5
5
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
6
6
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
7
+ import { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
8
+ import { enforceCommandOptimisticLock } from '@open-mercato/shared/lib/crud/optimistic-lock-command'
7
9
  import { BusinessRule } from '../../data/entities'
8
10
  import type { EntityManager } from '@mikro-orm/postgresql'
9
11
  import { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'
@@ -277,6 +279,20 @@ export async function PUT(req: Request) {
277
279
  return NextResponse.json({ error: 'Rule not found' }, { status: 404 })
278
280
  }
279
281
 
282
+ try {
283
+ enforceCommandOptimisticLock({
284
+ resourceKind: 'business_rules.rule',
285
+ resourceId: rule.id,
286
+ current: rule.updatedAt ?? null,
287
+ request: req,
288
+ })
289
+ } catch (err) {
290
+ if (isCrudHttpError(err)) {
291
+ return NextResponse.json(err.body, { status: err.status })
292
+ }
293
+ throw err
294
+ }
295
+
280
296
  em.assign(rule, parsed.data)
281
297
 
282
298
  try {
@@ -321,6 +337,20 @@ export async function DELETE(req: Request) {
321
337
  return NextResponse.json({ error: 'Rule not found' }, { status: 404 })
322
338
  }
323
339
 
340
+ try {
341
+ enforceCommandOptimisticLock({
342
+ resourceKind: 'business_rules.rule',
343
+ resourceId: rule.id,
344
+ current: rule.updatedAt ?? null,
345
+ request: req,
346
+ })
347
+ } catch (err) {
348
+ if (isCrudHttpError(err)) {
349
+ return NextResponse.json(err.body, { status: err.status })
350
+ }
351
+ throw err
352
+ }
353
+
324
354
  rule.deletedAt = new Date()
325
355
  await em.persist(rule).flush()
326
356
  await invalidateBusinessRuleDiscoveryCache(cache, rule.tenantId, rule.organizationId)
@@ -3,6 +3,8 @@ import { z } from 'zod'
3
3
  import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
4
4
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
5
5
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
6
+ import { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
7
+ import { enforceCommandOptimisticLock } from '@open-mercato/shared/lib/crud/optimistic-lock-command'
6
8
  import { RuleSet } from '../../data/entities'
7
9
  import type { EntityManager } from '@mikro-orm/postgresql'
8
10
  import { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'
@@ -221,6 +223,20 @@ export async function PUT(req: Request) {
221
223
  return NextResponse.json({ error: 'Rule set not found' }, { status: 404 })
222
224
  }
223
225
 
226
+ try {
227
+ enforceCommandOptimisticLock({
228
+ resourceKind: 'business_rules.ruleSet',
229
+ resourceId: ruleSet.id,
230
+ current: ruleSet.updatedAt ?? null,
231
+ request: req,
232
+ })
233
+ } catch (err) {
234
+ if (isCrudHttpError(err)) {
235
+ return NextResponse.json(err.body, { status: err.status })
236
+ }
237
+ throw err
238
+ }
239
+
224
240
  em.assign(ruleSet, parsed.data)
225
241
  await em.persist(ruleSet).flush()
226
242
 
@@ -254,6 +270,20 @@ export async function DELETE(req: Request) {
254
270
  return NextResponse.json({ error: 'Rule set not found' }, { status: 404 })
255
271
  }
256
272
 
273
+ try {
274
+ enforceCommandOptimisticLock({
275
+ resourceKind: 'business_rules.ruleSet',
276
+ resourceId: ruleSet.id,
277
+ current: ruleSet.updatedAt ?? null,
278
+ request: req,
279
+ })
280
+ } catch (err) {
281
+ if (isCrudHttpError(err)) {
282
+ return NextResponse.json(err.body, { status: err.status })
283
+ }
284
+ throw err
285
+ }
286
+
257
287
  ruleSet.deletedAt = new Date()
258
288
  await em.persist(ruleSet).flush()
259
289
 
@@ -8,7 +8,10 @@ import { Page, PageBody } from '@open-mercato/ui/backend/Page'
8
8
  import { CrudForm } from '@open-mercato/ui/backend/CrudForm'
9
9
  import { Spinner } from '@open-mercato/ui/primitives/spinner'
10
10
  import { Button } from '@open-mercato/ui/primitives/button'
11
- import { apiFetch } from '@open-mercato/ui/backend/utils/api'
11
+ import { apiFetch, withScopedApiHeaders } from '@open-mercato/ui/backend/utils/api'
12
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
13
+ import { readJsonSafe } from '@open-mercato/ui/backend/utils/serverErrors'
14
+ import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
12
15
  import { useT } from '@open-mercato/shared/lib/i18n/context'
13
16
  import { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
14
17
  import {
@@ -67,7 +70,7 @@ export default function EditBusinessRulePage() {
67
70
 
68
71
  const payload = buildRulePayload(values, effectiveTenantId, effectiveOrgId, undefined)
69
72
 
70
- const response = await apiFetch('/api/business_rules/rules', {
73
+ const updateRule = () => apiFetch('/api/business_rules/rules', {
71
74
  method: 'PUT',
72
75
  headers: { 'Content-Type': 'application/json' },
73
76
  body: JSON.stringify({
@@ -75,10 +78,18 @@ export default function EditBusinessRulePage() {
75
78
  id: ruleId,
76
79
  }),
77
80
  })
81
+ const headers = buildOptimisticLockHeader(rule?.updatedAt ?? rule?.updated_at ?? null)
82
+ const response = Object.keys(headers).length
83
+ ? await withScopedApiHeaders(headers, updateRule)
84
+ : await updateRule()
78
85
 
79
86
  if (!response.ok) {
80
- const error = await response.json()
81
- throw new Error(error.error || error.message || t('business_rules.errors.updateFailed'))
87
+ const body = (await readJsonSafe<Record<string, unknown>>(response)) ?? {}
88
+ const message =
89
+ (typeof body.error === 'string' && body.error) ||
90
+ (typeof body.message === 'string' && body.message) ||
91
+ t('business_rules.errors.updateFailed')
92
+ throw new CrudHttpError(response.status, { ...body, error: message })
82
93
  }
83
94
 
84
95
  router.push('/backend/rules')
@@ -134,6 +145,7 @@ export default function EditBusinessRulePage() {
134
145
  schema={businessRuleFormSchema}
135
146
  fields={fields}
136
147
  initialValues={initialValues}
148
+ optimisticLockUpdatedAt={rule?.updatedAt ?? rule?.updated_at ?? null}
137
149
  onSubmit={handleSubmit}
138
150
  cancelHref="/backend/rules"
139
151
  groups={formGroups}
@@ -8,7 +8,8 @@ import { DataTable } from '@open-mercato/ui/backend/DataTable'
8
8
  import type { ColumnDef } from '@tanstack/react-table'
9
9
  import { Button } from '@open-mercato/ui/primitives/button'
10
10
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
11
- import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
11
+ import { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
12
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
12
13
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
13
14
  import { useQuery, useQueryClient } from '@tanstack/react-query'
14
15
  import { useT } from '@open-mercato/shared/lib/i18n/context'
@@ -92,9 +93,13 @@ export default function RulesListPage() {
92
93
  })
93
94
  if (!confirmed) return
94
95
 
95
- const result = await apiCall(`/api/business_rules/rules?id=${id}`, {
96
- method: 'DELETE',
97
- })
96
+ const record = (data || []).find((item) => item.id === id)
97
+ const result = await withScopedApiRequestHeaders(
98
+ buildOptimisticLockHeader(record?.updatedAt),
99
+ () => apiCall(`/api/business_rules/rules?id=${id}`, {
100
+ method: 'DELETE',
101
+ }),
102
+ )
98
103
 
99
104
  if (result.ok) {
100
105
  flash(t('business_rules.messages.deleted'), 'success')
@@ -105,14 +110,18 @@ export default function RulesListPage() {
105
110
  }
106
111
 
107
112
  const handleToggleEnabled = async (id: string, currentEnabled: boolean) => {
108
- const result = await apiCall('/api/business_rules/rules', {
109
- method: 'PUT',
110
- headers: { 'Content-Type': 'application/json' },
111
- body: JSON.stringify({
112
- id,
113
- enabled: !currentEnabled,
113
+ const record = (data || []).find((item) => item.id === id)
114
+ const result = await withScopedApiRequestHeaders(
115
+ buildOptimisticLockHeader(record?.updatedAt),
116
+ () => apiCall('/api/business_rules/rules', {
117
+ method: 'PUT',
118
+ headers: { 'Content-Type': 'application/json' },
119
+ body: JSON.stringify({
120
+ id,
121
+ enabled: !currentEnabled,
122
+ }),
114
123
  }),
115
- })
124
+ )
116
125
 
117
126
  if (result.ok) {
118
127
  flash(t('business_rules.messages.updated'), 'success')
@@ -9,8 +9,11 @@ import { CrudForm } from '@open-mercato/ui/backend/CrudForm'
9
9
  import type { CrudField } from '@open-mercato/ui/backend/CrudForm'
10
10
  import { Spinner } from '@open-mercato/ui/primitives/spinner'
11
11
  import { Button } from '@open-mercato/ui/primitives/button'
12
- import { apiFetch } from '@open-mercato/ui/backend/utils/api'
12
+ import { apiFetch, withScopedApiHeaders } from '@open-mercato/ui/backend/utils/api'
13
13
  import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
14
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
15
+ import { readJsonSafe } from '@open-mercato/ui/backend/utils/serverErrors'
16
+ import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
14
17
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
15
18
  import { useT } from '@open-mercato/shared/lib/i18n/context'
16
19
  import { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
@@ -85,15 +88,23 @@ export default function EditRuleSetPage() {
85
88
  ...values,
86
89
  }
87
90
 
88
- const response = await apiFetch('/api/business_rules/sets', {
91
+ const updateSet = () => apiFetch('/api/business_rules/sets', {
89
92
  method: 'PUT',
90
93
  headers: { 'Content-Type': 'application/json' },
91
94
  body: JSON.stringify(payload),
92
95
  })
96
+ const headers = buildOptimisticLockHeader(ruleSet?.updatedAt ?? null)
97
+ const response = Object.keys(headers).length
98
+ ? await withScopedApiHeaders(headers, updateSet)
99
+ : await updateSet()
93
100
 
94
101
  if (!response.ok) {
95
- const error = await response.json()
96
- throw new Error(error.error || error.message || t('business_rules.sets.errors.updateFailed'))
102
+ const body = (await readJsonSafe<Record<string, unknown>>(response)) ?? {}
103
+ const message =
104
+ (typeof body.error === 'string' && body.error) ||
105
+ (typeof body.message === 'string' && body.message) ||
106
+ t('business_rules.sets.errors.updateFailed')
107
+ throw new CrudHttpError(response.status, { ...body, error: message })
97
108
  }
98
109
 
99
110
  flash(t('business_rules.sets.messages.updated'), 'success')
@@ -265,6 +276,7 @@ export default function EditRuleSetPage() {
265
276
  schema={ruleSetFormSchema}
266
277
  fields={fields}
267
278
  initialValues={initialValues}
279
+ optimisticLockUpdatedAt={ruleSet.updatedAt}
268
280
  onSubmit={handleSubmit}
269
281
  cancelHref="/backend/sets"
270
282
  submitLabel={t('business_rules.sets.form.update')}