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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (726) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/AGENTS.md +5 -0
  3. package/dist/generated/entities/role/index.js +3 -1
  4. package/dist/generated/entities/role/index.js.map +2 -2
  5. package/dist/generated/entities/step_instance/index.js +2 -0
  6. package/dist/generated/entities/step_instance/index.js.map +2 -2
  7. package/dist/generated/entities/user/index.js +3 -1
  8. package/dist/generated/entities/user/index.js.map +2 -2
  9. package/dist/generated/entities/user_task/index.js +2 -0
  10. package/dist/generated/entities/user_task/index.js.map +2 -2
  11. package/dist/generated/entities/workflow_branch_instance/index.js +39 -0
  12. package/dist/generated/entities/workflow_branch_instance/index.js.map +7 -0
  13. package/dist/generated/entities/workflow_event/index.js +2 -0
  14. package/dist/generated/entities/workflow_event/index.js.map +2 -2
  15. package/dist/generated/entities/workflow_instance/index.js +2 -0
  16. package/dist/generated/entities/workflow_instance/index.js.map +2 -2
  17. package/dist/generated/entities.ids.generated.js +1 -0
  18. package/dist/generated/entities.ids.generated.js.map +2 -2
  19. package/dist/generated/entity-fields-registry.js +26 -0
  20. package/dist/generated/entity-fields-registry.js.map +2 -2
  21. package/dist/helpers/integration/optimisticLockUi.js +104 -0
  22. package/dist/helpers/integration/optimisticLockUi.js.map +7 -0
  23. package/dist/helpers/integration/salesFixtures.js +17 -0
  24. package/dist/helpers/integration/salesFixtures.js.map +2 -2
  25. package/dist/modules/api_keys/backend/api-keys/page.js +9 -5
  26. package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
  27. package/dist/modules/attachments/components/AttachmentPartitionSettings.js +17 -9
  28. package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
  29. package/dist/modules/auth/api/roles/acl/route.js +32 -13
  30. package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
  31. package/dist/modules/auth/api/roles/route.js +3 -1
  32. package/dist/modules/auth/api/roles/route.js.map +2 -2
  33. package/dist/modules/auth/api/sidebar/preferences/route.js +71 -3
  34. package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
  35. package/dist/modules/auth/api/users/acl/route.js +42 -19
  36. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  37. package/dist/modules/auth/api/users/route.js +3 -1
  38. package/dist/modules/auth/api/users/route.js.map +2 -2
  39. package/dist/modules/auth/backend/roles/[id]/edit/page.js +24 -4
  40. package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
  41. package/dist/modules/auth/backend/roles/page.js +8 -4
  42. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  43. package/dist/modules/auth/backend/users/[id]/edit/page.js +27 -5
  44. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  45. package/dist/modules/auth/backend/users/page.js +6 -2
  46. package/dist/modules/auth/backend/users/page.js.map +2 -2
  47. package/dist/modules/auth/components/AclEditor.js +3 -1
  48. package/dist/modules/auth/components/AclEditor.js.map +2 -2
  49. package/dist/modules/auth/data/entities.js +6 -0
  50. package/dist/modules/auth/data/entities.js.map +2 -2
  51. package/dist/modules/auth/services/sidebarPreferencesService.js +32 -4
  52. package/dist/modules/auth/services/sidebarPreferencesService.js.map +2 -2
  53. package/dist/modules/business_rules/api/rules/route.js +28 -0
  54. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  55. package/dist/modules/business_rules/api/sets/route.js +28 -0
  56. package/dist/modules/business_rules/api/sets/route.js.map +2 -2
  57. package/dist/modules/business_rules/backend/rules/[id]/page.js +11 -4
  58. package/dist/modules/business_rules/backend/rules/[id]/page.js.map +3 -3
  59. package/dist/modules/business_rules/backend/rules/page.js +20 -11
  60. package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
  61. package/dist/modules/business_rules/backend/sets/[id]/page.js +11 -4
  62. package/dist/modules/business_rules/backend/sets/[id]/page.js.map +2 -2
  63. package/dist/modules/business_rules/backend/sets/page.js +20 -11
  64. package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
  65. package/dist/modules/catalog/api/categories/route.js +2 -0
  66. package/dist/modules/catalog/api/categories/route.js.map +2 -2
  67. package/dist/modules/catalog/api/products/route.js +2 -1
  68. package/dist/modules/catalog/api/products/route.js.map +2 -2
  69. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js +2 -0
  70. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js.map +2 -2
  71. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +94 -40
  72. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  73. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +37 -8
  74. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
  75. package/dist/modules/catalog/backend/catalog/products/optionSchemaClient.js.map +2 -2
  76. package/dist/modules/catalog/commands/variants.js +32 -31
  77. package/dist/modules/catalog/commands/variants.js.map +2 -2
  78. package/dist/modules/catalog/components/PriceKindSettings.js +12 -5
  79. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  80. package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
  81. package/dist/modules/catalog/components/products/ProductMediaManager.js.map +2 -2
  82. package/dist/modules/catalog/components/products/ProductsDataTable.js +5 -3
  83. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  84. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  85. package/dist/modules/catalog/components/products/variantForm.js +2 -1
  86. package/dist/modules/catalog/components/products/variantForm.js.map +2 -2
  87. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +5 -0
  88. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
  89. package/dist/modules/currencies/backend/currencies/[id]/page.js +6 -3
  90. package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
  91. package/dist/modules/currencies/backend/currencies/page.js +18 -11
  92. package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
  93. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js +1 -0
  94. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js.map +2 -2
  95. package/dist/modules/currencies/backend/exchange-rates/page.js +10 -6
  96. package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
  97. package/dist/modules/currencies/commands/currencies.js +7 -5
  98. package/dist/modules/currencies/commands/currencies.js.map +2 -2
  99. package/dist/modules/currencies/components/CurrencyFetchingConfig.js +26 -19
  100. package/dist/modules/currencies/components/CurrencyFetchingConfig.js.map +2 -2
  101. package/dist/modules/customer_accounts/api/admin/roles/[id].js +28 -5
  102. package/dist/modules/customer_accounts/api/admin/roles/[id].js.map +2 -2
  103. package/dist/modules/customer_accounts/api/admin/roles.js +4 -2
  104. package/dist/modules/customer_accounts/api/admin/roles.js.map +2 -2
  105. package/dist/modules/customer_accounts/api/admin/users/[id].js +28 -5
  106. package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
  107. package/dist/modules/customer_accounts/api/admin/users.js +2 -0
  108. package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
  109. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +16 -8
  110. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
  111. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +8 -4
  112. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
  113. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js +8 -4
  114. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js.map +2 -2
  115. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +29 -18
  116. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
  117. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +18 -11
  118. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
  119. package/dist/modules/customers/api/companies/route.js +13 -2
  120. package/dist/modules/customers/api/companies/route.js.map +2 -2
  121. package/dist/modules/customers/api/deals/route.js +2 -0
  122. package/dist/modules/customers/api/deals/route.js.map +2 -2
  123. package/dist/modules/customers/api/people/route.js +11 -2
  124. package/dist/modules/customers/api/people/route.js.map +2 -2
  125. package/dist/modules/customers/api/todos/route.js +1 -0
  126. package/dist/modules/customers/api/todos/route.js.map +2 -2
  127. package/dist/modules/customers/backend/config/customers/deals/page.js.map +2 -2
  128. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +34 -21
  129. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
  130. package/dist/modules/customers/backend/customers/companies/[id]/page.js +45 -27
  131. package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
  132. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  133. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +22 -5
  134. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  135. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js +30 -8
  136. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js.map +2 -2
  137. package/dist/modules/customers/backend/customers/deals/[id]/page.js +1 -0
  138. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  139. package/dist/modules/customers/backend/customers/deals/page.js +16 -6
  140. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  141. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +62 -39
  142. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
  143. package/dist/modules/customers/backend/customers/people/[id]/page.js +41 -26
  144. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  145. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  146. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +50 -23
  147. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  148. package/dist/modules/customers/commands/addresses.js +16 -14
  149. package/dist/modules/customers/commands/addresses.js.map +2 -2
  150. package/dist/modules/customers/commands/companies.js +1 -1
  151. package/dist/modules/customers/commands/companies.js.map +2 -2
  152. package/dist/modules/customers/commands/interactions.js +41 -4
  153. package/dist/modules/customers/commands/interactions.js.map +2 -2
  154. package/dist/modules/customers/commands/people.js +1 -1
  155. package/dist/modules/customers/commands/people.js.map +2 -2
  156. package/dist/modules/customers/commands/personCompanyLinks.js +8 -5
  157. package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
  158. package/dist/modules/customers/commands/pipeline-stages.js +13 -11
  159. package/dist/modules/customers/commands/pipeline-stages.js.map +3 -3
  160. package/dist/modules/customers/components/AddressFormatSettings.js.map +2 -2
  161. package/dist/modules/customers/components/DictionarySettings.js +20 -13
  162. package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
  163. package/dist/modules/customers/components/DictionarySortSettings.js +4 -0
  164. package/dist/modules/customers/components/DictionarySortSettings.js.map +2 -2
  165. package/dist/modules/customers/components/PipelineSettings.js +38 -23
  166. package/dist/modules/customers/components/PipelineSettings.js.map +2 -2
  167. package/dist/modules/customers/components/detail/ActivityTimeline.js +1 -1
  168. package/dist/modules/customers/components/detail/ActivityTimeline.js.map +2 -2
  169. package/dist/modules/customers/components/detail/AddressesSection.js +4 -0
  170. package/dist/modules/customers/components/detail/AddressesSection.js.map +2 -2
  171. package/dist/modules/customers/components/detail/CompanyPeopleSection.js +28 -22
  172. package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
  173. package/dist/modules/customers/components/detail/DealsSection.js +36 -24
  174. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  175. package/dist/modules/customers/components/detail/EmailCardActions.js +5 -0
  176. package/dist/modules/customers/components/detail/EmailCardActions.js.map +2 -2
  177. package/dist/modules/customers/components/detail/EntityTagsDialog.js +7 -0
  178. package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
  179. package/dist/modules/customers/components/detail/ManageTagsDialog.js +34 -22
  180. package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +2 -2
  181. package/dist/modules/customers/components/detail/PersonCompaniesSection.js +41 -29
  182. package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
  183. package/dist/modules/customers/components/detail/RoleAssignmentRow.js +14 -8
  184. package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +2 -2
  185. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +14 -6
  186. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  187. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +29 -13
  188. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +2 -2
  189. package/dist/modules/customers/components/detail/hooks/useInteractions.js +77 -35
  190. package/dist/modules/customers/components/detail/hooks/useInteractions.js.map +2 -2
  191. package/dist/modules/customers/components/detail/hooks/usePersonTasks.js +25 -17
  192. package/dist/modules/customers/components/detail/hooks/usePersonTasks.js.map +2 -2
  193. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
  194. package/dist/modules/customers/components/formConfig.js.map +2 -2
  195. package/dist/modules/customers/data/guards.js +66 -0
  196. package/dist/modules/customers/data/guards.js.map +7 -0
  197. package/dist/modules/customers/di.js +37 -0
  198. package/dist/modules/customers/di.js.map +2 -2
  199. package/dist/modules/customers/lib/todoCompatibility.js +11 -0
  200. package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
  201. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  202. package/dist/modules/data_sync/api/options.js +4 -4
  203. package/dist/modules/data_sync/api/options.js.map +2 -2
  204. package/dist/modules/data_sync/api/schedules/route.js +9 -1
  205. package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
  206. package/dist/modules/data_sync/backend/data-sync/page.js +17 -8
  207. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  208. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +43 -22
  209. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  210. package/dist/modules/data_sync/lib/sync-schedule-service.js +9 -0
  211. package/dist/modules/data_sync/lib/sync-schedule-service.js.map +2 -2
  212. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +8 -1
  213. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
  214. package/dist/modules/dictionaries/api/[dictionaryId]/route.js +17 -1
  215. package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
  216. package/dist/modules/dictionaries/components/DictionariesManager.js +31 -10
  217. package/dist/modules/dictionaries/components/DictionariesManager.js.map +2 -2
  218. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js +28 -15
  219. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js.map +2 -2
  220. package/dist/modules/directory/api/organizations/route.js +3 -0
  221. package/dist/modules/directory/api/organizations/route.js.map +2 -2
  222. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js +2 -0
  223. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js.map +2 -2
  224. package/dist/modules/directory/backend/directory/organizations/page.js +9 -5
  225. package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
  226. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js +7 -3
  227. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js.map +2 -2
  228. package/dist/modules/directory/backend/directory/tenants/page.js +8 -4
  229. package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
  230. package/dist/modules/directory/commands/organizations.js +7 -2
  231. package/dist/modules/directory/commands/organizations.js.map +2 -2
  232. package/dist/modules/entities/api/records.js +66 -0
  233. package/dist/modules/entities/api/records.js.map +2 -2
  234. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js +1 -0
  235. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js.map +2 -2
  236. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +8 -4
  237. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  238. package/dist/modules/entities/lib/helpers.js +17 -0
  239. package/dist/modules/entities/lib/helpers.js.map +2 -2
  240. package/dist/modules/feature_toggles/api/global/[id]/override/route.js +2 -1
  241. package/dist/modules/feature_toggles/api/global/[id]/override/route.js.map +2 -2
  242. package/dist/modules/feature_toggles/api/overrides/route.js +15 -0
  243. package/dist/modules/feature_toggles/api/overrides/route.js.map +2 -2
  244. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js +15 -14
  245. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js.map +2 -2
  246. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js +20 -12
  247. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js.map +2 -2
  248. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +6 -2
  249. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
  250. package/dist/modules/feature_toggles/components/formConfig.js +2 -1
  251. package/dist/modules/feature_toggles/components/formConfig.js.map +2 -2
  252. package/dist/modules/feature_toggles/components/overrideFormConfig.js +5 -1
  253. package/dist/modules/feature_toggles/components/overrideFormConfig.js.map +2 -2
  254. package/dist/modules/feature_toggles/data/validators.js +7 -4
  255. package/dist/modules/feature_toggles/data/validators.js.map +2 -2
  256. package/dist/modules/inbox_ops/api/settings/route.js +17 -2
  257. package/dist/modules/inbox_ops/api/settings/route.js.map +2 -2
  258. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js +13 -8
  259. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js.map +2 -2
  260. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +9 -4
  261. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
  262. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +18 -11
  263. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
  264. package/dist/modules/integrations/backend/integrations/page.js +12 -8
  265. package/dist/modules/integrations/backend/integrations/page.js.map +2 -2
  266. package/dist/modules/messages/commands/messages.js +13 -10
  267. package/dist/modules/messages/commands/messages.js.map +2 -2
  268. package/dist/modules/perspectives/api/[tableId]/route.js +39 -30
  269. package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
  270. package/dist/modules/perspectives/services/perspectiveService.js +7 -0
  271. package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
  272. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +6 -14
  273. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +3 -3
  274. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +4 -2
  275. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  276. package/dist/modules/planner/components/AvailabilityRuleSetForm.js +2 -0
  277. package/dist/modules/planner/components/AvailabilityRuleSetForm.js.map +2 -2
  278. package/dist/modules/planner/components/AvailabilityRulesEditor.js +36 -11
  279. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  280. package/dist/modules/planner/components/AvailabilitySchedule.js +9 -5
  281. package/dist/modules/planner/components/AvailabilitySchedule.js.map +2 -2
  282. package/dist/modules/progress/api/jobs/[id]/route.js +7 -1
  283. package/dist/modules/progress/api/jobs/[id]/route.js.map +2 -2
  284. package/dist/modules/query_index/lib/engine.js +19 -0
  285. package/dist/modules/query_index/lib/engine.js.map +2 -2
  286. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js +1 -0
  287. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js.map +2 -2
  288. package/dist/modules/resources/backend/resources/resource-types/page.js +4 -2
  289. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  290. package/dist/modules/resources/backend/resources/resources/[id]/page.js +14 -3
  291. package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
  292. package/dist/modules/resources/backend/resources/resources/page.js +8 -4
  293. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  294. package/dist/modules/resources/components/ResourceCrudForm.js +2 -0
  295. package/dist/modules/resources/components/ResourceCrudForm.js.map +2 -2
  296. package/dist/modules/resources/components/ResourceTypeCrudForm.js +1 -0
  297. package/dist/modules/resources/components/ResourceTypeCrudForm.js.map +2 -2
  298. package/dist/modules/sales/api/documents/factory.js +7 -2
  299. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  300. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +3 -1
  301. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
  302. package/dist/modules/sales/backend/sales/channels/offers/page.js +13 -4
  303. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  304. package/dist/modules/sales/backend/sales/channels/page.js +16 -4
  305. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  306. package/dist/modules/sales/backend/sales/documents/[id]/page.js +68 -22
  307. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  308. package/dist/modules/sales/backend/sales/documents/create/page.js.map +2 -2
  309. package/dist/modules/sales/commands/documentAddresses.js +181 -2
  310. package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
  311. package/dist/modules/sales/commands/documents.js +29 -1
  312. package/dist/modules/sales/commands/documents.js.map +2 -2
  313. package/dist/modules/sales/commands/returns.js +12 -2
  314. package/dist/modules/sales/commands/returns.js.map +2 -2
  315. package/dist/modules/sales/commands/shared.js +15 -0
  316. package/dist/modules/sales/commands/shared.js.map +2 -2
  317. package/dist/modules/sales/commands/shipments.js +4 -1
  318. package/dist/modules/sales/commands/shipments.js.map +2 -2
  319. package/dist/modules/sales/components/AdjustmentKindSettings.js +19 -11
  320. package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
  321. package/dist/modules/sales/components/DocumentNumberSettings.js.map +2 -2
  322. package/dist/modules/sales/components/OrderEditingSettings.js.map +2 -2
  323. package/dist/modules/sales/components/PaymentMethodsSettings.js +12 -4
  324. package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
  325. package/dist/modules/sales/components/ShippingMethodsSettings.js +12 -4
  326. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
  327. package/dist/modules/sales/components/StatusSettings.js +18 -11
  328. package/dist/modules/sales/components/StatusSettings.js.map +2 -2
  329. package/dist/modules/sales/components/TaxRatesSettings.js +12 -4
  330. package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
  331. package/dist/modules/sales/components/channels/ChannelOfferForm.js +47 -16
  332. package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
  333. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +8 -4
  334. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  335. package/dist/modules/sales/components/documents/AddressesSection.js +44 -25
  336. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  337. package/dist/modules/sales/components/documents/AdjustmentsSection.js +43 -23
  338. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  339. package/dist/modules/sales/components/documents/ItemsSection.js +22 -13
  340. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  341. package/dist/modules/sales/components/documents/LineItemDialog.js +23 -10
  342. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  343. package/dist/modules/sales/components/documents/PaymentDialog.js +29 -14
  344. package/dist/modules/sales/components/documents/PaymentDialog.js.map +2 -2
  345. package/dist/modules/sales/components/documents/PaymentsSection.js +20 -10
  346. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  347. package/dist/modules/sales/components/documents/ReturnDialog.js +26 -17
  348. package/dist/modules/sales/components/documents/ReturnDialog.js.map +2 -2
  349. package/dist/modules/sales/components/documents/ReturnsSection.js +3 -1
  350. package/dist/modules/sales/components/documents/ReturnsSection.js.map +2 -2
  351. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +10 -5
  352. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  353. package/dist/modules/sales/components/documents/ShipmentDialog.js +21 -7
  354. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  355. package/dist/modules/sales/components/documents/ShipmentsSection.js +19 -10
  356. package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
  357. package/dist/modules/sales/components/documents/optimisticLock.js +27 -0
  358. package/dist/modules/sales/components/documents/optimisticLock.js.map +7 -0
  359. package/dist/modules/sales/di.js +18 -0
  360. package/dist/modules/sales/di.js.map +2 -2
  361. package/dist/modules/shipping_carriers/api/cancel/route.js +2 -2
  362. package/dist/modules/shipping_carriers/api/cancel/route.js.map +2 -2
  363. package/dist/modules/shipping_carriers/lib/status-sync.js +8 -1
  364. package/dist/modules/shipping_carriers/lib/status-sync.js.map +2 -2
  365. package/dist/modules/staff/api/job-histories.js +11 -2
  366. package/dist/modules/staff/api/job-histories.js.map +2 -2
  367. package/dist/modules/staff/api/timesheets/time-entries/route.js +11 -4
  368. package/dist/modules/staff/api/timesheets/time-entries/route.js.map +2 -2
  369. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +13 -8
  370. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
  371. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +2 -1
  372. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
  373. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +7 -4
  374. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  375. package/dist/modules/staff/backend/staff/team-members/page.js +4 -2
  376. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  377. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js +1 -0
  378. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js.map +2 -2
  379. package/dist/modules/staff/backend/staff/team-roles/page.js +4 -2
  380. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  381. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +5 -2
  382. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  383. package/dist/modules/staff/backend/staff/teams/page.js +12 -3
  384. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  385. package/dist/modules/staff/backend/staff/timesheets/page.js +4 -1
  386. package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
  387. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +2 -2
  388. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +12 -3
  389. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
  390. package/dist/modules/staff/commands/job-histories.js +40 -3
  391. package/dist/modules/staff/commands/job-histories.js.map +2 -2
  392. package/dist/modules/staff/components/LeaveRequestForm.js +1 -0
  393. package/dist/modules/staff/components/LeaveRequestForm.js.map +2 -2
  394. package/dist/modules/staff/components/TeamForm.js +1 -0
  395. package/dist/modules/staff/components/TeamForm.js.map +2 -2
  396. package/dist/modules/staff/components/TeamMemberForm.js +1 -0
  397. package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
  398. package/dist/modules/staff/components/TeamRoleForm.js +1 -0
  399. package/dist/modules/staff/components/TeamRoleForm.js.map +2 -2
  400. package/dist/modules/staff/components/detail/JobHistorySection.js +20 -7
  401. package/dist/modules/staff/components/detail/JobHistorySection.js.map +2 -2
  402. package/dist/modules/staff/data/validators.js +7 -1
  403. package/dist/modules/staff/data/validators.js.map +2 -2
  404. package/dist/modules/staff/lib/leaveRequestHelpers.js +2 -1
  405. package/dist/modules/staff/lib/leaveRequestHelpers.js.map +2 -2
  406. package/dist/modules/translations/components/TranslationManager.js +12 -8
  407. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  408. package/dist/modules/workflows/api/definitions/[id]/route.js +106 -0
  409. package/dist/modules/workflows/api/definitions/[id]/route.js.map +2 -2
  410. package/dist/modules/workflows/backend/definitions/[id]/page.js +11 -3
  411. package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
  412. package/dist/modules/workflows/backend/definitions/page.js +19 -8
  413. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  414. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +29 -16
  415. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  416. package/dist/modules/workflows/components/NodeEditDialog.js +3 -1
  417. package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
  418. package/dist/modules/workflows/components/WorkflowGraphImpl.js +4 -2
  419. package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +2 -2
  420. package/dist/modules/workflows/components/formConfig.js +4 -1
  421. package/dist/modules/workflows/components/formConfig.js.map +2 -2
  422. package/dist/modules/workflows/components/nodes/ParallelForkNode.js +49 -0
  423. package/dist/modules/workflows/components/nodes/ParallelForkNode.js.map +7 -0
  424. package/dist/modules/workflows/components/nodes/ParallelJoinNode.js +49 -0
  425. package/dist/modules/workflows/components/nodes/ParallelJoinNode.js.map +7 -0
  426. package/dist/modules/workflows/components/nodes/index.js +4 -0
  427. package/dist/modules/workflows/components/nodes/index.js.map +2 -2
  428. package/dist/modules/workflows/data/entities.js +81 -0
  429. package/dist/modules/workflows/data/entities.js.map +2 -2
  430. package/dist/modules/workflows/data/validators.js +146 -1
  431. package/dist/modules/workflows/data/validators.js.map +2 -2
  432. package/dist/modules/workflows/di.js +12 -0
  433. package/dist/modules/workflows/di.js.map +2 -2
  434. package/dist/modules/workflows/events.js +7 -1
  435. package/dist/modules/workflows/events.js.map +2 -2
  436. package/dist/modules/workflows/lib/activity-executor.js +4 -2
  437. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  438. package/dist/modules/workflows/lib/activity-queue-types.js.map +2 -2
  439. package/dist/modules/workflows/lib/event-logger.js +2 -0
  440. package/dist/modules/workflows/lib/event-logger.js.map +2 -2
  441. package/dist/modules/workflows/lib/execution-token.js +98 -0
  442. package/dist/modules/workflows/lib/execution-token.js.map +7 -0
  443. package/dist/modules/workflows/lib/node-type-icons.js +14 -5
  444. package/dist/modules/workflows/lib/node-type-icons.js.map +2 -2
  445. package/dist/modules/workflows/lib/parallel-handler.js +364 -0
  446. package/dist/modules/workflows/lib/parallel-handler.js.map +7 -0
  447. package/dist/modules/workflows/lib/signal-handler.js +63 -1
  448. package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
  449. package/dist/modules/workflows/lib/step-handler.js +74 -30
  450. package/dist/modules/workflows/lib/step-handler.js.map +2 -2
  451. package/dist/modules/workflows/lib/task-handler.js +26 -0
  452. package/dist/modules/workflows/lib/task-handler.js.map +2 -2
  453. package/dist/modules/workflows/lib/timer-handler.js +26 -1
  454. package/dist/modules/workflows/lib/timer-handler.js.map +2 -2
  455. package/dist/modules/workflows/lib/transition-handler.js +33 -21
  456. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  457. package/dist/modules/workflows/lib/workflow-executor.js +39 -1
  458. package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
  459. package/dist/modules/workflows/migrations/Migration20260602120000.js +24 -0
  460. package/dist/modules/workflows/migrations/Migration20260602120000.js.map +7 -0
  461. package/dist/modules/workflows/workers/workflow-activities.worker.js +8 -4
  462. package/dist/modules/workflows/workers/workflow-activities.worker.js.map +2 -2
  463. package/generated/entities/role/index.ts +1 -0
  464. package/generated/entities/step_instance/index.ts +1 -0
  465. package/generated/entities/user/index.ts +1 -0
  466. package/generated/entities/user_task/index.ts +1 -0
  467. package/generated/entities/workflow_branch_instance/index.ts +18 -0
  468. package/generated/entities/workflow_event/index.ts +1 -0
  469. package/generated/entities/workflow_instance/index.ts +1 -0
  470. package/generated/entities.ids.generated.ts +1 -0
  471. package/generated/entity-fields-registry.ts +26 -0
  472. package/jest.setup.ts +17 -0
  473. package/package.json +8 -7
  474. package/src/helpers/integration/optimisticLockUi.ts +172 -0
  475. package/src/helpers/integration/salesFixtures.ts +29 -0
  476. package/src/modules/api_keys/backend/api-keys/page.tsx +10 -5
  477. package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +19 -9
  478. package/src/modules/auth/api/roles/acl/route.ts +37 -11
  479. package/src/modules/auth/api/roles/route.ts +2 -0
  480. package/src/modules/auth/api/sidebar/preferences/route.ts +73 -0
  481. package/src/modules/auth/api/users/acl/route.ts +46 -18
  482. package/src/modules/auth/api/users/route.ts +2 -0
  483. package/src/modules/auth/backend/roles/[id]/edit/page.tsx +29 -4
  484. package/src/modules/auth/backend/roles/page.tsx +9 -4
  485. package/src/modules/auth/backend/users/[id]/edit/page.tsx +37 -4
  486. package/src/modules/auth/backend/users/page.tsx +7 -2
  487. package/src/modules/auth/components/AclEditor.tsx +10 -1
  488. package/src/modules/auth/data/entities.ts +7 -1
  489. package/src/modules/auth/services/sidebarPreferencesService.ts +38 -4
  490. package/src/modules/business_rules/api/rules/route.ts +30 -0
  491. package/src/modules/business_rules/api/sets/route.ts +30 -0
  492. package/src/modules/business_rules/backend/rules/[id]/page.tsx +16 -4
  493. package/src/modules/business_rules/backend/rules/page.tsx +20 -11
  494. package/src/modules/business_rules/backend/sets/[id]/page.tsx +16 -4
  495. package/src/modules/business_rules/backend/sets/page.tsx +20 -11
  496. package/src/modules/catalog/api/categories/route.ts +3 -0
  497. package/src/modules/catalog/api/products/route.ts +4 -0
  498. package/src/modules/catalog/backend/catalog/categories/[id]/edit/page.tsx +5 -0
  499. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +112 -35
  500. package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +56 -7
  501. package/src/modules/catalog/backend/catalog/products/optionSchemaClient.ts +2 -0
  502. package/src/modules/catalog/commands/variants.ts +32 -32
  503. package/src/modules/catalog/components/PriceKindSettings.tsx +20 -7
  504. package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +1 -0
  505. package/src/modules/catalog/components/products/ProductMediaManager.tsx +2 -0
  506. package/src/modules/catalog/components/products/ProductsDataTable.tsx +8 -4
  507. package/src/modules/catalog/components/products/productForm.ts +3 -0
  508. package/src/modules/catalog/components/products/variantForm.ts +9 -0
  509. package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +5 -0
  510. package/src/modules/currencies/backend/currencies/[id]/page.tsx +13 -6
  511. package/src/modules/currencies/backend/currencies/page.tsx +18 -11
  512. package/src/modules/currencies/backend/exchange-rates/[id]/page.tsx +3 -0
  513. package/src/modules/currencies/backend/exchange-rates/page.tsx +10 -6
  514. package/src/modules/currencies/commands/currencies.ts +10 -5
  515. package/src/modules/currencies/components/CurrencyFetchingConfig.tsx +31 -21
  516. package/src/modules/customer_accounts/api/admin/roles/[id].ts +35 -5
  517. package/src/modules/customer_accounts/api/admin/roles.ts +2 -0
  518. package/src/modules/customer_accounts/api/admin/users/[id].ts +38 -5
  519. package/src/modules/customer_accounts/api/admin/users.ts +2 -0
  520. package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +34 -20
  521. package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +9 -4
  522. package/src/modules/customer_accounts/backend/customer_accounts/settings/domain/page.tsx +11 -4
  523. package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +28 -17
  524. package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +19 -11
  525. package/src/modules/customers/AGENTS.md +2 -2
  526. package/src/modules/customers/api/companies/route.ts +14 -1
  527. package/src/modules/customers/api/deals/route.ts +3 -0
  528. package/src/modules/customers/api/people/route.ts +12 -1
  529. package/src/modules/customers/api/todos/route.ts +1 -0
  530. package/src/modules/customers/backend/config/customers/deals/page.tsx +1 -0
  531. package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +36 -21
  532. package/src/modules/customers/backend/customers/companies/[id]/page.tsx +52 -27
  533. package/src/modules/customers/backend/customers/companies/page.tsx +2 -0
  534. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +27 -5
  535. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.ts +39 -7
  536. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +1 -0
  537. package/src/modules/customers/backend/customers/deals/page.tsx +18 -6
  538. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +64 -39
  539. package/src/modules/customers/backend/customers/people/[id]/page.tsx +46 -26
  540. package/src/modules/customers/backend/customers/people/page.tsx +2 -0
  541. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +84 -24
  542. package/src/modules/customers/commands/addresses.ts +16 -14
  543. package/src/modules/customers/commands/companies.ts +3 -1
  544. package/src/modules/customers/commands/interactions.ts +50 -4
  545. package/src/modules/customers/commands/people.ts +2 -1
  546. package/src/modules/customers/commands/personCompanyLinks.ts +8 -5
  547. package/src/modules/customers/commands/pipeline-stages.ts +16 -16
  548. package/src/modules/customers/components/AddressFormatSettings.tsx +1 -0
  549. package/src/modules/customers/components/DictionarySettings.tsx +18 -13
  550. package/src/modules/customers/components/DictionarySortSettings.tsx +4 -0
  551. package/src/modules/customers/components/PipelineSettings.tsx +42 -21
  552. package/src/modules/customers/components/detail/ActivityTimeline.tsx +3 -3
  553. package/src/modules/customers/components/detail/AddressesSection.tsx +4 -0
  554. package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +2 -0
  555. package/src/modules/customers/components/detail/DealsSection.tsx +4 -0
  556. package/src/modules/customers/components/detail/EmailCardActions.tsx +5 -0
  557. package/src/modules/customers/components/detail/EntityTagsDialog.tsx +7 -0
  558. package/src/modules/customers/components/detail/ManageTagsDialog.tsx +4 -0
  559. package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +4 -0
  560. package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +2 -0
  561. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +23 -7
  562. package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +25 -15
  563. package/src/modules/customers/components/detail/hooks/useInteractions.ts +76 -35
  564. package/src/modules/customers/components/detail/hooks/usePersonTasks.ts +30 -17
  565. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +2 -0
  566. package/src/modules/customers/components/detail/types.ts +1 -0
  567. package/src/modules/customers/components/formConfig.tsx +2 -0
  568. package/src/modules/customers/data/guards.ts +67 -0
  569. package/src/modules/customers/di.ts +66 -0
  570. package/src/modules/customers/i18n/de.json +2 -0
  571. package/src/modules/customers/i18n/en.json +2 -0
  572. package/src/modules/customers/i18n/es.json +2 -0
  573. package/src/modules/customers/i18n/pl.json +2 -0
  574. package/src/modules/customers/lib/todoCompatibility.ts +14 -0
  575. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +2 -0
  576. package/src/modules/data_sync/api/options.ts +7 -4
  577. package/src/modules/data_sync/api/schedules/route.ts +9 -1
  578. package/src/modules/data_sync/backend/data-sync/page.tsx +18 -5
  579. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +46 -19
  580. package/src/modules/data_sync/lib/sync-schedule-service.ts +11 -0
  581. package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +8 -1
  582. package/src/modules/dictionaries/api/[dictionaryId]/route.ts +23 -0
  583. package/src/modules/dictionaries/components/DictionariesManager.tsx +32 -9
  584. package/src/modules/dictionaries/components/DictionaryEntriesEditor.tsx +30 -14
  585. package/src/modules/dictionaries/i18n/de.json +1 -0
  586. package/src/modules/dictionaries/i18n/en.json +1 -0
  587. package/src/modules/dictionaries/i18n/es.json +1 -0
  588. package/src/modules/dictionaries/i18n/pl.json +1 -0
  589. package/src/modules/directory/api/organizations/route.ts +3 -0
  590. package/src/modules/directory/backend/directory/organizations/[id]/edit/page.tsx +8 -0
  591. package/src/modules/directory/backend/directory/organizations/page.tsx +10 -5
  592. package/src/modules/directory/backend/directory/tenants/[id]/edit/page.tsx +16 -5
  593. package/src/modules/directory/backend/directory/tenants/page.tsx +8 -4
  594. package/src/modules/directory/commands/organizations.ts +7 -4
  595. package/src/modules/entities/api/records.ts +99 -0
  596. package/src/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.tsx +7 -0
  597. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +8 -4
  598. package/src/modules/entities/lib/helpers.ts +17 -0
  599. package/src/modules/feature_toggles/api/global/[id]/override/route.ts +1 -0
  600. package/src/modules/feature_toggles/api/overrides/route.ts +19 -0
  601. package/src/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.tsx +19 -13
  602. package/src/modules/feature_toggles/components/FeatureToggleOverrideCard.tsx +22 -12
  603. package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +7 -2
  604. package/src/modules/feature_toggles/components/formConfig.tsx +2 -1
  605. package/src/modules/feature_toggles/components/overrideFormConfig.tsx +10 -1
  606. package/src/modules/feature_toggles/data/validators.ts +11 -3
  607. package/src/modules/inbox_ops/api/settings/route.ts +18 -0
  608. package/src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx +15 -10
  609. package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +9 -4
  610. package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +20 -11
  611. package/src/modules/integrations/backend/integrations/page.tsx +13 -8
  612. package/src/modules/messages/commands/messages.ts +27 -15
  613. package/src/modules/perspectives/api/[tableId]/route.ts +11 -2
  614. package/src/modules/perspectives/services/perspectiveService.ts +13 -1
  615. package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +16 -14
  616. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +6 -3
  617. package/src/modules/planner/components/AvailabilityRuleSetForm.tsx +3 -0
  618. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +58 -15
  619. package/src/modules/planner/components/AvailabilitySchedule.tsx +22 -7
  620. package/src/modules/progress/api/jobs/[id]/route.ts +7 -0
  621. package/src/modules/query_index/lib/engine.ts +34 -0
  622. package/src/modules/resources/backend/resources/resource-types/[id]/edit/page.tsx +7 -1
  623. package/src/modules/resources/backend/resources/resource-types/page.tsx +6 -3
  624. package/src/modules/resources/backend/resources/resources/[id]/page.tsx +23 -3
  625. package/src/modules/resources/backend/resources/resources/page.tsx +15 -4
  626. package/src/modules/resources/components/ResourceCrudForm.tsx +3 -0
  627. package/src/modules/resources/components/ResourceTypeCrudForm.tsx +2 -0
  628. package/src/modules/sales/api/documents/factory.ts +13 -1
  629. package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +6 -0
  630. package/src/modules/sales/backend/sales/channels/offers/page.tsx +10 -4
  631. package/src/modules/sales/backend/sales/channels/page.tsx +19 -4
  632. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +73 -20
  633. package/src/modules/sales/backend/sales/documents/create/page.tsx +2 -0
  634. package/src/modules/sales/commands/documentAddresses.ts +226 -4
  635. package/src/modules/sales/commands/documents.ts +28 -0
  636. package/src/modules/sales/commands/returns.ts +12 -3
  637. package/src/modules/sales/commands/shared.ts +36 -0
  638. package/src/modules/sales/commands/shipments.ts +17 -1
  639. package/src/modules/sales/components/AdjustmentKindSettings.tsx +20 -11
  640. package/src/modules/sales/components/DocumentNumberSettings.tsx +1 -0
  641. package/src/modules/sales/components/OrderEditingSettings.tsx +1 -0
  642. package/src/modules/sales/components/PaymentMethodsSettings.tsx +12 -4
  643. package/src/modules/sales/components/ShippingMethodsSettings.tsx +12 -4
  644. package/src/modules/sales/components/StatusSettings.tsx +20 -11
  645. package/src/modules/sales/components/TaxRatesSettings.tsx +12 -5
  646. package/src/modules/sales/components/channels/ChannelOfferForm.tsx +67 -14
  647. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +7 -4
  648. package/src/modules/sales/components/documents/AddressesSection.tsx +35 -25
  649. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +50 -25
  650. package/src/modules/sales/components/documents/ItemsSection.tsx +24 -13
  651. package/src/modules/sales/components/documents/LineItemDialog.tsx +26 -9
  652. package/src/modules/sales/components/documents/PaymentDialog.tsx +33 -14
  653. package/src/modules/sales/components/documents/PaymentsSection.tsx +22 -10
  654. package/src/modules/sales/components/documents/ReturnDialog.tsx +28 -17
  655. package/src/modules/sales/components/documents/ReturnsSection.tsx +4 -1
  656. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +11 -4
  657. package/src/modules/sales/components/documents/ShipmentDialog.tsx +23 -8
  658. package/src/modules/sales/components/documents/ShipmentsSection.tsx +20 -10
  659. package/src/modules/sales/components/documents/optimisticLock.ts +34 -0
  660. package/src/modules/sales/components/documents/shipmentTypes.ts +1 -0
  661. package/src/modules/sales/di.ts +35 -0
  662. package/src/modules/sales/i18n/de.json +3 -0
  663. package/src/modules/sales/i18n/en.json +3 -0
  664. package/src/modules/sales/i18n/es.json +3 -0
  665. package/src/modules/sales/i18n/pl.json +3 -0
  666. package/src/modules/shipping_carriers/api/cancel/route.ts +2 -2
  667. package/src/modules/shipping_carriers/lib/status-sync.ts +19 -0
  668. package/src/modules/staff/api/job-histories.ts +12 -2
  669. package/src/modules/staff/api/timesheets/time-entries/route.ts +16 -4
  670. package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +12 -7
  671. package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +2 -0
  672. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +16 -5
  673. package/src/modules/staff/backend/staff/team-members/page.tsx +6 -2
  674. package/src/modules/staff/backend/staff/team-roles/[id]/edit/page.tsx +8 -0
  675. package/src/modules/staff/backend/staff/team-roles/page.tsx +6 -2
  676. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +13 -3
  677. package/src/modules/staff/backend/staff/teams/page.tsx +9 -3
  678. package/src/modules/staff/backend/staff/timesheets/page.tsx +10 -1
  679. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +4 -0
  680. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +9 -3
  681. package/src/modules/staff/commands/job-histories.ts +42 -3
  682. package/src/modules/staff/components/LeaveRequestForm.tsx +2 -0
  683. package/src/modules/staff/components/TeamForm.tsx +2 -0
  684. package/src/modules/staff/components/TeamMemberForm.tsx +2 -0
  685. package/src/modules/staff/components/TeamRoleForm.tsx +2 -0
  686. package/src/modules/staff/components/detail/JobHistorySection.tsx +28 -6
  687. package/src/modules/staff/data/validators.ts +6 -0
  688. package/src/modules/staff/i18n/de.json +1 -0
  689. package/src/modules/staff/i18n/en.json +1 -0
  690. package/src/modules/staff/i18n/es.json +1 -0
  691. package/src/modules/staff/i18n/pl.json +1 -0
  692. package/src/modules/staff/lib/leaveRequestHelpers.ts +4 -0
  693. package/src/modules/translations/components/TranslationManager.tsx +13 -8
  694. package/src/modules/workflows/api/definitions/[id]/route.ts +112 -0
  695. package/src/modules/workflows/backend/definitions/[id]/page.tsx +20 -4
  696. package/src/modules/workflows/backend/definitions/page.tsx +20 -9
  697. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +29 -16
  698. package/src/modules/workflows/components/NodeEditDialog.tsx +2 -0
  699. package/src/modules/workflows/components/WorkflowGraphImpl.tsx +3 -1
  700. package/src/modules/workflows/components/formConfig.tsx +5 -0
  701. package/src/modules/workflows/components/nodes/ParallelForkNode.tsx +66 -0
  702. package/src/modules/workflows/components/nodes/ParallelJoinNode.tsx +66 -0
  703. package/src/modules/workflows/components/nodes/index.ts +6 -0
  704. package/src/modules/workflows/data/entities.ts +109 -0
  705. package/src/modules/workflows/data/validators.ts +223 -0
  706. package/src/modules/workflows/di.ts +20 -0
  707. package/src/modules/workflows/events.ts +7 -0
  708. package/src/modules/workflows/i18n/de.json +13 -0
  709. package/src/modules/workflows/i18n/en.json +13 -0
  710. package/src/modules/workflows/i18n/es.json +13 -0
  711. package/src/modules/workflows/i18n/pl.json +13 -0
  712. package/src/modules/workflows/lib/activity-executor.ts +8 -2
  713. package/src/modules/workflows/lib/activity-queue-types.ts +3 -0
  714. package/src/modules/workflows/lib/event-logger.ts +3 -0
  715. package/src/modules/workflows/lib/execution-token.ts +166 -0
  716. package/src/modules/workflows/lib/node-type-icons.ts +11 -2
  717. package/src/modules/workflows/lib/parallel-handler.ts +575 -0
  718. package/src/modules/workflows/lib/signal-handler.ts +72 -1
  719. package/src/modules/workflows/lib/step-handler.ts +94 -34
  720. package/src/modules/workflows/lib/task-handler.ts +32 -0
  721. package/src/modules/workflows/lib/timer-handler.ts +30 -1
  722. package/src/modules/workflows/lib/transition-handler.ts +56 -24
  723. package/src/modules/workflows/lib/workflow-executor.ts +53 -1
  724. package/src/modules/workflows/migrations/.snapshot-open-mercato.json +263 -0
  725. package/src/modules/workflows/migrations/Migration20260602120000.ts +25 -0
  726. package/src/modules/workflows/workers/workflow-activities.worker.ts +9 -4
