@open-mercato/core 0.6.5-develop.4534.1.b459babe6d → 0.6.5-develop.4544.1.71c003c861
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/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/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/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/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/backend/profile/communication-channels/page.tsx +5 -0
- 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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
2
2
|
import type { CacheStrategy } from '@open-mercato/cache'
|
|
3
|
+
import { enforceCommandOptimisticLock } from '@open-mercato/shared/lib/crud/optimistic-lock-command'
|
|
3
4
|
import { Perspective, RolePerspective } from '../data/entities'
|
|
4
5
|
import type {
|
|
5
6
|
PerspectiveSettings,
|
|
@@ -216,7 +217,12 @@ export async function loadPerspectivesState(
|
|
|
216
217
|
export async function saveUserPerspective(
|
|
217
218
|
em: EntityManager,
|
|
218
219
|
cache: CacheStrategy | null | undefined,
|
|
219
|
-
options: {
|
|
220
|
+
options: {
|
|
221
|
+
scope: PerspectiveScope
|
|
222
|
+
tableId: string
|
|
223
|
+
input: PerspectiveSaveInput
|
|
224
|
+
request?: Request | Headers | null
|
|
225
|
+
},
|
|
220
226
|
): Promise<ResolvedPerspective> {
|
|
221
227
|
const { scope, tableId, input } = options
|
|
222
228
|
const tenantId = scope.tenantId ?? null
|
|
@@ -235,6 +241,12 @@ export async function saveUserPerspective(
|
|
|
235
241
|
if (!entity) {
|
|
236
242
|
throw Object.assign(new Error('Perspective not found'), { code: 'NOT_FOUND' })
|
|
237
243
|
}
|
|
244
|
+
enforceCommandOptimisticLock({
|
|
245
|
+
resourceKind: 'perspectives.perspective',
|
|
246
|
+
resourceId: entity.id,
|
|
247
|
+
current: entity.updatedAt ?? null,
|
|
248
|
+
request: options.request ?? null,
|
|
249
|
+
})
|
|
238
250
|
} else {
|
|
239
251
|
entity = await em.findOne(Perspective, {
|
|
240
252
|
userId: scope.userId,
|
|
@@ -8,7 +8,6 @@ import { ErrorMessage, RecordNotFoundState } from '@open-mercato/ui/backend/deta
|
|
|
8
8
|
import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
|
|
9
9
|
import { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'
|
|
10
10
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
11
|
-
import { normalizeCrudServerError } from '@open-mercato/ui/backend/utils/serverErrors'
|
|
12
11
|
import { AvailabilityRulesEditor, type AvailabilityScheduleItemBuilder } from '@open-mercato/core/modules/planner/components/AvailabilityRulesEditor'
|
|
13
12
|
import { parseAvailabilityRuleWindow } from '@open-mercato/core/modules/planner/lib/availabilitySchedule'
|
|
14
13
|
import { extractCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields-client'
|
|
@@ -29,6 +28,7 @@ type RuleSetRecord = {
|
|
|
29
28
|
description?: string | null
|
|
30
29
|
timezone: string
|
|
31
30
|
updatedAt?: string | null
|
|
31
|
+
updated_at?: string | null
|
|
32
32
|
name_raw?: string | null
|
|
33
33
|
} & Record<string, unknown>
|
|
34
34
|
|
|
@@ -40,6 +40,7 @@ export default function PlannerAvailabilityRuleSetDetailPage({ params }: { param
|
|
|
40
40
|
const rulesetId = params?.id
|
|
41
41
|
const translate = useT()
|
|
42
42
|
const router = useRouter()
|
|
43
|
+
// optimistic-lock: AvailabilityRuleSetForm forwards optimisticLockUpdatedAt from initialValues.updatedAt (wrapper auto-derives the header on save + delete).
|
|
43
44
|
const [initialValues, setInitialValues] = React.useState<AvailabilityRuleSetFormValues | null>(null)
|
|
44
45
|
const [error, setError] = React.useState<string | null>(null)
|
|
45
46
|
const [isNotFound, setIsNotFound] = React.useState(false)
|
|
@@ -73,6 +74,11 @@ export default function PlannerAvailabilityRuleSetDetailPage({ params }: { param
|
|
|
73
74
|
name: record.name ?? record.name_raw ?? '',
|
|
74
75
|
description: record.description ?? '',
|
|
75
76
|
timezone: record.timezone ?? 'UTC',
|
|
77
|
+
updatedAt: typeof record.updatedAt === 'string'
|
|
78
|
+
? record.updatedAt
|
|
79
|
+
: typeof record.updated_at === 'string'
|
|
80
|
+
? record.updated_at
|
|
81
|
+
: null,
|
|
76
82
|
...customFields,
|
|
77
83
|
})
|
|
78
84
|
}
|
|
@@ -106,19 +112,15 @@ export default function PlannerAvailabilityRuleSetDetailPage({ params }: { param
|
|
|
106
112
|
|
|
107
113
|
const handleDelete = React.useCallback(async () => {
|
|
108
114
|
if (!rulesetId) return
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
normalized.message ?? translate('planner.availabilityRuleSets.form.errors.delete', 'Failed to delete schedule.'),
|
|
119
|
-
'error',
|
|
120
|
-
)
|
|
121
|
-
}
|
|
115
|
+
// Let a non-ok DELETE (e.g. the 409 optimistic-lock conflict) propagate so
|
|
116
|
+
// CrudForm surfaces the unified conflict bar and skips its success toast.
|
|
117
|
+
// Swallowing the error here made CrudForm treat the delete as successful and
|
|
118
|
+
// show a false "Schedule deleted." toast even though the record was kept.
|
|
119
|
+
await deleteCrud('planner/availability-rule-sets', rulesetId, {
|
|
120
|
+
errorMessage: translate('planner.availabilityRuleSets.form.errors.delete', 'Failed to delete schedule.'),
|
|
121
|
+
})
|
|
122
|
+
flash(translate('planner.availabilityRuleSets.form.flash.deleted', 'Schedule deleted.'), 'success')
|
|
123
|
+
router.push('/backend/planner/availability-rulesets')
|
|
122
124
|
}, [router, rulesetId, translate])
|
|
123
125
|
|
|
124
126
|
const buildScheduleItems: AvailabilityScheduleItemBuilder = React.useCallback(({ availabilityRules, bookedEvents, translate: translateLabel }) => {
|
|
@@ -9,8 +9,9 @@ import { markdownToPlainText } from '@open-mercato/ui/backend/markdown/markdownT
|
|
|
9
9
|
import { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'
|
|
10
10
|
import { RowActions } from '@open-mercato/ui/backend/RowActions'
|
|
11
11
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
12
|
-
import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
|
|
12
|
+
import { readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
|
|
13
13
|
import { deleteCrud } from '@open-mercato/ui/backend/utils/crud'
|
|
14
|
+
import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
|
|
14
15
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
15
16
|
import { normalizeCrudServerError } from '@open-mercato/ui/backend/utils/serverErrors'
|
|
16
17
|
import { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
|
|
@@ -126,7 +127,10 @@ export default function PlannerAvailabilityRuleSetsPage() {
|
|
|
126
127
|
})
|
|
127
128
|
if (!confirmed) return
|
|
128
129
|
try {
|
|
129
|
-
|
|
130
|
+
const headers = buildOptimisticLockHeader(entry.updatedAt)
|
|
131
|
+
await withScopedApiRequestHeaders(headers, () => (
|
|
132
|
+
deleteCrud('planner/availability-rule-sets', entry.id, { errorMessage: labels.errors.delete })
|
|
133
|
+
))
|
|
130
134
|
flash(labels.messages.deleted, 'success')
|
|
131
135
|
handleRefresh()
|
|
132
136
|
} catch (error) {
|
|
@@ -237,4 +241,3 @@ function mapRuleSet(item: Record<string, unknown>): RuleSetRow {
|
|
|
237
241
|
updatedAt,
|
|
238
242
|
}, item)
|
|
239
243
|
}
|
|
240
|
-
|
|
@@ -12,6 +12,7 @@ export type AvailabilityRuleSetFormValues = {
|
|
|
12
12
|
name?: string
|
|
13
13
|
description?: string | null
|
|
14
14
|
timezone?: string
|
|
15
|
+
updatedAt?: string | null
|
|
15
16
|
} & Record<string, unknown>
|
|
16
17
|
|
|
17
18
|
export type AvailabilityRuleSetFormProps = {
|
|
@@ -92,6 +93,8 @@ export function AvailabilityRuleSetForm(props: AvailabilityRuleSetFormProps) {
|
|
|
92
93
|
groups={groups}
|
|
93
94
|
entityId={E.planner.planner_availability_rule_set}
|
|
94
95
|
initialValues={initialValues}
|
|
96
|
+
hideFooterActions
|
|
97
|
+
optimisticLockUpdatedAt={initialValues.updatedAt}
|
|
95
98
|
onSubmit={onSubmit}
|
|
96
99
|
onDelete={onDelete}
|
|
97
100
|
isLoading={isLoading}
|
|
@@ -14,8 +14,9 @@ import {
|
|
|
14
14
|
SelectValue,
|
|
15
15
|
} from '@open-mercato/ui/primitives/select'
|
|
16
16
|
import { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'
|
|
17
|
-
import { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
|
|
17
|
+
import { apiCall, apiCallOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
|
|
18
18
|
import { createCrud, deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'
|
|
19
|
+
import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
|
|
19
20
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
20
21
|
import { Spinner } from '@open-mercato/ui/primitives/spinner'
|
|
21
22
|
import { ComboboxInput, TimePicker } from '@open-mercato/ui/backend/inputs'
|
|
@@ -53,12 +54,16 @@ type AvailabilityRule = {
|
|
|
53
54
|
unavailabilityReasonEntryId?: string | null
|
|
54
55
|
unavailabilityReasonValue?: string | null
|
|
55
56
|
createdAt?: string | null
|
|
57
|
+
updatedAt?: string | null
|
|
58
|
+
updated_at?: string | null
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
type AvailabilityRuleSet = {
|
|
59
62
|
id: string
|
|
60
63
|
name: string
|
|
61
64
|
timezone: string
|
|
65
|
+
updatedAt?: string | null
|
|
66
|
+
updated_at?: string | null
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
export type AvailabilityBookedEvent = {
|
|
@@ -95,6 +100,14 @@ type RuleSetFormValues = {
|
|
|
95
100
|
}
|
|
96
101
|
type WeeklyWindows = TimeWindow[][]
|
|
97
102
|
|
|
103
|
+
function withOptimisticLockForRule<T>(rule: AvailabilityRule, mutation: () => Promise<T>): Promise<T> {
|
|
104
|
+
return withScopedApiRequestHeaders(buildOptimisticLockHeader(rule.updatedAt ?? rule.updated_at ?? null), mutation)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function withOptimisticLockForRuleSet<T>(ruleSet: AvailabilityRuleSet | null | undefined, mutation: () => Promise<T>): Promise<T> {
|
|
108
|
+
return withScopedApiRequestHeaders(buildOptimisticLockHeader(ruleSet?.updatedAt ?? ruleSet?.updated_at ?? null), mutation)
|
|
109
|
+
}
|
|
110
|
+
|
|
98
111
|
const DAY_LABELS = [
|
|
99
112
|
{ code: 'SU', short: 'S', nameKey: 'schedule.weekday.sunday', fallback: 'Sunday' },
|
|
100
113
|
{ code: 'MO', short: 'M', nameKey: 'schedule.weekday.monday', fallback: 'Monday' },
|
|
@@ -886,16 +899,21 @@ export function AvailabilityRulesEditor({
|
|
|
886
899
|
try {
|
|
887
900
|
const updates: Array<Promise<unknown>> = []
|
|
888
901
|
rulesToUpdate.forEach((rule) => {
|
|
889
|
-
updates.push(
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
902
|
+
updates.push(withOptimisticLockForRule(rule, () => (
|
|
903
|
+
updateCrud('planner/availability', {
|
|
904
|
+
id: rule.id,
|
|
905
|
+
timezone: trimmedTimezone,
|
|
906
|
+
})
|
|
907
|
+
)))
|
|
893
908
|
})
|
|
894
909
|
if (rulesetTimezoneId) {
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
910
|
+
const ruleSet = ruleSets.find((entry) => entry.id === rulesetTimezoneId) ?? null
|
|
911
|
+
updates.push(withOptimisticLockForRuleSet(ruleSet, () => (
|
|
912
|
+
updateCrud('planner/availability-rule-sets', {
|
|
913
|
+
id: rulesetTimezoneId,
|
|
914
|
+
timezone: trimmedTimezone,
|
|
915
|
+
})
|
|
916
|
+
)))
|
|
899
917
|
}
|
|
900
918
|
if (updates.length) {
|
|
901
919
|
await Promise.all(updates)
|
|
@@ -915,6 +933,7 @@ export function AvailabilityRulesEditor({
|
|
|
915
933
|
listLabels.timezoneSaveError,
|
|
916
934
|
refreshAvailability,
|
|
917
935
|
refreshRuleSetRules,
|
|
936
|
+
ruleSets,
|
|
918
937
|
effectiveRulesetId,
|
|
919
938
|
subjectId,
|
|
920
939
|
subjectType,
|
|
@@ -979,8 +998,14 @@ export function AvailabilityRulesEditor({
|
|
|
979
998
|
}
|
|
980
999
|
try {
|
|
981
1000
|
const idsToDelete = selectCustomRuleIdsToDelete('reset', availabilityRules)
|
|
1001
|
+
const idsToDeleteSet = new Set(idsToDelete)
|
|
982
1002
|
await Promise.all(
|
|
983
|
-
|
|
1003
|
+
availabilityRules
|
|
1004
|
+
.filter((rule) => idsToDeleteSet.has(rule.id))
|
|
1005
|
+
.map((rule) => withOptimisticLockForRule(
|
|
1006
|
+
rule,
|
|
1007
|
+
() => deleteCrud('planner/availability', rule.id, { errorMessage: listLabels.saveWeeklyError }),
|
|
1008
|
+
)),
|
|
984
1009
|
)
|
|
985
1010
|
setCustomOverridesEnabled(false)
|
|
986
1011
|
await refreshAvailability()
|
|
@@ -996,8 +1021,14 @@ export function AvailabilityRulesEditor({
|
|
|
996
1021
|
// Switching preserves saved custom hours (#2325); only an explicit reset clears them.
|
|
997
1022
|
const idsToDelete = selectCustomRuleIdsToDelete('switch', availabilityRules)
|
|
998
1023
|
if (idsToDelete.length) {
|
|
1024
|
+
const idsToDeleteSet = new Set(idsToDelete)
|
|
999
1025
|
await Promise.all(
|
|
1000
|
-
|
|
1026
|
+
availabilityRules
|
|
1027
|
+
.filter((rule) => idsToDeleteSet.has(rule.id))
|
|
1028
|
+
.map((rule) => withOptimisticLockForRule(
|
|
1029
|
+
rule,
|
|
1030
|
+
() => deleteCrud('planner/availability', rule.id, { errorMessage: listLabels.saveWeeklyError }),
|
|
1031
|
+
)),
|
|
1001
1032
|
)
|
|
1002
1033
|
}
|
|
1003
1034
|
setSelectedRulesetId(nextId)
|
|
@@ -1030,7 +1061,11 @@ export function AvailabilityRulesEditor({
|
|
|
1030
1061
|
variant: 'destructive',
|
|
1031
1062
|
}),
|
|
1032
1063
|
deleteRuleSet: async (id) => {
|
|
1033
|
-
|
|
1064
|
+
// Version-check the schedule delete (the list page already does; the editor
|
|
1065
|
+
// previously sent no header → last-write-wins on delete). #2055 round-5.
|
|
1066
|
+
await withOptimisticLockForRuleSet(selected, () => (
|
|
1067
|
+
deleteCrud('planner/availability-rule-sets', id, { errorMessage: listLabels.ruleSetDeleteError })
|
|
1068
|
+
))
|
|
1034
1069
|
},
|
|
1035
1070
|
clearAssignment: async () => {
|
|
1036
1071
|
setCustomOverridesEnabled(false)
|
|
@@ -1258,9 +1293,12 @@ export function AvailabilityRulesEditor({
|
|
|
1258
1293
|
}, { errorMessage: listLabels.saveDateError })
|
|
1259
1294
|
} else {
|
|
1260
1295
|
const rulesToDelete = editorRules
|
|
1261
|
-
const
|
|
1296
|
+
const uniqueRulesById = new Map(rulesToDelete.map((rule) => [rule.id, rule]))
|
|
1262
1297
|
await Promise.all(
|
|
1263
|
-
|
|
1298
|
+
Array.from(uniqueRulesById.values()).map((rule) => withOptimisticLockForRule(
|
|
1299
|
+
rule,
|
|
1300
|
+
() => deleteCrud('planner/availability', rule.id, { errorMessage: listLabels.saveDateError }),
|
|
1301
|
+
)),
|
|
1264
1302
|
)
|
|
1265
1303
|
|
|
1266
1304
|
const creations: Array<Promise<unknown>> = []
|
|
@@ -1607,7 +1645,12 @@ export function AvailabilityRulesEditor({
|
|
|
1607
1645
|
variant="outline"
|
|
1608
1646
|
size="icon"
|
|
1609
1647
|
onClick={async () => {
|
|
1610
|
-
await Promise.all(
|
|
1648
|
+
await Promise.all(
|
|
1649
|
+
rules.map((rule) => withOptimisticLockForRule(
|
|
1650
|
+
rule,
|
|
1651
|
+
() => deleteCrud('planner/availability', rule.id),
|
|
1652
|
+
)),
|
|
1653
|
+
)
|
|
1611
1654
|
await refreshAvailability()
|
|
1612
1655
|
await refreshRuleSetRules()
|
|
1613
1656
|
}}
|
|
@@ -12,6 +12,8 @@ import { Input } from '@open-mercato/ui/primitives/input'
|
|
|
12
12
|
import { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'
|
|
13
13
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
14
14
|
import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
|
|
15
|
+
import { withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
|
|
16
|
+
import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
|
|
15
17
|
import { parseAvailabilityRuleWindow } from '@open-mercato/core/modules/planner/lib/availabilitySchedule'
|
|
16
18
|
import { GanttChart } from 'lucide-react'
|
|
17
19
|
|
|
@@ -27,6 +29,8 @@ export type AvailabilityRule = {
|
|
|
27
29
|
kind?: 'availability' | 'unavailability'
|
|
28
30
|
note?: string | null
|
|
29
31
|
createdAt?: string | null
|
|
32
|
+
updatedAt?: string | null
|
|
33
|
+
updated_at?: string | null
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
export type AvailabilityScheduleItemBuilder = (params: {
|
|
@@ -368,9 +372,12 @@ export function AvailabilitySchedule({
|
|
|
368
372
|
exdates: normalizeExdatesInput(values.exdates),
|
|
369
373
|
}
|
|
370
374
|
if (editingRule) {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
375
|
+
const headers = buildOptimisticLockHeader(editingRule.updatedAt ?? editingRule.updated_at ?? null)
|
|
376
|
+
await withScopedApiRequestHeaders(headers, () => (
|
|
377
|
+
updateCrud('planner/availability', { id: editingRule.id, ...payload }, {
|
|
378
|
+
errorMessage: availabilityLabels.updateError,
|
|
379
|
+
})
|
|
380
|
+
))
|
|
374
381
|
flash(availabilityLabels.updatedFlash, 'success')
|
|
375
382
|
} else {
|
|
376
383
|
await createCrud('planner/availability', payload, {
|
|
@@ -386,10 +393,17 @@ export function AvailabilitySchedule({
|
|
|
386
393
|
|
|
387
394
|
const handleAvailabilityDelete = React.useCallback(async () => {
|
|
388
395
|
if (!editingRule) return
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
396
|
+
const headers = buildOptimisticLockHeader(editingRule.updatedAt ?? editingRule.updated_at ?? null)
|
|
397
|
+
await withScopedApiRequestHeaders(headers, () => (
|
|
398
|
+
deleteCrud('planner/availability', editingRule.id, {
|
|
399
|
+
errorMessage: availabilityLabels.deleteError,
|
|
400
|
+
})
|
|
401
|
+
))
|
|
402
|
+
// Success/conflict UX is owned by the host CrudForm (it flashes delete success
|
|
403
|
+
// and surfaces an optimistic-lock 409 on the conflict bar). Do NOT flash success
|
|
404
|
+
// here: deleteCrud throws on a 409 so this line only ran on a real delete, but the
|
|
405
|
+
// extra toast duplicated CrudForm's and read as a misleading success (#2409). The
|
|
406
|
+
// side effects below still run only after a successful delete.
|
|
393
407
|
setDialogOpen(false)
|
|
394
408
|
setEditingRule(null)
|
|
395
409
|
setSlotSeed(null)
|
|
@@ -477,6 +491,7 @@ export function AvailabilitySchedule({
|
|
|
477
491
|
embedded
|
|
478
492
|
fields={availabilityFields}
|
|
479
493
|
initialValues={availabilityInitialValues}
|
|
494
|
+
optimisticLockUpdatedAt={editingRule?.updatedAt ?? editingRule?.updated_at ?? null}
|
|
480
495
|
submitLabel={editingRule ? availabilityLabels.submitSave : availabilityLabels.submitCreate}
|
|
481
496
|
onSubmit={handleAvailabilitySubmit}
|
|
482
497
|
onDelete={editingRule ? handleAvailabilityDelete : undefined}
|
|
@@ -113,6 +113,7 @@ export class HybridQueryEngine implements QueryEngine {
|
|
|
113
113
|
private customFieldKeysCache = new Map<string, { expiresAt: number; value: string[] }>()
|
|
114
114
|
private customFieldKeysTtlMs: number
|
|
115
115
|
private columnCache = new Map<string, boolean>()
|
|
116
|
+
private customEntityCache = new Map<string, boolean>()
|
|
116
117
|
private debugVerbosity: boolean | null = null
|
|
117
118
|
private sqlDebugEnabled: boolean | null = null
|
|
118
119
|
private forcePartialIndexEnabled: boolean | null = null
|
|
@@ -973,6 +974,9 @@ export class HybridQueryEngine implements QueryEngine {
|
|
|
973
974
|
}
|
|
974
975
|
|
|
975
976
|
private async isCustomEntity(entity: string): Promise<boolean> {
|
|
977
|
+
const cached = this.customEntityCache.get(entity)
|
|
978
|
+
if (cached !== undefined) return cached
|
|
979
|
+
let result = false
|
|
976
980
|
try {
|
|
977
981
|
const db = this.getDb() as any
|
|
978
982
|
const row = await db
|
|
@@ -981,6 +985,36 @@ export class HybridQueryEngine implements QueryEngine {
|
|
|
981
985
|
.where('entity_id', '=', entity)
|
|
982
986
|
.where('is_active', '=', true)
|
|
983
987
|
.executeTakeFirst()
|
|
988
|
+
if (row) {
|
|
989
|
+
result = true
|
|
990
|
+
} else {
|
|
991
|
+
// Read/write symmetry. Records written through the entities data engine
|
|
992
|
+
// (`de.createCustomEntityRecord`) always land in `custom_entities_storage`,
|
|
993
|
+
// even for module-declared custom entities whose id is also a frozen system
|
|
994
|
+
// id — those are NEVER registered in `custom_entities` (install treats a
|
|
995
|
+
// system id as non-registrable). Without this fallback the query routes to
|
|
996
|
+
// the empty ORM/index path and those records are write-only (created with
|
|
997
|
+
// 200 but unreadable on the edit form). A real ORM entity never writes rows
|
|
998
|
+
// to `custom_entities_storage`, so this can only ever re-classify genuine
|
|
999
|
+
// doc-storage entities — it cannot misroute table-backed entities.
|
|
1000
|
+
result = await this.hasCustomEntityStorageRows(entity)
|
|
1001
|
+
}
|
|
1002
|
+
} catch {
|
|
1003
|
+
result = false
|
|
1004
|
+
}
|
|
1005
|
+
this.customEntityCache.set(entity, result)
|
|
1006
|
+
return result
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
private async hasCustomEntityStorageRows(entity: string): Promise<boolean> {
|
|
1010
|
+
try {
|
|
1011
|
+
const db = this.getDb() as any
|
|
1012
|
+
const row = await db
|
|
1013
|
+
.selectFrom('custom_entities_storage')
|
|
1014
|
+
.select(sql<number>`1`.as('one'))
|
|
1015
|
+
.where('entity_type', '=', entity)
|
|
1016
|
+
.limit(1)
|
|
1017
|
+
.executeTakeFirst()
|
|
984
1018
|
return !!row
|
|
985
1019
|
} catch {
|
|
986
1020
|
return false
|
|
@@ -54,8 +54,13 @@ export default function ResourcesResourceTypeEditPage({ params }: { params?: { i
|
|
|
54
54
|
? item.appearanceColor
|
|
55
55
|
: typeof item.appearance_color === 'string'
|
|
56
56
|
? item.appearance_color
|
|
57
|
-
|
|
57
|
+
: null,
|
|
58
58
|
},
|
|
59
|
+
updatedAt: typeof item.updatedAt === 'string'
|
|
60
|
+
? item.updatedAt
|
|
61
|
+
: typeof item.updated_at === 'string'
|
|
62
|
+
? item.updated_at
|
|
63
|
+
: null,
|
|
59
64
|
...customValues,
|
|
60
65
|
})
|
|
61
66
|
setResourceCount(typeof item.resourceCount === 'number'
|
|
@@ -104,6 +109,7 @@ export default function ResourcesResourceTypeEditPage({ params }: { params?: { i
|
|
|
104
109
|
{error ? (
|
|
105
110
|
<ErrorMessage label={error} />
|
|
106
111
|
) : null}
|
|
112
|
+
{/* optimistic-lock: ResourceTypeCrudForm forwards optimisticLockUpdatedAt from initialValues.updatedAt (auto-derives the header on save + delete). */}
|
|
107
113
|
<ResourceTypeCrudForm
|
|
108
114
|
mode="edit"
|
|
109
115
|
initialValues={initialValues ?? { id: resourceTypeId, name: '', description: '', appearance: { icon: null, color: null } }}
|
|
@@ -10,8 +10,9 @@ import { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/Dat
|
|
|
10
10
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
11
11
|
import { RowActions } from '@open-mercato/ui/backend/RowActions'
|
|
12
12
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
13
|
-
import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
|
|
13
|
+
import { readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
|
|
14
14
|
import { deleteCrud } from '@open-mercato/ui/backend/utils/crud'
|
|
15
|
+
import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
|
|
15
16
|
import { renderDictionaryColor, renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'
|
|
16
17
|
import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
|
|
17
18
|
import { Package } from 'lucide-react'
|
|
@@ -228,7 +229,10 @@ export default function ResourcesResourceTypesPage() {
|
|
|
228
229
|
})
|
|
229
230
|
if (!confirmed) return
|
|
230
231
|
try {
|
|
231
|
-
|
|
232
|
+
const headers = buildOptimisticLockHeader(entry.updatedAt)
|
|
233
|
+
await withScopedApiRequestHeaders(headers, () => (
|
|
234
|
+
deleteCrud('resources/resource-types', entry.id, { errorMessage: translations.errors.delete })
|
|
235
|
+
))
|
|
232
236
|
flash(translations.messages.deleted, 'success')
|
|
233
237
|
handleRefresh()
|
|
234
238
|
} catch (error) {
|
|
@@ -314,4 +318,3 @@ function mapApiResourceType(item: Record<string, unknown>): ResourceTypeRow {
|
|
|
314
318
|
: 0
|
|
315
319
|
return withDataTableNamespaces({ id, name, description, appearanceIcon, appearanceColor, updatedAt, resourceCount }, item)
|
|
316
320
|
}
|
|
317
|
-
|
|
@@ -5,7 +5,8 @@ import { useRouter, useSearchParams } from 'next/navigation'
|
|
|
5
5
|
import { Page, PageBody } from '@open-mercato/ui/backend/Page'
|
|
6
6
|
import { FormHeader } from '@open-mercato/ui/backend/forms'
|
|
7
7
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
8
|
-
import { apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
|
|
8
|
+
import { apiCallOrThrow, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
|
|
9
|
+
import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
|
|
9
10
|
import { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'
|
|
10
11
|
import { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'
|
|
11
12
|
import { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'
|
|
@@ -446,6 +447,12 @@ export default function ResourcesResourceDetailPage({ params }: { params?: { id?
|
|
|
446
447
|
capacityUnitValue: resource.capacityUnitValue ?? '',
|
|
447
448
|
appearance: { icon: resource.appearanceIcon ?? null, color: resource.appearanceColor ?? null },
|
|
448
449
|
isActive: resource.isActive ?? true,
|
|
450
|
+
updatedAt:
|
|
451
|
+
typeof resource.updatedAt === 'string'
|
|
452
|
+
? resource.updatedAt
|
|
453
|
+
: typeof resource.updated_at === 'string'
|
|
454
|
+
? resource.updated_at
|
|
455
|
+
: null,
|
|
449
456
|
customFieldsetCode: resource.resourceTypeId
|
|
450
457
|
? resolveFieldsetCode(resource.resourceTypeId)
|
|
451
458
|
: RESOURCES_RESOURCE_FIELDSET_DEFAULT,
|
|
@@ -472,12 +479,20 @@ export default function ResourcesResourceDetailPage({ params }: { params?: { id?
|
|
|
472
479
|
|
|
473
480
|
const handleRulesetChange = React.useCallback(async (nextId: string | null) => {
|
|
474
481
|
if (!resourceId) return
|
|
475
|
-
|
|
482
|
+
const updateSchedule = () => updateCrud('resources/resources', { id: resourceId, availabilityRuleSetId: nextId }, {
|
|
476
483
|
errorMessage: t('resources.resources.availability.ruleset.updateError', 'Failed to update schedule.'),
|
|
477
484
|
})
|
|
485
|
+
const resourceOptimisticLockHeader = buildOptimisticLockHeader(
|
|
486
|
+
typeof initialValues?.updatedAt === 'string' ? initialValues.updatedAt : null,
|
|
487
|
+
)
|
|
488
|
+
if (Object.keys(resourceOptimisticLockHeader).length > 0) {
|
|
489
|
+
await withScopedApiRequestHeaders(resourceOptimisticLockHeader, updateSchedule)
|
|
490
|
+
} else {
|
|
491
|
+
await updateSchedule()
|
|
492
|
+
}
|
|
478
493
|
setAvailabilityRuleSetId(nextId)
|
|
479
494
|
flash(t('resources.resources.availability.ruleset.updateSuccess', 'Schedule updated.'), 'success')
|
|
480
|
-
}, [resourceId, t])
|
|
495
|
+
}, [initialValues?.updatedAt, resourceId, t])
|
|
481
496
|
|
|
482
497
|
const resourceTitle =
|
|
483
498
|
typeof initialValues?.name === 'string' && initialValues.name.trim().length > 0
|
|
@@ -647,6 +662,11 @@ export default function ResourcesResourceDetailPage({ params }: { params?: { id?
|
|
|
647
662
|
successRedirect="/backend/resources/resources"
|
|
648
663
|
formConfig={formConfig}
|
|
649
664
|
initialValues={initialValues ?? undefined}
|
|
665
|
+
optimisticLockUpdatedAt={
|
|
666
|
+
typeof initialValues?.updatedAt === 'string'
|
|
667
|
+
? initialValues.updatedAt
|
|
668
|
+
: null
|
|
669
|
+
}
|
|
650
670
|
onSubmit={handleSubmit}
|
|
651
671
|
onDelete={handleDelete}
|
|
652
672
|
isLoading={!initialValues}
|
|
@@ -9,8 +9,9 @@ import { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/Dat
|
|
|
9
9
|
import { RowActions } from '@open-mercato/ui/backend/RowActions'
|
|
10
10
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
11
11
|
import { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'
|
|
12
|
-
import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
|
|
12
|
+
import { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'
|
|
13
13
|
import { deleteCrud } from '@open-mercato/ui/backend/utils/crud'
|
|
14
|
+
import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'
|
|
14
15
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
15
16
|
import type { FilterDef, FilterOption, FilterValues } from '@open-mercato/ui/backend/FilterOverlay'
|
|
16
17
|
import type { TagOption } from '@open-mercato/ui/backend/detail'
|
|
@@ -31,6 +32,7 @@ type ResourceRow = {
|
|
|
31
32
|
isActive: boolean
|
|
32
33
|
appearanceIcon?: string | null
|
|
33
34
|
appearanceColor?: string | null
|
|
35
|
+
updatedAt?: string | null
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
type ResourceTypeRow = {
|
|
@@ -349,9 +351,12 @@ export default function ResourcesResourcesPage() {
|
|
|
349
351
|
})
|
|
350
352
|
if (!confirmed) return
|
|
351
353
|
try {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
354
|
+
const headers = buildOptimisticLockHeader(row.updatedAt)
|
|
355
|
+
await withScopedApiRequestHeaders(headers, () => (
|
|
356
|
+
deleteCrud('resources/resources', row.id, {
|
|
357
|
+
errorMessage: t('resources.resources.list.error.delete', 'Failed to delete resource.'),
|
|
358
|
+
})
|
|
359
|
+
))
|
|
355
360
|
flash(t('resources.resources.list.flash.deleted', 'Resource deleted.'), 'success')
|
|
356
361
|
setPage(1)
|
|
357
362
|
router.refresh()
|
|
@@ -536,6 +541,11 @@ function mapApiResource(item: Record<string, unknown>): ResourceRow {
|
|
|
536
541
|
? item.appearance_color
|
|
537
542
|
: null
|
|
538
543
|
const tags = Array.isArray(item.tags) ? item.tags as TagOption[] : []
|
|
544
|
+
const updatedAt = typeof item.updatedAt === 'string'
|
|
545
|
+
? item.updatedAt
|
|
546
|
+
: typeof item.updated_at === 'string'
|
|
547
|
+
? item.updated_at
|
|
548
|
+
: null
|
|
539
549
|
return withDataTableNamespaces({
|
|
540
550
|
id,
|
|
541
551
|
name,
|
|
@@ -545,5 +555,6 @@ function mapApiResource(item: Record<string, unknown>): ResourceRow {
|
|
|
545
555
|
isActive,
|
|
546
556
|
appearanceIcon,
|
|
547
557
|
appearanceColor,
|
|
558
|
+
updatedAt,
|
|
548
559
|
}, item)
|
|
549
560
|
}
|
|
@@ -316,6 +316,7 @@ export type ResourcesResourceFormProps = {
|
|
|
316
316
|
embedded?: boolean
|
|
317
317
|
successRedirect?: string
|
|
318
318
|
initialValues?: Record<string, unknown>
|
|
319
|
+
optimisticLockUpdatedAt?: string | null
|
|
319
320
|
onSubmit: (values: Record<string, unknown>) => Promise<void>
|
|
320
321
|
onDelete?: () => Promise<void>
|
|
321
322
|
isLoading?: boolean
|
|
@@ -332,6 +333,7 @@ export function ResourcesResourceForm(props: ResourcesResourceFormProps) {
|
|
|
332
333
|
embedded = false,
|
|
333
334
|
successRedirect,
|
|
334
335
|
initialValues,
|
|
336
|
+
optimisticLockUpdatedAt,
|
|
335
337
|
onSubmit,
|
|
336
338
|
onDelete,
|
|
337
339
|
isLoading,
|
|
@@ -368,6 +370,7 @@ export function ResourcesResourceForm(props: ResourcesResourceFormProps) {
|
|
|
368
370
|
fields={formConfig.fields}
|
|
369
371
|
groups={groups}
|
|
370
372
|
initialValues={initialValues}
|
|
373
|
+
optimisticLockUpdatedAt={optimisticLockUpdatedAt}
|
|
371
374
|
entityId={E.resources.resources_resource}
|
|
372
375
|
customFieldsetBindings={{ [E.resources.resources_resource]: { valueKey: 'customFieldsetCode' } }}
|
|
373
376
|
onSubmit={onSubmit}
|
|
@@ -13,6 +13,7 @@ export type ResourceTypeFormValues = {
|
|
|
13
13
|
name: string
|
|
14
14
|
description?: string
|
|
15
15
|
appearance?: { icon?: string | null; color?: string | null }
|
|
16
|
+
updatedAt?: string | null
|
|
16
17
|
} & Record<string, unknown>
|
|
17
18
|
|
|
18
19
|
type ResourceTypeCrudFormProps = {
|
|
@@ -118,6 +119,7 @@ export function ResourceTypeCrudForm({
|
|
|
118
119
|
groups={groups}
|
|
119
120
|
entityId={E.resources.resources_resource_type}
|
|
120
121
|
initialValues={initialValues}
|
|
122
|
+
optimisticLockUpdatedAt={mode === 'edit' ? initialValues.updatedAt : undefined}
|
|
121
123
|
isLoading={isLoading}
|
|
122
124
|
onSubmit={onSubmit}
|
|
123
125
|
onDelete={mode === 'edit' ? onDelete : undefined}
|
|
@@ -202,6 +202,12 @@ const mapUpdateResponse = (entity: any) => {
|
|
|
202
202
|
paymentMethodId: entity?.paymentMethodId ?? null,
|
|
203
203
|
paymentMethodCode: entity?.paymentMethodCode ?? null,
|
|
204
204
|
paymentMethodSnapshot: normalizeJsonRecord(entity?.paymentMethodSnapshot),
|
|
205
|
+
// Return the fresh version so the client can refresh its optimistic-lock
|
|
206
|
+
// token after a successful inline save — otherwise a second save on the same
|
|
207
|
+
// page sends the now-stale updatedAt and falsely 409s (#2055 QA).
|
|
208
|
+
updatedAt: entity?.updatedAt
|
|
209
|
+
? (entity.updatedAt instanceof Date ? entity.updatedAt.toISOString() : entity.updatedAt)
|
|
210
|
+
: null,
|
|
205
211
|
}
|
|
206
212
|
}
|
|
207
213
|
|
|
@@ -492,7 +498,13 @@ export function buildDocumentCrudOptions(binding: DocumentBinding) {
|
|
|
492
498
|
const organizationId =
|
|
493
499
|
typeof item?.organizationId === 'string' ? item.organizationId : ctx?.selectedOrganizationId ?? ctx?.auth?.orgId ?? null
|
|
494
500
|
if (orderId && tenantId && organizationId) {
|
|
495
|
-
const
|
|
501
|
+
const requestEm = ctx?.container?.resolve?.('em') as import('@mikro-orm/postgresql').EntityManager | undefined
|
|
502
|
+
// Display-only totals recalculation: run on a forked EntityManager so
|
|
503
|
+
// the order/line/adjustment entities loaded here never enter the
|
|
504
|
+
// request's Unit of Work. This guarantees a GET can never flush an
|
|
505
|
+
// UPDATE (and thus never advance `updated_at`), which would otherwise
|
|
506
|
+
// surface as a spurious optimistic-lock 409 in another tab.
|
|
507
|
+
const em = requestEm?.fork()
|
|
496
508
|
if (em) {
|
|
497
509
|
const totals = await recalculateOrderTotalsForDisplay(
|
|
498
510
|
em,
|