@open-mercato/core 0.6.5-develop.4534.1.b459babe6d → 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 (633) hide show
  1. package/.turbo/turbo-build.log +1 -1
  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/user/index.js +3 -1
  6. package/dist/generated/entities/user/index.js.map +2 -2
  7. package/dist/generated/entity-fields-registry.js +2 -0
  8. package/dist/generated/entity-fields-registry.js.map +2 -2
  9. package/dist/helpers/integration/optimisticLockUi.js +104 -0
  10. package/dist/helpers/integration/optimisticLockUi.js.map +7 -0
  11. package/dist/helpers/integration/salesFixtures.js +17 -0
  12. package/dist/helpers/integration/salesFixtures.js.map +2 -2
  13. package/dist/modules/api_keys/backend/api-keys/page.js +9 -5
  14. package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
  15. package/dist/modules/attachments/components/AttachmentPartitionSettings.js +17 -9
  16. package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
  17. package/dist/modules/auth/api/roles/acl/route.js +32 -13
  18. package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
  19. package/dist/modules/auth/api/roles/route.js +3 -1
  20. package/dist/modules/auth/api/roles/route.js.map +2 -2
  21. package/dist/modules/auth/api/sidebar/preferences/route.js +71 -3
  22. package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
  23. package/dist/modules/auth/api/users/acl/route.js +42 -19
  24. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  25. package/dist/modules/auth/api/users/route.js +3 -1
  26. package/dist/modules/auth/api/users/route.js.map +2 -2
  27. package/dist/modules/auth/backend/roles/[id]/edit/page.js +24 -4
  28. package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
  29. package/dist/modules/auth/backend/roles/page.js +8 -4
  30. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  31. package/dist/modules/auth/backend/users/[id]/edit/page.js +27 -5
  32. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  33. package/dist/modules/auth/backend/users/page.js +6 -2
  34. package/dist/modules/auth/backend/users/page.js.map +2 -2
  35. package/dist/modules/auth/components/AclEditor.js +3 -1
  36. package/dist/modules/auth/components/AclEditor.js.map +2 -2
  37. package/dist/modules/auth/data/entities.js +6 -0
  38. package/dist/modules/auth/data/entities.js.map +2 -2
  39. package/dist/modules/auth/services/sidebarPreferencesService.js +32 -4
  40. package/dist/modules/auth/services/sidebarPreferencesService.js.map +2 -2
  41. package/dist/modules/business_rules/api/rules/route.js +28 -0
  42. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  43. package/dist/modules/business_rules/api/sets/route.js +28 -0
  44. package/dist/modules/business_rules/api/sets/route.js.map +2 -2
  45. package/dist/modules/business_rules/backend/rules/[id]/page.js +11 -4
  46. package/dist/modules/business_rules/backend/rules/[id]/page.js.map +3 -3
  47. package/dist/modules/business_rules/backend/rules/page.js +20 -11
  48. package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
  49. package/dist/modules/business_rules/backend/sets/[id]/page.js +11 -4
  50. package/dist/modules/business_rules/backend/sets/[id]/page.js.map +2 -2
  51. package/dist/modules/business_rules/backend/sets/page.js +20 -11
  52. package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
  53. package/dist/modules/catalog/api/categories/route.js +2 -0
  54. package/dist/modules/catalog/api/categories/route.js.map +2 -2
  55. package/dist/modules/catalog/api/products/route.js +2 -1
  56. package/dist/modules/catalog/api/products/route.js.map +2 -2
  57. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js +2 -0
  58. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js.map +2 -2
  59. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +94 -40
  60. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  61. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +37 -8
  62. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
  63. package/dist/modules/catalog/backend/catalog/products/optionSchemaClient.js.map +2 -2
  64. package/dist/modules/catalog/commands/variants.js +32 -31
  65. package/dist/modules/catalog/commands/variants.js.map +2 -2
  66. package/dist/modules/catalog/components/PriceKindSettings.js +12 -5
  67. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  68. package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
  69. package/dist/modules/catalog/components/products/ProductMediaManager.js.map +2 -2
  70. package/dist/modules/catalog/components/products/ProductsDataTable.js +5 -3
  71. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  72. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  73. package/dist/modules/catalog/components/products/variantForm.js +2 -1
  74. package/dist/modules/catalog/components/products/variantForm.js.map +2 -2
  75. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +5 -0
  76. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
  77. package/dist/modules/currencies/backend/currencies/[id]/page.js +6 -3
  78. package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
  79. package/dist/modules/currencies/backend/currencies/page.js +18 -11
  80. package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
  81. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js +1 -0
  82. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js.map +2 -2
  83. package/dist/modules/currencies/backend/exchange-rates/page.js +10 -6
  84. package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
  85. package/dist/modules/currencies/commands/currencies.js +7 -5
  86. package/dist/modules/currencies/commands/currencies.js.map +2 -2
  87. package/dist/modules/currencies/components/CurrencyFetchingConfig.js +26 -19
  88. package/dist/modules/currencies/components/CurrencyFetchingConfig.js.map +2 -2
  89. package/dist/modules/customer_accounts/api/admin/roles/[id].js +28 -5
  90. package/dist/modules/customer_accounts/api/admin/roles/[id].js.map +2 -2
  91. package/dist/modules/customer_accounts/api/admin/roles.js +4 -2
  92. package/dist/modules/customer_accounts/api/admin/roles.js.map +2 -2
  93. package/dist/modules/customer_accounts/api/admin/users/[id].js +28 -5
  94. package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
  95. package/dist/modules/customer_accounts/api/admin/users.js +2 -0
  96. package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
  97. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +16 -8
  98. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
  99. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +8 -4
  100. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
  101. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js +8 -4
  102. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js.map +2 -2
  103. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +29 -18
  104. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
  105. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +18 -11
  106. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
  107. package/dist/modules/customers/api/companies/route.js +13 -2
  108. package/dist/modules/customers/api/companies/route.js.map +2 -2
  109. package/dist/modules/customers/api/deals/route.js +2 -0
  110. package/dist/modules/customers/api/deals/route.js.map +2 -2
  111. package/dist/modules/customers/api/people/route.js +11 -2
  112. package/dist/modules/customers/api/people/route.js.map +2 -2
  113. package/dist/modules/customers/api/todos/route.js +1 -0
  114. package/dist/modules/customers/api/todos/route.js.map +2 -2
  115. package/dist/modules/customers/backend/config/customers/deals/page.js.map +2 -2
  116. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +34 -21
  117. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
  118. package/dist/modules/customers/backend/customers/companies/[id]/page.js +45 -27
  119. package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
  120. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  121. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +22 -5
  122. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  123. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js +30 -8
  124. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js.map +2 -2
  125. package/dist/modules/customers/backend/customers/deals/[id]/page.js +1 -0
  126. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  127. package/dist/modules/customers/backend/customers/deals/page.js +16 -6
  128. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  129. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +62 -39
  130. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
  131. package/dist/modules/customers/backend/customers/people/[id]/page.js +41 -26
  132. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  133. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  134. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +50 -23
  135. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  136. package/dist/modules/customers/commands/addresses.js +16 -14
  137. package/dist/modules/customers/commands/addresses.js.map +2 -2
  138. package/dist/modules/customers/commands/companies.js +1 -1
  139. package/dist/modules/customers/commands/companies.js.map +2 -2
  140. package/dist/modules/customers/commands/interactions.js +41 -4
  141. package/dist/modules/customers/commands/interactions.js.map +2 -2
  142. package/dist/modules/customers/commands/people.js +1 -1
  143. package/dist/modules/customers/commands/people.js.map +2 -2
  144. package/dist/modules/customers/commands/personCompanyLinks.js +8 -5
  145. package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
  146. package/dist/modules/customers/commands/pipeline-stages.js +13 -11
  147. package/dist/modules/customers/commands/pipeline-stages.js.map +3 -3
  148. package/dist/modules/customers/components/AddressFormatSettings.js.map +2 -2
  149. package/dist/modules/customers/components/DictionarySettings.js +20 -13
  150. package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
  151. package/dist/modules/customers/components/DictionarySortSettings.js +4 -0
  152. package/dist/modules/customers/components/DictionarySortSettings.js.map +2 -2
  153. package/dist/modules/customers/components/PipelineSettings.js +38 -23
  154. package/dist/modules/customers/components/PipelineSettings.js.map +2 -2
  155. package/dist/modules/customers/components/detail/ActivityTimeline.js +1 -1
  156. package/dist/modules/customers/components/detail/ActivityTimeline.js.map +2 -2
  157. package/dist/modules/customers/components/detail/AddressesSection.js +4 -0
  158. package/dist/modules/customers/components/detail/AddressesSection.js.map +2 -2
  159. package/dist/modules/customers/components/detail/CompanyPeopleSection.js +28 -22
  160. package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
  161. package/dist/modules/customers/components/detail/DealsSection.js +36 -24
  162. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  163. package/dist/modules/customers/components/detail/EmailCardActions.js +5 -0
  164. package/dist/modules/customers/components/detail/EmailCardActions.js.map +2 -2
  165. package/dist/modules/customers/components/detail/EntityTagsDialog.js +7 -0
  166. package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
  167. package/dist/modules/customers/components/detail/ManageTagsDialog.js +34 -22
  168. package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +2 -2
  169. package/dist/modules/customers/components/detail/PersonCompaniesSection.js +41 -29
  170. package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
  171. package/dist/modules/customers/components/detail/RoleAssignmentRow.js +14 -8
  172. package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +2 -2
  173. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +14 -6
  174. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  175. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +29 -13
  176. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +2 -2
  177. package/dist/modules/customers/components/detail/hooks/useInteractions.js +77 -35
  178. package/dist/modules/customers/components/detail/hooks/useInteractions.js.map +2 -2
  179. package/dist/modules/customers/components/detail/hooks/usePersonTasks.js +25 -17
  180. package/dist/modules/customers/components/detail/hooks/usePersonTasks.js.map +2 -2
  181. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
  182. package/dist/modules/customers/components/formConfig.js.map +2 -2
  183. package/dist/modules/customers/data/guards.js +66 -0
  184. package/dist/modules/customers/data/guards.js.map +7 -0
  185. package/dist/modules/customers/di.js +37 -0
  186. package/dist/modules/customers/di.js.map +2 -2
  187. package/dist/modules/customers/lib/todoCompatibility.js +11 -0
  188. package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
  189. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  190. package/dist/modules/data_sync/api/options.js +4 -4
  191. package/dist/modules/data_sync/api/options.js.map +2 -2
  192. package/dist/modules/data_sync/api/schedules/route.js +9 -1
  193. package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
  194. package/dist/modules/data_sync/backend/data-sync/page.js +17 -8
  195. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  196. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +43 -22
  197. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  198. package/dist/modules/data_sync/lib/sync-schedule-service.js +9 -0
  199. package/dist/modules/data_sync/lib/sync-schedule-service.js.map +2 -2
  200. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +8 -1
  201. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
  202. package/dist/modules/dictionaries/api/[dictionaryId]/route.js +17 -1
  203. package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
  204. package/dist/modules/dictionaries/components/DictionariesManager.js +31 -10
  205. package/dist/modules/dictionaries/components/DictionariesManager.js.map +2 -2
  206. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js +28 -15
  207. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js.map +2 -2
  208. package/dist/modules/directory/api/organizations/route.js +3 -0
  209. package/dist/modules/directory/api/organizations/route.js.map +2 -2
  210. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js +2 -0
  211. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js.map +2 -2
  212. package/dist/modules/directory/backend/directory/organizations/page.js +9 -5
  213. package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
  214. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js +7 -3
  215. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js.map +2 -2
  216. package/dist/modules/directory/backend/directory/tenants/page.js +8 -4
  217. package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
  218. package/dist/modules/directory/commands/organizations.js +7 -2
  219. package/dist/modules/directory/commands/organizations.js.map +2 -2
  220. package/dist/modules/entities/api/records.js +66 -0
  221. package/dist/modules/entities/api/records.js.map +2 -2
  222. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js +1 -0
  223. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js.map +2 -2
  224. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +8 -4
  225. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  226. package/dist/modules/entities/lib/helpers.js +17 -0
  227. package/dist/modules/entities/lib/helpers.js.map +2 -2
  228. package/dist/modules/feature_toggles/api/global/[id]/override/route.js +2 -1
  229. package/dist/modules/feature_toggles/api/global/[id]/override/route.js.map +2 -2
  230. package/dist/modules/feature_toggles/api/overrides/route.js +15 -0
  231. package/dist/modules/feature_toggles/api/overrides/route.js.map +2 -2
  232. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js +15 -14
  233. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js.map +2 -2
  234. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js +20 -12
  235. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js.map +2 -2
  236. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +6 -2
  237. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
  238. package/dist/modules/feature_toggles/components/formConfig.js +2 -1
  239. package/dist/modules/feature_toggles/components/formConfig.js.map +2 -2
  240. package/dist/modules/feature_toggles/components/overrideFormConfig.js +5 -1
  241. package/dist/modules/feature_toggles/components/overrideFormConfig.js.map +2 -2
  242. package/dist/modules/feature_toggles/data/validators.js +7 -4
  243. package/dist/modules/feature_toggles/data/validators.js.map +2 -2
  244. package/dist/modules/inbox_ops/api/settings/route.js +17 -2
  245. package/dist/modules/inbox_ops/api/settings/route.js.map +2 -2
  246. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js +13 -8
  247. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js.map +2 -2
  248. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +9 -4
  249. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
  250. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +18 -11
  251. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
  252. package/dist/modules/integrations/backend/integrations/page.js +12 -8
  253. package/dist/modules/integrations/backend/integrations/page.js.map +2 -2
  254. package/dist/modules/messages/commands/messages.js +13 -10
  255. package/dist/modules/messages/commands/messages.js.map +2 -2
  256. package/dist/modules/perspectives/api/[tableId]/route.js +39 -30
  257. package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
  258. package/dist/modules/perspectives/services/perspectiveService.js +7 -0
  259. package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
  260. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +6 -14
  261. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +3 -3
  262. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +4 -2
  263. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  264. package/dist/modules/planner/components/AvailabilityRuleSetForm.js +2 -0
  265. package/dist/modules/planner/components/AvailabilityRuleSetForm.js.map +2 -2
  266. package/dist/modules/planner/components/AvailabilityRulesEditor.js +36 -11
  267. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  268. package/dist/modules/planner/components/AvailabilitySchedule.js +9 -5
  269. package/dist/modules/planner/components/AvailabilitySchedule.js.map +2 -2
  270. package/dist/modules/query_index/lib/engine.js +19 -0
  271. package/dist/modules/query_index/lib/engine.js.map +2 -2
  272. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js +1 -0
  273. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js.map +2 -2
  274. package/dist/modules/resources/backend/resources/resource-types/page.js +4 -2
  275. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  276. package/dist/modules/resources/backend/resources/resources/[id]/page.js +14 -3
  277. package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
  278. package/dist/modules/resources/backend/resources/resources/page.js +8 -4
  279. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  280. package/dist/modules/resources/components/ResourceCrudForm.js +2 -0
  281. package/dist/modules/resources/components/ResourceCrudForm.js.map +2 -2
  282. package/dist/modules/resources/components/ResourceTypeCrudForm.js +1 -0
  283. package/dist/modules/resources/components/ResourceTypeCrudForm.js.map +2 -2
  284. package/dist/modules/sales/api/documents/factory.js +7 -2
  285. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  286. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +3 -1
  287. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
  288. package/dist/modules/sales/backend/sales/channels/offers/page.js +13 -4
  289. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  290. package/dist/modules/sales/backend/sales/channels/page.js +16 -4
  291. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  292. package/dist/modules/sales/backend/sales/documents/[id]/page.js +68 -22
  293. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  294. package/dist/modules/sales/backend/sales/documents/create/page.js.map +2 -2
  295. package/dist/modules/sales/commands/documentAddresses.js +181 -2
  296. package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
  297. package/dist/modules/sales/commands/documents.js +29 -1
  298. package/dist/modules/sales/commands/documents.js.map +2 -2
  299. package/dist/modules/sales/commands/returns.js +12 -2
  300. package/dist/modules/sales/commands/returns.js.map +2 -2
  301. package/dist/modules/sales/commands/shared.js +15 -0
  302. package/dist/modules/sales/commands/shared.js.map +2 -2
  303. package/dist/modules/sales/commands/shipments.js +4 -1
  304. package/dist/modules/sales/commands/shipments.js.map +2 -2
  305. package/dist/modules/sales/components/AdjustmentKindSettings.js +19 -11
  306. package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
  307. package/dist/modules/sales/components/DocumentNumberSettings.js.map +2 -2
  308. package/dist/modules/sales/components/OrderEditingSettings.js.map +2 -2
  309. package/dist/modules/sales/components/PaymentMethodsSettings.js +12 -4
  310. package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
  311. package/dist/modules/sales/components/ShippingMethodsSettings.js +12 -4
  312. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
  313. package/dist/modules/sales/components/StatusSettings.js +18 -11
  314. package/dist/modules/sales/components/StatusSettings.js.map +2 -2
  315. package/dist/modules/sales/components/TaxRatesSettings.js +12 -4
  316. package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
  317. package/dist/modules/sales/components/channels/ChannelOfferForm.js +47 -16
  318. package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
  319. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +8 -4
  320. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  321. package/dist/modules/sales/components/documents/AddressesSection.js +44 -25
  322. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  323. package/dist/modules/sales/components/documents/AdjustmentsSection.js +43 -23
  324. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  325. package/dist/modules/sales/components/documents/ItemsSection.js +22 -13
  326. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  327. package/dist/modules/sales/components/documents/LineItemDialog.js +23 -10
  328. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  329. package/dist/modules/sales/components/documents/PaymentDialog.js +29 -14
  330. package/dist/modules/sales/components/documents/PaymentDialog.js.map +2 -2
  331. package/dist/modules/sales/components/documents/PaymentsSection.js +20 -10
  332. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  333. package/dist/modules/sales/components/documents/ReturnDialog.js +26 -17
  334. package/dist/modules/sales/components/documents/ReturnDialog.js.map +2 -2
  335. package/dist/modules/sales/components/documents/ReturnsSection.js +3 -1
  336. package/dist/modules/sales/components/documents/ReturnsSection.js.map +2 -2
  337. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +10 -5
  338. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  339. package/dist/modules/sales/components/documents/ShipmentDialog.js +21 -7
  340. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  341. package/dist/modules/sales/components/documents/ShipmentsSection.js +19 -10
  342. package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
  343. package/dist/modules/sales/components/documents/optimisticLock.js +27 -0
  344. package/dist/modules/sales/components/documents/optimisticLock.js.map +7 -0
  345. package/dist/modules/sales/di.js +18 -0
  346. package/dist/modules/sales/di.js.map +2 -2
  347. package/dist/modules/staff/api/job-histories.js +11 -2
  348. package/dist/modules/staff/api/job-histories.js.map +2 -2
  349. package/dist/modules/staff/api/timesheets/time-entries/route.js +11 -4
  350. package/dist/modules/staff/api/timesheets/time-entries/route.js.map +2 -2
  351. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +13 -8
  352. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
  353. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +2 -1
  354. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
  355. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +7 -4
  356. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  357. package/dist/modules/staff/backend/staff/team-members/page.js +4 -2
  358. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  359. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js +1 -0
  360. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js.map +2 -2
  361. package/dist/modules/staff/backend/staff/team-roles/page.js +4 -2
  362. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  363. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +5 -2
  364. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  365. package/dist/modules/staff/backend/staff/teams/page.js +12 -3
  366. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  367. package/dist/modules/staff/backend/staff/timesheets/page.js +4 -1
  368. package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
  369. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +2 -2
  370. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +12 -3
  371. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
  372. package/dist/modules/staff/commands/job-histories.js +40 -3
  373. package/dist/modules/staff/commands/job-histories.js.map +2 -2
  374. package/dist/modules/staff/components/LeaveRequestForm.js +1 -0
  375. package/dist/modules/staff/components/LeaveRequestForm.js.map +2 -2
  376. package/dist/modules/staff/components/TeamForm.js +1 -0
  377. package/dist/modules/staff/components/TeamForm.js.map +2 -2
  378. package/dist/modules/staff/components/TeamMemberForm.js +1 -0
  379. package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
  380. package/dist/modules/staff/components/TeamRoleForm.js +1 -0
  381. package/dist/modules/staff/components/TeamRoleForm.js.map +2 -2
  382. package/dist/modules/staff/components/detail/JobHistorySection.js +20 -7
  383. package/dist/modules/staff/components/detail/JobHistorySection.js.map +2 -2
  384. package/dist/modules/staff/data/validators.js +7 -1
  385. package/dist/modules/staff/data/validators.js.map +2 -2
  386. package/dist/modules/staff/lib/leaveRequestHelpers.js +2 -1
  387. package/dist/modules/staff/lib/leaveRequestHelpers.js.map +2 -2
  388. package/dist/modules/translations/components/TranslationManager.js +12 -8
  389. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  390. package/dist/modules/workflows/api/definitions/[id]/route.js +106 -0
  391. package/dist/modules/workflows/api/definitions/[id]/route.js.map +2 -2
  392. package/dist/modules/workflows/backend/definitions/[id]/page.js +11 -3
  393. package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
  394. package/dist/modules/workflows/backend/definitions/page.js +19 -8
  395. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  396. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +29 -16
  397. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  398. package/dist/modules/workflows/components/formConfig.js +4 -1
  399. package/dist/modules/workflows/components/formConfig.js.map +2 -2
  400. package/dist/modules/workflows/di.js +12 -0
  401. package/dist/modules/workflows/di.js.map +2 -2
  402. package/generated/entities/role/index.ts +1 -0
  403. package/generated/entities/user/index.ts +1 -0
  404. package/generated/entity-fields-registry.ts +2 -0
  405. package/jest.setup.ts +17 -0
  406. package/package.json +8 -7
  407. package/src/helpers/integration/optimisticLockUi.ts +172 -0
  408. package/src/helpers/integration/salesFixtures.ts +29 -0
  409. package/src/modules/api_keys/backend/api-keys/page.tsx +10 -5
  410. package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +19 -9
  411. package/src/modules/auth/api/roles/acl/route.ts +37 -11
  412. package/src/modules/auth/api/roles/route.ts +2 -0
  413. package/src/modules/auth/api/sidebar/preferences/route.ts +73 -0
  414. package/src/modules/auth/api/users/acl/route.ts +46 -18
  415. package/src/modules/auth/api/users/route.ts +2 -0
  416. package/src/modules/auth/backend/roles/[id]/edit/page.tsx +29 -4
  417. package/src/modules/auth/backend/roles/page.tsx +9 -4
  418. package/src/modules/auth/backend/users/[id]/edit/page.tsx +37 -4
  419. package/src/modules/auth/backend/users/page.tsx +7 -2
  420. package/src/modules/auth/components/AclEditor.tsx +10 -1
  421. package/src/modules/auth/data/entities.ts +7 -1
  422. package/src/modules/auth/services/sidebarPreferencesService.ts +38 -4
  423. package/src/modules/business_rules/api/rules/route.ts +30 -0
  424. package/src/modules/business_rules/api/sets/route.ts +30 -0
  425. package/src/modules/business_rules/backend/rules/[id]/page.tsx +16 -4
  426. package/src/modules/business_rules/backend/rules/page.tsx +20 -11
  427. package/src/modules/business_rules/backend/sets/[id]/page.tsx +16 -4
  428. package/src/modules/business_rules/backend/sets/page.tsx +20 -11
  429. package/src/modules/catalog/api/categories/route.ts +3 -0
  430. package/src/modules/catalog/api/products/route.ts +4 -0
  431. package/src/modules/catalog/backend/catalog/categories/[id]/edit/page.tsx +5 -0
  432. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +112 -35
  433. package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +56 -7
  434. package/src/modules/catalog/backend/catalog/products/optionSchemaClient.ts +2 -0
  435. package/src/modules/catalog/commands/variants.ts +32 -32
  436. package/src/modules/catalog/components/PriceKindSettings.tsx +20 -7
  437. package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +1 -0
  438. package/src/modules/catalog/components/products/ProductMediaManager.tsx +2 -0
  439. package/src/modules/catalog/components/products/ProductsDataTable.tsx +8 -4
  440. package/src/modules/catalog/components/products/productForm.ts +3 -0
  441. package/src/modules/catalog/components/products/variantForm.ts +9 -0
  442. package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +5 -0
  443. package/src/modules/currencies/backend/currencies/[id]/page.tsx +13 -6
  444. package/src/modules/currencies/backend/currencies/page.tsx +18 -11
  445. package/src/modules/currencies/backend/exchange-rates/[id]/page.tsx +3 -0
  446. package/src/modules/currencies/backend/exchange-rates/page.tsx +10 -6
  447. package/src/modules/currencies/commands/currencies.ts +10 -5
  448. package/src/modules/currencies/components/CurrencyFetchingConfig.tsx +31 -21
  449. package/src/modules/customer_accounts/api/admin/roles/[id].ts +35 -5
  450. package/src/modules/customer_accounts/api/admin/roles.ts +2 -0
  451. package/src/modules/customer_accounts/api/admin/users/[id].ts +38 -5
  452. package/src/modules/customer_accounts/api/admin/users.ts +2 -0
  453. package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +34 -20
  454. package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +9 -4
  455. package/src/modules/customer_accounts/backend/customer_accounts/settings/domain/page.tsx +11 -4
  456. package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +28 -17
  457. package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +19 -11
  458. package/src/modules/customers/AGENTS.md +2 -2
  459. package/src/modules/customers/api/companies/route.ts +14 -1
  460. package/src/modules/customers/api/deals/route.ts +3 -0
  461. package/src/modules/customers/api/people/route.ts +12 -1
  462. package/src/modules/customers/api/todos/route.ts +1 -0
  463. package/src/modules/customers/backend/config/customers/deals/page.tsx +1 -0
  464. package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +36 -21
  465. package/src/modules/customers/backend/customers/companies/[id]/page.tsx +52 -27
  466. package/src/modules/customers/backend/customers/companies/page.tsx +2 -0
  467. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +27 -5
  468. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.ts +39 -7
  469. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +1 -0
  470. package/src/modules/customers/backend/customers/deals/page.tsx +18 -6
  471. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +64 -39
  472. package/src/modules/customers/backend/customers/people/[id]/page.tsx +46 -26
  473. package/src/modules/customers/backend/customers/people/page.tsx +2 -0
  474. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +84 -24
  475. package/src/modules/customers/commands/addresses.ts +16 -14
  476. package/src/modules/customers/commands/companies.ts +3 -1
  477. package/src/modules/customers/commands/interactions.ts +50 -4
  478. package/src/modules/customers/commands/people.ts +2 -1
  479. package/src/modules/customers/commands/personCompanyLinks.ts +8 -5
  480. package/src/modules/customers/commands/pipeline-stages.ts +16 -16
  481. package/src/modules/customers/components/AddressFormatSettings.tsx +1 -0
  482. package/src/modules/customers/components/DictionarySettings.tsx +18 -13
  483. package/src/modules/customers/components/DictionarySortSettings.tsx +4 -0
  484. package/src/modules/customers/components/PipelineSettings.tsx +42 -21
  485. package/src/modules/customers/components/detail/ActivityTimeline.tsx +3 -3
  486. package/src/modules/customers/components/detail/AddressesSection.tsx +4 -0
  487. package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +2 -0
  488. package/src/modules/customers/components/detail/DealsSection.tsx +4 -0
  489. package/src/modules/customers/components/detail/EmailCardActions.tsx +5 -0
  490. package/src/modules/customers/components/detail/EntityTagsDialog.tsx +7 -0
  491. package/src/modules/customers/components/detail/ManageTagsDialog.tsx +4 -0
  492. package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +4 -0
  493. package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +2 -0
  494. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +23 -7
  495. package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +25 -15
  496. package/src/modules/customers/components/detail/hooks/useInteractions.ts +76 -35
  497. package/src/modules/customers/components/detail/hooks/usePersonTasks.ts +30 -17
  498. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +2 -0
  499. package/src/modules/customers/components/detail/types.ts +1 -0
  500. package/src/modules/customers/components/formConfig.tsx +2 -0
  501. package/src/modules/customers/data/guards.ts +67 -0
  502. package/src/modules/customers/di.ts +66 -0
  503. package/src/modules/customers/i18n/de.json +2 -0
  504. package/src/modules/customers/i18n/en.json +2 -0
  505. package/src/modules/customers/i18n/es.json +2 -0
  506. package/src/modules/customers/i18n/pl.json +2 -0
  507. package/src/modules/customers/lib/todoCompatibility.ts +14 -0
  508. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +2 -0
  509. package/src/modules/data_sync/api/options.ts +7 -4
  510. package/src/modules/data_sync/api/schedules/route.ts +9 -1
  511. package/src/modules/data_sync/backend/data-sync/page.tsx +18 -5
  512. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +46 -19
  513. package/src/modules/data_sync/lib/sync-schedule-service.ts +11 -0
  514. package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +8 -1
  515. package/src/modules/dictionaries/api/[dictionaryId]/route.ts +23 -0
  516. package/src/modules/dictionaries/components/DictionariesManager.tsx +32 -9
  517. package/src/modules/dictionaries/components/DictionaryEntriesEditor.tsx +30 -14
  518. package/src/modules/dictionaries/i18n/de.json +1 -0
  519. package/src/modules/dictionaries/i18n/en.json +1 -0
  520. package/src/modules/dictionaries/i18n/es.json +1 -0
  521. package/src/modules/dictionaries/i18n/pl.json +1 -0
  522. package/src/modules/directory/api/organizations/route.ts +3 -0
  523. package/src/modules/directory/backend/directory/organizations/[id]/edit/page.tsx +8 -0
  524. package/src/modules/directory/backend/directory/organizations/page.tsx +10 -5
  525. package/src/modules/directory/backend/directory/tenants/[id]/edit/page.tsx +16 -5
  526. package/src/modules/directory/backend/directory/tenants/page.tsx +8 -4
  527. package/src/modules/directory/commands/organizations.ts +7 -4
  528. package/src/modules/entities/api/records.ts +99 -0
  529. package/src/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.tsx +7 -0
  530. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +8 -4
  531. package/src/modules/entities/lib/helpers.ts +17 -0
  532. package/src/modules/feature_toggles/api/global/[id]/override/route.ts +1 -0
  533. package/src/modules/feature_toggles/api/overrides/route.ts +19 -0
  534. package/src/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.tsx +19 -13
  535. package/src/modules/feature_toggles/components/FeatureToggleOverrideCard.tsx +22 -12
  536. package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +7 -2
  537. package/src/modules/feature_toggles/components/formConfig.tsx +2 -1
  538. package/src/modules/feature_toggles/components/overrideFormConfig.tsx +10 -1
  539. package/src/modules/feature_toggles/data/validators.ts +11 -3
  540. package/src/modules/inbox_ops/api/settings/route.ts +18 -0
  541. package/src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx +15 -10
  542. package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +9 -4
  543. package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +20 -11
  544. package/src/modules/integrations/backend/integrations/page.tsx +13 -8
  545. package/src/modules/messages/commands/messages.ts +27 -15
  546. package/src/modules/perspectives/api/[tableId]/route.ts +11 -2
  547. package/src/modules/perspectives/services/perspectiveService.ts +13 -1
  548. package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +16 -14
  549. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +6 -3
  550. package/src/modules/planner/components/AvailabilityRuleSetForm.tsx +3 -0
  551. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +58 -15
  552. package/src/modules/planner/components/AvailabilitySchedule.tsx +22 -7
  553. package/src/modules/query_index/lib/engine.ts +34 -0
  554. package/src/modules/resources/backend/resources/resource-types/[id]/edit/page.tsx +7 -1
  555. package/src/modules/resources/backend/resources/resource-types/page.tsx +6 -3
  556. package/src/modules/resources/backend/resources/resources/[id]/page.tsx +23 -3
  557. package/src/modules/resources/backend/resources/resources/page.tsx +15 -4
  558. package/src/modules/resources/components/ResourceCrudForm.tsx +3 -0
  559. package/src/modules/resources/components/ResourceTypeCrudForm.tsx +2 -0
  560. package/src/modules/sales/api/documents/factory.ts +13 -1
  561. package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +6 -0
  562. package/src/modules/sales/backend/sales/channels/offers/page.tsx +10 -4
  563. package/src/modules/sales/backend/sales/channels/page.tsx +19 -4
  564. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +73 -20
  565. package/src/modules/sales/backend/sales/documents/create/page.tsx +2 -0
  566. package/src/modules/sales/commands/documentAddresses.ts +226 -4
  567. package/src/modules/sales/commands/documents.ts +28 -0
  568. package/src/modules/sales/commands/returns.ts +12 -3
  569. package/src/modules/sales/commands/shared.ts +36 -0
  570. package/src/modules/sales/commands/shipments.ts +17 -1
  571. package/src/modules/sales/components/AdjustmentKindSettings.tsx +20 -11
  572. package/src/modules/sales/components/DocumentNumberSettings.tsx +1 -0
  573. package/src/modules/sales/components/OrderEditingSettings.tsx +1 -0
  574. package/src/modules/sales/components/PaymentMethodsSettings.tsx +12 -4
  575. package/src/modules/sales/components/ShippingMethodsSettings.tsx +12 -4
  576. package/src/modules/sales/components/StatusSettings.tsx +20 -11
  577. package/src/modules/sales/components/TaxRatesSettings.tsx +12 -5
  578. package/src/modules/sales/components/channels/ChannelOfferForm.tsx +67 -14
  579. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +7 -4
  580. package/src/modules/sales/components/documents/AddressesSection.tsx +35 -25
  581. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +50 -25
  582. package/src/modules/sales/components/documents/ItemsSection.tsx +24 -13
  583. package/src/modules/sales/components/documents/LineItemDialog.tsx +26 -9
  584. package/src/modules/sales/components/documents/PaymentDialog.tsx +33 -14
  585. package/src/modules/sales/components/documents/PaymentsSection.tsx +22 -10
  586. package/src/modules/sales/components/documents/ReturnDialog.tsx +28 -17
  587. package/src/modules/sales/components/documents/ReturnsSection.tsx +4 -1
  588. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +11 -4
  589. package/src/modules/sales/components/documents/ShipmentDialog.tsx +23 -8
  590. package/src/modules/sales/components/documents/ShipmentsSection.tsx +20 -10
  591. package/src/modules/sales/components/documents/optimisticLock.ts +34 -0
  592. package/src/modules/sales/components/documents/shipmentTypes.ts +1 -0
  593. package/src/modules/sales/di.ts +35 -0
  594. package/src/modules/sales/i18n/de.json +3 -0
  595. package/src/modules/sales/i18n/en.json +3 -0
  596. package/src/modules/sales/i18n/es.json +3 -0
  597. package/src/modules/sales/i18n/pl.json +3 -0
  598. package/src/modules/staff/api/job-histories.ts +12 -2
  599. package/src/modules/staff/api/timesheets/time-entries/route.ts +16 -4
  600. package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +12 -7
  601. package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +2 -0
  602. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +16 -5
  603. package/src/modules/staff/backend/staff/team-members/page.tsx +6 -2
  604. package/src/modules/staff/backend/staff/team-roles/[id]/edit/page.tsx +8 -0
  605. package/src/modules/staff/backend/staff/team-roles/page.tsx +6 -2
  606. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +13 -3
  607. package/src/modules/staff/backend/staff/teams/page.tsx +9 -3
  608. package/src/modules/staff/backend/staff/timesheets/page.tsx +10 -1
  609. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +4 -0
  610. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +9 -3
  611. package/src/modules/staff/commands/job-histories.ts +42 -3
  612. package/src/modules/staff/components/LeaveRequestForm.tsx +2 -0
  613. package/src/modules/staff/components/TeamForm.tsx +2 -0
  614. package/src/modules/staff/components/TeamMemberForm.tsx +2 -0
  615. package/src/modules/staff/components/TeamRoleForm.tsx +2 -0
  616. package/src/modules/staff/components/detail/JobHistorySection.tsx +28 -6
  617. package/src/modules/staff/data/validators.ts +6 -0
  618. package/src/modules/staff/i18n/de.json +1 -0
  619. package/src/modules/staff/i18n/en.json +1 -0
  620. package/src/modules/staff/i18n/es.json +1 -0
  621. package/src/modules/staff/i18n/pl.json +1 -0
  622. package/src/modules/staff/lib/leaveRequestHelpers.ts +4 -0
  623. package/src/modules/translations/components/TranslationManager.tsx +13 -8
  624. package/src/modules/workflows/api/definitions/[id]/route.ts +112 -0
  625. package/src/modules/workflows/backend/definitions/[id]/page.tsx +20 -4
  626. package/src/modules/workflows/backend/definitions/page.tsx +20 -9
  627. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +29 -16
  628. package/src/modules/workflows/components/formConfig.tsx +5 -0
  629. package/src/modules/workflows/di.ts +20 -0
  630. package/src/modules/workflows/i18n/de.json +1 -0
  631. package/src/modules/workflows/i18n/en.json +1 -0
  632. package/src/modules/workflows/i18n/es.json +1 -0
  633. package/src/modules/workflows/i18n/pl.json +1 -0
