@open-mercato/core 0.6.5-develop.4534.1.b459babe6d → 0.6.5-develop.4559.1.839e136509

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 (644) 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/communicationChannelsFixtures.js.map +2 -2
  10. package/dist/helpers/integration/dbFixtures.js +2 -1
  11. package/dist/helpers/integration/dbFixtures.js.map +2 -2
  12. package/dist/helpers/integration/optimisticLockUi.js +104 -0
  13. package/dist/helpers/integration/optimisticLockUi.js.map +7 -0
  14. package/dist/helpers/integration/salesFixtures.js +17 -0
  15. package/dist/helpers/integration/salesFixtures.js.map +2 -2
  16. package/dist/modules/api_keys/backend/api-keys/page.js +9 -5
  17. package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
  18. package/dist/modules/attachments/components/AttachmentPartitionSettings.js +17 -9
  19. package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
  20. package/dist/modules/auth/api/roles/acl/route.js +32 -13
  21. package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
  22. package/dist/modules/auth/api/roles/route.js +3 -1
  23. package/dist/modules/auth/api/roles/route.js.map +2 -2
  24. package/dist/modules/auth/api/sidebar/preferences/route.js +71 -3
  25. package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
  26. package/dist/modules/auth/api/users/acl/route.js +42 -19
  27. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  28. package/dist/modules/auth/api/users/route.js +3 -1
  29. package/dist/modules/auth/api/users/route.js.map +2 -2
  30. package/dist/modules/auth/backend/roles/[id]/edit/page.js +24 -4
  31. package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
  32. package/dist/modules/auth/backend/roles/page.js +8 -4
  33. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  34. package/dist/modules/auth/backend/users/[id]/edit/page.js +27 -5
  35. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  36. package/dist/modules/auth/backend/users/page.js +6 -2
  37. package/dist/modules/auth/backend/users/page.js.map +2 -2
  38. package/dist/modules/auth/components/AclEditor.js +3 -1
  39. package/dist/modules/auth/components/AclEditor.js.map +2 -2
  40. package/dist/modules/auth/data/entities.js +6 -0
  41. package/dist/modules/auth/data/entities.js.map +2 -2
  42. package/dist/modules/auth/services/sidebarPreferencesService.js +32 -4
  43. package/dist/modules/auth/services/sidebarPreferencesService.js.map +2 -2
  44. package/dist/modules/business_rules/api/rules/route.js +28 -0
  45. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  46. package/dist/modules/business_rules/api/sets/route.js +28 -0
  47. package/dist/modules/business_rules/api/sets/route.js.map +2 -2
  48. package/dist/modules/business_rules/backend/rules/[id]/page.js +11 -4
  49. package/dist/modules/business_rules/backend/rules/[id]/page.js.map +3 -3
  50. package/dist/modules/business_rules/backend/rules/page.js +20 -11
  51. package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
  52. package/dist/modules/business_rules/backend/sets/[id]/page.js +11 -4
  53. package/dist/modules/business_rules/backend/sets/[id]/page.js.map +2 -2
  54. package/dist/modules/business_rules/backend/sets/page.js +20 -11
  55. package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
  56. package/dist/modules/catalog/api/categories/route.js +2 -0
  57. package/dist/modules/catalog/api/categories/route.js.map +2 -2
  58. package/dist/modules/catalog/api/products/route.js +2 -1
  59. package/dist/modules/catalog/api/products/route.js.map +2 -2
  60. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js +2 -0
  61. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js.map +2 -2
  62. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +94 -40
  63. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  64. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +37 -8
  65. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
  66. package/dist/modules/catalog/backend/catalog/products/optionSchemaClient.js.map +2 -2
  67. package/dist/modules/catalog/commands/variants.js +32 -31
  68. package/dist/modules/catalog/commands/variants.js.map +2 -2
  69. package/dist/modules/catalog/components/PriceKindSettings.js +12 -5
  70. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  71. package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
  72. package/dist/modules/catalog/components/products/ProductMediaManager.js.map +2 -2
  73. package/dist/modules/catalog/components/products/ProductsDataTable.js +5 -3
  74. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  75. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  76. package/dist/modules/catalog/components/products/variantForm.js +2 -1
  77. package/dist/modules/catalog/components/products/variantForm.js.map +2 -2
  78. package/dist/modules/communication_channels/api/post/test-seed/route.js +23 -2
  79. package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
  80. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +5 -0
  81. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
  82. package/dist/modules/communication_channels/commands/set-primary-channel.js +2 -1
  83. package/dist/modules/communication_channels/commands/set-primary-channel.js.map +2 -2
  84. package/dist/modules/currencies/backend/currencies/[id]/page.js +6 -3
  85. package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
  86. package/dist/modules/currencies/backend/currencies/page.js +18 -11
  87. package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
  88. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js +1 -0
  89. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js.map +2 -2
  90. package/dist/modules/currencies/backend/exchange-rates/page.js +10 -6
  91. package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
  92. package/dist/modules/currencies/commands/currencies.js +7 -5
  93. package/dist/modules/currencies/commands/currencies.js.map +2 -2
  94. package/dist/modules/currencies/components/CurrencyFetchingConfig.js +26 -19
  95. package/dist/modules/currencies/components/CurrencyFetchingConfig.js.map +2 -2
  96. package/dist/modules/customer_accounts/api/admin/roles/[id].js +28 -5
  97. package/dist/modules/customer_accounts/api/admin/roles/[id].js.map +2 -2
  98. package/dist/modules/customer_accounts/api/admin/roles.js +4 -2
  99. package/dist/modules/customer_accounts/api/admin/roles.js.map +2 -2
  100. package/dist/modules/customer_accounts/api/admin/users/[id].js +28 -5
  101. package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
  102. package/dist/modules/customer_accounts/api/admin/users.js +2 -0
  103. package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
  104. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +16 -8
  105. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
  106. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +8 -4
  107. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
  108. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js +8 -4
  109. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js.map +2 -2
  110. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +29 -18
  111. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
  112. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +18 -11
  113. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
  114. package/dist/modules/customers/api/companies/route.js +13 -2
  115. package/dist/modules/customers/api/companies/route.js.map +2 -2
  116. package/dist/modules/customers/api/deals/route.js +2 -0
  117. package/dist/modules/customers/api/deals/route.js.map +2 -2
  118. package/dist/modules/customers/api/people/route.js +11 -2
  119. package/dist/modules/customers/api/people/route.js.map +2 -2
  120. package/dist/modules/customers/api/todos/route.js +1 -0
  121. package/dist/modules/customers/api/todos/route.js.map +2 -2
  122. package/dist/modules/customers/backend/config/customers/deals/page.js.map +2 -2
  123. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +34 -21
  124. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
  125. package/dist/modules/customers/backend/customers/companies/[id]/page.js +45 -27
  126. package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
  127. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  128. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +22 -5
  129. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  130. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js +30 -8
  131. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js.map +2 -2
  132. package/dist/modules/customers/backend/customers/deals/[id]/page.js +1 -0
  133. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  134. package/dist/modules/customers/backend/customers/deals/page.js +16 -6
  135. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  136. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +62 -39
  137. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
  138. package/dist/modules/customers/backend/customers/people/[id]/page.js +41 -26
  139. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  140. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  141. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +50 -23
  142. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  143. package/dist/modules/customers/commands/addresses.js +16 -14
  144. package/dist/modules/customers/commands/addresses.js.map +2 -2
  145. package/dist/modules/customers/commands/companies.js +1 -1
  146. package/dist/modules/customers/commands/companies.js.map +2 -2
  147. package/dist/modules/customers/commands/interactions.js +41 -4
  148. package/dist/modules/customers/commands/interactions.js.map +2 -2
  149. package/dist/modules/customers/commands/people.js +1 -1
  150. package/dist/modules/customers/commands/people.js.map +2 -2
  151. package/dist/modules/customers/commands/personCompanyLinks.js +8 -5
  152. package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
  153. package/dist/modules/customers/commands/pipeline-stages.js +13 -11
  154. package/dist/modules/customers/commands/pipeline-stages.js.map +3 -3
  155. package/dist/modules/customers/components/AddressFormatSettings.js.map +2 -2
  156. package/dist/modules/customers/components/DictionarySettings.js +20 -13
  157. package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
  158. package/dist/modules/customers/components/DictionarySortSettings.js +4 -0
  159. package/dist/modules/customers/components/DictionarySortSettings.js.map +2 -2
  160. package/dist/modules/customers/components/PipelineSettings.js +38 -23
  161. package/dist/modules/customers/components/PipelineSettings.js.map +2 -2
  162. package/dist/modules/customers/components/detail/ActivityTimeline.js +1 -1
  163. package/dist/modules/customers/components/detail/ActivityTimeline.js.map +2 -2
  164. package/dist/modules/customers/components/detail/AddressesSection.js +4 -0
  165. package/dist/modules/customers/components/detail/AddressesSection.js.map +2 -2
  166. package/dist/modules/customers/components/detail/CompanyPeopleSection.js +28 -22
  167. package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
  168. package/dist/modules/customers/components/detail/DealsSection.js +36 -24
  169. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  170. package/dist/modules/customers/components/detail/EmailCardActions.js +5 -0
  171. package/dist/modules/customers/components/detail/EmailCardActions.js.map +2 -2
  172. package/dist/modules/customers/components/detail/EntityTagsDialog.js +7 -0
  173. package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
  174. package/dist/modules/customers/components/detail/ManageTagsDialog.js +34 -22
  175. package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +2 -2
  176. package/dist/modules/customers/components/detail/PersonCompaniesSection.js +41 -29
  177. package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
  178. package/dist/modules/customers/components/detail/RoleAssignmentRow.js +14 -8
  179. package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +2 -2
  180. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +14 -6
  181. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  182. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +29 -13
  183. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +2 -2
  184. package/dist/modules/customers/components/detail/hooks/useInteractions.js +77 -35
  185. package/dist/modules/customers/components/detail/hooks/useInteractions.js.map +2 -2
  186. package/dist/modules/customers/components/detail/hooks/usePersonTasks.js +25 -17
  187. package/dist/modules/customers/components/detail/hooks/usePersonTasks.js.map +2 -2
  188. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
  189. package/dist/modules/customers/components/formConfig.js.map +2 -2
  190. package/dist/modules/customers/data/guards.js +66 -0
  191. package/dist/modules/customers/data/guards.js.map +7 -0
  192. package/dist/modules/customers/di.js +37 -0
  193. package/dist/modules/customers/di.js.map +2 -2
  194. package/dist/modules/customers/lib/todoCompatibility.js +11 -0
  195. package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
  196. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  197. package/dist/modules/data_sync/api/options.js +4 -4
  198. package/dist/modules/data_sync/api/options.js.map +2 -2
  199. package/dist/modules/data_sync/api/schedules/route.js +9 -1
  200. package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
  201. package/dist/modules/data_sync/backend/data-sync/page.js +17 -8
  202. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  203. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +43 -22
  204. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  205. package/dist/modules/data_sync/lib/sync-schedule-service.js +9 -0
  206. package/dist/modules/data_sync/lib/sync-schedule-service.js.map +2 -2
  207. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +8 -1
  208. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
  209. package/dist/modules/dictionaries/api/[dictionaryId]/route.js +17 -1
  210. package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
  211. package/dist/modules/dictionaries/components/DictionariesManager.js +31 -10
  212. package/dist/modules/dictionaries/components/DictionariesManager.js.map +2 -2
  213. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js +28 -15
  214. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js.map +2 -2
  215. package/dist/modules/directory/api/organizations/route.js +3 -0
  216. package/dist/modules/directory/api/organizations/route.js.map +2 -2
  217. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js +2 -0
  218. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js.map +2 -2
  219. package/dist/modules/directory/backend/directory/organizations/page.js +9 -5
  220. package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
  221. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js +7 -3
  222. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js.map +2 -2
  223. package/dist/modules/directory/backend/directory/tenants/page.js +8 -4
  224. package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
  225. package/dist/modules/directory/commands/organizations.js +7 -2
  226. package/dist/modules/directory/commands/organizations.js.map +2 -2
  227. package/dist/modules/entities/api/records.js +66 -0
  228. package/dist/modules/entities/api/records.js.map +2 -2
  229. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js +1 -0
  230. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js.map +2 -2
  231. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +8 -4
  232. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  233. package/dist/modules/entities/lib/helpers.js +17 -0
  234. package/dist/modules/entities/lib/helpers.js.map +2 -2
  235. package/dist/modules/feature_toggles/api/global/[id]/override/route.js +2 -1
  236. package/dist/modules/feature_toggles/api/global/[id]/override/route.js.map +2 -2
  237. package/dist/modules/feature_toggles/api/overrides/route.js +15 -0
  238. package/dist/modules/feature_toggles/api/overrides/route.js.map +2 -2
  239. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js +15 -14
  240. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js.map +2 -2
  241. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js +20 -12
  242. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js.map +2 -2
  243. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +6 -2
  244. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
  245. package/dist/modules/feature_toggles/components/formConfig.js +2 -1
  246. package/dist/modules/feature_toggles/components/formConfig.js.map +2 -2
  247. package/dist/modules/feature_toggles/components/overrideFormConfig.js +5 -1
  248. package/dist/modules/feature_toggles/components/overrideFormConfig.js.map +2 -2
  249. package/dist/modules/feature_toggles/data/validators.js +7 -4
  250. package/dist/modules/feature_toggles/data/validators.js.map +2 -2
  251. package/dist/modules/inbox_ops/api/settings/route.js +17 -2
  252. package/dist/modules/inbox_ops/api/settings/route.js.map +2 -2
  253. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js +13 -8
  254. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js.map +2 -2
  255. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +9 -4
  256. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
  257. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +18 -11
  258. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
  259. package/dist/modules/integrations/backend/integrations/page.js +12 -8
  260. package/dist/modules/integrations/backend/integrations/page.js.map +2 -2
  261. package/dist/modules/messages/commands/messages.js +13 -10
  262. package/dist/modules/messages/commands/messages.js.map +2 -2
  263. package/dist/modules/perspectives/api/[tableId]/route.js +39 -30
  264. package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
  265. package/dist/modules/perspectives/services/perspectiveService.js +7 -0
  266. package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
  267. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +6 -14
  268. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +3 -3
  269. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +4 -2
  270. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  271. package/dist/modules/planner/components/AvailabilityRuleSetForm.js +2 -0
  272. package/dist/modules/planner/components/AvailabilityRuleSetForm.js.map +2 -2
  273. package/dist/modules/planner/components/AvailabilityRulesEditor.js +36 -11
  274. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  275. package/dist/modules/planner/components/AvailabilitySchedule.js +9 -5
  276. package/dist/modules/planner/components/AvailabilitySchedule.js.map +2 -2
  277. package/dist/modules/query_index/lib/engine.js +19 -0
  278. package/dist/modules/query_index/lib/engine.js.map +2 -2
  279. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js +1 -0
  280. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js.map +2 -2
  281. package/dist/modules/resources/backend/resources/resource-types/page.js +4 -2
  282. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  283. package/dist/modules/resources/backend/resources/resources/[id]/page.js +14 -3
  284. package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
  285. package/dist/modules/resources/backend/resources/resources/page.js +8 -4
  286. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  287. package/dist/modules/resources/components/ResourceCrudForm.js +2 -0
  288. package/dist/modules/resources/components/ResourceCrudForm.js.map +2 -2
  289. package/dist/modules/resources/components/ResourceTypeCrudForm.js +1 -0
  290. package/dist/modules/resources/components/ResourceTypeCrudForm.js.map +2 -2
  291. package/dist/modules/sales/api/documents/factory.js +7 -2
  292. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  293. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +3 -1
  294. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
  295. package/dist/modules/sales/backend/sales/channels/offers/page.js +13 -4
  296. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  297. package/dist/modules/sales/backend/sales/channels/page.js +16 -4
  298. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  299. package/dist/modules/sales/backend/sales/documents/[id]/page.js +68 -22
  300. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  301. package/dist/modules/sales/backend/sales/documents/create/page.js.map +2 -2
  302. package/dist/modules/sales/commands/documentAddresses.js +181 -2
  303. package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
  304. package/dist/modules/sales/commands/documents.js +29 -1
  305. package/dist/modules/sales/commands/documents.js.map +2 -2
  306. package/dist/modules/sales/commands/returns.js +12 -2
  307. package/dist/modules/sales/commands/returns.js.map +2 -2
  308. package/dist/modules/sales/commands/shared.js +15 -0
  309. package/dist/modules/sales/commands/shared.js.map +2 -2
  310. package/dist/modules/sales/commands/shipments.js +4 -1
  311. package/dist/modules/sales/commands/shipments.js.map +2 -2
  312. package/dist/modules/sales/components/AdjustmentKindSettings.js +19 -11
  313. package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
  314. package/dist/modules/sales/components/DocumentNumberSettings.js.map +2 -2
  315. package/dist/modules/sales/components/OrderEditingSettings.js.map +2 -2
  316. package/dist/modules/sales/components/PaymentMethodsSettings.js +12 -4
  317. package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
  318. package/dist/modules/sales/components/ShippingMethodsSettings.js +12 -4
  319. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
  320. package/dist/modules/sales/components/StatusSettings.js +18 -11
  321. package/dist/modules/sales/components/StatusSettings.js.map +2 -2
  322. package/dist/modules/sales/components/TaxRatesSettings.js +12 -4
  323. package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
  324. package/dist/modules/sales/components/channels/ChannelOfferForm.js +47 -16
  325. package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
  326. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +8 -4
  327. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  328. package/dist/modules/sales/components/documents/AddressesSection.js +44 -25
  329. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  330. package/dist/modules/sales/components/documents/AdjustmentsSection.js +43 -23
  331. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  332. package/dist/modules/sales/components/documents/ItemsSection.js +22 -13
  333. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  334. package/dist/modules/sales/components/documents/LineItemDialog.js +23 -10
  335. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  336. package/dist/modules/sales/components/documents/PaymentDialog.js +29 -14
  337. package/dist/modules/sales/components/documents/PaymentDialog.js.map +2 -2
  338. package/dist/modules/sales/components/documents/PaymentsSection.js +20 -10
  339. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  340. package/dist/modules/sales/components/documents/ReturnDialog.js +26 -17
  341. package/dist/modules/sales/components/documents/ReturnDialog.js.map +2 -2
  342. package/dist/modules/sales/components/documents/ReturnsSection.js +3 -1
  343. package/dist/modules/sales/components/documents/ReturnsSection.js.map +2 -2
  344. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +10 -5
  345. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  346. package/dist/modules/sales/components/documents/ShipmentDialog.js +21 -7
  347. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  348. package/dist/modules/sales/components/documents/ShipmentsSection.js +19 -10
  349. package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
  350. package/dist/modules/sales/components/documents/optimisticLock.js +27 -0
  351. package/dist/modules/sales/components/documents/optimisticLock.js.map +7 -0
  352. package/dist/modules/sales/di.js +18 -0
  353. package/dist/modules/sales/di.js.map +2 -2
  354. package/dist/modules/staff/api/job-histories.js +11 -2
  355. package/dist/modules/staff/api/job-histories.js.map +2 -2
  356. package/dist/modules/staff/api/timesheets/time-entries/route.js +11 -4
  357. package/dist/modules/staff/api/timesheets/time-entries/route.js.map +2 -2
  358. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +13 -8
  359. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
  360. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +2 -1
  361. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
  362. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +7 -4
  363. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  364. package/dist/modules/staff/backend/staff/team-members/page.js +4 -2
  365. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  366. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js +1 -0
  367. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js.map +2 -2
  368. package/dist/modules/staff/backend/staff/team-roles/page.js +4 -2
  369. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  370. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +5 -2
  371. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  372. package/dist/modules/staff/backend/staff/teams/page.js +12 -3
  373. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  374. package/dist/modules/staff/backend/staff/timesheets/page.js +4 -1
  375. package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
  376. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +2 -2
  377. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +12 -3
  378. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
  379. package/dist/modules/staff/commands/job-histories.js +40 -3
  380. package/dist/modules/staff/commands/job-histories.js.map +2 -2
  381. package/dist/modules/staff/components/LeaveRequestForm.js +1 -0
  382. package/dist/modules/staff/components/LeaveRequestForm.js.map +2 -2
  383. package/dist/modules/staff/components/TeamForm.js +1 -0
  384. package/dist/modules/staff/components/TeamForm.js.map +2 -2
  385. package/dist/modules/staff/components/TeamMemberForm.js +1 -0
  386. package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
  387. package/dist/modules/staff/components/TeamRoleForm.js +1 -0
  388. package/dist/modules/staff/components/TeamRoleForm.js.map +2 -2
  389. package/dist/modules/staff/components/detail/JobHistorySection.js +20 -7
  390. package/dist/modules/staff/components/detail/JobHistorySection.js.map +2 -2
  391. package/dist/modules/staff/data/validators.js +7 -1
  392. package/dist/modules/staff/data/validators.js.map +2 -2
  393. package/dist/modules/staff/lib/leaveRequestHelpers.js +2 -1
  394. package/dist/modules/staff/lib/leaveRequestHelpers.js.map +2 -2
  395. package/dist/modules/translations/components/TranslationManager.js +12 -8
  396. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  397. package/dist/modules/workflows/api/definitions/[id]/route.js +106 -0
  398. package/dist/modules/workflows/api/definitions/[id]/route.js.map +2 -2
  399. package/dist/modules/workflows/backend/definitions/[id]/page.js +11 -3
  400. package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
  401. package/dist/modules/workflows/backend/definitions/page.js +19 -8
  402. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  403. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +29 -16
  404. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  405. package/dist/modules/workflows/components/formConfig.js +4 -1
  406. package/dist/modules/workflows/components/formConfig.js.map +2 -2
  407. package/dist/modules/workflows/di.js +12 -0
  408. package/dist/modules/workflows/di.js.map +2 -2
  409. package/generated/entities/role/index.ts +1 -0
  410. package/generated/entities/user/index.ts +1 -0
  411. package/generated/entity-fields-registry.ts +2 -0
  412. package/jest.setup.ts +17 -0
  413. package/package.json +8 -7
  414. package/src/helpers/integration/communicationChannelsFixtures.ts +6 -0
  415. package/src/helpers/integration/dbFixtures.ts +1 -1
  416. package/src/helpers/integration/optimisticLockUi.ts +172 -0
  417. package/src/helpers/integration/salesFixtures.ts +29 -0
  418. package/src/modules/api_keys/backend/api-keys/page.tsx +10 -5
  419. package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +19 -9
  420. package/src/modules/auth/api/roles/acl/route.ts +37 -11
  421. package/src/modules/auth/api/roles/route.ts +2 -0
  422. package/src/modules/auth/api/sidebar/preferences/route.ts +73 -0
  423. package/src/modules/auth/api/users/acl/route.ts +46 -18
  424. package/src/modules/auth/api/users/route.ts +2 -0
  425. package/src/modules/auth/backend/roles/[id]/edit/page.tsx +29 -4
  426. package/src/modules/auth/backend/roles/page.tsx +9 -4
  427. package/src/modules/auth/backend/users/[id]/edit/page.tsx +37 -4
  428. package/src/modules/auth/backend/users/page.tsx +7 -2
  429. package/src/modules/auth/components/AclEditor.tsx +10 -1
  430. package/src/modules/auth/data/entities.ts +7 -1
  431. package/src/modules/auth/services/sidebarPreferencesService.ts +38 -4
  432. package/src/modules/business_rules/api/rules/route.ts +30 -0
  433. package/src/modules/business_rules/api/sets/route.ts +30 -0
  434. package/src/modules/business_rules/backend/rules/[id]/page.tsx +16 -4
  435. package/src/modules/business_rules/backend/rules/page.tsx +20 -11
  436. package/src/modules/business_rules/backend/sets/[id]/page.tsx +16 -4
  437. package/src/modules/business_rules/backend/sets/page.tsx +20 -11
  438. package/src/modules/catalog/api/categories/route.ts +3 -0
  439. package/src/modules/catalog/api/products/route.ts +4 -0
  440. package/src/modules/catalog/backend/catalog/categories/[id]/edit/page.tsx +5 -0
  441. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +112 -35
  442. package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +56 -7
  443. package/src/modules/catalog/backend/catalog/products/optionSchemaClient.ts +2 -0
  444. package/src/modules/catalog/commands/variants.ts +32 -32
  445. package/src/modules/catalog/components/PriceKindSettings.tsx +20 -7
  446. package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +1 -0
  447. package/src/modules/catalog/components/products/ProductMediaManager.tsx +2 -0
  448. package/src/modules/catalog/components/products/ProductsDataTable.tsx +8 -4
  449. package/src/modules/catalog/components/products/productForm.ts +3 -0
  450. package/src/modules/catalog/components/products/variantForm.ts +9 -0
  451. package/src/modules/communication_channels/api/post/test-seed/route.ts +28 -1
  452. package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +5 -0
  453. package/src/modules/communication_channels/commands/set-primary-channel.ts +10 -7
  454. package/src/modules/currencies/backend/currencies/[id]/page.tsx +13 -6
  455. package/src/modules/currencies/backend/currencies/page.tsx +18 -11
  456. package/src/modules/currencies/backend/exchange-rates/[id]/page.tsx +3 -0
  457. package/src/modules/currencies/backend/exchange-rates/page.tsx +10 -6
  458. package/src/modules/currencies/commands/currencies.ts +10 -5
  459. package/src/modules/currencies/components/CurrencyFetchingConfig.tsx +31 -21
  460. package/src/modules/customer_accounts/api/admin/roles/[id].ts +35 -5
  461. package/src/modules/customer_accounts/api/admin/roles.ts +2 -0
  462. package/src/modules/customer_accounts/api/admin/users/[id].ts +38 -5
  463. package/src/modules/customer_accounts/api/admin/users.ts +2 -0
  464. package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +34 -20
  465. package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +9 -4
  466. package/src/modules/customer_accounts/backend/customer_accounts/settings/domain/page.tsx +11 -4
  467. package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +28 -17
  468. package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +19 -11
  469. package/src/modules/customers/AGENTS.md +2 -2
  470. package/src/modules/customers/api/companies/route.ts +14 -1
  471. package/src/modules/customers/api/deals/route.ts +3 -0
  472. package/src/modules/customers/api/people/route.ts +12 -1
  473. package/src/modules/customers/api/todos/route.ts +1 -0
  474. package/src/modules/customers/backend/config/customers/deals/page.tsx +1 -0
  475. package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +36 -21
  476. package/src/modules/customers/backend/customers/companies/[id]/page.tsx +52 -27
  477. package/src/modules/customers/backend/customers/companies/page.tsx +2 -0
  478. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +27 -5
  479. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.ts +39 -7
  480. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +1 -0
  481. package/src/modules/customers/backend/customers/deals/page.tsx +18 -6
  482. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +64 -39
  483. package/src/modules/customers/backend/customers/people/[id]/page.tsx +46 -26
  484. package/src/modules/customers/backend/customers/people/page.tsx +2 -0
  485. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +84 -24
  486. package/src/modules/customers/commands/addresses.ts +16 -14
  487. package/src/modules/customers/commands/companies.ts +3 -1
  488. package/src/modules/customers/commands/interactions.ts +50 -4
  489. package/src/modules/customers/commands/people.ts +2 -1
  490. package/src/modules/customers/commands/personCompanyLinks.ts +8 -5
  491. package/src/modules/customers/commands/pipeline-stages.ts +16 -16
  492. package/src/modules/customers/components/AddressFormatSettings.tsx +1 -0
  493. package/src/modules/customers/components/DictionarySettings.tsx +18 -13
  494. package/src/modules/customers/components/DictionarySortSettings.tsx +4 -0
  495. package/src/modules/customers/components/PipelineSettings.tsx +42 -21
  496. package/src/modules/customers/components/detail/ActivityTimeline.tsx +3 -3
  497. package/src/modules/customers/components/detail/AddressesSection.tsx +4 -0
  498. package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +2 -0
  499. package/src/modules/customers/components/detail/DealsSection.tsx +4 -0
  500. package/src/modules/customers/components/detail/EmailCardActions.tsx +5 -0
  501. package/src/modules/customers/components/detail/EntityTagsDialog.tsx +7 -0
  502. package/src/modules/customers/components/detail/ManageTagsDialog.tsx +4 -0
  503. package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +4 -0
  504. package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +2 -0
  505. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +23 -7
  506. package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +25 -15
  507. package/src/modules/customers/components/detail/hooks/useInteractions.ts +76 -35
  508. package/src/modules/customers/components/detail/hooks/usePersonTasks.ts +30 -17
  509. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +2 -0
  510. package/src/modules/customers/components/detail/types.ts +1 -0
  511. package/src/modules/customers/components/formConfig.tsx +2 -0
  512. package/src/modules/customers/data/guards.ts +67 -0
  513. package/src/modules/customers/di.ts +66 -0
  514. package/src/modules/customers/i18n/de.json +2 -0
  515. package/src/modules/customers/i18n/en.json +2 -0
  516. package/src/modules/customers/i18n/es.json +2 -0
  517. package/src/modules/customers/i18n/pl.json +2 -0
  518. package/src/modules/customers/lib/todoCompatibility.ts +14 -0
  519. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +2 -0
  520. package/src/modules/data_sync/api/options.ts +7 -4
  521. package/src/modules/data_sync/api/schedules/route.ts +9 -1
  522. package/src/modules/data_sync/backend/data-sync/page.tsx +18 -5
  523. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +46 -19
  524. package/src/modules/data_sync/lib/sync-schedule-service.ts +11 -0
  525. package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +8 -1
  526. package/src/modules/dictionaries/api/[dictionaryId]/route.ts +23 -0
  527. package/src/modules/dictionaries/components/DictionariesManager.tsx +32 -9
  528. package/src/modules/dictionaries/components/DictionaryEntriesEditor.tsx +30 -14
  529. package/src/modules/dictionaries/i18n/de.json +1 -0
  530. package/src/modules/dictionaries/i18n/en.json +1 -0
  531. package/src/modules/dictionaries/i18n/es.json +1 -0
  532. package/src/modules/dictionaries/i18n/pl.json +1 -0
  533. package/src/modules/directory/api/organizations/route.ts +3 -0
  534. package/src/modules/directory/backend/directory/organizations/[id]/edit/page.tsx +8 -0
  535. package/src/modules/directory/backend/directory/organizations/page.tsx +10 -5
  536. package/src/modules/directory/backend/directory/tenants/[id]/edit/page.tsx +16 -5
  537. package/src/modules/directory/backend/directory/tenants/page.tsx +8 -4
  538. package/src/modules/directory/commands/organizations.ts +7 -4
  539. package/src/modules/entities/api/records.ts +99 -0
  540. package/src/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.tsx +7 -0
  541. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +8 -4
  542. package/src/modules/entities/lib/helpers.ts +17 -0
  543. package/src/modules/feature_toggles/api/global/[id]/override/route.ts +1 -0
  544. package/src/modules/feature_toggles/api/overrides/route.ts +19 -0
  545. package/src/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.tsx +19 -13
  546. package/src/modules/feature_toggles/components/FeatureToggleOverrideCard.tsx +22 -12
  547. package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +7 -2
  548. package/src/modules/feature_toggles/components/formConfig.tsx +2 -1
  549. package/src/modules/feature_toggles/components/overrideFormConfig.tsx +10 -1
  550. package/src/modules/feature_toggles/data/validators.ts +11 -3
  551. package/src/modules/inbox_ops/api/settings/route.ts +18 -0
  552. package/src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx +15 -10
  553. package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +9 -4
  554. package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +20 -11
  555. package/src/modules/integrations/backend/integrations/page.tsx +13 -8
  556. package/src/modules/messages/commands/messages.ts +27 -15
  557. package/src/modules/perspectives/api/[tableId]/route.ts +11 -2
  558. package/src/modules/perspectives/services/perspectiveService.ts +13 -1
  559. package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +16 -14
  560. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +6 -3
  561. package/src/modules/planner/components/AvailabilityRuleSetForm.tsx +3 -0
  562. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +58 -15
  563. package/src/modules/planner/components/AvailabilitySchedule.tsx +22 -7
  564. package/src/modules/query_index/lib/engine.ts +34 -0
  565. package/src/modules/resources/backend/resources/resource-types/[id]/edit/page.tsx +7 -1
  566. package/src/modules/resources/backend/resources/resource-types/page.tsx +6 -3
  567. package/src/modules/resources/backend/resources/resources/[id]/page.tsx +23 -3
  568. package/src/modules/resources/backend/resources/resources/page.tsx +15 -4
  569. package/src/modules/resources/components/ResourceCrudForm.tsx +3 -0
  570. package/src/modules/resources/components/ResourceTypeCrudForm.tsx +2 -0
  571. package/src/modules/sales/api/documents/factory.ts +13 -1
  572. package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +6 -0
  573. package/src/modules/sales/backend/sales/channels/offers/page.tsx +10 -4
  574. package/src/modules/sales/backend/sales/channels/page.tsx +19 -4
  575. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +73 -20
  576. package/src/modules/sales/backend/sales/documents/create/page.tsx +2 -0
  577. package/src/modules/sales/commands/documentAddresses.ts +226 -4
  578. package/src/modules/sales/commands/documents.ts +28 -0
  579. package/src/modules/sales/commands/returns.ts +12 -3
  580. package/src/modules/sales/commands/shared.ts +36 -0
  581. package/src/modules/sales/commands/shipments.ts +17 -1
  582. package/src/modules/sales/components/AdjustmentKindSettings.tsx +20 -11
  583. package/src/modules/sales/components/DocumentNumberSettings.tsx +1 -0
  584. package/src/modules/sales/components/OrderEditingSettings.tsx +1 -0
  585. package/src/modules/sales/components/PaymentMethodsSettings.tsx +12 -4
  586. package/src/modules/sales/components/ShippingMethodsSettings.tsx +12 -4
  587. package/src/modules/sales/components/StatusSettings.tsx +20 -11
  588. package/src/modules/sales/components/TaxRatesSettings.tsx +12 -5
  589. package/src/modules/sales/components/channels/ChannelOfferForm.tsx +67 -14
  590. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +7 -4
  591. package/src/modules/sales/components/documents/AddressesSection.tsx +35 -25
  592. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +50 -25
  593. package/src/modules/sales/components/documents/ItemsSection.tsx +24 -13
  594. package/src/modules/sales/components/documents/LineItemDialog.tsx +26 -9
  595. package/src/modules/sales/components/documents/PaymentDialog.tsx +33 -14
  596. package/src/modules/sales/components/documents/PaymentsSection.tsx +22 -10
  597. package/src/modules/sales/components/documents/ReturnDialog.tsx +28 -17
  598. package/src/modules/sales/components/documents/ReturnsSection.tsx +4 -1
  599. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +11 -4
  600. package/src/modules/sales/components/documents/ShipmentDialog.tsx +23 -8
  601. package/src/modules/sales/components/documents/ShipmentsSection.tsx +20 -10
  602. package/src/modules/sales/components/documents/optimisticLock.ts +34 -0
  603. package/src/modules/sales/components/documents/shipmentTypes.ts +1 -0
  604. package/src/modules/sales/di.ts +35 -0
  605. package/src/modules/sales/i18n/de.json +3 -0
  606. package/src/modules/sales/i18n/en.json +3 -0
  607. package/src/modules/sales/i18n/es.json +3 -0
  608. package/src/modules/sales/i18n/pl.json +3 -0
  609. package/src/modules/staff/api/job-histories.ts +12 -2
  610. package/src/modules/staff/api/timesheets/time-entries/route.ts +16 -4
  611. package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +12 -7
  612. package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +2 -0
  613. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +16 -5
  614. package/src/modules/staff/backend/staff/team-members/page.tsx +6 -2
  615. package/src/modules/staff/backend/staff/team-roles/[id]/edit/page.tsx +8 -0
  616. package/src/modules/staff/backend/staff/team-roles/page.tsx +6 -2
  617. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +13 -3
  618. package/src/modules/staff/backend/staff/teams/page.tsx +9 -3
  619. package/src/modules/staff/backend/staff/timesheets/page.tsx +10 -1
  620. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +4 -0
  621. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +9 -3
  622. package/src/modules/staff/commands/job-histories.ts +42 -3
  623. package/src/modules/staff/components/LeaveRequestForm.tsx +2 -0
  624. package/src/modules/staff/components/TeamForm.tsx +2 -0
  625. package/src/modules/staff/components/TeamMemberForm.tsx +2 -0
  626. package/src/modules/staff/components/TeamRoleForm.tsx +2 -0
  627. package/src/modules/staff/components/detail/JobHistorySection.tsx +28 -6
  628. package/src/modules/staff/data/validators.ts +6 -0
  629. package/src/modules/staff/i18n/de.json +1 -0
  630. package/src/modules/staff/i18n/en.json +1 -0
  631. package/src/modules/staff/i18n/es.json +1 -0
  632. package/src/modules/staff/i18n/pl.json +1 -0
  633. package/src/modules/staff/lib/leaveRequestHelpers.ts +4 -0
  634. package/src/modules/translations/components/TranslationManager.tsx +13 -8
  635. package/src/modules/workflows/api/definitions/[id]/route.ts +112 -0
  636. package/src/modules/workflows/backend/definitions/[id]/page.tsx +20 -4
  637. package/src/modules/workflows/backend/definitions/page.tsx +20 -9
  638. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +29 -16
  639. package/src/modules/workflows/components/formConfig.tsx +5 -0
  640. package/src/modules/workflows/di.ts +20 -0
  641. package/src/modules/workflows/i18n/de.json +1 -0
  642. package/src/modules/workflows/i18n/en.json +1 -0
  643. package/src/modules/workflows/i18n/es.json +1 -0
  644. package/src/modules/workflows/i18n/pl.json +1 -0
