@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
@@ -24,7 +24,9 @@ import { Label } from '@open-mercato/ui/primitives/label'
24
24
  import { SwitchField } from '@open-mercato/ui/primitives/switch-field'
25
25
  import { CrudForm, type CrudCustomFieldRenderProps, type CrudField } from '@open-mercato/ui/backend/CrudForm'
26
26
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
27
- import { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
27
+ import { apiCall, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
28
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
29
+ import { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'
28
30
  import { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'
29
31
  import { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
30
32
  import { useT } from '@open-mercato/shared/lib/i18n/context'
@@ -549,12 +551,14 @@ export function ShippingMethodsSettings() {
549
551
  })
550
552
  if (!confirmed) return
551
553
  try {
552
- const call = await apiCall('/api/sales/shipping-methods', {
554
+ const headers = buildOptimisticLockHeader(entry.updatedAt)
555
+ const call = await withScopedApiRequestHeaders(headers, () => apiCall('/api/sales/shipping-methods', {
553
556
  method: 'DELETE',
554
557
  headers: { 'content-type': 'application/json' },
555
558
  body: JSON.stringify({ id: entry.id }),
556
- })
559
+ }))
557
560
  if (!call.ok) {
561
+ if (surfaceRecordConflict({ status: call.status, body: call.result }, t)) return
558
562
  await raiseCrudError(call.response, translations.errors.delete)
559
563
  }
560
564
  flash(translations.messages.deleted, 'success')
@@ -642,12 +646,15 @@ export function ShippingMethodsSettings() {
642
646
  const method = dialog.mode === 'create' ? 'POST' : 'PUT'
643
647
  if (dialog.mode === 'edit') payload.id = dialog.entry.id
644
648
  try {
645
- const call = await apiCall(path, {
649
+ const saveShippingMethod = () => apiCall(path, {
646
650
  method,
647
651
  headers: { 'content-type': 'application/json' },
648
652
  body: JSON.stringify(payload),
649
653
  })
654
+ const headers = buildOptimisticLockHeader(dialog.mode === 'edit' ? dialog.entry.updatedAt : null)
655
+ const call = await withScopedApiRequestHeaders(headers, saveShippingMethod)
650
656
  if (!call.ok) {
657
+ if (surfaceRecordConflict({ status: call.status, body: call.result }, t)) return
651
658
  await raiseCrudError(call.response, translations.errors.save)
652
659
  }
653
660
  flash(translations.messages.saved, 'success')
@@ -770,6 +777,7 @@ export function ShippingMethodsSettings() {
770
777
  schema={shippingFormSchema}
771
778
  fields={fields}
772
779
  initialValues={formValues}
780
+ optimisticLockUpdatedAt={dialog?.mode === 'edit' ? dialog.entry.updatedAt : null}
773
781
  submitLabel={translations.form.save}
774
782
  cancelHref={undefined}
775
783
  embedded
@@ -8,7 +8,8 @@ import {
8
8
  DialogTitle,
9
9
  } from '@open-mercato/ui/primitives/dialog'
10
10
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
11
- import { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
11
+ import { apiCall, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
12
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
12
13
  import { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
13
14
  import { useT } from '@open-mercato/shared/lib/i18n/context'
14
15
  import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
@@ -197,11 +198,15 @@ export function StatusSettings() {
197
198
  })
198
199
  if (!confirmed) return
199
200
  try {
200
- const call = await apiCall(apiPaths[kind], {
201
- method: 'DELETE',
202
- headers: { 'content-type': 'application/json' },
203
- body: JSON.stringify({ id: entry.id }),
204
- })
201
+ const call = await withScopedApiRequestHeaders(
202
+ buildOptimisticLockHeader(entry.updatedAt),
203
+ () =>
204
+ apiCall(apiPaths[kind], {
205
+ method: 'DELETE',
206
+ headers: { 'content-type': 'application/json' },
207
+ body: JSON.stringify({ id: entry.id }),
208
+ })
209
+ )
205
210
  if (!call.ok) {
206
211
  await raiseCrudError(call.response, translate('sales.config.statuses.error.delete', 'Failed to delete status.'))
207
212
  }
@@ -238,11 +243,15 @@ export function StatusSettings() {
238
243
  if (nextColor !== (entry.color ?? null)) body.color = nextColor
239
244
  const nextIcon = values.icon ?? null
240
245
  if (nextIcon !== (entry.icon ?? null)) body.icon = nextIcon
241
- const call = await apiCall(path, {
242
- method: 'PUT',
243
- headers: { 'content-type': 'application/json' },
244
- body: JSON.stringify(body),
245
- })
246
+ const call = await withScopedApiRequestHeaders(
247
+ buildOptimisticLockHeader(entry.updatedAt),
248
+ () =>
249
+ apiCall(path, {
250
+ method: 'PUT',
251
+ headers: { 'content-type': 'application/json' },
252
+ body: JSON.stringify(body),
253
+ })
254
+ )
246
255
  if (!call.ok) {
247
256
  await raiseCrudError(call.response, translate('sales.config.statuses.error.save', 'Failed to save status.'))
248
257
  }
@@ -10,7 +10,9 @@ import { Badge } from '@open-mercato/ui/primitives/badge'
10
10
  import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'
11
11
  import { CrudForm, type CrudField } from '@open-mercato/ui/backend/CrudForm'
12
12
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
13
- import { readApiResultOrThrow, apiCall } from '@open-mercato/ui/backend/utils/apiCall'
13
+ import { readApiResultOrThrow, apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
14
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
15
+ import { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'
14
16
  import { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'
15
17
  import { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
16
18
  import { useT } from '@open-mercato/shared/lib/i18n/context'
@@ -206,12 +208,15 @@ export function TaxRatesSettings() {
206
208
  payload.id = dialog.entry.id
207
209
  }
208
210
  try {
209
- const call = await apiCall('/api/sales/tax-rates', {
211
+ const saveTaxRate = () => apiCall('/api/sales/tax-rates', {
210
212
  method,
211
213
  headers: { 'content-type': 'application/json' },
212
214
  body: JSON.stringify(payload),
213
215
  })
216
+ const headers = buildOptimisticLockHeader(dialog.mode === 'edit' ? dialog.entry.updatedAt : null)
217
+ const call = await withScopedApiRequestHeaders(headers, saveTaxRate)
214
218
  if (!call.ok) {
219
+ if (surfaceRecordConflict({ status: call.status, body: call.result }, t)) return
215
220
  await raiseCrudError(call.response, translations.errors.save)
216
221
  return
217
222
  }
@@ -232,12 +237,14 @@ export function TaxRatesSettings() {
232
237
  })
233
238
  if (!confirmed) return
234
239
  try {
235
- const call = await apiCall('/api/sales/tax-rates', {
240
+ const headers = buildOptimisticLockHeader(entry.updatedAt)
241
+ const call = await withScopedApiRequestHeaders(headers, () => apiCall('/api/sales/tax-rates', {
236
242
  method: 'DELETE',
237
243
  headers: { 'content-type': 'application/json' },
238
244
  body: JSON.stringify({ id: entry.id }),
239
- })
245
+ }))
240
246
  if (!call.ok) {
247
+ if (surfaceRecordConflict({ status: call.status, body: call.result }, t)) return
241
248
  await raiseCrudError(call.response, translations.errors.delete)
242
249
  return
243
250
  }
@@ -361,6 +368,7 @@ export function TaxRatesSettings() {
361
368
  schema={taxRateFormSchema}
362
369
  fields={fields}
363
370
  initialValues={dialogValues}
371
+ optimisticLockUpdatedAt={dialog?.mode === 'edit' ? dialog.entry.updatedAt : null}
364
372
  submitLabel={translations.form.save}
365
373
  cancelHref={undefined}
366
374
  embedded
@@ -387,4 +395,3 @@ function formatLocation(entry: TaxRateRow): string {
387
395
  return parts.length ? parts.join(', ') : '—'
388
396
  }
389
397
 
390
-
@@ -7,7 +7,9 @@ import { CrudForm, type CrudField, type CrudFormGroup, type CrudFormGroupCompone
7
7
  import { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'
8
8
  import { createCrud, updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'
9
9
  import { createCrudFormError, type CrudServerFieldErrors } from '@open-mercato/ui/backend/utils/serverErrors'
10
- import { readApiResultOrThrow, apiCall } from '@open-mercato/ui/backend/utils/apiCall'
10
+ import { readApiResultOrThrow, apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
11
+ import { buildOptimisticLockHeader, extractOptimisticLockConflict } from '@open-mercato/ui/backend/utils/optimisticLock'
12
+ import { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'
11
13
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
12
14
  import { Button } from '@open-mercato/ui/primitives/button'
13
15
  import { Input } from '@open-mercato/ui/primitives/input'
@@ -41,6 +43,8 @@ type PriceOverrideDraft = {
41
43
  currencyCode?: string | null
42
44
  displayMode?: 'including-tax' | 'excluding-tax' | null
43
45
  amount?: string
46
+ /** The price row's version, for the per-price optimistic-lock header (#2332). */
47
+ updatedAt?: string | null
44
48
  }
45
49
 
46
50
  export type OfferFormValues = {
@@ -51,6 +55,7 @@ export type OfferFormValues = {
51
55
  defaultMediaId?: string | null
52
56
  isActive: boolean
53
57
  priceOverrides: PriceOverrideDraft[]
58
+ updatedAt?: string | null
54
59
  } & Record<string, unknown>
55
60
 
56
61
  type ChannelOfferFormProps = {
@@ -141,13 +146,15 @@ export function ChannelOfferForm({ channelId: lockedChannelId, offerId, mode }:
141
146
  const variantMediaCache = React.useRef<Map<string, VariantThumbnailInfo>>(new Map())
142
147
  const [selectedChannelId, setSelectedChannelId] = React.useState<string | null>(lockedChannelId ?? null)
143
148
  const manualMediaSelections = React.useRef<Set<string>>(new Set())
144
- const initialPriceIdsRef = React.useRef<Set<string>>(new Set())
149
+ // Map of the loaded price-override id → its `updatedAt`, so deletes during the
150
+ // offer save can send the price's own optimistic-lock version (#2332).
151
+ const initialPriceVersionsRef = React.useRef<Map<string, string | null>>(new Map())
145
152
  const [currentProductId, setCurrentProductId] = React.useState<string | null>(null)
146
153
  React.useEffect(() => {
147
154
  if (initialValues) {
148
- initialPriceIdsRef.current = collectPriceIds(initialValues.priceOverrides)
155
+ initialPriceVersionsRef.current = collectPriceVersions(initialValues.priceOverrides)
149
156
  } else {
150
- initialPriceIdsRef.current = new Set()
157
+ initialPriceVersionsRef.current = new Map()
151
158
  }
152
159
  }, [initialValues])
153
160
  const channelOffersHref = React.useMemo(
@@ -438,12 +445,16 @@ export function ChannelOfferForm({ channelId: lockedChannelId, offerId, mode }:
438
445
  if (!priceId) return true
439
446
  if (mode !== 'edit') return true
440
447
  try {
441
- await deleteCrud('catalog/prices', priceId, {
442
- errorMessage: t('sales.channels.offers.errors.removePrice', 'Failed to remove price override.'),
443
- })
444
- initialPriceIdsRef.current.delete(priceId)
448
+ await withScopedApiRequestHeaders(
449
+ buildOptimisticLockHeader(draft.updatedAt),
450
+ () => deleteCrud('catalog/prices', priceId, {
451
+ errorMessage: t('sales.channels.offers.errors.removePrice', 'Failed to remove price override.'),
452
+ }),
453
+ )
454
+ initialPriceVersionsRef.current.delete(priceId)
445
455
  return true
446
456
  } catch (err) {
457
+ if (surfaceRecordConflict(err, t)) return false
447
458
  console.error('sales.channels.pricing.remove', err)
448
459
  flash(t('sales.channels.offers.errors.removePrice', 'Failed to remove price override.'), 'error')
449
460
  return false
@@ -594,10 +605,11 @@ export function ChannelOfferForm({ channelId: lockedChannelId, offerId, mode }:
594
605
  }
595
606
  const submittedPriceIds = collectPriceIds(overrides)
596
607
  const deletedIdSet = new Set<string>()
597
- initialPriceIdsRef.current.forEach((id) => {
608
+ initialPriceVersionsRef.current.forEach((_version, id) => {
598
609
  if (!submittedPriceIds.has(id)) deletedIdSet.add(id)
599
610
  })
600
611
  const deletedIds = Array.from(deletedIdSet)
612
+ const deletedVersions = new Map(deletedIds.map((id) => [id, initialPriceVersionsRef.current.get(id) ?? null]))
601
613
  let savedId = offerId ?? null
602
614
  try {
603
615
  if (mode === 'create') {
@@ -612,6 +624,13 @@ export function ChannelOfferForm({ channelId: lockedChannelId, offerId, mode }:
612
624
  savedId = offerId
613
625
  }
614
626
  } catch (err) {
627
+ // Let an optimistic-lock 409 propagate untouched so CrudForm's
628
+ // extractOptimisticLockConflict still sees the top-level `code` /
629
+ // `currentUpdatedAt` / `expectedUpdatedAt` and surfaces the unified
630
+ // conflict bar. Re-wrapping via createCrudFormError below would drop them.
631
+ if (extractOptimisticLockConflict(err)) {
632
+ throw err
633
+ }
615
634
  const details = (err as { details?: unknown })?.details
616
635
  const rawFieldErrors = (err as { fieldErrors?: unknown })?.fieldErrors
617
636
  const fieldErrors = rawFieldErrors && typeof rawFieldErrors === 'object'
@@ -634,15 +653,16 @@ export function ChannelOfferForm({ channelId: lockedChannelId, offerId, mode }:
634
653
  await syncPriceOverrides({
635
654
  overrides,
636
655
  deletedIds,
656
+ deletedVersions,
637
657
  offerId: savedId,
638
658
  channelId,
639
659
  productId,
640
660
  })
641
- initialPriceIdsRef.current = submittedPriceIds
661
+ initialPriceVersionsRef.current = collectPriceVersions(overrides)
642
662
  }
643
663
  flash(t('sales.channels.offers.messages.saved', 'Offer saved.'), 'success')
644
664
  router.push(buildChannelOffersHref(channelId))
645
- }, [attachmentCache, initialPriceIdsRef, lockedChannelId, mode, offerId, router, selectedChannelId, t])
665
+ }, [attachmentCache, lockedChannelId, mode, offerId, router, selectedChannelId, t])
646
666
 
647
667
  const handleDelete = React.useCallback(async () => {
648
668
  if (!offerId) return
@@ -669,6 +689,7 @@ export function ChannelOfferForm({ channelId: lockedChannelId, offerId, mode }:
669
689
  fields={fields}
670
690
  groups={groups}
671
691
  initialValues={initialValues ?? undefined}
692
+ optimisticLockUpdatedAt={initialValues?.updatedAt}
672
693
  isLoading={loading}
673
694
  loadingMessage={t('sales.channels.offers.form.loading', 'Loading offer…')}
674
695
  submitLabel={mode === 'create'
@@ -706,6 +727,11 @@ function mapOfferToFormValues(item: Record<string, unknown>, lockedChannelId?: s
706
727
  : null,
707
728
  isActive: item.isActive === true || item.is_active === true,
708
729
  priceOverrides: [],
730
+ updatedAt: typeof item.updatedAt === 'string'
731
+ ? item.updatedAt
732
+ : typeof item.updated_at === 'string'
733
+ ? item.updated_at
734
+ : null,
709
735
  }
710
736
  mergeCustomFieldValues(values, item)
711
737
  return values
@@ -742,6 +768,11 @@ function mapPriceRow(row: Record<string, unknown>): PriceOverrideDraft {
742
768
  : typeof row.unit_price_gross === 'string'
743
769
  ? row.unit_price_gross
744
770
  : '',
771
+ updatedAt: typeof row.updatedAt === 'string'
772
+ ? row.updatedAt
773
+ : typeof row.updated_at === 'string'
774
+ ? row.updated_at
775
+ : null,
745
776
  }
746
777
  }
747
778
 
@@ -753,6 +784,17 @@ function collectPriceIds(source: PriceOverrideDraft[] | null | undefined): Set<s
753
784
  return new Set(ids)
754
785
  }
755
786
 
787
+ function collectPriceVersions(source: PriceOverrideDraft[] | null | undefined): Map<string, string | null> {
788
+ const versions = new Map<string, string | null>()
789
+ if (!Array.isArray(source)) return versions
790
+ for (const entry of source) {
791
+ if (typeof entry?.priceId === 'string' && entry.priceId) {
792
+ versions.set(entry.priceId, typeof entry.updatedAt === 'string' ? entry.updatedAt : null)
793
+ }
794
+ }
795
+ return versions
796
+ }
797
+
756
798
  function mergeCustomFieldValues(target: Record<string, unknown>, source: Record<string, unknown> | null | undefined) {
757
799
  Object.assign(target, extractCustomFieldEntries(source ?? {}))
758
800
  }
@@ -766,11 +808,12 @@ function buildChannelOffersHref(channelId?: string | null): string {
766
808
  async function syncPriceOverrides(params: {
767
809
  overrides: PriceOverrideDraft[]
768
810
  deletedIds: string[]
811
+ deletedVersions: Map<string, string | null>
769
812
  offerId: string
770
813
  channelId: string
771
814
  productId: string
772
815
  }) {
773
- const { overrides, deletedIds, offerId, channelId, productId } = params
816
+ const { overrides, deletedIds, deletedVersions, offerId, channelId, productId } = params
774
817
  for (const draft of overrides) {
775
818
  if (!draft.priceKindId || !draft.amount) continue
776
819
  const amount = Number(draft.amount)
@@ -788,7 +831,14 @@ async function syncPriceOverrides(params: {
788
831
  payload.unitPriceNet = amount
789
832
  }
790
833
  if (draft.priceId) {
791
- await updateCrud('catalog/prices', { id: draft.priceId, ...payload })
834
+ // Send the PRICE's own version, overriding the offer header the parent
835
+ // CrudForm submit scope put on the stack (otherwise the price guard would
836
+ // compare the offer's `updated_at` and 409 falsely). #2332.
837
+ const priceId = draft.priceId
838
+ await withScopedApiRequestHeaders(
839
+ buildOptimisticLockHeader(draft.updatedAt),
840
+ () => updateCrud('catalog/prices', { id: priceId, ...payload }),
841
+ )
792
842
  } else {
793
843
  await createCrud('catalog/prices', payload)
794
844
  }
@@ -799,7 +849,10 @@ async function syncPriceOverrides(params: {
799
849
  for (const id of uniqueDeletedIds) {
800
850
  if (!id) continue
801
851
  try {
802
- await deleteCrud('catalog/prices', id)
852
+ await withScopedApiRequestHeaders(
853
+ buildOptimisticLockHeader(deletedVersions.get(id) ?? null),
854
+ () => deleteCrud('catalog/prices', id),
855
+ )
803
856
  } catch (err) {
804
857
  console.error('catalog.prices.delete', err)
805
858
  }
@@ -9,7 +9,8 @@ import { RowActions } from '@open-mercato/ui/backend/RowActions'
9
9
  import { Button } from '@open-mercato/ui/primitives/button'
10
10
  import { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'
11
11
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
12
- import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
12
+ import { readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
13
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
13
14
  import { deleteCrud } from '@open-mercato/ui/backend/utils/crud'
14
15
  import { useT } from '@open-mercato/shared/lib/i18n/context'
15
16
  import { mapOfferRow, renderOfferPriceSummary, type OfferRow } from './offerTableUtils'
@@ -123,9 +124,11 @@ export function SalesChannelOffersPanel({ channelId, channelName }: { channelId:
123
124
 
124
125
  const handleDelete = React.useCallback(async (row: OfferRow) => {
125
126
  try {
126
- await deleteCrud('catalog/offers', row.id, {
127
- errorMessage: t('sales.channels.offers.errors.delete', 'Failed to delete offer.'),
128
- })
127
+ await withScopedApiRequestHeaders(buildOptimisticLockHeader(row.updatedAt), () =>
128
+ deleteCrud('catalog/offers', row.id, {
129
+ errorMessage: t('sales.channels.offers.errors.delete', 'Failed to delete offer.'),
130
+ }),
131
+ )
129
132
  flash(t('sales.channels.offers.messages.deleted', 'Offer deleted.'), 'success')
130
133
  setReloadToken((token) => token + 1)
131
134
  } catch (err) {
@@ -4,7 +4,8 @@
4
4
 
5
5
  import * as React from 'react'
6
6
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
7
- import { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
7
+ import { apiCall, apiCallOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
8
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
8
9
  import { createCrud } from '@open-mercato/ui/backend/utils/crud'
9
10
  import { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'
10
11
  import { ErrorMessage, LoadingMessage, TabEmptyState } from '@open-mercato/ui/backend/detail'
@@ -691,14 +692,17 @@ export function SalesDocumentAddressesSection({
691
692
  }
692
693
  await runGuardedMutation(
693
694
  () =>
694
- apiCallOrThrow(
695
- '/api/sales/document-addresses',
696
- {
697
- method: 'PUT',
698
- headers: { 'Content-Type': 'application/json' },
699
- body: JSON.stringify(payload),
700
- },
701
- { errorMessage: t('sales.documents.detail.addresses.saveError', 'Failed to update addresses.') },
695
+ // TODO(#2373-C): thread document updatedAt
696
+ withScopedApiRequestHeaders(buildOptimisticLockHeader(undefined), () =>
697
+ apiCallOrThrow(
698
+ '/api/sales/document-addresses',
699
+ {
700
+ method: 'PUT',
701
+ headers: { 'Content-Type': 'application/json' },
702
+ body: JSON.stringify(payload),
703
+ },
704
+ { errorMessage: t('sales.documents.detail.addresses.saveError', 'Failed to update addresses.') },
705
+ ),
702
706
  ),
703
707
  payload,
704
708
  )
@@ -750,14 +754,17 @@ export function SalesDocumentAddressesSection({
750
754
  const payload = { id, documentId, documentKind: kind }
751
755
  await runGuardedMutation(
752
756
  () =>
753
- apiCallOrThrow(
754
- '/api/sales/document-addresses',
755
- {
756
- method: 'DELETE',
757
- headers: { 'Content-Type': 'application/json' },
758
- body: JSON.stringify(payload),
759
- },
760
- { errorMessage: t('sales.documents.detail.addresses.deleteError', 'Failed to remove address.') },
757
+ // TODO(#2373-C): thread document updatedAt
758
+ withScopedApiRequestHeaders(buildOptimisticLockHeader(undefined), () =>
759
+ apiCallOrThrow(
760
+ '/api/sales/document-addresses',
761
+ {
762
+ method: 'DELETE',
763
+ headers: { 'Content-Type': 'application/json' },
764
+ body: JSON.stringify(payload),
765
+ },
766
+ { errorMessage: t('sales.documents.detail.addresses.deleteError', 'Failed to remove address.') },
767
+ ),
761
768
  ),
762
769
  payload,
763
770
  )
@@ -849,14 +856,17 @@ export function SalesDocumentAddressesSection({
849
856
  const endpoint = kind === 'order' ? '/api/sales/orders' : '/api/sales/quotes'
850
857
  const call = await runGuardedMutation(
851
858
  () =>
852
- apiCallOrThrow<Record<string, unknown>>(
853
- endpoint,
854
- {
855
- method: 'PUT',
856
- headers: { 'Content-Type': 'application/json' },
857
- body: JSON.stringify(payload),
858
- },
859
- { errorMessage: t('sales.documents.detail.updateError', 'Failed to update document.') },
859
+ // TODO(#2373-C): thread document updatedAt
860
+ withScopedApiRequestHeaders(buildOptimisticLockHeader(undefined), () =>
861
+ apiCallOrThrow<Record<string, unknown>>(
862
+ endpoint,
863
+ {
864
+ method: 'PUT',
865
+ headers: { 'Content-Type': 'application/json' },
866
+ body: JSON.stringify(payload),
867
+ },
868
+ { errorMessage: t('sales.documents.detail.updateError', 'Failed to update document.') },
869
+ ),
860
870
  ),
861
871
  payload,
862
872
  )
@@ -8,9 +8,11 @@ import { Badge } from '@open-mercato/ui/primitives/badge'
8
8
  import { DataTable } from '@open-mercato/ui/backend/DataTable'
9
9
  import { ErrorMessage, LoadingMessage, TabEmptyState } from '@open-mercato/ui/backend/detail'
10
10
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
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 { createCrud, deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'
13
14
  import { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'
15
+ import { handleSectionMutationError } from './optimisticLock'
14
16
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
15
17
  import { type DictionaryOption } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'
16
18
  import {
@@ -31,6 +33,7 @@ type SalesDocumentAdjustmentsSectionProps = {
31
33
  documentId: string
32
34
  kind: 'order' | 'quote'
33
35
  currencyCode: string | null | undefined
36
+ documentUpdatedAt?: string | null
34
37
  organizationId?: string | null
35
38
  tenantId?: string | null
36
39
  onActionChange?: (action: SectionAction | null) => void
@@ -64,6 +67,7 @@ export function SalesDocumentAdjustmentsSection({
64
67
  documentId,
65
68
  kind,
66
69
  currencyCode,
70
+ documentUpdatedAt,
67
71
  organizationId: orgFromProps,
68
72
  tenantId: tenantFromProps,
69
73
  onActionChange,
@@ -317,27 +321,43 @@ export function SalesDocumentAdjustmentsSection({
317
321
  }
318
322
 
319
323
  const action = values.id ? updateCrud : createCrud
320
- const result = await action(
321
- crudResourcePath,
322
- values.id ? { id: values.id, ...payload } : payload,
323
- {
324
- successMessage: values.id
325
- ? t('sales.documents.adjustments.updated', 'Adjustment updated.')
326
- : t('sales.documents.adjustments.created', 'Adjustment added.'),
327
- errorMessage: t('sales.documents.adjustments.errorSave', 'Failed to save adjustment.'),
324
+ try {
325
+ const result = await withScopedApiRequestHeaders(
326
+ buildOptimisticLockHeader(documentUpdatedAt),
327
+ () =>
328
+ action(
329
+ crudResourcePath,
330
+ values.id ? { id: values.id, ...payload } : payload,
331
+ {
332
+ successMessage: values.id
333
+ ? t('sales.documents.adjustments.updated', 'Adjustment updated.')
334
+ : t('sales.documents.adjustments.created', 'Adjustment added.'),
335
+ errorMessage: t('sales.documents.adjustments.errorSave', 'Failed to save adjustment.'),
336
+ }
337
+ )
338
+ )
339
+ if (result.ok) {
340
+ await loadAdjustments()
341
+ emitSalesDocumentTotalsRefresh({ documentId, kind })
342
+ setDialogOpen(false)
343
+ setActiveAdjustment(null)
328
344
  }
329
- )
330
- if (result.ok) {
331
- await loadAdjustments()
332
- emitSalesDocumentTotalsRefresh({ documentId, kind })
333
- setDialogOpen(false)
334
- setActiveAdjustment(null)
345
+ } catch (err) {
346
+ if (
347
+ handleSectionMutationError(err, t, () => void loadAdjustments())
348
+ ) {
349
+ setDialogOpen(false)
350
+ setActiveAdjustment(null)
351
+ return
352
+ }
353
+ throw err
335
354
  }
336
355
  },
337
356
  [
338
357
  currencyCode,
339
358
  documentId,
340
359
  documentKey,
360
+ documentUpdatedAt,
341
361
  kind,
342
362
  loadAdjustments,
343
363
  crudResourcePath,
@@ -350,25 +370,30 @@ export function SalesDocumentAdjustmentsSection({
350
370
  const handleDelete = React.useCallback(
351
371
  async (row: AdjustmentRow) => {
352
372
  try {
353
- const result = await deleteCrud(crudResourcePath, {
354
- body: {
355
- id: row.id,
356
- [documentKey]: documentId,
357
- organizationId: resolvedOrganizationId ?? undefined,
358
- tenantId: resolvedTenantId ?? undefined,
359
- },
360
- errorMessage: t('sales.documents.adjustments.errorDelete', 'Failed to delete adjustment.'),
361
- })
373
+ const result = await withScopedApiRequestHeaders(
374
+ buildOptimisticLockHeader(documentUpdatedAt),
375
+ () =>
376
+ deleteCrud(crudResourcePath, {
377
+ body: {
378
+ id: row.id,
379
+ [documentKey]: documentId,
380
+ organizationId: resolvedOrganizationId ?? undefined,
381
+ tenantId: resolvedTenantId ?? undefined,
382
+ },
383
+ errorMessage: t('sales.documents.adjustments.errorDelete', 'Failed to delete adjustment.'),
384
+ })
385
+ )
362
386
  if (result.ok) {
363
387
  await loadAdjustments()
364
388
  emitSalesDocumentTotalsRefresh({ documentId, kind })
365
389
  }
366
390
  } catch (err) {
391
+ if (handleSectionMutationError(err, t, () => void loadAdjustments())) return
367
392
  console.error('sales.document.adjustments.delete', err)
368
393
  flash(t('sales.documents.adjustments.errorDelete', 'Failed to delete adjustment.'), 'error')
369
394
  }
370
395
  },
371
- [crudResourcePath, documentId, documentKey, kind, loadAdjustments, resolvedOrganizationId, resolvedTenantId, t]
396
+ [crudResourcePath, documentId, documentKey, documentUpdatedAt, kind, loadAdjustments, resolvedOrganizationId, resolvedTenantId, t]
372
397
  )
373
398
 
374
399
  const columns = React.useMemo<ColumnDef<AdjustmentRow>[]>(