@@ -10,6 +10,11 @@ const projectColorSchema = z
10
10
 
11
11
  const tagsSchema = z.array(z.string().min(1)).optional().default([])
12
12
 
13
+ export const optimisticUpdatedAtSchema = z.string().refine(
14
+ (value) => !Number.isNaN(new Date(value).getTime()),
15
+ { message: 'Invalid datetime' },
16
+ )
17
+
13
18
  const scopedCreateFields = {
14
19
  tenantId: z.string().uuid(),
15
20
  organizationId: z.string().uuid(),
@@ -121,6 +126,7 @@ export const staffTeamMemberJobHistoryCreateSchema = z.object({
121
126
  export const staffTeamMemberJobHistoryUpdateSchema = z
122
127
  .object({
123
128
  id: z.string().uuid(),
129
+ updatedAt: optimisticUpdatedAtSchema.optional(),
124
130
  })
125
131
  .merge(staffTeamMemberJobHistoryCreateSchema.partial())
126
132
 
@@ -702,6 +702,7 @@
702
702
  "staff.teamMembers.detail.inline.urlInvalid": "Geben Sie eine gültige URL ein",
703
703
  "staff.teamMembers.detail.jobHistory.add": "Job hinzufügen",
704
704
  "staff.teamMembers.detail.jobHistory.cancel": "Abbrechen",
705
+ "staff.teamMembers.detail.jobHistory.conflict": "Dieser Datensatz wurde von jemand anderem geändert. Bitte aktualisieren und erneut versuchen.",
705
706
  "staff.teamMembers.detail.jobHistory.deleteConfirm": "Diesen Eintrag im Beschäftigungsverlauf löschen?",
706
707
  "staff.teamMembers.detail.jobHistory.deleted": "Beschäftigungsverlauf gelöscht.",
707
708
  "staff.teamMembers.detail.jobHistory.edit": "Job bearbeiten",
@@ -702,6 +702,7 @@
702
702
  "staff.teamMembers.detail.inline.urlInvalid": "Enter a valid URL",
703
703
  "staff.teamMembers.detail.jobHistory.add": "Add job",
704
704
  "staff.teamMembers.detail.jobHistory.cancel": "Cancel",
705
+ "staff.teamMembers.detail.jobHistory.conflict": "This record was modified by someone else. Refresh and try again.",
705
706
  "staff.teamMembers.detail.jobHistory.deleteConfirm": "Delete this job history entry?",
706
707
  "staff.teamMembers.detail.jobHistory.deleted": "Job history deleted.",
707
708
  "staff.teamMembers.detail.jobHistory.edit": "Edit job",
@@ -702,6 +702,7 @@
702
702
  "staff.teamMembers.detail.inline.urlInvalid": "Introduce una URL válida",
703
703
  "staff.teamMembers.detail.jobHistory.add": "Agregar empleo",
704
704
  "staff.teamMembers.detail.jobHistory.cancel": "Cancelar",
705
+ "staff.teamMembers.detail.jobHistory.conflict": "Otro usuario modificó este registro. Actualiza e inténtalo de nuevo.",
705
706
  "staff.teamMembers.detail.jobHistory.deleteConfirm": "¿Eliminar esta entrada de historial laboral?",
706
707
  "staff.teamMembers.detail.jobHistory.deleted": "Historial laboral eliminado.",
707
708
  "staff.teamMembers.detail.jobHistory.edit": "Editar empleo",
@@ -702,6 +702,7 @@
702
702
  "staff.teamMembers.detail.inline.urlInvalid": "Wprowadź prawidłowy adres URL",
703
703
  "staff.teamMembers.detail.jobHistory.add": "Dodaj stanowisko",
704
704
  "staff.teamMembers.detail.jobHistory.cancel": "Anuluj",
705
+ "staff.teamMembers.detail.jobHistory.conflict": "Ten rekord został zmieniony przez inną osobę. Odśwież i spróbuj ponownie.",
705
706
  "staff.teamMembers.detail.jobHistory.deleteConfirm": "Usunąć ten wpis historii zatrudnienia?",
706
707
  "staff.teamMembers.detail.jobHistory.deleted": "Wpis historii zatrudnienia usunięty.",
707
708
  "staff.teamMembers.detail.jobHistory.edit": "Edytuj stanowisko",
@@ -18,6 +18,8 @@ export type LeaveRequestRecord = {
18
18
  decision_comment?: string | null
19
19
  decidedAt?: string | null
20
20
  decided_at?: string | null
21
+ updatedAt?: string | null
22
+ updated_at?: string | null
21
23
  } & Record<string, unknown>
22
24
 
23
25
  export type NormalizedLeaveRequest = {
@@ -33,6 +35,7 @@ export type NormalizedLeaveRequest = {
33
35
  note: string | null
34
36
  decisionComment: string | null
35
37
  decidedAt: string | null
38
+ updatedAt: string | null
36
39
  } & Record<string, unknown>
37
40
 
38
41
  export function normalizeLeaveRequest(record: LeaveRequestRecord): NormalizedLeaveRequest {
@@ -50,6 +53,7 @@ export function normalizeLeaveRequest(record: LeaveRequestRecord): NormalizedLea
50
53
  note: record.note ?? null,
51
54
  decisionComment: record.decisionComment ?? record.decision_comment ?? null,
52
55
  decidedAt: record.decidedAt ?? record.decided_at ?? null,
56
+ updatedAt: record.updatedAt ?? record.updated_at ?? null,
53
57
  }
54
58
  }
55
59
 
@@ -7,7 +7,8 @@ import { Input } from '@open-mercato/ui/primitives/input'
7
7
  import { ComboboxInput } from '@open-mercato/ui/backend/inputs'
8
8
  import { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'
9
9
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
10
- import { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
10
+ import { apiCall, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
11
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
11
12
  import { useCustomFieldDefs } from '@open-mercato/ui/backend/utils/customFieldDefs'
12
13
  import { Save, Plus, X } from 'lucide-react'
13
14
  import { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
@@ -238,13 +239,16 @@ export function TranslationManager({
238
239
  console.warn('[translations] Save skipped: payload is empty — no locale contains any non-empty field')
239
240
  throw new Error(t('translations.manager.errors.nothingToSave', 'Nothing to save — enter a translation first'))
240
241
  }
241
- const res = await apiCall(
242
- `/api/translations/${encodeURIComponent(entityType)}/${encodeURIComponent(recordId)}`,
243
- {
244
- method: 'PUT',
245
- headers: { 'content-type': 'application/json' },
246
- body: JSON.stringify(body),
247
- },
242
+ const res = await withScopedApiRequestHeaders(
243
+ buildOptimisticLockHeader(translationData?.updatedAt),
244
+ () => apiCall(
245
+ `/api/translations/${encodeURIComponent(entityType)}/${encodeURIComponent(recordId)}`,
246
+ {
247
+ method: 'PUT',
248
+ headers: { 'content-type': 'application/json' },
249
+ body: JSON.stringify(body),
250
+ },
251
+ ),
248
252
  )
249
253
  if (!res.ok) {
250
254
  throw new Error(t('translations.manager.errors.save', 'Failed to save translations'))
@@ -539,6 +543,7 @@ export function LocaleManager() {
539
543
 
540
544
  const mutation = useMutation({
541
545
  mutationFn: async (updatedLocales: string[]) => {
546
+ // optimistic-lock-exempt: single-row tenant supported-locales settings list — no per-record version / concurrent record edit
542
547
  const res = await apiCall<{ locales: string[] }>('/api/translations/locales', {
543
548
  method: 'PUT',
544
549
  headers: { 'content-type': 'application/json' },
@@ -21,6 +21,21 @@ import {
21
21
  import { serializeWorkflowDefinition, serializeCodeWorkflowDefinition } from '../serialize'
22
22
  import { invalidateTriggerCache } from '../../../lib/event-trigger-service'
23
23
  import { getCodeWorkflow } from '../../../lib/code-registry'
24
+ import { createGenericOptimisticLockReader } from '@open-mercato/shared/lib/crud/optimistic-lock'
25
+ import { registerOptimisticLockReaderIfAbsent } from '@open-mercato/shared/lib/crud/optimistic-lock-store'
26
+ import { validateCrudMutationGuard, runCrudMutationGuardAfterSuccess } from '@open-mercato/shared/lib/crud/mutation-guard'
27
+ import { enforceCommandOptimisticLock } from '@open-mercato/shared/lib/crud/optimistic-lock-command'
28
+ import { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
29
+
30
+ registerOptimisticLockReaderIfAbsent({
31
+ 'workflows.definition': createGenericOptimisticLockReader({
32
+ entity: WorkflowDefinition,
33
+ idField: 'id',
34
+ tenantField: 'tenantId',
35
+ orgField: 'organizationId',
36
+ softDeleteField: 'deletedAt',
37
+ }),
38
+ })
24
39
 
25
40
  export const metadata = {
26
41
  requireAuth: true,
@@ -151,6 +166,20 @@ export async function PUT(
151
166
  }
152
167
 
153
168
  const input: UpdateWorkflowDefinitionApiInput = validation.data
169
+ const guardResult = await validateCrudMutationGuard(container, {
170
+ tenantId: tenantId ?? '',
171
+ organizationId: organizationId ?? null,
172
+ userId: auth.sub ?? '',
173
+ resourceKind: 'workflows.definition',
174
+ resourceId: params.id,
175
+ operation: 'update',
176
+ requestMethod: 'PUT',
177
+ requestHeaders: request.headers,
178
+ mutationPayload: input as Record<string, unknown>,
179
+ })
180
+ if (guardResult && !guardResult.ok) {
181
+ return NextResponse.json(guardResult.body, { status: guardResult.status })
182
+ }
154
183
 
155
184
  // Handle customizing a code-based workflow definition
156
185
  if (params.id.startsWith('code:')) {
@@ -171,6 +200,19 @@ export async function PUT(
171
200
 
172
201
  let savedOverride: WorkflowDefinition
173
202
  if (existingOverride) {
203
+ try {
204
+ enforceCommandOptimisticLock({
205
+ resourceKind: 'workflows.definition',
206
+ resourceId: existingOverride.id,
207
+ current: existingOverride.updatedAt ?? null,
208
+ request,
209
+ })
210
+ } catch (lockError) {
211
+ if (isCrudHttpError(lockError)) {
212
+ return NextResponse.json(lockError.body, { status: lockError.status })
213
+ }
214
+ throw lockError
215
+ }
174
216
  // Revive if soft-deleted, then apply updates
175
217
  existingOverride.deletedAt = null
176
218
  existingOverride.workflowName = codeDef.workflowName
@@ -230,6 +272,20 @@ export async function PUT(
230
272
  console.error('Failed to emit workflows.definition.customized event:', eventError)
231
273
  }
232
274
 
275
+ if (guardResult?.shouldRunAfterSuccess) {
276
+ await runCrudMutationGuardAfterSuccess(container, {
277
+ tenantId: tenantId ?? '',
278
+ organizationId: organizationId ?? null,
279
+ userId: auth.sub ?? '',
280
+ resourceKind: 'workflows.definition',
281
+ resourceId: String(savedOverride.id),
282
+ operation: 'update',
283
+ requestMethod: 'PUT',
284
+ requestHeaders: request.headers,
285
+ metadata: guardResult.metadata,
286
+ })
287
+ }
288
+
233
289
  return NextResponse.json({
234
290
  data: serializeWorkflowDefinition(savedOverride),
235
291
  message: 'Workflow definition customized successfully',
@@ -251,6 +307,20 @@ export async function PUT(
251
307
  )
252
308
  }
253
309
 
310
+ try {
311
+ enforceCommandOptimisticLock({
312
+ resourceKind: 'workflows.definition',
313
+ resourceId: definition.id,
314
+ current: definition.updatedAt ?? null,
315
+ request,
316
+ })
317
+ } catch (lockError) {
318
+ if (isCrudHttpError(lockError)) {
319
+ return NextResponse.json(lockError.body, { status: lockError.status })
320
+ }
321
+ throw lockError
322
+ }
323
+
254
324
  // Update fields. workflowId is intentionally ignored — it identifies the
255
325
  // row and renaming would break references. Version is user-managed and
256
326
  // applied when supplied so the edit form can bump it explicitly.
@@ -283,6 +353,20 @@ export async function PUT(
283
353
 
284
354
  await em.flush()
285
355
 
356
+ if (guardResult?.shouldRunAfterSuccess) {
357
+ await runCrudMutationGuardAfterSuccess(container, {
358
+ tenantId: tenantId ?? '',
359
+ organizationId: organizationId ?? null,
360
+ userId: auth.sub ?? '',
361
+ resourceKind: 'workflows.definition',
362
+ resourceId: String(definition.id),
363
+ operation: 'update',
364
+ requestMethod: 'PUT',
365
+ requestHeaders: request.headers,
366
+ metadata: guardResult.metadata,
367
+ })
368
+ }
369
+
286
370
  // Embedded triggers may have changed; invalidate the in-memory cache so
287
371
  // the wildcard event subscriber reloads them on the next event.
288
372
  if (tenantId) invalidateTriggerCache(tenantId, organizationId ?? undefined)
@@ -356,6 +440,20 @@ export async function DELETE(
356
440
  )
357
441
  }
358
442
 
443
+ const guardResult = await validateCrudMutationGuard(container, {
444
+ tenantId: tenantId ?? '',
445
+ organizationId: organizationId ?? null,
446
+ userId: auth.sub ?? '',
447
+ resourceKind: 'workflows.definition',
448
+ resourceId: params.id,
449
+ operation: 'delete',
450
+ requestMethod: 'DELETE',
451
+ requestHeaders: request.headers,
452
+ })
453
+ if (guardResult && !guardResult.ok) {
454
+ return NextResponse.json(guardResult.body, { status: guardResult.status })
455
+ }
456
+
359
457
  // Check if there are active workflow instances using this definition
360
458
  const { WorkflowInstance } = await import('../../../data/entities')
361
459
  const activeInstances = await em.count(WorkflowInstance, {
@@ -378,6 +476,20 @@ export async function DELETE(
378
476
 
379
477
  await em.flush()
380
478
 
479
+ if (guardResult?.shouldRunAfterSuccess) {
480
+ await runCrudMutationGuardAfterSuccess(container, {
481
+ tenantId: tenantId ?? '',
482
+ organizationId: organizationId ?? null,
483
+ userId: auth.sub ?? '',
484
+ resourceKind: 'workflows.definition',
485
+ resourceId: String(definition.id),
486
+ operation: 'delete',
487
+ requestMethod: 'DELETE',
488
+ requestHeaders: request.headers,
489
+ metadata: guardResult.metadata,
490
+ })
491
+ }
492
+
381
493
  if (tenantId) invalidateTriggerCache(tenantId, organizationId ?? undefined)
382
494
 
383
495
  return NextResponse.json({
@@ -8,8 +8,9 @@ import { CrudForm } from '@open-mercato/ui/backend/CrudForm'
8
8
  import { Spinner } from '@open-mercato/ui/primitives/spinner'
9
9
  import { Button } from '@open-mercato/ui/primitives/button'
10
10
  import { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'
11
+ import { apiFetch, withScopedApiHeaders } from '@open-mercato/ui/backend/utils/api'
12
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
11
13
  import { ErrorMessage, RecordNotFoundState } from '@open-mercato/ui/backend/detail'
12
- import { apiFetch } from '@open-mercato/ui/backend/utils/api'
13
14
  import { readJsonSafe } from '@open-mercato/ui/backend/utils/serverErrors'
14
15
  import { formatWorkflowValidationError } from '../../../lib/format-validation-error'
15
16
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
@@ -95,17 +96,32 @@ export default function EditWorkflowDefinitionPage() {
95
96
 
96
97
  const handleSubmit = async (values: WorkflowDefinitionFormValues) => {
97
98
  const payload = buildWorkflowPayload({ ...values, triggers })
99
+ const optimisticLockHeader = buildOptimisticLockHeader(
100
+ typeof definition?.updatedAt === 'string' ? definition.updatedAt : null,
101
+ )
98
102
 
99
103
  await runMutation({
100
104
  operation: async () => {
101
- const response = await apiFetch(`/api/workflows/definitions/${definitionId}`, {
105
+ const updateDefinition = () => apiFetch(`/api/workflows/definitions/${definitionId}`, {
102
106
  method: 'PUT',
103
107
  headers: { 'Content-Type': 'application/json' },
104
108
  body: JSON.stringify(payload),
105
109
  })
110
+ const response = Object.keys(optimisticLockHeader).length > 0
111
+ ? await withScopedApiHeaders(optimisticLockHeader, updateDefinition)
112
+ : await updateDefinition()
106
113
  if (!response.ok) {
107
- const errorBody = await readJsonSafe<{ error?: string; details?: Array<{ path?: Array<string | number>; message?: string }> }>(response, null)
108
- throw new Error(formatWorkflowValidationError(errorBody, t('workflows.errors.updateFailed')))
114
+ const errorBody = await readJsonSafe<{
115
+ error?: string
116
+ code?: string
117
+ currentUpdatedAt?: string
118
+ expectedUpdatedAt?: string
119
+ details?: Array<{ path?: Array<string | number>; message?: string }>
120
+ }>(response, null)
121
+ throw Object.assign(
122
+ new Error(formatWorkflowValidationError(errorBody, t('workflows.errors.updateFailed'))),
123
+ { status: response.status, ...(errorBody ?? {}) },
124
+ )
109
125
  }
110
126
  return response
111
127
  },
@@ -18,7 +18,9 @@ import {
18
18
  DialogHeader,
19
19
  DialogTitle,
20
20
  } from '@open-mercato/ui/primitives/dialog'
21
- import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
21
+ import { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
22
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
23
+ import { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'
22
24
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
23
25
  import { useQuery, useQueryClient } from '@tanstack/react-query'
24
26
  import { useT } from '@open-mercato/shared/lib/i18n/context'
@@ -86,7 +88,7 @@ export default function WorkflowDefinitionsListPage() {
86
88
  const router = useRouter()
87
89
  const queryClient = useQueryClient()
88
90
  const [filterValues, setFilterValues] = React.useState<FilterValues>({})
89
- const [deleteTarget, setDeleteTarget] = React.useState<{ id: string; name: string } | null>(null)
91
+ const [deleteTarget, setDeleteTarget] = React.useState<{ id: string; name: string; updatedAt: string | null } | null>(null)
90
92
 
91
93
  const { data, isLoading, error } = useQuery({
92
94
  queryKey: ['workflow-definitions', 'list', filterValues, page],
@@ -121,22 +123,31 @@ export default function WorkflowDefinitionsListPage() {
121
123
  },
122
124
  })
123
125
 
124
- const handleDelete = (id: string, workflowName: string) => {
125
- setDeleteTarget({ id, name: workflowName })
126
+ const handleDelete = (id: string, workflowName: string, updatedAt: string | null) => {
127
+ setDeleteTarget({ id, name: workflowName, updatedAt })
126
128
  }
127
129
 
128
130
  const confirmDelete = async () => {
129
131
  if (!deleteTarget) return
130
132
 
131
- const result = await apiCall(`/api/workflows/definitions/${deleteTarget.id}`, {
132
- method: 'DELETE',
133
- })
133
+ const result = await withScopedApiRequestHeaders(
134
+ buildOptimisticLockHeader(deleteTarget.updatedAt),
135
+ () => apiCall(`/api/workflows/definitions/${deleteTarget.id}`, {
136
+ method: 'DELETE',
137
+ }),
138
+ )
134
139
 
135
140
  if (result.ok) {
136
141
  flash(t('workflows.messages.deleted'), 'success')
137
142
  queryClient.invalidateQueries({ queryKey: ['workflow-definitions'] })
138
143
  } else {
139
- flash(t('workflows.messages.deleteFailed'), 'error')
144
+ const conflictError = Object.assign(new Error(t('workflows.messages.deleteFailed')), {
145
+ status: result.status,
146
+ ...(result.result && typeof result.result === 'object' ? result.result : {}),
147
+ })
148
+ if (!surfaceRecordConflict(conflictError, t)) {
149
+ flash(t('workflows.messages.deleteFailed'), 'error')
150
+ }
140
151
  }
141
152
  setDeleteTarget(null)
142
153
  }
@@ -354,7 +365,7 @@ export default function WorkflowDefinitionsListPage() {
354
365
  ...(!isCodeOnly ? [{
355
366
  id: 'delete',
356
367
  label: t('common.delete'),
357
- onSelect: () => handleDelete(row.original.id, row.original.workflowName),
368
+ onSelect: () => handleDelete(row.original.id, row.original.workflowName, row.original.updatedAt),
358
369
  destructive: true,
359
370
  }] : []),
360
371
  ]
@@ -32,7 +32,9 @@ import { Alert, AlertTitle } from '@open-mercato/ui/primitives/alert'
32
32
  import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
33
33
  import { useT } from '@open-mercato/shared/lib/i18n/context'
34
34
  import { FormHeader } from '@open-mercato/ui/backend/forms'
35
- import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
35
+ import { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
36
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
37
+ import { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'
36
38
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
37
39
  import { CircleQuestionMark, Info, PanelTopClose, PanelTopOpen, Play, Save, Trash2 } from 'lucide-react'
38
40
  import { NODE_TYPE_ICONS, NODE_TYPE_COLORS, NODE_TYPE_LABELS } from '../../../lib/node-type-icons'
@@ -107,6 +109,7 @@ export default function VisualEditorPage() {
107
109
  const [effectiveTo, setEffectiveTo] = useState('')
108
110
  const [triggers, setTriggers] = useState<WorkflowDefinitionTrigger[]>([])
109
111
  const [source, setSource] = useState<'code' | 'code_override' | 'user' | null>(null)
112
+ const [updatedAt, setUpdatedAt] = useState<string | null>(null)
110
113
 
111
114
  const isCodeOnly = source === 'code'
112
115
  const isCodeOverride = source === 'code_override'
@@ -154,6 +157,7 @@ export default function VisualEditorPage() {
154
157
  // code → read-only with Customize button; code_override → editable
155
158
  // with Reset to code; user → editable, no banner.
156
159
  setSource((definition.source as 'code' | 'code_override' | 'user') ?? null)
160
+ setUpdatedAt(typeof definition.updatedAt === 'string' ? definition.updatedAt : null)
157
161
  } catch (error) {
158
162
  console.error('Error loading workflow definition:', error)
159
163
  flash('Failed to load workflow definition', 'error')
@@ -372,20 +376,23 @@ export default function VisualEditorPage() {
372
376
  // edits (name, description, version, category, tags, icon, effective
373
377
  // dates) actually persist. Previously only `definition` + `enabled`
374
378
  // were sent, silently dropping every other field.
375
- result = await apiCall<{ data: any; error?: string }>(`/api/workflows/definitions/${definitionId}`, {
376
- method: 'PUT',
377
- headers: { 'Content-Type': 'application/json' },
378
- body: JSON.stringify({
379
- workflowName,
380
- description: description || null,
381
- version,
382
- definition: definitionData,
383
- metadata: Object.keys(metadata).length > 0 ? metadata : null,
384
- enabled,
385
- effectiveFrom: effectiveFrom || null,
386
- effectiveTo: effectiveTo || null,
379
+ result = await withScopedApiRequestHeaders(
380
+ buildOptimisticLockHeader(updatedAt),
381
+ () => apiCall<{ data: any; error?: string }>(`/api/workflows/definitions/${definitionId}`, {
382
+ method: 'PUT',
383
+ headers: { 'Content-Type': 'application/json' },
384
+ body: JSON.stringify({
385
+ workflowName,
386
+ description: description || null,
387
+ version,
388
+ definition: definitionData,
389
+ metadata: Object.keys(metadata).length > 0 ? metadata : null,
390
+ enabled,
391
+ effectiveFrom: effectiveFrom || null,
392
+ effectiveTo: effectiveTo || null,
393
+ }),
387
394
  }),
388
- })
395
+ )
389
396
  } else {
390
397
  // Create new definition
391
398
  result = await apiCall<{ data: any; error?: string }>('/api/workflows/definitions', {
@@ -406,7 +413,13 @@ export default function VisualEditorPage() {
406
413
  }
407
414
 
408
415
  if (!result.ok) {
409
- flash(`Failed to save: ${result.result?.error || 'Unknown error'}`, 'error')
416
+ const conflictError = Object.assign(new Error(t('workflows.messages.saveFailed', 'Failed to save')), {
417
+ status: result.status,
418
+ ...(result.result && typeof result.result === 'object' ? result.result : {}),
419
+ })
420
+ if (!surfaceRecordConflict(conflictError, t)) {
421
+ flash(`Failed to save: ${result.result?.error || 'Unknown error'}`, 'error')
422
+ }
410
423
  return
411
424
  }
412
425
 
@@ -425,7 +438,7 @@ export default function VisualEditorPage() {
425
438
  } finally {
426
439
  setIsSaving(false)
427
440
  }
428
- }, [nodes, edges, workflowId, workflowName, description, version, enabled, category, tags, icon, effectiveFrom, effectiveTo, triggers, definitionId, router])
441
+ }, [nodes, edges, workflowId, workflowName, description, version, enabled, category, tags, icon, effectiveFrom, effectiveTo, triggers, definitionId, updatedAt, router])
429
442
 
430
443
  // Customize a code-defined workflow → creates an override and reloads the
431
444
  // editor pointed at the new UUID. Mirrors the non-visual edit page button.
@@ -28,6 +28,8 @@ export type WorkflowDefinitionFormValues = {
28
28
  steps: any[]
29
29
  transitions: any[]
30
30
  triggers: WorkflowDefinitionTrigger[]
31
+ id?: string
32
+ updatedAt?: string | null
31
33
  }
32
34
 
33
35
  /**
@@ -235,6 +237,7 @@ import { toDateInputValue } from '@open-mercato/shared/lib/date/format'
235
237
  * Parse workflow definition to form values
236
238
  */
237
239
  export function parseWorkflowToFormValues(workflow: any): WorkflowDefinitionFormValues {
240
+ const updatedAt = workflow.updatedAt ?? workflow.updated_at ?? null
238
241
  const metadata = workflow.metadata || {}
239
242
  return {
240
243
  workflowId: workflow.workflowId || '',
@@ -251,6 +254,8 @@ export function parseWorkflowToFormValues(workflow: any): WorkflowDefinitionForm
251
254
  steps: workflow.definition?.steps || [],
252
255
  transitions: workflow.definition?.transitions || [],
253
256
  triggers: workflow.definition?.triggers || [],
257
+ id: workflow.id,
258
+ updatedAt: typeof updatedAt === 'string' ? updatedAt : updatedAt ? String(updatedAt) : null,
254
259
  }
255
260
  }
256
261
 
@@ -6,6 +6,9 @@
6
6
 
7
7
  import type { AwilixContainer } from 'awilix'
8
8
  import { asFunction } from 'awilix'
9
+ import { createGenericOptimisticLockReader } from '@open-mercato/shared/lib/crud/optimistic-lock'
10
+ import { registerOptimisticLockReaders } from '@open-mercato/shared/lib/crud/optimistic-lock-store'
11
+ import { WorkflowDefinition } from './data/entities'
9
12
  import * as workflowExecutor from './lib/workflow-executor'
10
13
  import * as stepHandler from './lib/step-handler'
11
14
  import * as transitionHandler from './lib/transition-handler'
@@ -14,6 +17,23 @@ import * as eventLogger from './lib/event-logger'
14
17
  import * as signalHandler from './lib/signal-handler'
15
18
  import * as timerHandler from './lib/timer-handler'
16
19
 
20
+ // Register the `workflows.definition` optimistic-lock reader at module-DI load
21
+ // time (top-level, like sales/customers) so it is present in the global reader
22
+ // store before any request-scoped `crudMutationGuardService` snapshots
23
+ // `getAllOptimisticLockReaders()`. Registering it only as a side-effect of
24
+ // importing the definition route module left it absent from that snapshot, so
25
+ // the guard short-circuited and the visual editor's stale saves overwrote with
26
+ // no 409 and no conflict bar.
27
+ registerOptimisticLockReaders({
28
+ 'workflows.definition': createGenericOptimisticLockReader({
29
+ entity: WorkflowDefinition,
30
+ idField: 'id',
31
+ tenantField: 'tenantId',
32
+ orgField: 'organizationId',
33
+ softDeleteField: 'deletedAt',
34
+ }),
35
+ })
36
+
17
37
  export function register(container: AwilixContainer): void {
18
38
  container.register({
19
39
  workflowExecutor: asFunction(() => workflowExecutor).scoped(),
@@ -860,6 +860,7 @@
860
860
  "workflows.messages.instanceStarted": "Workflow-Instanz gestartet",
861
861
  "workflows.messages.invalidWorkflow": "Ungültige Workflow-Definition",
862
862
  "workflows.messages.loadFailed": "Workflows konnten nicht geladen werden",
863
+ "workflows.messages.saveFailed": "Speichern fehlgeschlagen",
863
864
  "workflows.messages.taskAlreadyClaimed": "Aufgabe wurde bereits von einem anderen Benutzer übernommen",
864
865
  "workflows.messages.taskClaimed": "Aufgabe erfolgreich übernommen",
865
866
  "workflows.messages.taskCompleted": "Aufgabe erfolgreich abgeschlossen",
@@ -860,6 +860,7 @@
860
860
  "workflows.messages.instanceStarted": "Workflow instance started",
861
861
  "workflows.messages.invalidWorkflow": "Invalid workflow definition",
862
862
  "workflows.messages.loadFailed": "Failed to load workflows",
863
+ "workflows.messages.saveFailed": "Failed to save",
863
864
  "workflows.messages.taskAlreadyClaimed": "Task is already claimed by another user",
864
865
  "workflows.messages.taskClaimed": "Task claimed successfully",
865
866
  "workflows.messages.taskCompleted": "Task completed successfully",
@@ -860,6 +860,7 @@
860
860
  "workflows.messages.instanceStarted": "Instancia del flujo de trabajo iniciada",
861
861
  "workflows.messages.invalidWorkflow": "Definicion de flujo de trabajo no valida",
862
862
  "workflows.messages.loadFailed": "No se pudieron cargar los flujos de trabajo",
863
+ "workflows.messages.saveFailed": "Error al guardar",
863
864
  "workflows.messages.taskAlreadyClaimed": "La tarea ya ha sido reclamada por otro usuario",
864
865
  "workflows.messages.taskClaimed": "Tarea reclamada correctamente",
865
866
  "workflows.messages.taskCompleted": "Tarea completada correctamente",
@@ -860,6 +860,7 @@
860
860
  "workflows.messages.instanceStarted": "Instancja przepływu rozpoczęta",
861
861
  "workflows.messages.invalidWorkflow": "Nieprawidłowa definicja przepływu",
862
862
  "workflows.messages.loadFailed": "Nie udało się załadować przepływów",
863
+ "workflows.messages.saveFailed": "Nie udało się zapisać",
863
864
  "workflows.messages.taskAlreadyClaimed": "Zadanie zostało już przejęte przez innego użytkownika",
864
865
  "workflows.messages.taskClaimed": "Zadanie przejęte pomyślnie",
865
866
  "workflows.messages.taskCompleted": "Zadanie ukończone pomyślnie",