@@ -6,8 +6,9 @@ import { useRouter, useSearchParams } from 'next/navigation'
6
6
  import type { ColumnDef, SortingState } from '@tanstack/react-table'
7
7
  import { Page, PageBody } from '@open-mercato/ui/backend/Page'
8
8
  import { ErrorMessage, RecordNotFoundState } from '@open-mercato/ui/backend/detail'
9
- import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
9
+ import { readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
10
10
  import { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'
11
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
11
12
  import { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'
12
13
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
13
14
  import { Button } from '@open-mercato/ui/primitives/button'
@@ -29,6 +30,8 @@ type TeamRecord = {
29
30
  description?: string | null
30
31
  isActive?: boolean
31
32
  is_active?: boolean
33
+ updatedAt?: string | null
34
+ updated_at?: string | null
32
35
  } & Record<string, unknown>
33
36
 
34
37
  type TeamResponse = {
@@ -199,6 +202,11 @@ export default function StaffTeamEditPage({ params }: { params?: { id?: string }
199
202
  name: record.name ?? '',
200
203
  description: record.description ?? '',
201
204
  isActive,
205
+ updatedAt: typeof record.updatedAt === 'string'
206
+ ? record.updatedAt
207
+ : typeof record.updated_at === 'string'
208
+ ? record.updated_at
209
+ : null,
202
210
  ...customFields,
203
211
  })
204
212
  }
@@ -278,7 +286,10 @@ export default function StaffTeamEditPage({ params }: { params?: { id?: string }
278
286
  const handleUnassignMember = React.useCallback(async (entry: TeamMemberRow) => {
279
287
  if (!teamId || entry.teamId !== teamId) return
280
288
  try {
281
- await updateCrud('staff/team-members', { id: entry.id, teamId: null }, { errorMessage: memberLabels.errors.unassign })
289
+ const headers = buildOptimisticLockHeader(entry.updatedAt)
290
+ await withScopedApiRequestHeaders(headers, () => (
291
+ updateCrud('staff/team-members', { id: entry.id, teamId: null }, { errorMessage: memberLabels.errors.unassign })
292
+ ))
282
293
  flash(memberLabels.messages.unassigned, 'success')
283
294
  handleMemberRefresh()
284
295
  } catch (error) {
@@ -468,4 +479,3 @@ function mapApiTeamMember(item: Record<string, unknown>): TeamMemberRow {
468
479
  teamId,
469
480
  }, item)
470
481
  }
471
-
@@ -10,7 +10,9 @@ import { RowActions } from '@open-mercato/ui/backend/RowActions'
10
10
  import { MarkdownPreview } from '@open-mercato/ui/backend/markdown/MarkdownContent'
11
11
  import { Button } from '@open-mercato/ui/primitives/button'
12
12
  import { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'
13
- import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
13
+ import { readApiResultOrThrow, 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 { deleteCrud } from '@open-mercato/ui/backend/utils/crud'
15
17
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
16
18
  import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
@@ -207,14 +209,18 @@ export default function StaffTeamsPage() {
207
209
  })
208
210
  if (!confirmed) return
209
211
  try {
210
- await deleteCrud('staff/teams', entry.id, { errorMessage: labels.errors.delete })
212
+ await withScopedApiRequestHeaders(
213
+ buildOptimisticLockHeader(entry.updatedAt),
214
+ () => deleteCrud('staff/teams', entry.id, { errorMessage: labels.errors.delete }),
215
+ )
211
216
  flash(labels.messages.deleted, 'success')
212
217
  handleRefresh()
213
218
  } catch (error) {
219
+ if (surfaceRecordConflict(error, t)) { handleRefresh(); return }
214
220
  console.error('staff.teams.delete', error)
215
221
  flash(labels.errors.delete, 'error')
216
222
  }
217
- }, [confirm, handleRefresh, labels.actions.deleteConfirm, labels.actions.delete, labels.errors.delete, labels.errors.deleteAssigned, labels.messages.deleted])
223
+ }, [confirm, handleRefresh, labels.actions.deleteConfirm, labels.actions.delete, labels.errors.delete, labels.errors.deleteAssigned, labels.messages.deleted, t])
218
224
 
219
225
  return (
220
226
  <Page>
@@ -290,6 +290,10 @@ export default function MyTimesheetsPage() {
290
290
  .filter((id) => id.length > 0),
291
291
  )
292
292
 
293
+ const entriesParams = new URLSearchParams({ pageSize: '100', staffMemberId: memberId })
294
+ if (dateRange.from) entriesParams.set('from', dateRange.from)
295
+ if (dateRange.to) entriesParams.set('to', dateRange.to)
296
+
293
297
  const [projectsRes, entriesRes] = await Promise.all([
294
298
  assignedProjectIds.length > 0
295
299
  ? readApiResultOrThrow<{ items?: Array<Record<string, unknown>> }>(
@@ -299,7 +303,7 @@ export default function MyTimesheetsPage() {
299
303
  )
300
304
  : Promise.resolve({ items: [] as Array<Record<string, unknown>> }),
301
305
  readApiResultOrThrow<{ items?: Array<Record<string, unknown>> }>(
302
- `/api/staff/timesheets/time-entries?pageSize=100&staffMemberId=${memberId}&from=${dateRange.from}&to=${dateRange.to}`,
306
+ `/api/staff/timesheets/time-entries?${entriesParams.toString()}`,
303
307
  undefined,
304
308
  { errorMessage: t('staff.timesheets.my.errors.load', 'Failed to load timesheets.'), fallback: { items: [] } },
305
309
  ),
@@ -530,6 +534,11 @@ export default function MyTimesheetsPage() {
530
534
  // --- Add row handler ---
531
535
  const visibleProjectIds = React.useMemo(() => new Set(projects.map((p) => p.id)), [projects])
532
536
 
537
+ // optimistic-lock-exempt: the my-projects PATCH calls below only toggle the
538
+ // caller's own `showInGrid` preference on the staff.timesheets.time_project_member
539
+ // junction (a per-user membership flag). There is no shared, multi-user-editable
540
+ // state to lose, so version-locking the toggle would surface false 409s without
541
+ // protecting any data.
533
542
  const handleAddProject = React.useCallback(async (project: ProjectRow) => {
534
543
  try {
535
544
  const payload = { showInGrid: true }
@@ -210,6 +210,10 @@ export default function TimesheetProjectDetailPage({ params }: { params?: { id?:
210
210
  })
211
211
  }, [])
212
212
 
213
+ // optimistic-lock-exempt: the employee add/remove calls below mutate the
214
+ // time-project ↔ staff-member assignment junction (createCrud/deleteCrud of a
215
+ // membership row), not a shared editable aggregate. Junction add/remove is exempt
216
+ // from OSS optimistic locking per the data-integrity contract.
213
217
  // --- Remove employee ---
214
218
  const handleRemoveEmployee = React.useCallback(async (emp: EmployeeAssignment) => {
215
219
  const confirmed = await confirm({
@@ -9,7 +9,9 @@ import { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/Dat
9
9
  import type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterOverlay'
10
10
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
11
11
  import { Button } from '@open-mercato/ui/primitives/button'
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'
14
+ import { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'
13
15
  import { deleteCrud } from '@open-mercato/ui/backend/utils/crud'
14
16
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
15
17
  import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
@@ -467,15 +469,19 @@ export default function TimesheetProjectsPage() {
467
469
  })
468
470
  if (!confirmed) return
469
471
  try {
470
- await deleteCrud('staff/timesheets/time-projects', entry.id, { errorMessage: labels.errors.delete })
472
+ await withScopedApiRequestHeaders(
473
+ buildOptimisticLockHeader(entry.updatedAt),
474
+ () => deleteCrud('staff/timesheets/time-projects', entry.id, { errorMessage: labels.errors.delete }),
475
+ )
471
476
  flash(labels.messages.deleted, 'success')
472
477
  handleRefresh()
473
478
  } catch (error) {
479
+ if (surfaceRecordConflict(error, t)) { handleRefresh(); return }
474
480
  console.error('staff.timesheets.projects.delete', error)
475
481
  flash(labels.errors.delete, 'error')
476
482
  }
477
483
  },
478
- [confirm, handleRefresh, labels.actions.deleteConfirm, labels.actions.delete, labels.errors.delete, labels.messages.deleted],
484
+ [confirm, handleRefresh, t, labels.actions.deleteConfirm, labels.actions.delete, labels.errors.delete, labels.messages.deleted],
479
485
  )
480
486
 
481
487
  const columns = React.useMemo<ColumnDef<ProjectRow>[]>(
@@ -19,9 +19,15 @@ import {
19
19
  } from './shared'
20
20
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
21
21
  import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
22
+ import {
23
+ enforceCommandOptimisticLock,
24
+ enforceRecordGoneIsConflict,
25
+ } from '@open-mercato/shared/lib/crud/optimistic-lock-command'
22
26
  import type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'
23
27
  import { E } from '#generated/entities.ids.generated'
24
28
 
29
+ const JOB_HISTORY_LOCK_RESOURCE_KIND = 'staff.jobHistory'
30
+
25
31
  const jobHistoryCrudIndexer: CrudIndexerConfig<StaffTeamMemberJobHistory> = {
26
32
  entityType: E.staff.staff_team_member_job_history,
27
33
  }
@@ -36,6 +42,7 @@ type JobHistorySnapshot = {
36
42
  description: string | null
37
43
  startDate: string
38
44
  endDate: string | null
45
+ updatedAt: string
39
46
  }
40
47
 
41
48
  type JobHistoryUndoPayload = {
@@ -56,6 +63,7 @@ async function loadJobHistorySnapshot(em: EntityManager, id: string): Promise<Jo
56
63
  description: record.description ?? null,
57
64
  startDate: record.startDate.toISOString(),
58
65
  endDate: record.endDate ? record.endDate.toISOString() : null,
66
+ updatedAt: record.updatedAt.toISOString(),
59
67
  }
60
68
  }
61
69
 
@@ -149,9 +157,24 @@ const updateJobHistoryCommand: CommandHandler<StaffTeamMemberJobHistoryUpdateInp
149
157
  const parsed = staffTeamMemberJobHistoryUpdateSchema.parse(rawInput)
150
158
  const em = (ctx.container.resolve('em') as EntityManager).fork()
151
159
  const record = await em.findOne(StaffTeamMemberJobHistory, { id: parsed.id })
152
- if (!record) throw new CrudHttpError(404, { error: 'Job history entry not found' })
160
+ if (!record) {
161
+ enforceRecordGoneIsConflict({
162
+ resourceKind: JOB_HISTORY_LOCK_RESOURCE_KIND,
163
+ resourceId: parsed.id,
164
+ expected: parsed.updatedAt ?? null,
165
+ request: ctx.request ?? null,
166
+ })
167
+ throw new CrudHttpError(404, { error: 'Job history entry not found' })
168
+ }
153
169
  ensureTenantScope(ctx, record.tenantId)
154
170
  ensureOrganizationScope(ctx, record.organizationId)
171
+ enforceCommandOptimisticLock({
172
+ resourceKind: JOB_HISTORY_LOCK_RESOURCE_KIND,
173
+ resourceId: record.id,
174
+ current: record.updatedAt ?? null,
175
+ expected: parsed.updatedAt ?? null,
176
+ request: ctx.request ?? null,
177
+ })
155
178
 
156
179
  if (parsed.entityId !== undefined) {
157
180
  const member = await requireTeamMember(em, parsed.entityId, 'Team member not found')
@@ -268,7 +291,7 @@ const updateJobHistoryCommand: CommandHandler<StaffTeamMemberJobHistoryUpdateInp
268
291
  },
269
292
  }
270
293
 
271
- const deleteJobHistoryCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { jobHistoryId: string }> =
294
+ const deleteJobHistoryCommand: CommandHandler<{ id?: string; updatedAt?: string; body?: Record<string, unknown>; query?: Record<string, unknown> }, { jobHistoryId: string }> =
272
295
  {
273
296
  id: 'staff.team-member-job-histories.delete',
274
297
  async prepare(input, ctx) {
@@ -279,11 +302,27 @@ const deleteJobHistoryCommand: CommandHandler<{ body?: Record<string, unknown>;
279
302
  },
280
303
  async execute(input, ctx) {
281
304
  const id = requireId(input, 'Job history id required')
305
+ const expectedUpdatedAt = typeof input.updatedAt === 'string' ? input.updatedAt : undefined
282
306
  const em = (ctx.container.resolve('em') as EntityManager).fork()
283
307
  const record = await em.findOne(StaffTeamMemberJobHistory, { id })
284
- if (!record) throw new CrudHttpError(404, { error: 'Job history entry not found' })
308
+ if (!record) {
309
+ enforceRecordGoneIsConflict({
310
+ resourceKind: JOB_HISTORY_LOCK_RESOURCE_KIND,
311
+ resourceId: id,
312
+ expected: expectedUpdatedAt ?? null,
313
+ request: ctx.request ?? null,
314
+ })
315
+ throw new CrudHttpError(404, { error: 'Job history entry not found' })
316
+ }
285
317
  ensureTenantScope(ctx, record.tenantId)
286
318
  ensureOrganizationScope(ctx, record.organizationId)
319
+ enforceCommandOptimisticLock({
320
+ resourceKind: JOB_HISTORY_LOCK_RESOURCE_KIND,
321
+ resourceId: record.id,
322
+ current: record.updatedAt ?? null,
323
+ expected: expectedUpdatedAt ?? null,
324
+ request: ctx.request ?? null,
325
+ })
287
326
  em.remove(record)
288
327
  await em.flush()
289
328
 
@@ -32,6 +32,7 @@ export type LeaveRequestFormValues = {
32
32
  unavailabilityReasonEntryId?: string | null
33
33
  unavailabilityReasonValue?: string | null
34
34
  note?: string | null
35
+ updatedAt?: string | null
35
36
  }
36
37
 
37
38
  export type LeaveRequestFormProps = {
@@ -317,6 +318,7 @@ export function LeaveRequestForm(props: LeaveRequestFormProps) {
317
318
  title={title}
318
319
  fields={fields}
319
320
  initialValues={normalizedInitialValues}
321
+ optimisticLockUpdatedAt={normalizedInitialValues.updatedAt}
320
322
  submitLabel={submitLabel}
321
323
  backHref={backHref}
322
324
  cancelHref={cancelHref}
@@ -12,6 +12,7 @@ export type TeamFormValues = {
12
12
  name: string
13
13
  description?: string | null
14
14
  isActive?: boolean
15
+ updatedAt?: string | null
15
16
  } & Record<string, unknown>
16
17
 
17
18
  export type TeamFormProps = {
@@ -89,6 +90,7 @@ export function TeamForm(props: TeamFormProps) {
89
90
  groups={groups}
90
91
  entityId={E.staff.staff_team}
91
92
  initialValues={initialValues}
93
+ optimisticLockUpdatedAt={initialValues.updatedAt}
92
94
  onSubmit={onSubmit}
93
95
  onDelete={onDelete}
94
96
  isLoading={isLoading}
@@ -32,6 +32,7 @@ export type TeamMemberFormValues = {
32
32
  roleIds?: string[]
33
33
  tags?: string[]
34
34
  isActive?: boolean
35
+ updatedAt?: string | null
35
36
  } & Record<string, unknown>
36
37
 
37
38
  export type TeamMemberFormProps = {
@@ -515,6 +516,7 @@ export function TeamMemberForm(props: TeamMemberFormProps) {
515
516
  groups={groups}
516
517
  entityId={E.staff.staff_team_member}
517
518
  initialValues={initialValues}
519
+ optimisticLockUpdatedAt={initialValues.updatedAt}
518
520
  onSubmit={onSubmit}
519
521
  onDelete={onDelete}
520
522
  isLoading={isLoading}
@@ -14,6 +14,7 @@ export type TeamRoleFormValues = {
14
14
  name: string
15
15
  description?: string | null
16
16
  appearance?: { icon?: string | null; color?: string | null }
17
+ updatedAt?: string | null
17
18
  } & Record<string, unknown>
18
19
 
19
20
  export type TeamRoleOption = {
@@ -152,6 +153,7 @@ export function TeamRoleForm(props: TeamRoleFormProps) {
152
153
  groups={groups}
153
154
  entityId={E.staff.staff_team_role}
154
155
  initialValues={initialValues}
156
+ optimisticLockUpdatedAt={initialValues.updatedAt}
155
157
  onSubmit={onSubmit}
156
158
  onDelete={onDelete}
157
159
  isLoading={isLoading}
@@ -9,6 +9,7 @@ import { LoadingMessage, ErrorMessage, TabEmptyState } from '@open-mercato/ui/ba
9
9
  import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
10
10
  import { createCrud, updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'
11
11
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
12
+ import { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'
12
13
  import { useT } from '@open-mercato/shared/lib/i18n/context'
13
14
  import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
14
15
 
@@ -19,6 +20,7 @@ type JobHistoryRecord = {
19
20
  description: string | null
20
21
  startDate: string | null
21
22
  endDate: string | null
23
+ updatedAt: string | undefined
22
24
  }
23
25
 
24
26
  type JobHistoryResponse = {
@@ -54,6 +56,7 @@ export function JobHistorySection({ memberId }: { memberId: string | null }) {
54
56
  errorLoad: t('staff.teamMembers.detail.jobHistory.errorLoad', 'Failed to load job history.'),
55
57
  errorSave: t('staff.teamMembers.detail.jobHistory.errorSave', 'Failed to save job history.'),
56
58
  errorDelete: t('staff.teamMembers.detail.jobHistory.errorDelete', 'Failed to delete job history.'),
59
+ conflict: t('staff.teamMembers.detail.jobHistory.conflict', 'This record was modified by someone else. Refresh and try again.'),
57
60
  loading: t('staff.teamMembers.detail.jobHistory.loading', 'Loading job history...'),
58
61
  saved: t('staff.teamMembers.detail.jobHistory.saved', 'Job history saved.'),
59
62
  updated: t('staff.teamMembers.detail.jobHistory.updated', 'Job history updated.'),
@@ -137,7 +140,11 @@ export function JobHistorySection({ memberId }: { memberId: string | null }) {
137
140
  if (!memberId) return
138
141
  const payload = buildJobHistoryPayload(values)
139
142
  if (dialogMode === 'edit' && activeRecord) {
140
- await updateCrud('staff/job-histories', { id: activeRecord.id, ...payload }, { errorMessage: labels.errorSave })
143
+ // Let any error (including the optimistic-lock 409) propagate so the
144
+ // enclosing CrudForm surfaces the unified "Record changed" conflict bar
145
+ // via surfaceRecordConflict. Catching it here and routing it to a flash
146
+ // toast would hide the conflict bar (see TC-LOCK-OSS-036).
147
+ await updateCrud('staff/job-histories', { id: activeRecord.id, updatedAt: activeRecord.updatedAt, ...payload }, { errorMessage: labels.errorSave })
141
148
  flash(labels.updated, 'success')
142
149
  } else {
143
150
  await createCrud('staff/job-histories', { entityId: memberId, ...payload }, { errorMessage: labels.errorSave })
@@ -145,7 +152,7 @@ export function JobHistorySection({ memberId }: { memberId: string | null }) {
145
152
  }
146
153
  closeDialog()
147
154
  setReloadToken((prev) => prev + 1)
148
- }, [activeRecord, closeDialog, dialogMode, labels.errorSave, labels.saved, labels.updated, memberId])
155
+ }, [activeRecord, closeDialog, dialogMode, labels.conflict, labels.errorSave, labels.saved, labels.updated, memberId])
149
156
 
150
157
  const handleDelete = React.useCallback(async (record: JobHistoryRecord) => {
151
158
  const confirmed = await confirmDialog({
@@ -153,10 +160,19 @@ export function JobHistorySection({ memberId }: { memberId: string | null }) {
153
160
  variant: 'destructive',
154
161
  })
155
162
  if (!confirmed) return
156
- await deleteCrud('staff/job-histories', { id: record.id, errorMessage: labels.errorDelete })
157
- flash(labels.deleted, 'success')
158
- setReloadToken((prev) => prev + 1)
159
- }, [labels.deleteConfirm, labels.deleted, labels.errorDelete, confirmDialog])
163
+ try {
164
+ await deleteCrud('staff/job-histories', {
165
+ id: record.id,
166
+ body: { id: record.id, updatedAt: record.updatedAt },
167
+ errorMessage: labels.errorDelete,
168
+ })
169
+ flash(labels.deleted, 'success')
170
+ setReloadToken((prev) => prev + 1)
171
+ } catch (error) {
172
+ if (surfaceRecordConflict(error, t)) return
173
+ flash(labels.errorDelete, 'error')
174
+ }
175
+ }, [labels.deleteConfirm, labels.deleted, labels.errorDelete, confirmDialog, t])
160
176
 
161
177
  const dialogTitle = dialogMode === 'edit' ? labels.edit : labels.add
162
178
 
@@ -240,6 +256,7 @@ export function JobHistorySection({ memberId }: { memberId: string | null }) {
240
256
  <CrudForm<JobHistoryFormValues>
241
257
  fields={fields}
242
258
  initialValues={initialValues}
259
+ optimisticLockUpdatedAt={activeRecord?.updatedAt ?? null}
243
260
  onSubmit={handleSubmit}
244
261
  submitLabel={dialogMode === 'edit' ? labels.update : labels.save}
245
262
  extraActions={(
@@ -290,6 +307,11 @@ function normalizeJobHistoryItems(items?: Record<string, unknown>[]): JobHistory
290
307
  : typeof record.endDate === 'string'
291
308
  ? record.endDate
292
309
  : null,
310
+ updatedAt: typeof record.updated_at === 'string'
311
+ ? record.updated_at
312
+ : typeof record.updatedAt === 'string'
313
+ ? record.updatedAt
314
+ : undefined,
293
315
  }
294
316
  })
295
317
  .filter((value): value is JobHistoryRecord => value !== null)
@@ -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' },