@@ -1,6 +1,8 @@
1
1
  // @ts-nocheck
2
2
 
3
3
  import { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'
4
+ import { emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'
5
+ import type { DataEngine } from '@open-mercato/shared/lib/data/engine'
4
6
  import type { EntityManager } from '@mikro-orm/postgresql'
5
7
  import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
6
8
  import {
@@ -8,12 +10,123 @@ import {
8
10
  documentAddressDeleteSchema,
9
11
  documentAddressUpdateSchema,
10
12
  type DocumentAddressCreateInput,
13
+ type DocumentAddressDeleteInput,
11
14
  type DocumentAddressUpdateInput,
12
15
  } from '../data/validators'
13
16
  import { SalesDocumentAddress, SalesOrder, SalesQuote } from '../data/entities'
14
- import { ensureOrganizationScope, ensureSameScope, ensureTenantScope, assertFound } from './shared'
17
+ import { ensureOrganizationScope, ensureSameScope, ensureTenantScope, assertFound, extractUndoPayload } from './shared'
15
18
  import { loadSalesSettings } from './settings'
16
19
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
20
+ import { E } from '#generated/entities.ids.generated'
21
+
22
+ const DOCUMENT_ADDRESS_ENTITY_TYPE = E.sales.sales_document_address
23
+
24
+ type DocumentAddressSnapshot = {
25
+ id: string
26
+ organizationId: string
27
+ tenantId: string
28
+ documentId: string
29
+ documentKind: 'order' | 'quote'
30
+ customerAddressId: string | null
31
+ name: string | null
32
+ purpose: string | null
33
+ companyName: string | null
34
+ addressLine1: string
35
+ addressLine2: string | null
36
+ buildingNumber: string | null
37
+ flatNumber: string | null
38
+ city: string | null
39
+ region: string | null
40
+ postalCode: string | null
41
+ country: string | null
42
+ latitude: number | null
43
+ longitude: number | null
44
+ }
45
+
46
+ type DocumentAddressUndoPayload = {
47
+ before?: DocumentAddressSnapshot | null
48
+ after?: DocumentAddressSnapshot | null
49
+ }
50
+
51
+ function snapshotDocumentAddress(entity: SalesDocumentAddress): DocumentAddressSnapshot {
52
+ return {
53
+ id: entity.id,
54
+ organizationId: entity.organizationId,
55
+ tenantId: entity.tenantId,
56
+ documentId: entity.documentId,
57
+ documentKind: entity.documentKind as 'order' | 'quote',
58
+ customerAddressId: entity.customerAddressId ?? null,
59
+ name: entity.name ?? null,
60
+ purpose: entity.purpose ?? null,
61
+ companyName: entity.companyName ?? null,
62
+ addressLine1: entity.addressLine1,
63
+ addressLine2: entity.addressLine2 ?? null,
64
+ buildingNumber: entity.buildingNumber ?? null,
65
+ flatNumber: entity.flatNumber ?? null,
66
+ city: entity.city ?? null,
67
+ region: entity.region ?? null,
68
+ postalCode: entity.postalCode ?? null,
69
+ country: entity.country ?? null,
70
+ latitude: entity.latitude ?? null,
71
+ longitude: entity.longitude ?? null,
72
+ }
73
+ }
74
+
75
+ async function loadDocumentAddressSnapshot(
76
+ em: EntityManager,
77
+ id: string
78
+ ): Promise<DocumentAddressSnapshot | null> {
79
+ const entity = await em.findOne(SalesDocumentAddress, { id })
80
+ return entity ? snapshotDocumentAddress(entity) : null
81
+ }
82
+
83
+ function applyDocumentAddressSnapshot(em: EntityManager, entity: SalesDocumentAddress, snapshot: DocumentAddressSnapshot): void {
84
+ entity.organizationId = snapshot.organizationId
85
+ entity.tenantId = snapshot.tenantId
86
+ entity.documentId = snapshot.documentId
87
+ entity.documentKind = snapshot.documentKind
88
+ entity.customerAddressId = snapshot.customerAddressId
89
+ entity.name = snapshot.name
90
+ entity.purpose = snapshot.purpose
91
+ entity.companyName = snapshot.companyName
92
+ entity.addressLine1 = snapshot.addressLine1
93
+ entity.addressLine2 = snapshot.addressLine2
94
+ entity.buildingNumber = snapshot.buildingNumber
95
+ entity.flatNumber = snapshot.flatNumber
96
+ entity.city = snapshot.city
97
+ entity.region = snapshot.region
98
+ entity.postalCode = snapshot.postalCode
99
+ entity.country = snapshot.country
100
+ entity.latitude = snapshot.latitude
101
+ entity.longitude = snapshot.longitude
102
+ entity.order = snapshot.documentKind === 'order' ? em.getReference(SalesOrder, snapshot.documentId) : null
103
+ entity.quote = snapshot.documentKind === 'quote' ? em.getReference(SalesQuote, snapshot.documentId) : null
104
+ }
105
+
106
+ async function emitDocumentAddressIndexSideEffects(
107
+ ctx: { container: { resolve: (name: string) => unknown } },
108
+ action: 'created' | 'updated' | 'deleted',
109
+ snapshot: DocumentAddressSnapshot
110
+ ): Promise<void> {
111
+ let dataEngine: DataEngine | null = null
112
+ try {
113
+ dataEngine = ctx.container.resolve('dataEngine') as DataEngine
114
+ } catch {
115
+ dataEngine = null
116
+ }
117
+ if (!dataEngine) return
118
+ await emitCrudSideEffects({
119
+ dataEngine,
120
+ action,
121
+ entity: snapshot,
122
+ identifiers: {
123
+ id: snapshot.id,
124
+ organizationId: snapshot.organizationId,
125
+ tenantId: snapshot.tenantId,
126
+ },
127
+ indexer: { entityType: DOCUMENT_ADDRESS_ENTITY_TYPE },
128
+ })
129
+ }
17
130
 
18
131
  async function requireDocument(
19
132
  em: EntityManager,
@@ -90,10 +203,48 @@ const createDocumentAddress: CommandHandler<DocumentAddressCreateInput, { id: st
90
203
  await em.persist(entity).flush()
91
204
  return { id: entity.id }
92
205
  },
206
+ captureAfter: async (_input, result, ctx) => {
207
+ const em = (ctx.container.resolve('em') as EntityManager).fork()
208
+ return result?.id ? loadDocumentAddressSnapshot(em, result.id) : null
209
+ },
210
+ buildLog: async ({ result, snapshots }) => {
211
+ const after = snapshots.after as DocumentAddressSnapshot | undefined
212
+ if (!after) return null
213
+ const { translate } = await resolveTranslations()
214
+ return {
215
+ actionLabel: translate('sales.audit.document_addresses.create', 'Add document address'),
216
+ resourceKind: 'sales.document_address',
217
+ resourceId: result.id,
218
+ parentResourceKind: after.documentKind === 'order' ? 'sales.order' : 'sales.quote',
219
+ parentResourceId: after.documentId,
220
+ tenantId: after.tenantId,
221
+ organizationId: after.organizationId,
222
+ snapshotAfter: after,
223
+ payload: { undo: { after } satisfies DocumentAddressUndoPayload },
224
+ }
225
+ },
226
+ undo: async ({ logEntry, ctx }) => {
227
+ const payload = extractUndoPayload<DocumentAddressUndoPayload>(logEntry)
228
+ const after = payload?.after
229
+ if (!after) return
230
+ ensureTenantScope(ctx, after.tenantId)
231
+ ensureOrganizationScope(ctx, after.organizationId)
232
+ const em = (ctx.container.resolve('em') as EntityManager).fork()
233
+ const entity = await em.findOne(SalesDocumentAddress, { id: after.id })
234
+ if (!entity) return
235
+ await em.remove(entity).flush()
236
+ await emitDocumentAddressIndexSideEffects(ctx, 'deleted', after)
237
+ },
93
238
  }
94
239
 
95
240
  const updateDocumentAddress: CommandHandler<DocumentAddressUpdateInput, { id: string }> = {
96
241
  id: 'sales.document-addresses.update',
242
+ async prepare(rawInput, ctx) {
243
+ const parsed = documentAddressUpdateSchema.parse(rawInput)
244
+ const em = ctx.container.resolve('em') as EntityManager
245
+ const snapshot = await loadDocumentAddressSnapshot(em, parsed.id)
246
+ return snapshot ? { before: snapshot } : {}
247
+ },
97
248
  async execute(rawInput, ctx) {
98
249
  const input = documentAddressUpdateSchema.parse(rawInput)
99
250
  ensureTenantScope(ctx, input.tenantId)
@@ -133,13 +284,55 @@ const updateDocumentAddress: CommandHandler<DocumentAddressUpdateInput, { id: st
133
284
  await em.flush()
134
285
  return { id: entity.id }
135
286
  },
287
+ captureAfter: async (_input, result, ctx) => {
288
+ const em = (ctx.container.resolve('em') as EntityManager).fork()
289
+ return result?.id ? loadDocumentAddressSnapshot(em, result.id) : null
290
+ },
291
+ buildLog: async ({ result, snapshots }) => {
292
+ const before = snapshots.before as DocumentAddressSnapshot | undefined
293
+ const after = snapshots.after as DocumentAddressSnapshot | undefined
294
+ if (!after) return null
295
+ const { translate } = await resolveTranslations()
296
+ return {
297
+ actionLabel: translate('sales.audit.document_addresses.update', 'Update document address'),
298
+ resourceKind: 'sales.document_address',
299
+ resourceId: result.id,
300
+ parentResourceKind: after.documentKind === 'order' ? 'sales.order' : 'sales.quote',
301
+ parentResourceId: after.documentId,
302
+ tenantId: after.tenantId,
303
+ organizationId: after.organizationId,
304
+ snapshotBefore: before ?? null,
305
+ snapshotAfter: after,
306
+ payload: { undo: { before: before ?? null, after } satisfies DocumentAddressUndoPayload },
307
+ }
308
+ },
309
+ undo: async ({ logEntry, ctx }) => {
310
+ const payload = extractUndoPayload<DocumentAddressUndoPayload>(logEntry)
311
+ const before = payload?.before
312
+ if (!before) return
313
+ ensureTenantScope(ctx, before.tenantId)
314
+ ensureOrganizationScope(ctx, before.organizationId)
315
+ const em = (ctx.container.resolve('em') as EntityManager).fork()
316
+ const entity =
317
+ (await em.findOne(SalesDocumentAddress, { id: before.id })) ??
318
+ em.create(SalesDocumentAddress, { id: before.id } as Partial<SalesDocumentAddress>)
319
+ applyDocumentAddressSnapshot(em, entity, before)
320
+ await em.persist(entity).flush()
321
+ await emitDocumentAddressIndexSideEffects(ctx, 'updated', before)
322
+ },
136
323
  }
137
324
 
138
325
  const deleteDocumentAddress: CommandHandler<
139
- { id: string; documentId: string; documentKind: 'order' | 'quote'; organizationId: string; tenantId: string },
140
- { ok: true }
326
+ DocumentAddressDeleteInput,
327
+ { ok: true; id: string }
141
328
  > = {
142
329
  id: 'sales.document-addresses.delete',
330
+ async prepare(rawInput, ctx) {
331
+ const parsed = documentAddressDeleteSchema.parse(rawInput)
332
+ const em = ctx.container.resolve('em') as EntityManager
333
+ const snapshot = await loadDocumentAddressSnapshot(em, parsed.id)
334
+ return snapshot ? { before: snapshot } : {}
335
+ },
143
336
  async execute(rawInput, ctx) {
144
337
  const input = documentAddressDeleteSchema.parse(rawInput)
145
338
  ensureTenantScope(ctx, input.tenantId)
@@ -159,7 +352,36 @@ const deleteDocumentAddress: CommandHandler<
159
352
  })
160
353
  }
161
354
  await em.remove(entity).flush()
162
- return { ok: true }
355
+ return { ok: true, id: input.id }
356
+ },
357
+ buildLog: async ({ result, snapshots }) => {
358
+ const before = snapshots.before as DocumentAddressSnapshot | undefined
359
+ if (!before) return null
360
+ const { translate } = await resolveTranslations()
361
+ return {
362
+ actionLabel: translate('sales.audit.document_addresses.delete', 'Remove document address'),
363
+ resourceKind: 'sales.document_address',
364
+ resourceId: result.id,
365
+ parentResourceKind: before.documentKind === 'order' ? 'sales.order' : 'sales.quote',
366
+ parentResourceId: before.documentId,
367
+ tenantId: before.tenantId,
368
+ organizationId: before.organizationId,
369
+ snapshotBefore: before,
370
+ payload: { undo: { before } satisfies DocumentAddressUndoPayload },
371
+ }
372
+ },
373
+ undo: async ({ logEntry, ctx }) => {
374
+ const payload = extractUndoPayload<DocumentAddressUndoPayload>(logEntry)
375
+ const before = payload?.before
376
+ if (!before) return
377
+ ensureTenantScope(ctx, before.tenantId)
378
+ ensureOrganizationScope(ctx, before.organizationId)
379
+ const em = (ctx.container.resolve('em') as EntityManager).fork()
380
+ const existing = await em.findOne(SalesDocumentAddress, { id: before.id })
381
+ const entity = existing ?? em.create(SalesDocumentAddress, { id: before.id } as Partial<SalesDocumentAddress>)
382
+ applyDocumentAddressSnapshot(em, entity, before)
383
+ await em.persist(entity).flush()
384
+ await emitDocumentAddressIndexSideEffects(ctx, 'created', before)
163
385
  },
164
386
  }
165
387
 
@@ -96,6 +96,9 @@ import {
96
96
  ensureTenantScope,
97
97
  extractUndoPayload,
98
98
  toNumericString,
99
+ enforceSalesDocumentOptimisticLock,
100
+ SALES_RESOURCE_KIND_ORDER,
101
+ SALES_RESOURCE_KIND_QUOTE,
99
102
  } from "./shared";
100
103
  import {
101
104
  loadShipmentSnapshot,
@@ -4935,6 +4938,7 @@ const updateQuoteCommand: CommandHandler<
4935
4938
  if (!quote)
4936
4939
  throw new CrudHttpError(404, { error: "Sales quote not found" });
4937
4940
  ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
4941
+ enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
4938
4942
  const shouldInvalidateSentToken = (quote.status ?? null) === "sent";
4939
4943
  if (shouldInvalidateSentToken) {
4940
4944
  quote.acceptanceToken = null;
@@ -4970,6 +4974,13 @@ const updateQuoteCommand: CommandHandler<
4970
4974
  value: "draft",
4971
4975
  });
4972
4976
  }
