@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.
- package/.turbo/turbo-build.log +1 -1
- package/AGENTS.md +5 -0
- package/dist/generated/entities/role/index.js +3 -1
- package/dist/generated/entities/role/index.js.map +2 -2
- package/dist/generated/entities/user/index.js +3 -1
- package/dist/generated/entities/user/index.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
- package/dist/helpers/integration/dbFixtures.js +2 -1
- package/dist/helpers/integration/dbFixtures.js.map +2 -2
- package/dist/helpers/integration/optimisticLockUi.js +104 -0
- package/dist/helpers/integration/optimisticLockUi.js.map +7 -0
- package/dist/helpers/integration/salesFixtures.js +17 -0
- package/dist/helpers/integration/salesFixtures.js.map +2 -2
- package/dist/modules/api_keys/backend/api-keys/page.js +9 -5
- package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js +17 -9
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
- package/dist/modules/auth/api/roles/acl/route.js +32 -13
- package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
- package/dist/modules/auth/api/roles/route.js +3 -1
- package/dist/modules/auth/api/roles/route.js.map +2 -2
- package/dist/modules/auth/api/sidebar/preferences/route.js +71 -3
- package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
- package/dist/modules/auth/api/users/acl/route.js +42 -19
- package/dist/modules/auth/api/users/acl/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +3 -1
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/roles/[id]/edit/page.js +24 -4
- package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/roles/page.js +8 -4
- package/dist/modules/auth/backend/roles/page.js.map +2 -2
- package/dist/modules/auth/backend/users/[id]/edit/page.js +27 -5
- package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/users/page.js +6 -2
- package/dist/modules/auth/backend/users/page.js.map +2 -2
- package/dist/modules/auth/components/AclEditor.js +3 -1
- package/dist/modules/auth/components/AclEditor.js.map +2 -2
- package/dist/modules/auth/data/entities.js +6 -0
- package/dist/modules/auth/data/entities.js.map +2 -2
- package/dist/modules/auth/services/sidebarPreferencesService.js +32 -4
- package/dist/modules/auth/services/sidebarPreferencesService.js.map +2 -2
- package/dist/modules/business_rules/api/rules/route.js +28 -0
- package/dist/modules/business_rules/api/rules/route.js.map +2 -2
- package/dist/modules/business_rules/api/sets/route.js +28 -0
- package/dist/modules/business_rules/api/sets/route.js.map +2 -2
- package/dist/modules/business_rules/backend/rules/[id]/page.js +11 -4
- package/dist/modules/business_rules/backend/rules/[id]/page.js.map +3 -3
- package/dist/modules/business_rules/backend/rules/page.js +20 -11
- package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
- package/dist/modules/business_rules/backend/sets/[id]/page.js +11 -4
- package/dist/modules/business_rules/backend/sets/[id]/page.js.map +2 -2
- package/dist/modules/business_rules/backend/sets/page.js +20 -11
- package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
- package/dist/modules/catalog/api/categories/route.js +2 -0
- package/dist/modules/catalog/api/categories/route.js.map +2 -2
- package/dist/modules/catalog/api/products/route.js +2 -1
- package/dist/modules/catalog/api/products/route.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js +2 -0
- package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +94 -40
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +37 -8
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/optionSchemaClient.js.map +2 -2
- package/dist/modules/catalog/commands/variants.js +32 -31
- package/dist/modules/catalog/commands/variants.js.map +2 -2
- package/dist/modules/catalog/components/PriceKindSettings.js +12 -5
- package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductMediaManager.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js +5 -3
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/productForm.js.map +2 -2
- package/dist/modules/catalog/components/products/variantForm.js +2 -1
- package/dist/modules/catalog/components/products/variantForm.js.map +2 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js +23 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +5 -0
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
- package/dist/modules/communication_channels/commands/set-primary-channel.js +2 -1
- package/dist/modules/communication_channels/commands/set-primary-channel.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/[id]/page.js +6 -3
- package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +18 -11
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/[id]/page.js +1 -0
- package/dist/modules/currencies/backend/exchange-rates/[id]/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +10 -6
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/currencies/commands/currencies.js +7 -5
- package/dist/modules/currencies/commands/currencies.js.map +2 -2
- package/dist/modules/currencies/components/CurrencyFetchingConfig.js +26 -19
- package/dist/modules/currencies/components/CurrencyFetchingConfig.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/roles/[id].js +28 -5
- package/dist/modules/customer_accounts/api/admin/roles/[id].js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/roles.js +4 -2
- package/dist/modules/customer_accounts/api/admin/roles.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/users/[id].js +28 -5
- package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/users.js +2 -0
- package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +16 -8
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +8 -4
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js +8 -4
- package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +29 -18
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +18 -11
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
- package/dist/modules/customers/api/companies/route.js +13 -2
- package/dist/modules/customers/api/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/route.js +2 -0
- package/dist/modules/customers/api/deals/route.js.map +2 -2
- package/dist/modules/customers/api/people/route.js +11 -2
- package/dist/modules/customers/api/people/route.js.map +2 -2
- package/dist/modules/customers/api/todos/route.js +1 -0
- package/dist/modules/customers/api/todos/route.js.map +2 -2
- package/dist/modules/customers/backend/config/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +34 -21
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/[id]/page.js +45 -27
- package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +22 -5
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js +30 -8
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +1 -0
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +16 -6
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js +62 -39
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/[id]/page.js +41 -26
- package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +50 -23
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/commands/addresses.js +16 -14
- package/dist/modules/customers/commands/addresses.js.map +2 -2
- package/dist/modules/customers/commands/companies.js +1 -1
- package/dist/modules/customers/commands/companies.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js +41 -4
- package/dist/modules/customers/commands/interactions.js.map +2 -2
- package/dist/modules/customers/commands/people.js +1 -1
- package/dist/modules/customers/commands/people.js.map +2 -2
- package/dist/modules/customers/commands/personCompanyLinks.js +8 -5
- package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
- package/dist/modules/customers/commands/pipeline-stages.js +13 -11
- package/dist/modules/customers/commands/pipeline-stages.js.map +3 -3
- package/dist/modules/customers/components/AddressFormatSettings.js.map +2 -2
- package/dist/modules/customers/components/DictionarySettings.js +20 -13
- package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
- package/dist/modules/customers/components/DictionarySortSettings.js +4 -0
- package/dist/modules/customers/components/DictionarySortSettings.js.map +2 -2
- package/dist/modules/customers/components/PipelineSettings.js +38 -23
- package/dist/modules/customers/components/PipelineSettings.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityTimeline.js +1 -1
- package/dist/modules/customers/components/detail/ActivityTimeline.js.map +2 -2
- package/dist/modules/customers/components/detail/AddressesSection.js +4 -0
- package/dist/modules/customers/components/detail/AddressesSection.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js +28 -22
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
- package/dist/modules/customers/components/detail/DealsSection.js +36 -24
- package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
- package/dist/modules/customers/components/detail/EmailCardActions.js +5 -0
- package/dist/modules/customers/components/detail/EmailCardActions.js.map +2 -2
- package/dist/modules/customers/components/detail/EntityTagsDialog.js +7 -0
- package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/ManageTagsDialog.js +34 -22
- package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js +41 -29
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
- package/dist/modules/customers/components/detail/RoleAssignmentRow.js +14 -8
- package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +2 -2
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +14 -6
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +29 -13
- package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +2 -2
- package/dist/modules/customers/components/detail/hooks/useInteractions.js +77 -35
- package/dist/modules/customers/components/detail/hooks/useInteractions.js.map +2 -2
- package/dist/modules/customers/components/detail/hooks/usePersonTasks.js +25 -17
- package/dist/modules/customers/components/detail/hooks/usePersonTasks.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
- package/dist/modules/customers/components/formConfig.js.map +2 -2
- package/dist/modules/customers/data/guards.js +66 -0
- package/dist/modules/customers/data/guards.js.map +7 -0
- package/dist/modules/customers/di.js +37 -0
- package/dist/modules/customers/di.js.map +2 -2
- package/dist/modules/customers/lib/todoCompatibility.js +11 -0
- package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
- package/dist/modules/data_sync/api/options.js +4 -4
- package/dist/modules/data_sync/api/options.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/route.js +9 -1
- package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.js +17 -8
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js +43 -22
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-schedule-service.js +9 -0
- package/dist/modules/data_sync/lib/sync-schedule-service.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +8 -1
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/route.js +17 -1
- package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionariesManager.js +31 -10
- package/dist/modules/dictionaries/components/DictionariesManager.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js +28 -15
- package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js.map +2 -2
- package/dist/modules/directory/api/organizations/route.js +3 -0
- package/dist/modules/directory/api/organizations/route.js.map +2 -2
- package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js +2 -0
- package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/organizations/page.js +9 -5
- package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js +7 -3
- package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js +8 -4
- package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
- package/dist/modules/directory/commands/organizations.js +7 -2
- package/dist/modules/directory/commands/organizations.js.map +2 -2
- package/dist/modules/entities/api/records.js +66 -0
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js +1 -0
- package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +8 -4
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- package/dist/modules/entities/lib/helpers.js +17 -0
- package/dist/modules/entities/lib/helpers.js.map +2 -2
- package/dist/modules/feature_toggles/api/global/[id]/override/route.js +2 -1
- package/dist/modules/feature_toggles/api/global/[id]/override/route.js.map +2 -2
- package/dist/modules/feature_toggles/api/overrides/route.js +15 -0
- package/dist/modules/feature_toggles/api/overrides/route.js.map +2 -2
- package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js +15 -14
- package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js.map +2 -2
- package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js +20 -12
- package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js.map +2 -2
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +6 -2
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
- package/dist/modules/feature_toggles/components/formConfig.js +2 -1
- package/dist/modules/feature_toggles/components/formConfig.js.map +2 -2
- package/dist/modules/feature_toggles/components/overrideFormConfig.js +5 -1
- package/dist/modules/feature_toggles/components/overrideFormConfig.js.map +2 -2
- package/dist/modules/feature_toggles/data/validators.js +7 -4
- package/dist/modules/feature_toggles/data/validators.js.map +2 -2
- package/dist/modules/inbox_ops/api/settings/route.js +17 -2
- package/dist/modules/inbox_ops/api/settings/route.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js +13 -8
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js.map +2 -2
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +9 -4
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +18 -11
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/page.js +12 -8
- package/dist/modules/integrations/backend/integrations/page.js.map +2 -2
- package/dist/modules/messages/commands/messages.js +13 -10
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/perspectives/api/[tableId]/route.js +39 -30
- package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
- package/dist/modules/perspectives/services/perspectiveService.js +7 -0
- package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +6 -14
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +3 -3
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js +4 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
- package/dist/modules/planner/components/AvailabilityRuleSetForm.js +2 -0
- package/dist/modules/planner/components/AvailabilityRuleSetForm.js.map +2 -2
- package/dist/modules/planner/components/AvailabilityRulesEditor.js +36 -11
- package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
- package/dist/modules/planner/components/AvailabilitySchedule.js +9 -5
- package/dist/modules/planner/components/AvailabilitySchedule.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +19 -0
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js +1 -0
- package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js +4 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js +14 -3
- package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js +8 -4
- package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
- package/dist/modules/resources/components/ResourceCrudForm.js +2 -0
- package/dist/modules/resources/components/ResourceCrudForm.js.map +2 -2
- package/dist/modules/resources/components/ResourceTypeCrudForm.js +1 -0
- package/dist/modules/resources/components/ResourceTypeCrudForm.js.map +2 -2
- package/dist/modules/sales/api/documents/factory.js +7 -2
- package/dist/modules/sales/api/documents/factory.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +3 -1
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +13 -4
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +16 -4
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +68 -22
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/create/page.js.map +2 -2
- package/dist/modules/sales/commands/documentAddresses.js +181 -2
- package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +29 -1
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/returns.js +12 -2
- package/dist/modules/sales/commands/returns.js.map +2 -2
- package/dist/modules/sales/commands/shared.js +15 -0
- package/dist/modules/sales/commands/shared.js.map +2 -2
- package/dist/modules/sales/commands/shipments.js +4 -1
- package/dist/modules/sales/commands/shipments.js.map +2 -2
- package/dist/modules/sales/components/AdjustmentKindSettings.js +19 -11
- package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
- package/dist/modules/sales/components/DocumentNumberSettings.js.map +2 -2
- package/dist/modules/sales/components/OrderEditingSettings.js.map +2 -2
- package/dist/modules/sales/components/PaymentMethodsSettings.js +12 -4
- package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
- package/dist/modules/sales/components/ShippingMethodsSettings.js +12 -4
- package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
- package/dist/modules/sales/components/StatusSettings.js +18 -11
- package/dist/modules/sales/components/StatusSettings.js.map +2 -2
- package/dist/modules/sales/components/TaxRatesSettings.js +12 -4
- package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
- package/dist/modules/sales/components/channels/ChannelOfferForm.js +47 -16
- package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +8 -4
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/sales/components/documents/AddressesSection.js +44 -25
- package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js +43 -23
- package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +22 -13
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +23 -10
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentDialog.js +29 -14
- package/dist/modules/sales/components/documents/PaymentDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js +20 -10
- package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ReturnDialog.js +26 -17
- package/dist/modules/sales/components/documents/ReturnDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/ReturnsSection.js +3 -1
- package/dist/modules/sales/components/documents/ReturnsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +10 -5
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentDialog.js +21 -7
- package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentsSection.js +19 -10
- package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/optimisticLock.js +27 -0
- package/dist/modules/sales/components/documents/optimisticLock.js.map +7 -0
- package/dist/modules/sales/di.js +18 -0
- package/dist/modules/sales/di.js.map +2 -2
- package/dist/modules/staff/api/job-histories.js +11 -2
- package/dist/modules/staff/api/job-histories.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/route.js +11 -4
- package/dist/modules/staff/api/timesheets/time-entries/route.js.map +2 -2
- package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +13 -8
- package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +2 -1
- package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js +7 -4
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/page.js +4 -2
- package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js +1 -0
- package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js +4 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +5 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js +12 -3
- package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/page.js +4 -1
- package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js +12 -3
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
- package/dist/modules/staff/commands/job-histories.js +40 -3
- package/dist/modules/staff/commands/job-histories.js.map +2 -2
- package/dist/modules/staff/components/LeaveRequestForm.js +1 -0
- package/dist/modules/staff/components/LeaveRequestForm.js.map +2 -2
- package/dist/modules/staff/components/TeamForm.js +1 -0
- package/dist/modules/staff/components/TeamForm.js.map +2 -2
- package/dist/modules/staff/components/TeamMemberForm.js +1 -0
- package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
- package/dist/modules/staff/components/TeamRoleForm.js +1 -0
- package/dist/modules/staff/components/TeamRoleForm.js.map +2 -2
- package/dist/modules/staff/components/detail/JobHistorySection.js +20 -7
- package/dist/modules/staff/components/detail/JobHistorySection.js.map +2 -2
- package/dist/modules/staff/data/validators.js +7 -1
- package/dist/modules/staff/data/validators.js.map +2 -2
- package/dist/modules/staff/lib/leaveRequestHelpers.js +2 -1
- package/dist/modules/staff/lib/leaveRequestHelpers.js.map +2 -2
- package/dist/modules/translations/components/TranslationManager.js +12 -8
- package/dist/modules/translations/components/TranslationManager.js.map +2 -2
- package/dist/modules/workflows/api/definitions/[id]/route.js +106 -0
- package/dist/modules/workflows/api/definitions/[id]/route.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.js +11 -3
- package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/page.js +19 -8
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +29 -16
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
- package/dist/modules/workflows/components/formConfig.js +4 -1
- package/dist/modules/workflows/components/formConfig.js.map +2 -2
- package/dist/modules/workflows/di.js +12 -0
- package/dist/modules/workflows/di.js.map +2 -2
- package/generated/entities/role/index.ts +1 -0
- package/generated/entities/user/index.ts +1 -0
- package/generated/entity-fields-registry.ts +2 -0
- package/jest.setup.ts +17 -0
- package/package.json +8 -7
- package/src/helpers/integration/communicationChannelsFixtures.ts +6 -0
- package/src/helpers/integration/dbFixtures.ts +1 -1
- package/src/helpers/integration/optimisticLockUi.ts +172 -0
- package/src/helpers/integration/salesFixtures.ts +29 -0
- package/src/modules/api_keys/backend/api-keys/page.tsx +10 -5
- package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +19 -9
- package/src/modules/auth/api/roles/acl/route.ts +37 -11
- package/src/modules/auth/api/roles/route.ts +2 -0
- package/src/modules/auth/api/sidebar/preferences/route.ts +73 -0
- package/src/modules/auth/api/users/acl/route.ts +46 -18
- package/src/modules/auth/api/users/route.ts +2 -0
- package/src/modules/auth/backend/roles/[id]/edit/page.tsx +29 -4
- package/src/modules/auth/backend/roles/page.tsx +9 -4
- package/src/modules/auth/backend/users/[id]/edit/page.tsx +37 -4
- package/src/modules/auth/backend/users/page.tsx +7 -2
- package/src/modules/auth/components/AclEditor.tsx +10 -1
- package/src/modules/auth/data/entities.ts +7 -1
- package/src/modules/auth/services/sidebarPreferencesService.ts +38 -4
- package/src/modules/business_rules/api/rules/route.ts +30 -0
- package/src/modules/business_rules/api/sets/route.ts +30 -0
- package/src/modules/business_rules/backend/rules/[id]/page.tsx +16 -4
- package/src/modules/business_rules/backend/rules/page.tsx +20 -11
- package/src/modules/business_rules/backend/sets/[id]/page.tsx +16 -4
- package/src/modules/business_rules/backend/sets/page.tsx +20 -11
- package/src/modules/catalog/api/categories/route.ts +3 -0
- package/src/modules/catalog/api/products/route.ts +4 -0
- package/src/modules/catalog/backend/catalog/categories/[id]/edit/page.tsx +5 -0
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +112 -35
- package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +56 -7
- package/src/modules/catalog/backend/catalog/products/optionSchemaClient.ts +2 -0
- package/src/modules/catalog/commands/variants.ts +32 -32
- package/src/modules/catalog/components/PriceKindSettings.tsx +20 -7
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +1 -0
- package/src/modules/catalog/components/products/ProductMediaManager.tsx +2 -0
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +8 -4
- package/src/modules/catalog/components/products/productForm.ts +3 -0
- package/src/modules/catalog/components/products/variantForm.ts +9 -0
- package/src/modules/communication_channels/api/post/test-seed/route.ts +28 -1
- package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +5 -0
- package/src/modules/communication_channels/commands/set-primary-channel.ts +10 -7
- package/src/modules/currencies/backend/currencies/[id]/page.tsx +13 -6
- package/src/modules/currencies/backend/currencies/page.tsx +18 -11
- package/src/modules/currencies/backend/exchange-rates/[id]/page.tsx +3 -0
- package/src/modules/currencies/backend/exchange-rates/page.tsx +10 -6
- package/src/modules/currencies/commands/currencies.ts +10 -5
- package/src/modules/currencies/components/CurrencyFetchingConfig.tsx +31 -21
- package/src/modules/customer_accounts/api/admin/roles/[id].ts +35 -5
- package/src/modules/customer_accounts/api/admin/roles.ts +2 -0
- package/src/modules/customer_accounts/api/admin/users/[id].ts +38 -5
- package/src/modules/customer_accounts/api/admin/users.ts +2 -0
- package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +34 -20
- package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +9 -4
- package/src/modules/customer_accounts/backend/customer_accounts/settings/domain/page.tsx +11 -4
- package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +28 -17
- package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +19 -11
- package/src/modules/customers/AGENTS.md +2 -2
- package/src/modules/customers/api/companies/route.ts +14 -1
- package/src/modules/customers/api/deals/route.ts +3 -0
- package/src/modules/customers/api/people/route.ts +12 -1
- package/src/modules/customers/api/todos/route.ts +1 -0
- package/src/modules/customers/backend/config/customers/deals/page.tsx +1 -0
- package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +36 -21
- package/src/modules/customers/backend/customers/companies/[id]/page.tsx +52 -27
- package/src/modules/customers/backend/customers/companies/page.tsx +2 -0
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +27 -5
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.ts +39 -7
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +1 -0
- package/src/modules/customers/backend/customers/deals/page.tsx +18 -6
- package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +64 -39
- package/src/modules/customers/backend/customers/people/[id]/page.tsx +46 -26
- package/src/modules/customers/backend/customers/people/page.tsx +2 -0
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +84 -24
- package/src/modules/customers/commands/addresses.ts +16 -14
- package/src/modules/customers/commands/companies.ts +3 -1
- package/src/modules/customers/commands/interactions.ts +50 -4
- package/src/modules/customers/commands/people.ts +2 -1
- package/src/modules/customers/commands/personCompanyLinks.ts +8 -5
- package/src/modules/customers/commands/pipeline-stages.ts +16 -16
- package/src/modules/customers/components/AddressFormatSettings.tsx +1 -0
- package/src/modules/customers/components/DictionarySettings.tsx +18 -13
- package/src/modules/customers/components/DictionarySortSettings.tsx +4 -0
- package/src/modules/customers/components/PipelineSettings.tsx +42 -21
- package/src/modules/customers/components/detail/ActivityTimeline.tsx +3 -3
- package/src/modules/customers/components/detail/AddressesSection.tsx +4 -0
- package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +2 -0
- package/src/modules/customers/components/detail/DealsSection.tsx +4 -0
- package/src/modules/customers/components/detail/EmailCardActions.tsx +5 -0
- package/src/modules/customers/components/detail/EntityTagsDialog.tsx +7 -0
- package/src/modules/customers/components/detail/ManageTagsDialog.tsx +4 -0
- package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +4 -0
- package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +2 -0
- package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +23 -7
- package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +25 -15
- package/src/modules/customers/components/detail/hooks/useInteractions.ts +76 -35
- package/src/modules/customers/components/detail/hooks/usePersonTasks.ts +30 -17
- package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +2 -0
- package/src/modules/customers/components/detail/types.ts +1 -0
- package/src/modules/customers/components/formConfig.tsx +2 -0
- package/src/modules/customers/data/guards.ts +67 -0
- package/src/modules/customers/di.ts +66 -0
- package/src/modules/customers/i18n/de.json +2 -0
- package/src/modules/customers/i18n/en.json +2 -0
- package/src/modules/customers/i18n/es.json +2 -0
- package/src/modules/customers/i18n/pl.json +2 -0
- package/src/modules/customers/lib/todoCompatibility.ts +14 -0
- package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +2 -0
- package/src/modules/data_sync/api/options.ts +7 -4
- package/src/modules/data_sync/api/schedules/route.ts +9 -1
- package/src/modules/data_sync/backend/data-sync/page.tsx +18 -5
- package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +46 -19
- package/src/modules/data_sync/lib/sync-schedule-service.ts +11 -0
- package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +8 -1
- package/src/modules/dictionaries/api/[dictionaryId]/route.ts +23 -0
- package/src/modules/dictionaries/components/DictionariesManager.tsx +32 -9
- package/src/modules/dictionaries/components/DictionaryEntriesEditor.tsx +30 -14
- package/src/modules/dictionaries/i18n/de.json +1 -0
- package/src/modules/dictionaries/i18n/en.json +1 -0
- package/src/modules/dictionaries/i18n/es.json +1 -0
- package/src/modules/dictionaries/i18n/pl.json +1 -0
- package/src/modules/directory/api/organizations/route.ts +3 -0
- package/src/modules/directory/backend/directory/organizations/[id]/edit/page.tsx +8 -0
- package/src/modules/directory/backend/directory/organizations/page.tsx +10 -5
- package/src/modules/directory/backend/directory/tenants/[id]/edit/page.tsx +16 -5
- package/src/modules/directory/backend/directory/tenants/page.tsx +8 -4
- package/src/modules/directory/commands/organizations.ts +7 -4
- package/src/modules/entities/api/records.ts +99 -0
- package/src/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.tsx +7 -0
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +8 -4
- package/src/modules/entities/lib/helpers.ts +17 -0
- package/src/modules/feature_toggles/api/global/[id]/override/route.ts +1 -0
- package/src/modules/feature_toggles/api/overrides/route.ts +19 -0
- package/src/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.tsx +19 -13
- package/src/modules/feature_toggles/components/FeatureToggleOverrideCard.tsx +22 -12
- package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +7 -2
- package/src/modules/feature_toggles/components/formConfig.tsx +2 -1
- package/src/modules/feature_toggles/components/overrideFormConfig.tsx +10 -1
- package/src/modules/feature_toggles/data/validators.ts +11 -3
- package/src/modules/inbox_ops/api/settings/route.ts +18 -0
- package/src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx +15 -10
- package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +9 -4
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +20 -11
- package/src/modules/integrations/backend/integrations/page.tsx +13 -8
- package/src/modules/messages/commands/messages.ts +27 -15
- package/src/modules/perspectives/api/[tableId]/route.ts +11 -2
- package/src/modules/perspectives/services/perspectiveService.ts +13 -1
- package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +16 -14
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +6 -3
- package/src/modules/planner/components/AvailabilityRuleSetForm.tsx +3 -0
- package/src/modules/planner/components/AvailabilityRulesEditor.tsx +58 -15
- package/src/modules/planner/components/AvailabilitySchedule.tsx +22 -7
- package/src/modules/query_index/lib/engine.ts +34 -0
- package/src/modules/resources/backend/resources/resource-types/[id]/edit/page.tsx +7 -1
- package/src/modules/resources/backend/resources/resource-types/page.tsx +6 -3
- package/src/modules/resources/backend/resources/resources/[id]/page.tsx +23 -3
- package/src/modules/resources/backend/resources/resources/page.tsx +15 -4
- package/src/modules/resources/components/ResourceCrudForm.tsx +3 -0
- package/src/modules/resources/components/ResourceTypeCrudForm.tsx +2 -0
- package/src/modules/sales/api/documents/factory.ts +13 -1
- package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +6 -0
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +10 -4
- package/src/modules/sales/backend/sales/channels/page.tsx +19 -4
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +73 -20
- package/src/modules/sales/backend/sales/documents/create/page.tsx +2 -0
- package/src/modules/sales/commands/documentAddresses.ts +226 -4
- package/src/modules/sales/commands/documents.ts +28 -0
- package/src/modules/sales/commands/returns.ts +12 -3
- package/src/modules/sales/commands/shared.ts +36 -0
- package/src/modules/sales/commands/shipments.ts +17 -1
- package/src/modules/sales/components/AdjustmentKindSettings.tsx +20 -11
- package/src/modules/sales/components/DocumentNumberSettings.tsx +1 -0
- package/src/modules/sales/components/OrderEditingSettings.tsx +1 -0
- package/src/modules/sales/components/PaymentMethodsSettings.tsx +12 -4
- package/src/modules/sales/components/ShippingMethodsSettings.tsx +12 -4
- package/src/modules/sales/components/StatusSettings.tsx +20 -11
- package/src/modules/sales/components/TaxRatesSettings.tsx +12 -5
- package/src/modules/sales/components/channels/ChannelOfferForm.tsx +67 -14
- package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +7 -4
- package/src/modules/sales/components/documents/AddressesSection.tsx +35 -25
- package/src/modules/sales/components/documents/AdjustmentsSection.tsx +50 -25
- package/src/modules/sales/components/documents/ItemsSection.tsx +24 -13
- package/src/modules/sales/components/documents/LineItemDialog.tsx +26 -9
- package/src/modules/sales/components/documents/PaymentDialog.tsx +33 -14
- package/src/modules/sales/components/documents/PaymentsSection.tsx +22 -10
- package/src/modules/sales/components/documents/ReturnDialog.tsx +28 -17
- package/src/modules/sales/components/documents/ReturnsSection.tsx +4 -1
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +11 -4
- package/src/modules/sales/components/documents/ShipmentDialog.tsx +23 -8
- package/src/modules/sales/components/documents/ShipmentsSection.tsx +20 -10
- package/src/modules/sales/components/documents/optimisticLock.ts +34 -0
- package/src/modules/sales/components/documents/shipmentTypes.ts +1 -0
- package/src/modules/sales/di.ts +35 -0
- package/src/modules/sales/i18n/de.json +3 -0
- package/src/modules/sales/i18n/en.json +3 -0
- package/src/modules/sales/i18n/es.json +3 -0
- package/src/modules/sales/i18n/pl.json +3 -0
- package/src/modules/staff/api/job-histories.ts +12 -2
- package/src/modules/staff/api/timesheets/time-entries/route.ts +16 -4
- package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +12 -7
- package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +2 -0
- package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +16 -5
- package/src/modules/staff/backend/staff/team-members/page.tsx +6 -2
- package/src/modules/staff/backend/staff/team-roles/[id]/edit/page.tsx +8 -0
- package/src/modules/staff/backend/staff/team-roles/page.tsx +6 -2
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +13 -3
- package/src/modules/staff/backend/staff/teams/page.tsx +9 -3
- package/src/modules/staff/backend/staff/timesheets/page.tsx +10 -1
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +4 -0
- package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +9 -3
- package/src/modules/staff/commands/job-histories.ts +42 -3
- package/src/modules/staff/components/LeaveRequestForm.tsx +2 -0
- package/src/modules/staff/components/TeamForm.tsx +2 -0
- package/src/modules/staff/components/TeamMemberForm.tsx +2 -0
- package/src/modules/staff/components/TeamRoleForm.tsx +2 -0
- package/src/modules/staff/components/detail/JobHistorySection.tsx +28 -6
- package/src/modules/staff/data/validators.ts +6 -0
- package/src/modules/staff/i18n/de.json +1 -0
- package/src/modules/staff/i18n/en.json +1 -0
- package/src/modules/staff/i18n/es.json +1 -0
- package/src/modules/staff/i18n/pl.json +1 -0
- package/src/modules/staff/lib/leaveRequestHelpers.ts +4 -0
- package/src/modules/translations/components/TranslationManager.tsx +13 -8
- package/src/modules/workflows/api/definitions/[id]/route.ts +112 -0
- package/src/modules/workflows/backend/definitions/[id]/page.tsx +20 -4
- package/src/modules/workflows/backend/definitions/page.tsx +20 -9
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +29 -16
- package/src/modules/workflows/components/formConfig.tsx +5 -0
- package/src/modules/workflows/di.ts +20 -0
- package/src/modules/workflows/i18n/de.json +1 -0
- package/src/modules/workflows/i18n/en.json +1 -0
- package/src/modules/workflows/i18n/es.json +1 -0
- package/src/modules/workflows/i18n/pl.json +1 -0
|
@@ -8,7 +8,8 @@ import { DataTable } from '@open-mercato/ui/backend/DataTable'
|
|
|
8
8
|
import type { ColumnDef } from '@tanstack/react-table'
|
|
9
9
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
10
10
|
import { RowActions } from '@open-mercato/ui/backend/RowActions'
|
|
11
|
-
import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
|
|
11
|
+
import { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
|
|
12
|
+
import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
|
|
12
13
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
13
14
|
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
|
14
15
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
@@ -92,9 +93,13 @@ export default function RulesListPage() {
|
|
|
92
93
|
})
|
|
93
94
|
if (!confirmed) return
|
|
94
95
|
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
const record = (data || []).find((item) => item.id === id)
|
|
97
|
+
const result = await withScopedApiRequestHeaders(
|
|
98
|
+
buildOptimisticLockHeader(record?.updatedAt),
|
|
99
|
+
() => apiCall(`/api/business_rules/rules?id=${id}`, {
|
|
100
|
+
method: 'DELETE',
|
|
101
|
+
}),
|
|
102
|
+
)
|
|
98
103
|
|
|
99
104
|
if (result.ok) {
|
|
100
105
|
flash(t('business_rules.messages.deleted'), 'success')
|
|
@@ -105,14 +110,18 @@ export default function RulesListPage() {
|
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
const handleToggleEnabled = async (id: string, currentEnabled: boolean) => {
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
const record = (data || []).find((item) => item.id === id)
|
|
114
|
+
const result = await withScopedApiRequestHeaders(
|
|
115
|
+
buildOptimisticLockHeader(record?.updatedAt),
|
|
116
|
+
() => apiCall('/api/business_rules/rules', {
|
|
117
|
+
method: 'PUT',
|
|
118
|
+
headers: { 'Content-Type': 'application/json' },
|
|
119
|
+
body: JSON.stringify({
|
|
120
|
+
id,
|
|
121
|
+
enabled: !currentEnabled,
|
|
122
|
+
}),
|
|
114
123
|
}),
|
|
115
|
-
|
|
124
|
+
)
|
|
116
125
|
|
|
117
126
|
if (result.ok) {
|
|
118
127
|
flash(t('business_rules.messages.updated'), 'success')
|
|
@@ -9,8 +9,11 @@ import { CrudForm } from '@open-mercato/ui/backend/CrudForm'
|
|
|
9
9
|
import type { CrudField } from '@open-mercato/ui/backend/CrudForm'
|
|
10
10
|
import { Spinner } from '@open-mercato/ui/primitives/spinner'
|
|
11
11
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
12
|
-
import { apiFetch } from '@open-mercato/ui/backend/utils/api'
|
|
12
|
+
import { apiFetch, withScopedApiHeaders } from '@open-mercato/ui/backend/utils/api'
|
|
13
13
|
import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
|
|
14
|
+
import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
|
|
15
|
+
import { readJsonSafe } from '@open-mercato/ui/backend/utils/serverErrors'
|
|
16
|
+
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
14
17
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
15
18
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
16
19
|
import { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
|
|
@@ -85,15 +88,23 @@ export default function EditRuleSetPage() {
|
|
|
85
88
|
...values,
|
|
86
89
|
}
|
|
87
90
|
|
|
88
|
-
const
|
|
91
|
+
const updateSet = () => apiFetch('/api/business_rules/sets', {
|
|
89
92
|
method: 'PUT',
|
|
90
93
|
headers: { 'Content-Type': 'application/json' },
|
|
91
94
|
body: JSON.stringify(payload),
|
|
92
95
|
})
|
|
96
|
+
const headers = buildOptimisticLockHeader(ruleSet?.updatedAt ?? null)
|
|
97
|
+
const response = Object.keys(headers).length
|
|
98
|
+
? await withScopedApiHeaders(headers, updateSet)
|
|
99
|
+
: await updateSet()
|
|
93
100
|
|
|
94
101
|
if (!response.ok) {
|
|
95
|
-
const
|
|
96
|
-
|
|
102
|
+
const body = (await readJsonSafe<Record<string, unknown>>(response)) ?? {}
|
|
103
|
+
const message =
|
|
104
|
+
(typeof body.error === 'string' && body.error) ||
|
|
105
|
+
(typeof body.message === 'string' && body.message) ||
|
|
106
|
+
t('business_rules.sets.errors.updateFailed')
|
|
107
|
+
throw new CrudHttpError(response.status, { ...body, error: message })
|
|
97
108
|
}
|
|
98
109
|
|
|
99
110
|
flash(t('business_rules.sets.messages.updated'), 'success')
|
|
@@ -265,6 +276,7 @@ export default function EditRuleSetPage() {
|
|
|
265
276
|
schema={ruleSetFormSchema}
|
|
266
277
|
fields={fields}
|
|
267
278
|
initialValues={initialValues}
|
|
279
|
+
optimisticLockUpdatedAt={ruleSet.updatedAt}
|
|
268
280
|
onSubmit={handleSubmit}
|
|
269
281
|
cancelHref="/backend/sets"
|
|
270
282
|
submitLabel={t('business_rules.sets.form.update')}
|
|
@@ -8,7 +8,8 @@ import { DataTable } from '@open-mercato/ui/backend/DataTable'
|
|
|
8
8
|
import type { ColumnDef } from '@tanstack/react-table'
|
|
9
9
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
10
10
|
import { RowActions } from '@open-mercato/ui/backend/RowActions'
|
|
11
|
-
import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
|
|
11
|
+
import { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
|
|
12
|
+
import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
|
|
12
13
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
13
14
|
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
|
14
15
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
@@ -83,9 +84,13 @@ export default function RuleSetsListPage() {
|
|
|
83
84
|
})
|
|
84
85
|
if (!confirmed) return
|
|
85
86
|
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
const record = (data || []).find((item) => item.id === id)
|
|
88
|
+
const result = await withScopedApiRequestHeaders(
|
|
89
|
+
buildOptimisticLockHeader(record?.updatedAt),
|
|
90
|
+
() => apiCall(`/api/business_rules/sets?id=${id}`, {
|
|
91
|
+
method: 'DELETE',
|
|
92
|
+
}),
|
|
93
|
+
)
|
|
89
94
|
|
|
90
95
|
if (result.ok) {
|
|
91
96
|
flash(t('business_rules.sets.messages.deleted'), 'success')
|
|
@@ -96,14 +101,18 @@ export default function RuleSetsListPage() {
|
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
const handleToggleEnabled = async (id: string, currentEnabled: boolean) => {
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
const record = (data || []).find((item) => item.id === id)
|
|
105
|
+
const result = await withScopedApiRequestHeaders(
|
|
106
|
+
buildOptimisticLockHeader(record?.updatedAt),
|
|
107
|
+
() => apiCall('/api/business_rules/sets', {
|
|
108
|
+
method: 'PUT',
|
|
109
|
+
headers: { 'Content-Type': 'application/json' },
|
|
110
|
+
body: JSON.stringify({
|
|
111
|
+
id,
|
|
112
|
+
enabled: !currentEnabled,
|
|
113
|
+
}),
|
|
105
114
|
}),
|
|
106
|
-
|
|
115
|
+
)
|
|
107
116
|
|
|
108
117
|
if (result.ok) {
|
|
109
118
|
flash(t('business_rules.sets.messages.updated'), 'success')
|
|
@@ -99,6 +99,7 @@ type ManageCategoryRow = {
|
|
|
99
99
|
childCount: number
|
|
100
100
|
descendantCount: number
|
|
101
101
|
isActive: boolean
|
|
102
|
+
updatedAt: string | null
|
|
102
103
|
organizationId: string
|
|
103
104
|
tenantId: string
|
|
104
105
|
}
|
|
@@ -262,6 +263,7 @@ export async function GET(req: Request) {
|
|
|
262
263
|
childCount: node.childIds.length,
|
|
263
264
|
descendantCount: node.descendantIds.length,
|
|
264
265
|
isActive: node.isActive,
|
|
266
|
+
updatedAt: category?.updatedAt ? new Date(category.updatedAt).toISOString() : null,
|
|
265
267
|
organizationId,
|
|
266
268
|
tenantId,
|
|
267
269
|
...(cfValues[recordId] ?? {}),
|
|
@@ -297,6 +299,7 @@ const categoryListItemSchema = z.object({
|
|
|
297
299
|
childCount: z.number(),
|
|
298
300
|
descendantCount: z.number(),
|
|
299
301
|
isActive: z.boolean(),
|
|
302
|
+
updatedAt: z.string().nullable().optional(),
|
|
300
303
|
organizationId: z.string().uuid(),
|
|
301
304
|
tenantId: z.string().uuid(),
|
|
302
305
|
})
|
|
@@ -425,6 +425,10 @@ async function decorateProductsAfterList(
|
|
|
425
425
|
defaultMediaId: offer.defaultMediaId ?? null,
|
|
426
426
|
defaultMediaUrl: offer.defaultMediaUrl ?? null,
|
|
427
427
|
metadata: offer.metadata ?? null,
|
|
428
|
+
updatedAt:
|
|
429
|
+
offer.updatedAt instanceof Date
|
|
430
|
+
? offer.updatedAt.toISOString()
|
|
431
|
+
: (typeof offer.updatedAt === "string" ? offer.updatedAt : null),
|
|
428
432
|
});
|
|
429
433
|
offersByProduct.set(productId, entry);
|
|
430
434
|
}
|
|
@@ -22,6 +22,8 @@ type CategoryRow = {
|
|
|
22
22
|
description: string | null
|
|
23
23
|
parentId: string | null
|
|
24
24
|
isActive: boolean
|
|
25
|
+
updatedAt?: string | null
|
|
26
|
+
updated_at?: string | null
|
|
25
27
|
pathLabel?: string
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -36,6 +38,7 @@ type CategoryFormValues = {
|
|
|
36
38
|
description?: string
|
|
37
39
|
parentId?: string | null
|
|
38
40
|
isActive?: boolean
|
|
41
|
+
updatedAt?: string | null
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
async function submitCategoryUpdate(
|
|
@@ -116,6 +119,7 @@ export default function EditCatalogCategoryPage({ params }: { params?: { id?: st
|
|
|
116
119
|
description: record.description ?? '',
|
|
117
120
|
parentId: record.parentId ?? '',
|
|
118
121
|
isActive: record.isActive,
|
|
122
|
+
updatedAt: record.updatedAt ?? record.updated_at ?? null,
|
|
119
123
|
...customValues,
|
|
120
124
|
})
|
|
121
125
|
setPathLabel(record.pathLabel ?? '')
|
|
@@ -238,6 +242,7 @@ export default function EditCatalogCategoryPage({ params }: { params?: { id?: st
|
|
|
238
242
|
groups={groups}
|
|
239
243
|
entityId={E.catalog.catalog_product_category}
|
|
240
244
|
initialValues={initialValues ?? { id: categoryId, name: '', slug: '', description: '', parentId: '', isActive: true }}
|
|
245
|
+
optimisticLockUpdatedAt={initialValues?.updatedAt}
|
|
241
246
|
isLoading={loading}
|
|
242
247
|
loadingMessage={t('catalog.categories.form.loading', 'Loading category...')}
|
|
243
248
|
submitLabel={t('catalog.categories.form.action.save', 'Save')}
|
|
@@ -37,7 +37,10 @@ import { Spinner } from "@open-mercato/ui/primitives/spinner";
|
|
|
37
37
|
import {
|
|
38
38
|
apiCall,
|
|
39
39
|
readApiResultOrThrow,
|
|
40
|
+
withScopedApiRequestHeaders,
|
|
40
41
|
} from "@open-mercato/ui/backend/utils/apiCall";
|
|
42
|
+
import { buildOptimisticLockHeader } from "@open-mercato/ui/backend/utils/optimisticLock";
|
|
43
|
+
import { surfaceRecordConflict } from "@open-mercato/ui/backend/conflicts";
|
|
41
44
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
42
45
|
import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
|
|
43
46
|
import { E } from "#generated/entities.ids.generated";
|
|
@@ -157,6 +160,8 @@ type VariantSummaryApi = {
|
|
|
157
160
|
default_media_id?: string | null;
|
|
158
161
|
defaultMediaId?: string | null;
|
|
159
162
|
metadata?: Record<string, unknown> | null;
|
|
163
|
+
updated_at?: string | null;
|
|
164
|
+
updatedAt?: string | null;
|
|
160
165
|
};
|
|
161
166
|
|
|
162
167
|
type AttachmentListResponse = {
|
|
@@ -181,6 +186,7 @@ type VariantSummary = {
|
|
|
181
186
|
defaultMediaId: string | null;
|
|
182
187
|
prices: VariantPriceSummary[];
|
|
183
188
|
optionValues: Record<string, string> | null;
|
|
189
|
+
updatedAt: string | null;
|
|
184
190
|
};
|
|
185
191
|
|
|
186
192
|
type VariantPriceListResponse = {
|
|
@@ -221,6 +227,7 @@ type OfferSnapshot = {
|
|
|
221
227
|
isActive: boolean;
|
|
222
228
|
channelName: string | null;
|
|
223
229
|
channelCode: string | null;
|
|
230
|
+
updatedAt: string | null;
|
|
224
231
|
};
|
|
225
232
|
|
|
226
233
|
function mapVariantPriceSummary(
|
|
@@ -273,7 +280,7 @@ function readProductConversionRows(
|
|
|
273
280
|
): ProductUnitConversionDraft[] {
|
|
274
281
|
const rows = Array.isArray(items) ? items : [];
|
|
275
282
|
return rows
|
|
276
|
-
.map((item) => {
|
|
283
|
+
.map((item): ProductUnitConversionDraft | null => {
|
|
277
284
|
const id = toTrimmedOrNull(item.id);
|
|
278
285
|
const unitCode = canonicalizeUnitCode(item.unit_code ?? item.unitCode);
|
|
279
286
|
const factor = toPositiveNumberOrNull(
|
|
@@ -298,6 +305,12 @@ function readProductConversionRows(
|
|
|
298
305
|
toBaseFactor: String(factor),
|
|
299
306
|
sortOrder: String(sortOrderRaw),
|
|
300
307
|
isActive,
|
|
308
|
+
updatedAt:
|
|
309
|
+
typeof item.updated_at === "string"
|
|
310
|
+
? item.updated_at
|
|
311
|
+
: typeof item.updatedAt === "string"
|
|
312
|
+
? item.updatedAt
|
|
313
|
+
: null,
|
|
301
314
|
} satisfies ProductUnitConversionDraft;
|
|
302
315
|
})
|
|
303
316
|
.filter((entry): entry is ProductUnitConversionDraft => Boolean(entry));
|
|
@@ -405,6 +418,12 @@ export default function EditCatalogProductPage({
|
|
|
405
418
|
: null,
|
|
406
419
|
prices: priceMap[variantId] ?? [],
|
|
407
420
|
optionValues,
|
|
421
|
+
updatedAt:
|
|
422
|
+
typeof variant.updatedAt === "string"
|
|
423
|
+
? variant.updatedAt
|
|
424
|
+
: typeof variant.updated_at === "string"
|
|
425
|
+
? variant.updated_at
|
|
426
|
+
: null,
|
|
408
427
|
};
|
|
409
428
|
})
|
|
410
429
|
.filter((entry): entry is VariantSummary => Boolean(entry));
|
|
@@ -712,6 +731,12 @@ export default function EditCatalogProductPage({
|
|
|
712
731
|
categoryIds,
|
|
713
732
|
channelIds,
|
|
714
733
|
tags: tagValues,
|
|
734
|
+
updatedAt:
|
|
735
|
+
typeof record.updatedAt === "string"
|
|
736
|
+
? record.updatedAt
|
|
737
|
+
: typeof record.updated_at === "string"
|
|
738
|
+
? record.updated_at
|
|
739
|
+
: null,
|
|
715
740
|
};
|
|
716
741
|
if (!cancelled) {
|
|
717
742
|
setInitialValues({ ...initial, ...customValues });
|
|
@@ -1225,12 +1250,18 @@ export default function EditCatalogProductPage({
|
|
|
1225
1250
|
try {
|
|
1226
1251
|
for (const offer of removedOffers) {
|
|
1227
1252
|
if (!offer.id) continue;
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
),
|
|
1233
|
-
|
|
1253
|
+
const offerId = offer.id;
|
|
1254
|
+
// Send the offer's own version, overriding the product header the
|
|
1255
|
+
// parent CrudForm submit scope put on the stack (#2055).
|
|
1256
|
+
await withScopedApiRequestHeaders(
|
|
1257
|
+
buildOptimisticLockHeader(offer.updatedAt),
|
|
1258
|
+
() => deleteCrud("catalog/offers", offerId, {
|
|
1259
|
+
errorMessage: t(
|
|
1260
|
+
"catalog.products.edit.offers.deleteError",
|
|
1261
|
+
"Failed to remove sales channel offer.",
|
|
1262
|
+
),
|
|
1263
|
+
}),
|
|
1264
|
+
);
|
|
1234
1265
|
}
|
|
1235
1266
|
} catch (err) {
|
|
1236
1267
|
console.error("catalog.products.edit.offers.delete", err);
|
|
@@ -1248,6 +1279,15 @@ export default function EditCatalogProductPage({
|
|
|
1248
1279
|
.map((entry) => toTrimmedOrNull(entry.id))
|
|
1249
1280
|
.filter((id): id is string => Boolean(id)),
|
|
1250
1281
|
);
|
|
1282
|
+
// Loaded conversion id → version, so the sync sends each row's own
|
|
1283
|
+
// optimistic-lock version (overriding the product header leaked by the
|
|
1284
|
+
// parent CrudForm submit scope onto the catalog/product-unit-conversions
|
|
1285
|
+
// guard) (#2055).
|
|
1286
|
+
const conversionVersions = new Map<string, string | null>();
|
|
1287
|
+
for (const entry of initialConversionsRef.current) {
|
|
1288
|
+
const cid = toTrimmedOrNull(entry.id);
|
|
1289
|
+
if (cid) conversionVersions.set(cid, entry.updatedAt ?? null);
|
|
1290
|
+
}
|
|
1251
1291
|
const nextConversionIds = new Set(
|
|
1252
1292
|
conversionInputs
|
|
1253
1293
|
.map((entry) =>
|
|
@@ -1259,23 +1299,30 @@ export default function EditCatalogProductPage({
|
|
|
1259
1299
|
(id) => !nextConversionIds.has(id),
|
|
1260
1300
|
);
|
|
1261
1301
|
for (const conversionId of removedConversionIds) {
|
|
1262
|
-
await
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1302
|
+
await withScopedApiRequestHeaders(
|
|
1303
|
+
buildOptimisticLockHeader(conversionVersions.get(conversionId) ?? null),
|
|
1304
|
+
() => deleteCrud("catalog/product-unit-conversions", conversionId, {
|
|
1305
|
+
errorMessage: t(
|
|
1306
|
+
"catalog.products.uom.errors.sync",
|
|
1307
|
+
"Failed to synchronize product conversions.",
|
|
1308
|
+
),
|
|
1309
|
+
}),
|
|
1310
|
+
);
|
|
1268
1311
|
}
|
|
1269
1312
|
const persistedConversions: ProductUnitConversionDraft[] = [];
|
|
1270
1313
|
for (const conversion of conversionInputs) {
|
|
1271
1314
|
if (conversion.id) {
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1315
|
+
const conversionId = conversion.id;
|
|
1316
|
+
await withScopedApiRequestHeaders(
|
|
1317
|
+
buildOptimisticLockHeader(conversionVersions.get(conversionId) ?? null),
|
|
1318
|
+
() => updateCrud("catalog/product-unit-conversions", {
|
|
1319
|
+
id: conversionId,
|
|
1320
|
+
unitCode: conversion.unitCode,
|
|
1321
|
+
toBaseFactor: conversion.toBaseFactor,
|
|
1322
|
+
sortOrder: conversion.sortOrder,
|
|
1323
|
+
isActive: conversion.isActive,
|
|
1324
|
+
}),
|
|
1325
|
+
);
|
|
1279
1326
|
persistedConversions.push({
|
|
1280
1327
|
id: conversion.id,
|
|
1281
1328
|
unitCode: conversion.unitCode,
|
|
@@ -1766,23 +1813,29 @@ function ProductOptionsSection({ values, setValue }: ProductFormGroupProps) {
|
|
|
1766
1813
|
|
|
1767
1814
|
const handleDeleteSchema = React.useCallback(
|
|
1768
1815
|
async (id: string) => {
|
|
1816
|
+
const target = schemaTemplates.find((entry) => entry.id === id);
|
|
1817
|
+
const lockVersion = target?.updatedAt ?? target?.updated_at ?? null;
|
|
1769
1818
|
try {
|
|
1770
|
-
await
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1819
|
+
await withScopedApiRequestHeaders(
|
|
1820
|
+
buildOptimisticLockHeader(lockVersion),
|
|
1821
|
+
() => deleteCrud("catalog/option-schemas", id, {
|
|
1822
|
+
errorMessage: t(
|
|
1823
|
+
"catalog.products.edit.schemas.deleteError",
|
|
1824
|
+
"Failed to delete schema.",
|
|
1825
|
+
),
|
|
1826
|
+
}),
|
|
1827
|
+
);
|
|
1776
1828
|
flash(
|
|
1777
1829
|
t("catalog.products.edit.schemas.deleted", "Schema deleted."),
|
|
1778
1830
|
"success",
|
|
1779
1831
|
);
|
|
1780
1832
|
void loadSchemas();
|
|
1781
1833
|
} catch (err) {
|
|
1834
|
+
if (surfaceRecordConflict(err, t)) { void loadSchemas(); return; }
|
|
1782
1835
|
console.error("catalog.option-schemas.delete failed", err);
|
|
1783
1836
|
}
|
|
1784
1837
|
},
|
|
1785
|
-
[loadSchemas, t],
|
|
1838
|
+
[loadSchemas, schemaTemplates, t],
|
|
1786
1839
|
);
|
|
1787
1840
|
|
|
1788
1841
|
const handleSaveSchema = React.useCallback(
|
|
@@ -1814,8 +1867,25 @@ function ProductOptionsSection({ values, setValue }: ProductFormGroupProps) {
|
|
|
1814
1867
|
isActive: true,
|
|
1815
1868
|
};
|
|
1816
1869
|
if (schemaToEdit?.id) payload.id = schemaToEdit.id;
|
|
1817
|
-
|
|
1818
|
-
|
|
1870
|
+
try {
|
|
1871
|
+
if (schemaToEdit?.id) {
|
|
1872
|
+
const lockVersion = schemaToEdit.updatedAt ?? schemaToEdit.updated_at ?? null;
|
|
1873
|
+
await withScopedApiRequestHeaders(
|
|
1874
|
+
buildOptimisticLockHeader(lockVersion),
|
|
1875
|
+
() => updateCrud("catalog/option-schemas", payload),
|
|
1876
|
+
);
|
|
1877
|
+
} else {
|
|
1878
|
+
await createCrud("catalog/option-schemas", payload);
|
|
1879
|
+
}
|
|
1880
|
+
} catch (err) {
|
|
1881
|
+
if (surfaceRecordConflict(err, t)) {
|
|
1882
|
+
setSaveSchemaOpen(false);
|
|
1883
|
+
setSchemaToEdit(null);
|
|
1884
|
+
void loadSchemas();
|
|
1885
|
+
return;
|
|
1886
|
+
}
|
|
1887
|
+
throw err;
|
|
1888
|
+
}
|
|
1819
1889
|
flash(
|
|
1820
1890
|
t("catalog.products.edit.schemas.saved", "Schema saved."),
|
|
1821
1891
|
"success",
|
|
@@ -2138,18 +2208,23 @@ function ProductVariantsSection({
|
|
|
2138
2208
|
if (!confirmed) return;
|
|
2139
2209
|
setDeletingId(variant.id);
|
|
2140
2210
|
try {
|
|
2141
|
-
await
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
"
|
|
2145
|
-
|
|
2146
|
-
|
|
2211
|
+
await withScopedApiRequestHeaders(
|
|
2212
|
+
buildOptimisticLockHeader(variant.updatedAt),
|
|
2213
|
+
() =>
|
|
2214
|
+
deleteCrud("catalog/variants", variant.id, {
|
|
2215
|
+
errorMessage: t(
|
|
2216
|
+
"catalog.variants.form.deleteError",
|
|
2217
|
+
"Failed to delete variant.",
|
|
2218
|
+
),
|
|
2219
|
+
}),
|
|
2220
|
+
);
|
|
2147
2221
|
flash(
|
|
2148
2222
|
t("catalog.variants.form.deleted", "Variant deleted."),
|
|
2149
2223
|
"success",
|
|
2150
2224
|
);
|
|
2151
2225
|
onVariantDeleted(variant.id);
|
|
2152
2226
|
} catch (err) {
|
|
2227
|
+
if (surfaceRecordConflict(err, t)) return;
|
|
2153
2228
|
console.error("catalog.products.edit.variants.delete", err);
|
|
2154
2229
|
flash(
|
|
2155
2230
|
t("catalog.variants.form.deleteError", "Failed to delete variant."),
|
|
@@ -2767,6 +2842,7 @@ function readOfferSnapshots(record: Record<string, unknown>): OfferSnapshot[] {
|
|
|
2767
2842
|
getString(offer.channelName) ?? getString(offer.channel_name),
|
|
2768
2843
|
channelCode:
|
|
2769
2844
|
getString(offer.channelCode) ?? getString(offer.channel_code),
|
|
2845
|
+
updatedAt: getString(offer.updatedAt) ?? getString(offer.updated_at) ?? null,
|
|
2770
2846
|
});
|
|
2771
2847
|
}
|
|
2772
2848
|
return snapshots;
|
|
@@ -2867,6 +2943,7 @@ function mergeOfferSnapshots(
|
|
|
2867
2943
|
isActive: entry.isActive ?? previous?.isActive ?? true,
|
|
2868
2944
|
channelName: previous?.channelName ?? null,
|
|
2869
2945
|
channelCode: previous?.channelCode ?? null,
|
|
2946
|
+
updatedAt: previous?.updatedAt ?? null,
|
|
2870
2947
|
};
|
|
2871
2948
|
});
|
|
2872
2949
|
}
|
package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx
CHANGED
|
@@ -7,7 +7,9 @@ import { CrudForm, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'
|
|
|
7
7
|
import { createCrud, updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'
|
|
8
8
|
import { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'
|
|
9
9
|
import { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'
|
|
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'
|
|
12
|
+
import { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'
|
|
11
13
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
12
14
|
import { ErrorMessage, RecordNotFoundState } from '@open-mercato/ui/backend/detail'
|
|
13
15
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
@@ -67,6 +69,17 @@ type AttachmentListResponse = {
|
|
|
67
69
|
items?: ProductMediaItem[]
|
|
68
70
|
}
|
|
69
71
|
|
|
72
|
+
export function handleVariantDeleteError(
|
|
73
|
+
err: unknown,
|
|
74
|
+
t: (key: string, fallback?: string) => string,
|
|
75
|
+
): void {
|
|
76
|
+
if (surfaceRecordConflict(err, t)) return
|
|
77
|
+
const message = err instanceof Error && err.message
|
|
78
|
+
? err.message
|
|
79
|
+
: t('catalog.variants.form.deleteError', 'Failed to delete variant.')
|
|
80
|
+
flash(message, 'error')
|
|
81
|
+
}
|
|
82
|
+
|
|
70
83
|
function resolveVariantPriceLabel(prices: Record<string, VariantPriceDraft> | undefined): string | null {
|
|
71
84
|
if (!prices || typeof prices !== 'object') return null
|
|
72
85
|
const entries = Object.values(prices)
|
|
@@ -93,6 +106,10 @@ export default function EditVariantPage({ params }: { params?: { productId?: str
|
|
|
93
106
|
const [optionDefinitions, setOptionDefinitions] = React.useState<OptionDefinition[]>([])
|
|
94
107
|
const [initialValues, setInitialValues] = React.useState<VariantFormValues | null>(null)
|
|
95
108
|
const [existingPriceIds, setExistingPriceIds] = React.useState<Record<string, string>>({})
|
|
109
|
+
// price-kind id → loaded price `updatedAt`, so the price sync sends each price's
|
|
110
|
+
// own optimistic-lock version (the variant CrudForm submit scope would otherwise
|
|
111
|
+
// leak the variant's version onto the catalog/prices guard) (#2055).
|
|
112
|
+
const [existingPriceVersions, setExistingPriceVersions] = React.useState<Record<string, string | null>>({})
|
|
96
113
|
const [loading, setLoading] = React.useState(true)
|
|
97
114
|
const [error, setError] = React.useState<string | null>(null)
|
|
98
115
|
const [isNotFound, setIsNotFound] = React.useState(false)
|
|
@@ -191,10 +208,15 @@ export default function EditVariantPage({ params }: { params?: { productId?: str
|
|
|
191
208
|
const attachments = await fetchVariantAttachments(variantId!)
|
|
192
209
|
const priceDrafts = await loadVariantPrices(variantId!, priceKinds)
|
|
193
210
|
const priceIdMap: Record<string, string> = {}
|
|
211
|
+
const priceVersionMap: Record<string, string | null> = {}
|
|
194
212
|
Object.entries(priceDrafts).forEach(([kindId, draft]) => {
|
|
195
|
-
if (draft.priceId)
|
|
213
|
+
if (draft.priceId) {
|
|
214
|
+
priceIdMap[kindId] = draft.priceId
|
|
215
|
+
priceVersionMap[kindId] = draft.updatedAt ?? null
|
|
216
|
+
}
|
|
196
217
|
})
|
|
197
218
|
setExistingPriceIds(priceIdMap)
|
|
219
|
+
setExistingPriceVersions(priceVersionMap)
|
|
198
220
|
const customDefaults = extractCustomFieldEntries(record)
|
|
199
221
|
let loadedOptionDefinitions: OptionDefinition[] = []
|
|
200
222
|
if (resolvedProductId) {
|
|
@@ -300,6 +322,12 @@ export default function EditVariantPage({ params }: { params?: { productId?: str
|
|
|
300
322
|
: typeof record.customFieldsetCode === 'string'
|
|
301
323
|
? record.customFieldsetCode
|
|
302
324
|
: null,
|
|
325
|
+
updatedAt:
|
|
326
|
+
typeof record.updatedAt === 'string'
|
|
327
|
+
? record.updatedAt
|
|
328
|
+
: typeof record.updated_at === 'string'
|
|
329
|
+
? record.updated_at
|
|
330
|
+
: null,
|
|
303
331
|
...customDefaults,
|
|
304
332
|
})
|
|
305
333
|
}
|
|
@@ -429,6 +457,9 @@ export default function EditVariantPage({ params }: { params?: { productId?: str
|
|
|
429
457
|
: t('catalog.variants.form.editTitle', 'Edit variant')
|
|
430
458
|
const productVariantsHref = `/backend/catalog/products/${currentProductId}#variants`
|
|
431
459
|
|
|
460
|
+
// When the variant was deleted (e.g. concurrently in another tab) the GET
|
|
461
|
+
// returns no record. Render a dedicated not-found state with a recovery link
|
|
462
|
+
// instead of an empty CrudForm that throws runtime errors (#2055 QA).
|
|
432
463
|
if (isNotFound) {
|
|
433
464
|
return (
|
|
434
465
|
<Page>
|
|
@@ -549,6 +580,7 @@ export default function EditVariantPage({ params }: { params?: { productId?: str
|
|
|
549
580
|
priceKinds,
|
|
550
581
|
priceDrafts: values.prices ?? {},
|
|
551
582
|
existingPriceIds,
|
|
583
|
+
existingPriceVersions,
|
|
552
584
|
productId: currentProductId,
|
|
553
585
|
variantId,
|
|
554
586
|
taxRates,
|
|
@@ -560,9 +592,14 @@ export default function EditVariantPage({ params }: { params?: { productId?: str
|
|
|
560
592
|
router.push(productVariantsHref)
|
|
561
593
|
}}
|
|
562
594
|
onDelete={async () => {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
595
|
+
try {
|
|
596
|
+
await deleteCrud('catalog/variants', variantId!, {
|
|
597
|
+
errorMessage: t('catalog.variants.form.deleteError', 'Failed to delete variant.'),
|
|
598
|
+
})
|
|
599
|
+
} catch (err) {
|
|
600
|
+
handleVariantDeleteError(err, t)
|
|
601
|
+
throw err
|
|
602
|
+
}
|
|
566
603
|
flash(t('catalog.variants.form.deleted', 'Variant deleted.'), 'success')
|
|
567
604
|
router.push(productVariantsHref)
|
|
568
605
|
}}
|
|
@@ -669,6 +706,7 @@ async function syncVariantPricesUpdate({
|
|
|
669
706
|
priceKinds,
|
|
670
707
|
priceDrafts,
|
|
671
708
|
existingPriceIds,
|
|
709
|
+
existingPriceVersions,
|
|
672
710
|
productId,
|
|
673
711
|
variantId,
|
|
674
712
|
taxRates,
|
|
@@ -679,6 +717,7 @@ async function syncVariantPricesUpdate({
|
|
|
679
717
|
priceKinds: PriceKindSummary[]
|
|
680
718
|
priceDrafts: Record<string, VariantPriceDraft>
|
|
681
719
|
existingPriceIds: Record<string, string>
|
|
720
|
+
existingPriceVersions: Record<string, string | null>
|
|
682
721
|
productId: string
|
|
683
722
|
variantId: string
|
|
684
723
|
taxRates: TaxRateSummary[]
|
|
@@ -700,10 +739,17 @@ async function syncVariantPricesUpdate({
|
|
|
700
739
|
const draft = priceDrafts?.[kind.id]
|
|
701
740
|
const amount = typeof draft?.amount === 'string' ? draft.amount.trim() : ''
|
|
702
741
|
const existingId = draft?.priceId ?? existingPriceIds[kind.id]
|
|
742
|
+
// The price's own version — overrides the variant header the parent CrudForm
|
|
743
|
+
// submit scope put on the stack, so the catalog/prices guard compares the
|
|
744
|
+
// right row (otherwise a stale/false 409). #2055.
|
|
745
|
+
const lockVersion = draft?.updatedAt ?? existingPriceVersions[kind.id] ?? null
|
|
703
746
|
if (!amount) {
|
|
704
747
|
if (existingId) {
|
|
705
748
|
try {
|
|
706
|
-
await
|
|
749
|
+
await withScopedApiRequestHeaders(
|
|
750
|
+
buildOptimisticLockHeader(lockVersion),
|
|
751
|
+
() => deleteCrud('catalog/prices', existingId),
|
|
752
|
+
)
|
|
707
753
|
} catch (err) {
|
|
708
754
|
console.error('catalog.prices.delete', err)
|
|
709
755
|
}
|
|
@@ -723,7 +769,10 @@ async function syncVariantPricesUpdate({
|
|
|
723
769
|
if (kind.displayMode === 'including-tax') payload.unitPriceGross = numeric
|
|
724
770
|
else payload.unitPriceNet = numeric
|
|
725
771
|
if (existingId) {
|
|
726
|
-
await
|
|
772
|
+
await withScopedApiRequestHeaders(
|
|
773
|
+
buildOptimisticLockHeader(lockVersion),
|
|
774
|
+
() => updateCrud('catalog/prices', { id: existingId, ...payload }),
|
|
775
|
+
)
|
|
727
776
|
} else {
|
|
728
777
|
await createCrud('catalog/prices', payload)
|
|
729
778
|
}
|