4977
+ },
4978
+ // Scalar mutations above are persisted by withAtomicFlush's per-phase
4979
+ // flush boundary before the recalc reads below run any query on the same
4980
+ // EntityManager. MikroORM v7 would otherwise silently discard pending
4981
+ // scalar changes on `quote` when the `em.find` line/adjustment lookups
4982
+ // reset the changeset (see SPEC-018).
4983
+ async () => {
4973
4984
  if (shouldRecalculateTotals) {
4974
4985
  const [existingLines, adjustments] = await Promise.all([
4975
4986
  em.find(
@@ -5183,6 +5194,14 @@ const updateOrderCommand: CommandHandler<
5183
5194
  input: parsed,
5184
5195
  em,
5185
5196
  });
5197
+ },
5198
+ // Scalar mutations above are persisted by withAtomicFlush's per-phase
5199
+ // flush boundary before the recalc reads and the status-change-note
5200
+ // lookup below run any query on the same EntityManager. MikroORM v7 would
5201
+ // otherwise silently discard pending scalar changes on `order` when the
5202
+ // `em.find` lines/adjustments or appendOrderStatusChangeNote queries
5203
+ // reset the changeset (see SPEC-018).
5204
+ async () => {
5186
5205
  if (shouldRecalculateTotals) {
5187
5206
  const [existingLines, adjustments] = await Promise.all([
5188
5207
  em.find(
@@ -5984,6 +6003,7 @@ const convertQuoteToOrderCommand: CommandHandler<
5984
6003
  ),
5985
6004
  });
5986
6005
  ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
6006
+ enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
5987
6007
  const snapshot = await loadQuoteSnapshot(em, payload.quoteId);
5988
6008
  if (!snapshot)
5989
6009
  throw new CrudHttpError(404, {
@@ -6453,6 +6473,7 @@ const orderLineUpsertCommand: CommandHandler<
6453
6473
  if (!order)
6454
6474
  throw new CrudHttpError(404, { error: "Sales order not found" });
6455
6475
  ensureOrderScope(ctx, order.organizationId, order.tenantId);
6476
+ enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
6456
6477
 
6457
6478
  const [existingLines, adjustments] = await Promise.all([
6458
6479
  em.find(SalesOrderLine, { order }, { orderBy: { lineNumber: "asc" } }),
@@ -6773,6 +6794,7 @@ const orderLineDeleteCommand: CommandHandler<
6773
6794
  ),
6774
6795
  });
6775
6796
  ensureOrderScope(ctx, order.organizationId, order.tenantId);
6797
+ enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
6776
6798
  const shipmentCount = await em.count(SalesShipmentItem, {
6777
6799
  orderLine: parsed.id,
6778
6800
  shipment: { deletedAt: null },
@@ -6943,6 +6965,7 @@ const quoteLineUpsertCommand: CommandHandler<
6943
6965
  if (!quote)
6944
6966
  throw new CrudHttpError(404, { error: "Sales quote not found" });
6945
6967
  ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
6968
+ enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
6946
6969
  const [existingLines, adjustments] = await Promise.all([
6947
6970
  em.find(SalesQuoteLine, { quote }, { orderBy: { lineNumber: "asc" } }),
6948
6971
  em.find(
@@ -7254,6 +7277,7 @@ const quoteLineDeleteCommand: CommandHandler<
7254
7277
  if (!quote)
7255
7278
  throw new CrudHttpError(404, { error: "Sales quote not found" });
7256
7279
  ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
7280
+ enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
7257
7281
  const existingLines = await em.find(
7258
7282
  SalesQuoteLine,
7259
7283
  { quote },
@@ -7407,6 +7431,7 @@ const orderAdjustmentUpsertCommand: CommandHandler<
7407
7431
  if (!order)
7408
7432
  throw new CrudHttpError(404, { error: "Sales order not found" });
7409
7433
  ensureOrderScope(ctx, order.organizationId, order.tenantId);
7434
+ enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
7410
7435
  if (parsed.scope === "line") {
7411
7436
  throw new CrudHttpError(400, {
7412
7437
  error: "Line-scoped adjustments are not supported yet.",
@@ -7700,6 +7725,7 @@ const orderAdjustmentDeleteCommand: CommandHandler<
7700
7725
  if (!order)
7701
7726
  throw new CrudHttpError(404, { error: "Sales order not found" });
7702
7727
  ensureOrderScope(ctx, order.organizationId, order.tenantId);
7728
+ enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
7703
7729
 
7704
7730
  const [existingLines, adjustments] = await Promise.all([
7705
7731
  em.find(SalesOrderLine, { order }, { orderBy: { lineNumber: "asc" } }),
@@ -7864,6 +7890,7 @@ const quoteAdjustmentUpsertCommand: CommandHandler<
7864
7890
  if (!quote)
7865
7891
  throw new CrudHttpError(404, { error: "Sales quote not found" });
7866
7892
  ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
7893
+ enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
7867
7894
  if (parsed.scope === "line") {
7868
7895
  throw new CrudHttpError(400, {
7869
7896
  error: "Line-scoped adjustments are not supported yet.",
@@ -8155,6 +8182,7 @@ const quoteAdjustmentDeleteCommand: CommandHandler<
8155
8182
  if (!quote)
8156
8183
  throw new CrudHttpError(404, { error: "Sales quote not found" });
8157
8184
  ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
8185
+ enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
8158
8186
 
8159
8187
  const [existingLines, adjustments] = await Promise.all([
8160
8188
  em.find(SalesQuoteLine, { quote }, { orderBy: { lineNumber: "asc" } }),
@@ -12,7 +12,7 @@ import { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/
12
12
  import { SalesDocumentNumberGenerator } from '../services/salesDocumentNumberGenerator'
13
13
  import type { SalesCalculationService } from '../services/salesCalculationService'
14
14
  import type { SalesAdjustmentDraft, SalesLineSnapshot, SalesDocumentCalculationResult } from '../lib/types'
15
- import { cloneJson, ensureOrganizationScope, ensureSameScope, ensureTenantScope, extractUndoPayload, toNumericString } from './shared'
15
+ import { cloneJson, ensureOrganizationScope, ensureSameScope, ensureTenantScope, extractUndoPayload, toNumericString, enforceSalesDocumentOptimisticLock, SALES_RESOURCE_KIND_ORDER } from './shared'
16
16
  import { SalesOrder, SalesOrderAdjustment, SalesOrderLine, SalesReturn, SalesReturnLine } from '../data/entities'
17
17
  import { returnCreateSchema, type ReturnCreateInput } from '../data/validators'
18
18
  import { E } from '#generated/entities.ids.generated'
@@ -286,6 +286,7 @@ const createReturnCommand: CommandHandler<ReturnCreateInput, { returnId: string
286
286
  throw new CrudHttpError(404, { error: translate('sales.returns.orderMissing', 'Order not found.') })
287
287
  }
288
288
  ensureSameScope(order, input.organizationId, input.tenantId)
289
+ enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER)
289
290
 
290
291
  const orderLines = await findWithDecryption(
291
292
  tx,
@@ -476,11 +477,12 @@ const createReturnCommand: CommandHandler<ReturnCreateInput, { returnId: string
476
477
  // Line reversals, adjustment/return removals, and the order-total recompute
477
478
  // interleave queries on the same EntityManager with scalar mutations, so they
478
479
  // must run inside an atomic flush to avoid lost updates and partial commits.
480
+ let lines: SalesOrderLine[] = []
479
481
  await withAtomicFlush(
480
482
  em,
481
483
  [
482
484
  async () => {
483
- const lines = await findWithDecryption(
485
+ lines = await findWithDecryption(
484
486
  em,
485
487
  SalesOrderLine,
486
488
  { order: order.id, deletedAt: null },
@@ -496,7 +498,14 @@ const createReturnCommand: CommandHandler<ReturnCreateInput, { returnId: string
496
498
  line.updatedAt = new Date()
497
499
  em.persist(line)
498
500
  })
499
-
501
+ },
502
+ // The line returnedQuantity reversals above are persisted by
503
+ // withAtomicFlush's per-phase flush boundary before the adjustment /
504
+ // header / return-line lookups below run any query on this
505
+ // EntityManager. MikroORM v7 would otherwise silently discard the pending
506
+ // scalar changes on the managed `lines` when the next read resets the
507
+ // changeset (see SPEC-018).
508
+ async () => {
500
509
  if (after.adjustmentIds.length) {
501
510
  const adjustments = await findWithDecryption(
502
511
  em,
@@ -2,10 +2,46 @@ import type { EntityManager } from '@mikro-orm/postgresql'
2
2
  import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
3
3
  import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
4
4
  import type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
5
+ import { enforceCommandOptimisticLock } from '@open-mercato/shared/lib/crud/optimistic-lock-command'
5
6
  export { assertFound } from '@open-mercato/shared/lib/crud/errors'
6
7
  export { ensureOrganizationScope, ensureSameScope, ensureTenantScope } from '@open-mercato/shared/lib/commands/scope'
7
8
  export { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'
8
9
 
10
+ /** Resource kinds used by the document-aggregate optimistic-lock check. */
11
+ export const SALES_RESOURCE_KIND_ORDER = 'sales.order'
12
+ export const SALES_RESOURCE_KIND_QUOTE = 'sales.quote'
13
+
14
+ /**
15
+ * Enforce the document-aggregate OSS optimistic lock for a sales sub-resource
16
+ * command (lines, adjustments, shipments, payments, returns, quote
17
+ * conversion). The client sends the parent order/quote's expected `updated_at`
18
+ * via the optimistic-lock extension header; this compares it against the
19
+ * already-loaded document and throws the structured 409 on mismatch.
20
+ *
21
+ * The parent document is the consistency boundary: sub-resource mutations
22
+ * recalculate document totals (or transition the document), which dirties the
23
+ * parent so its `updated_at` advances on flush — meaning concurrent sub-edits
24
+ * observe each other and conflict. Call this AFTER loading + scope-checking the
25
+ * document and BEFORE mutating, so `document.updatedAt` is the pre-mutation
26
+ * version.
27
+ *
28
+ * Strictly additive: when the client sends no header the check is a no-op, so
29
+ * existing API consumers are unaffected. Respects `OM_OPTIMISTIC_LOCK`.
30
+ */
31
+ export function enforceSalesDocumentOptimisticLock(
32
+ ctx: CommandRuntimeContext,
33
+ document: { id: string; updatedAt?: Date | string | null } | null | undefined,
34
+ resourceKind: string,
35
+ ): void {
36
+ if (!document) return
37
+ enforceCommandOptimisticLock({
38
+ resourceKind,
39
+ resourceId: document.id,
40
+ current: document.updatedAt ?? null,
41
+ request: ctx.request ?? null,
42
+ })
43
+ }
44
+
9
45
  export function cloneJson<T>(value: T): T {
10
46
  if (value === null || value === undefined) return value
11
47
  return JSON.parse(JSON.stringify(value)) as T
@@ -657,11 +657,17 @@ const updateShipmentCommand: CommandHandler<ShipmentUpdateInput, { shipmentId: s
657
657
  : null
658
658
  const normalizedItems = validatedItems?.items ?? null
659
659
  const lineMap = validatedItems?.lineMap ?? new Map<string, SalesOrderLine>()
660
+ // Resolve the status label BEFORE mutating shipment scalars so this
661
+ // dictionary read does not interleave with (and drop) the pending
662
+ // shipment changeset under MikroORM v7 (SPEC-018 / #2453 class).
663
+ const resolvedShipmentStatus = input.statusEntryId !== undefined
664
+ ? await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null)
665
+ : undefined
660
666
  if (input.shipmentNumber !== undefined) shipmentEntity.shipmentNumber = input.shipmentNumber ?? null
661
667
  if (input.shippingMethodId !== undefined) shipmentEntity.shippingMethodId = input.shippingMethodId ?? null
662
668
  if (input.statusEntryId !== undefined) {
663
669
  shipmentEntity.statusEntryId = input.statusEntryId ?? null
664
- shipmentEntity.status = await resolveDictionaryEntryValue(tx, input.statusEntryId ?? null)
670
+ shipmentEntity.status = resolvedShipmentStatus ?? null
665
671
  }
666
672
  if (input.carrierName !== undefined) shipmentEntity.carrierName = input.carrierName ?? null
667
673
  if (input.trackingNumbers !== undefined) shipmentEntity.trackingNumbers = parseTrackingNumbers(input.trackingNumbers)
@@ -685,6 +691,13 @@ const updateShipmentCommand: CommandHandler<ShipmentUpdateInput, { shipmentId: s
685
691
  }
686
692
  shipmentEntity.updatedAt = new Date()
687
693
 
694
+ // Persist the shipment scalar mutations before the item reads below run on
695
+ // the same EntityManager. Under MikroORM v7 an interleaved query (the
696
+ // findWithDecryption on SalesShipmentItem here and in the snapshot step)
697
+ // resets the identity-map changeset, so shippingMethodId/status/carrier/etc.
698
+ // would silently not persist even though the write returns 200 (#2453).
699
+ await tx.flush()
700
+
688
701
  const shouldLoadItems = Boolean(normalizedItems || input.lineStatusEntryId !== undefined)
689
702
  const existingItems = shouldLoadItems ? await findWithDecryption(tx, SalesShipmentItem, { shipment: shipmentEntity }, {}, { tenantId: shipmentEntity.tenantId, organizationId: shipmentEntity.organizationId }) : []
690
703
  const newItems: SalesShipmentItem[] = []
@@ -758,6 +771,9 @@ const updateShipmentCommand: CommandHandler<ShipmentUpdateInput, { shipmentId: s
758
771
  }
759
772
  }
760
773
 
774
+ // Flush any order/line status mutations applied above before the snapshot
775
+ // read below queries the same EntityManager (same interleaved-read hazard).
776
+ await tx.flush()
761
777
  const itemsForSnapshot =
762
778
  normalizedItems || shouldLoadItems
763
779
  ? (normalizedItems ? newItems : existingItems)
@@ -16,7 +16,8 @@ import {
16
16
  import { Input } from '@open-mercato/ui/primitives/input'
17
17
  import { Label } from '@open-mercato/ui/primitives/label'
18
18
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
19
- import { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
19
+ import { apiCall, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
20
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
20
21
  import { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'
21
22
  import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
22
23
  import { AppearanceSelector } from '@open-mercato/core/modules/dictionaries/components/AppearanceSelector'
@@ -219,11 +220,15 @@ export function AdjustmentKindSettings() {
219
220
  ? JSON.stringify(payload)
220
221
  : JSON.stringify({ id: dialog.entry.id, ...payload })
221
222
 
222
- const call = await apiCall('/api/sales/adjustment-kinds', {
223
- method,
224
- headers: { 'content-type': 'application/json' },
225
- body,
226
- })
223
+ const lockHeader =
224
+ dialog.mode === 'edit' ? buildOptimisticLockHeader(dialog.entry.updatedAt) : {}
225
+ const call = await withScopedApiRequestHeaders(lockHeader, () =>
226
+ apiCall('/api/sales/adjustment-kinds', {
227
+ method,
228
+ headers: { 'content-type': 'application/json' },
229
+ body,
230
+ })
231
+ )
227
232
  if (!call.ok) {
228
233
  await raiseCrudError(call.response, labels.saveError)
229
234
  }
@@ -248,11 +253,15 @@ export function AdjustmentKindSettings() {
248
253
  })
249
254
  if (!confirmed) return
250
255
  try {
251
- const call = await apiCall('/api/sales/adjustment-kinds', {
252
- method: 'DELETE',
253
- headers: { 'content-type': 'application/json' },
254
- body: JSON.stringify({ id: entry.id }),
255
- })
256
+ const call = await withScopedApiRequestHeaders(
257
+ buildOptimisticLockHeader(entry.updatedAt),
258
+ () =>
259
+ apiCall('/api/sales/adjustment-kinds', {
260
+ method: 'DELETE',
261
+ headers: { 'content-type': 'application/json' },
262
+ body: JSON.stringify({ id: entry.id }),
263
+ })
264
+ )
256
265
  if (!call.ok) {
257
266
  await raiseCrudError(call.response, labels.deleteError)
258
267
  }
@@ -128,6 +128,7 @@ export function DocumentNumberSettings() {
128
128
  orderNextNumber: Number.parseInt(formState.orderNextNumber, 10) || undefined,
129
129
  quoteNextNumber: Number.parseInt(formState.quoteNextNumber, 10) || undefined,
130
130
  }
131
+ // optimistic-lock-exempt: single-row tenant numbering settings blob — no per-record version / concurrent record edit
131
132
  const call = await apiCall<SettingsResponse>('/api/sales/settings/document-numbers', {
132
133
  method: 'PUT',
133
134
  headers: { 'content-type': 'application/json' },
@@ -121,6 +121,7 @@ export function OrderEditingSettings() {
121
121
  orderCustomerEditableStatuses: customerStatuses,
122
122
  orderAddressEditableStatuses: addressStatuses,
123
123
  }
124
+ // optimistic-lock-exempt: single-row tenant order-editing settings blob — no per-record version / concurrent record edit
124
125
  const call = await apiCall<SettingsResponse>('/api/sales/settings/order-editing', {
125
126
  method: 'PUT',
126
127
  headers: { 'content-type': 'application/json' },
@@ -15,7 +15,9 @@ import {
15
15
  import { Label } from '@open-mercato/ui/primitives/label'
16
16
  import { CrudForm, type CrudField, type CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'
17
17
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
18
- import { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
18
+ import { apiCall, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
19
+ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
20
+ import { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'
19
21
  import { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'
20
22
  import { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
21
23
  import { useT } from '@open-mercato/shared/lib/i18n/context'
@@ -291,12 +293,14 @@ export function PaymentMethodsSettings() {
291
293
  })
292
294
  if (!confirmed) return
293
295
  try {
294
- const call = await apiCall('/api/sales/payment-methods', {
296
+ const headers = buildOptimisticLockHeader(entry.updatedAt)
297
+ const call = await withScopedApiRequestHeaders(headers, () => apiCall('/api/sales/payment-methods', {
295
298
  method: 'DELETE',
296
299
  headers: { 'content-type': 'application/json' },
297
300
  body: JSON.stringify({ id: entry.id }),
298
- })
301
+ }))
299
302
  if (!call.ok) {
303
+ if (surfaceRecordConflict({ status: call.status, body: call.result }, t)) return
300
304
  await raiseCrudError(call.response, translations.errors.delete)
301
305
  }
302
306
  flash(translations.messages.deleted, 'success')
@@ -325,12 +329,15 @@ export function PaymentMethodsSettings() {
325
329
  const method = dialog.mode === 'create' ? 'POST' : 'PUT'
326
330
  if (dialog.mode === 'edit') payload.id = dialog.entry.id
327
331
  try {
328
- const call = await apiCall(path, {
332
+ const savePaymentMethod = () => apiCall(path, {
329
333
  method,
330
334
  headers: { 'content-type': 'application/json' },
331
335
  body: JSON.stringify(payload),
332
336
  })
337
+ const headers = buildOptimisticLockHeader(dialog.mode === 'edit' ? dialog.entry.updatedAt : null)
338
+ const call = await withScopedApiRequestHeaders(headers, savePaymentMethod)
333
339
  if (!call.ok) {
340
+ if (surfaceRecordConflict({ status: call.status, body: call.result }, t)) return
334
341
  await raiseCrudError(call.response, translations.errors.save)
335
342
  }
336
343
  flash(translations.messages.saved, 'success')
@@ -466,6 +473,7 @@ export function PaymentMethodsSettings() {
466
473
  schema={paymentFormSchema}
467
474
  fields={fields}
468
475
  initialValues={formValues}
476
+ optimisticLockUpdatedAt={dialog?.mode === 'edit' ? dialog.entry.updatedAt : null}
469
477
  submitLabel={translations.form.save}
470
478
  onSubmit={handleSubmit}
471
479
  cancelHref={undefined}