@open-mercato/core 0.4.2-canary-ed15f2e753 → 0.4.2-canary-e2aeb1a7bf
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/dist/generated/entities/notification/index.js +57 -0
- package/dist/generated/entities/notification/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +5 -2
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -2
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/api_docs/frontend/docs/api/page.js +3 -2
- package/dist/modules/api_docs/frontend/docs/api/page.js.map +2 -2
- package/dist/modules/api_keys/backend/api-keys/page.js +1 -1
- package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
- package/dist/modules/api_keys/setup.js +11 -0
- package/dist/modules/api_keys/setup.js.map +7 -0
- package/dist/modules/attachments/components/AttachmentLibrary.js +5 -1
- package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js +2 -0
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
- package/dist/modules/attachments/lib/assignmentDetails.js +31 -17
- package/dist/modules/attachments/lib/assignmentDetails.js.map +2 -2
- package/dist/modules/attachments/lib/partitions.js +3 -3
- package/dist/modules/attachments/lib/partitions.js.map +2 -2
- package/dist/modules/attachments/setup.js +11 -0
- package/dist/modules/attachments/setup.js.map +7 -0
- package/dist/modules/audit_logs/setup.js +12 -0
- package/dist/modules/audit_logs/setup.js.map +7 -0
- package/dist/modules/auth/api/admin/nav.js +4 -3
- package/dist/modules/auth/api/admin/nav.js.map +2 -2
- package/dist/modules/auth/api/login.js +25 -6
- package/dist/modules/auth/api/login.js.map +2 -2
- package/dist/modules/auth/api/profile/route.js +157 -0
- package/dist/modules/auth/api/profile/route.js.map +7 -0
- package/dist/modules/auth/api/reset/confirm.js +25 -2
- package/dist/modules/auth/api/reset/confirm.js.map +2 -2
- package/dist/modules/auth/api/reset.js +23 -0
- package/dist/modules/auth/api/reset.js.map +2 -2
- package/dist/modules/auth/api/sidebar/preferences/route.js +14 -9
- package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +4 -2
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/auth/profile/page.js +141 -0
- package/dist/modules/auth/backend/auth/profile/page.js.map +7 -0
- package/dist/modules/auth/backend/auth/profile/page.meta.js +13 -0
- package/dist/modules/auth/backend/auth/profile/page.meta.js.map +7 -0
- package/dist/modules/auth/backend/roles/[id]/edit/page.js +4 -1
- package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/roles/page.js +3 -3
- package/dist/modules/auth/backend/roles/page.js.map +2 -2
- package/dist/modules/auth/backend/users/[id]/edit/page.js +18 -3
- package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/users/create/page.js +15 -2
- package/dist/modules/auth/backend/users/create/page.js.map +2 -2
- package/dist/modules/auth/backend/users/page.js +3 -3
- package/dist/modules/auth/backend/users/page.js.map +2 -2
- package/dist/modules/auth/cli.js +25 -11
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/auth/commands/users.js +59 -2
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/data/validators.js +6 -3
- package/dist/modules/auth/data/validators.js.map +2 -2
- package/dist/modules/auth/frontend/login.js +112 -3
- package/dist/modules/auth/frontend/login.js.map +2 -2
- package/dist/modules/auth/frontend/reset/[token]/page.js +20 -10
- package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
- package/dist/modules/auth/lib/setup-app.js +70 -167
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/notifications.js +112 -0
- package/dist/modules/auth/notifications.js.map +7 -0
- package/dist/modules/auth/services/authService.js +24 -3
- package/dist/modules/auth/services/authService.js.map +2 -2
- package/dist/modules/auth/setup.js +11 -0
- package/dist/modules/auth/setup.js.map +7 -0
- package/dist/modules/business_rules/api/execute/route.js +7 -1
- package/dist/modules/business_rules/api/execute/route.js.map +2 -2
- package/dist/modules/business_rules/backend/rules/page.js +4 -0
- package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
- package/dist/modules/business_rules/backend/sets/page.js +3 -0
- package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
- package/dist/modules/business_rules/cli.js +2 -1
- package/dist/modules/business_rules/cli.js.map +2 -2
- package/dist/modules/business_rules/data/validators.js +0 -34
- package/dist/modules/business_rules/data/validators.js.map +2 -2
- package/dist/modules/business_rules/index.js +1 -21
- package/dist/modules/business_rules/index.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +34 -185
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/business_rules/notifications.js +28 -0
- package/dist/modules/business_rules/notifications.js.map +7 -0
- package/dist/modules/business_rules/setup.js +11 -0
- package/dist/modules/business_rules/setup.js.map +7 -0
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +37 -0
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +7 -0
- package/dist/modules/catalog/components/PriceKindSettings.js +2 -0
- package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js +2 -0
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/catalog/notifications.js +28 -0
- package/dist/modules/catalog/notifications.js.map +7 -0
- package/dist/modules/catalog/setup.js +22 -0
- package/dist/modules/catalog/setup.js.map +7 -0
- package/dist/modules/catalog/subscribers/low-stock-notification.js +38 -0
- package/dist/modules/catalog/subscribers/low-stock-notification.js.map +7 -0
- package/dist/modules/configs/cli.js +6 -0
- package/dist/modules/configs/cli.js.map +2 -2
- package/dist/modules/configs/components/CachePanel.js +4 -4
- package/dist/modules/configs/components/CachePanel.js.map +2 -2
- package/dist/modules/configs/lib/system-status.js +48 -1
- package/dist/modules/configs/lib/system-status.js.map +2 -2
- package/dist/modules/configs/lib/upgrade-actions.js +1 -302
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/configs/setup.js +16 -0
- package/dist/modules/configs/setup.js.map +7 -0
- package/dist/modules/currencies/backend/currencies/page.js +3 -0
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +2 -0
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/currencies/setup.js +16 -0
- package/dist/modules/currencies/setup.js.map +7 -0
- package/dist/modules/customers/backend/customers/companies/page.js +3 -0
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +3 -0
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/page.js +3 -0
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +31 -0
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
- package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
- package/dist/modules/customers/notifications.js +48 -0
- package/dist/modules/customers/notifications.js.map +7 -0
- package/dist/modules/customers/setup.js +36 -0
- package/dist/modules/customers/setup.js.map +7 -0
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js.map +2 -2
- package/dist/modules/dashboards/cli.js +44 -5
- package/dist/modules/dashboards/cli.js.map +2 -2
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +16 -11
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +3 -3
- package/dist/modules/dashboards/lib/role-widgets.js +58 -0
- package/dist/modules/dashboards/lib/role-widgets.js.map +7 -0
- package/dist/modules/dashboards/services/widgetDataService.js +139 -3
- package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
- package/dist/modules/dashboards/setup.js +27 -0
- package/dist/modules/dashboards/setup.js.map +7 -0
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryTable.js +2 -0
- package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
- package/dist/modules/dictionaries/setup.js +12 -0
- package/dist/modules/dictionaries/setup.js.map +7 -0
- package/dist/modules/directory/api/get/tenants/lookup.js +70 -0
- package/dist/modules/directory/api/get/tenants/lookup.js.map +7 -0
- package/dist/modules/directory/backend/directory/organizations/page.js +2 -2
- package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
- package/dist/modules/directory/setup.js +12 -0
- package/dist/modules/directory/setup.js.map +7 -0
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- package/dist/modules/entities/components/SystemEntitiesTable.js +1 -1
- package/dist/modules/entities/components/SystemEntitiesTable.js.map +2 -2
- package/dist/modules/entities/components/UserEntitiesTable.js +2 -2
- package/dist/modules/entities/components/UserEntitiesTable.js.map +2 -2
- package/dist/modules/entities/setup.js +11 -0
- package/dist/modules/entities/setup.js.map +7 -0
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +3 -3
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
- package/dist/modules/feature_toggles/components/OverridesTable.js +1 -1
- package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
- package/dist/modules/feature_toggles/setup.js +11 -0
- package/dist/modules/feature_toggles/setup.js.map +7 -0
- package/dist/modules/notifications/acl.js +11 -0
- package/dist/modules/notifications/acl.js.map +7 -0
- package/dist/modules/notifications/api/[id]/action/route.js +74 -0
- package/dist/modules/notifications/api/[id]/action/route.js.map +7 -0
- package/dist/modules/notifications/api/[id]/dismiss/route.js +15 -0
- package/dist/modules/notifications/api/[id]/dismiss/route.js.map +7 -0
- package/dist/modules/notifications/api/[id]/read/route.js +15 -0
- package/dist/modules/notifications/api/[id]/read/route.js.map +7 -0
- package/dist/modules/notifications/api/[id]/restore/route.js +53 -0
- package/dist/modules/notifications/api/[id]/restore/route.js.map +7 -0
- package/dist/modules/notifications/api/batch/route.js +17 -0
- package/dist/modules/notifications/api/batch/route.js.map +7 -0
- package/dist/modules/notifications/api/feature/route.js +17 -0
- package/dist/modules/notifications/api/feature/route.js.map +7 -0
- package/dist/modules/notifications/api/mark-all-read/route.js +35 -0
- package/dist/modules/notifications/api/mark-all-read/route.js.map +7 -0
- package/dist/modules/notifications/api/openapi.js +76 -0
- package/dist/modules/notifications/api/openapi.js.map +7 -0
- package/dist/modules/notifications/api/role/route.js +17 -0
- package/dist/modules/notifications/api/role/route.js.map +7 -0
- package/dist/modules/notifications/api/route.js +85 -0
- package/dist/modules/notifications/api/route.js.map +7 -0
- package/dist/modules/notifications/api/settings/route.js +155 -0
- package/dist/modules/notifications/api/settings/route.js.map +7 -0
- package/dist/modules/notifications/api/unread-count/route.js +38 -0
- package/dist/modules/notifications/api/unread-count/route.js.map +7 -0
- package/dist/modules/notifications/backend/config/notifications/page.js +10 -0
- package/dist/modules/notifications/backend/config/notifications/page.js.map +7 -0
- package/dist/modules/notifications/backend/config/notifications/page.meta.js +24 -0
- package/dist/modules/notifications/backend/config/notifications/page.meta.js.map +7 -0
- package/dist/modules/notifications/cli.js +16 -0
- package/dist/modules/notifications/cli.js.map +7 -0
- package/dist/modules/notifications/data/entities.js +112 -0
- package/dist/modules/notifications/data/entities.js.map +7 -0
- package/dist/modules/notifications/data/validators.js +98 -0
- package/dist/modules/notifications/data/validators.js.map +7 -0
- package/dist/modules/notifications/di.js +13 -0
- package/dist/modules/notifications/di.js.map +7 -0
- package/dist/modules/notifications/emails/NotificationEmail.js +58 -0
- package/dist/modules/notifications/emails/NotificationEmail.js.map +7 -0
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js +44 -0
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js.map +7 -0
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +220 -0
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +7 -0
- package/dist/modules/notifications/index.js +14 -0
- package/dist/modules/notifications/index.js.map +7 -0
- package/dist/modules/notifications/lib/deliveryConfig.js +107 -0
- package/dist/modules/notifications/lib/deliveryConfig.js.map +7 -0
- package/dist/modules/notifications/lib/deliveryStrategies.js +14 -0
- package/dist/modules/notifications/lib/deliveryStrategies.js.map +7 -0
- package/dist/modules/notifications/lib/events.js +12 -0
- package/dist/modules/notifications/lib/events.js.map +7 -0
- package/dist/modules/notifications/lib/notificationBuilder.js +66 -0
- package/dist/modules/notifications/lib/notificationBuilder.js.map +7 -0
- package/dist/modules/notifications/lib/notificationFactory.js +54 -0
- package/dist/modules/notifications/lib/notificationFactory.js.map +7 -0
- package/dist/modules/notifications/lib/notificationMapper.js +34 -0
- package/dist/modules/notifications/lib/notificationMapper.js.map +7 -0
- package/dist/modules/notifications/lib/notificationRecipients.js +35 -0
- package/dist/modules/notifications/lib/notificationRecipients.js.map +7 -0
- package/dist/modules/notifications/lib/notificationService.js +279 -0
- package/dist/modules/notifications/lib/notificationService.js.map +7 -0
- package/dist/modules/notifications/lib/routeHelpers.js +101 -0
- package/dist/modules/notifications/lib/routeHelpers.js.map +7 -0
- package/dist/modules/notifications/lib/safeHref.js +24 -0
- package/dist/modules/notifications/lib/safeHref.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260123000001.js +70 -0
- package/dist/modules/notifications/migrations/Migration20260123000001.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260126150000.js +37 -0
- package/dist/modules/notifications/migrations/Migration20260126150000.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260129082610.js +13 -0
- package/dist/modules/notifications/migrations/Migration20260129082610.js.map +7 -0
- package/dist/modules/notifications/subscribers/deliver-notification.js +165 -0
- package/dist/modules/notifications/subscribers/deliver-notification.js.map +7 -0
- package/dist/modules/notifications/workers/create-notification.worker.js +70 -0
- package/dist/modules/notifications/workers/create-notification.worker.js.map +7 -0
- package/dist/modules/perspectives/setup.js +12 -0
- package/dist/modules/perspectives/setup.js.map +7 -0
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
- package/dist/modules/planner/setup.js +21 -0
- package/dist/modules/planner/setup.js.map +7 -0
- package/dist/modules/query_index/cli.js +63 -7
- package/dist/modules/query_index/cli.js.map +2 -2
- package/dist/modules/query_index/components/QueryIndexesTable.js +7 -1
- package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
- package/dist/modules/query_index/setup.js +11 -0
- package/dist/modules/query_index/setup.js.map +7 -0
- package/dist/modules/resources/backend/resources/resource-types/page.js +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
- package/dist/modules/resources/setup.js +21 -0
- package/dist/modules/resources/setup.js.map +7 -0
- package/dist/modules/sales/acl.js +0 -1
- package/dist/modules/sales/acl.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +2 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +2 -0
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +0 -12
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/cli.js +2 -42
- package/dist/modules/sales/cli.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +53 -62
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +26 -0
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/sales/components/AdjustmentKindSettings.js +2 -2
- package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
- package/dist/modules/sales/components/PaymentMethodsSettings.js +2 -2
- package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
- package/dist/modules/sales/components/ShippingMethodsSettings.js +2 -2
- package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
- package/dist/modules/sales/components/TaxRatesSettings.js +2 -2
- package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +2 -0
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js +2 -0
- package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js +2 -1
- package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +2 -0
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/lib/dictionaries.js +0 -3
- package/dist/modules/sales/lib/dictionaries.js.map +2 -2
- package/dist/modules/sales/lib/seeds.js +48 -0
- package/dist/modules/sales/lib/seeds.js.map +7 -0
- package/dist/modules/sales/notifications.client.js +51 -0
- package/dist/modules/sales/notifications.client.js.map +7 -0
- package/dist/modules/sales/notifications.js +88 -0
- package/dist/modules/sales/notifications.js.map +7 -0
- package/dist/modules/sales/setup.js +99 -0
- package/dist/modules/sales/setup.js.map +7 -0
- package/dist/modules/sales/subscribers/quote-expiring-notification.js +38 -0
- package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +137 -0
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +137 -0
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/index.js +7 -0
- package/dist/modules/sales/widgets/notifications/index.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js +60 -0
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js.map +7 -0
- package/dist/modules/staff/backend/staff/team-members/page.js +1 -1
- package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js +2 -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 +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
- package/dist/modules/staff/commands/leave-requests.js +79 -0
- package/dist/modules/staff/commands/leave-requests.js.map +2 -2
- package/dist/modules/staff/notifications.js +75 -0
- package/dist/modules/staff/notifications.js.map +7 -0
- package/dist/modules/staff/setup.js +27 -0
- package/dist/modules/staff/setup.js.map +7 -0
- package/dist/modules/workflows/acl.js +0 -2
- package/dist/modules/workflows/acl.js.map +2 -2
- package/dist/modules/workflows/api/instances/route.js +6 -18
- package/dist/modules/workflows/api/instances/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/route.js +1 -6
- package/dist/modules/workflows/api/tasks/route.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.js +1 -9
- package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.js +15 -24
- package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/create/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/page.js +5 -0
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +132 -150
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/visual-editor/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.js +1 -1
- package/dist/modules/workflows/backend/events/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.js +3 -0
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.js +1 -1
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +9 -5
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/cli.js +15 -93
- package/dist/modules/workflows/cli.js.map +3 -3
- package/dist/modules/workflows/data/entities.js +1 -64
- package/dist/modules/workflows/data/entities.js.map +2 -2
- package/dist/modules/workflows/data/validators.js +0 -115
- package/dist/modules/workflows/data/validators.js.map +2 -2
- package/dist/modules/workflows/examples/checkout-demo-definition.json +5 -1
- package/dist/modules/workflows/lib/activity-executor.js +13 -75
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/graph-utils.js +2 -71
- package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
- package/dist/modules/workflows/lib/seeds.js +7 -36
- package/dist/modules/workflows/lib/seeds.js.map +2 -2
- package/dist/modules/workflows/lib/start-validator.js +23 -33
- package/dist/modules/workflows/lib/start-validator.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +57 -161
- package/dist/modules/workflows/lib/transition-handler.js.map +3 -3
- package/dist/modules/workflows/migrations/Migration20251207131955.js +76 -72
- package/dist/modules/workflows/migrations/Migration20251207131955.js.map +2 -2
- package/dist/modules/workflows/notifications.js +28 -0
- package/dist/modules/workflows/notifications.js.map +7 -0
- package/dist/modules/workflows/setup.js +16 -0
- package/dist/modules/workflows/setup.js.map +7 -0
- package/dist/modules/workflows/subscribers/task-assigned-notification.js +38 -0
- package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +7 -0
- package/generated/entities/notification/index.ts +27 -0
- package/generated/entities.ids.generated.ts +5 -2
- package/generated/entity-fields-registry.ts +2 -2
- package/package.json +2 -2
- package/src/__tests__/module-decoupling.test.ts +356 -0
- package/src/modules/api_docs/frontend/docs/api/page.tsx +3 -2
- package/src/modules/api_keys/backend/api-keys/page.tsx +1 -1
- package/src/modules/api_keys/setup.ts +9 -0
- package/src/modules/attachments/components/AttachmentLibrary.tsx +6 -2
- package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +2 -0
- package/src/modules/attachments/lib/assignmentDetails.ts +32 -16
- package/src/modules/attachments/lib/partitions.ts +3 -3
- package/src/modules/attachments/setup.ts +9 -0
- package/src/modules/audit_logs/setup.ts +10 -0
- package/src/modules/auth/README.md +1 -1
- package/src/modules/auth/__tests__/cli-setup-acl.test.ts +31 -1
- package/src/modules/auth/api/__tests__/login.test.ts +2 -0
- package/src/modules/auth/api/admin/nav.ts +10 -6
- package/src/modules/auth/api/login.ts +26 -7
- package/src/modules/auth/api/profile/route.ts +163 -0
- package/src/modules/auth/api/reset/confirm.ts +25 -2
- package/src/modules/auth/api/reset.ts +23 -0
- package/src/modules/auth/api/sidebar/preferences/route.ts +21 -12
- package/src/modules/auth/api/users/route.ts +5 -2
- package/src/modules/auth/backend/auth/profile/page.meta.ts +9 -0
- package/src/modules/auth/backend/auth/profile/page.tsx +174 -0
- package/src/modules/auth/backend/roles/[id]/edit/page.tsx +4 -1
- package/src/modules/auth/backend/roles/page.tsx +3 -3
- package/src/modules/auth/backend/users/[id]/edit/page.tsx +22 -3
- package/src/modules/auth/backend/users/create/page.tsx +19 -2
- package/src/modules/auth/backend/users/page.tsx +3 -3
- package/src/modules/auth/cli.ts +38 -11
- package/src/modules/auth/commands/users.ts +73 -2
- package/src/modules/auth/data/validators.ts +6 -2
- package/src/modules/auth/frontend/login.tsx +134 -5
- package/src/modules/auth/frontend/reset/[token]/page.tsx +24 -11
- package/src/modules/auth/i18n/de.json +48 -1
- package/src/modules/auth/i18n/en.json +48 -1
- package/src/modules/auth/i18n/es.json +48 -1
- package/src/modules/auth/i18n/pl.json +48 -1
- package/src/modules/auth/lib/setup-app.ts +97 -186
- package/src/modules/auth/notifications.ts +109 -0
- package/src/modules/auth/services/authService.ts +27 -4
- package/src/modules/auth/setup.ts +9 -0
- package/src/modules/business_rules/api/execute/route.ts +8 -1
- package/src/modules/business_rules/backend/rules/page.tsx +4 -0
- package/src/modules/business_rules/backend/sets/page.tsx +3 -0
- package/src/modules/business_rules/cli.ts +2 -1
- package/src/modules/business_rules/data/validators.ts +0 -40
- package/src/modules/business_rules/i18n/en.json +3 -1
- package/src/modules/business_rules/index.ts +0 -25
- package/src/modules/business_rules/lib/__tests__/rule-engine.test.ts +51 -0
- package/src/modules/business_rules/lib/rule-engine.ts +51 -277
- package/src/modules/business_rules/notifications.ts +25 -0
- package/src/modules/business_rules/setup.ts +9 -0
- package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +50 -0
- package/src/modules/catalog/components/PriceKindSettings.tsx +2 -0
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +2 -2
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +2 -0
- package/src/modules/catalog/i18n/en.json +3 -1
- package/src/modules/catalog/notifications.ts +25 -0
- package/src/modules/catalog/setup.ts +22 -0
- package/src/modules/catalog/subscribers/low-stock-notification.ts +52 -0
- package/src/modules/configs/cli.ts +6 -0
- package/src/modules/configs/components/CachePanel.tsx +4 -4
- package/src/modules/configs/i18n/en.json +12 -2
- package/src/modules/configs/i18n/pl.json +12 -2
- package/src/modules/configs/lib/system-status.ts +48 -1
- package/src/modules/configs/lib/system-status.types.ts +1 -0
- package/src/modules/configs/lib/upgrade-actions.ts +5 -338
- package/src/modules/configs/setup.ts +14 -0
- package/src/modules/currencies/backend/currencies/page.tsx +3 -0
- package/src/modules/currencies/backend/exchange-rates/page.tsx +2 -0
- package/src/modules/currencies/setup.ts +15 -0
- package/src/modules/customers/backend/customers/companies/page.tsx +3 -0
- package/src/modules/customers/backend/customers/deals/page.tsx +3 -0
- package/src/modules/customers/backend/customers/people/page.tsx +3 -0
- package/src/modules/customers/commands/deals.ts +39 -0
- package/src/modules/customers/components/CustomerTodosTable.tsx +1 -0
- package/src/modules/customers/i18n/en.json +5 -1
- package/src/modules/customers/notifications.ts +44 -0
- package/src/modules/customers/setup.ts +36 -0
- package/src/modules/customers/widgets/dashboard/customer-todos/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/new-customers/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/new-deals/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/next-interactions/widget.ts +2 -2
- package/src/modules/dashboards/cli.ts +55 -5
- package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +22 -11
- package/src/modules/dashboards/lib/role-widgets.ts +80 -0
- package/src/modules/dashboards/services/widgetDataService.ts +164 -4
- package/src/modules/dashboards/setup.ts +26 -0
- package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/top-customers/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/top-products/widget.ts +2 -2
- package/src/modules/dictionaries/components/DictionaryTable.tsx +2 -0
- package/src/modules/dictionaries/setup.ts +10 -0
- package/src/modules/directory/api/get/tenants/lookup.ts +75 -0
- package/src/modules/directory/backend/directory/organizations/page.tsx +2 -2
- package/src/modules/directory/backend/directory/tenants/page.tsx +2 -2
- package/src/modules/directory/setup.ts +10 -0
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +2 -2
- package/src/modules/entities/components/SystemEntitiesTable.tsx +1 -1
- package/src/modules/entities/components/UserEntitiesTable.tsx +2 -2
- package/src/modules/entities/setup.ts +9 -0
- package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +3 -4
- package/src/modules/feature_toggles/components/OverridesTable.tsx +1 -1
- package/src/modules/feature_toggles/setup.ts +9 -0
- package/src/modules/notifications/__tests__/deliver-notification.test.ts +195 -0
- package/src/modules/notifications/__tests__/deliveryStrategies.test.ts +19 -0
- package/src/modules/notifications/__tests__/notificationService.test.ts +208 -0
- package/src/modules/notifications/acl.ts +7 -0
- package/src/modules/notifications/api/[id]/action/route.ts +75 -0
- package/src/modules/notifications/api/[id]/dismiss/route.ts +12 -0
- package/src/modules/notifications/api/[id]/read/route.ts +12 -0
- package/src/modules/notifications/api/[id]/restore/route.ts +53 -0
- package/src/modules/notifications/api/batch/route.ts +14 -0
- package/src/modules/notifications/api/feature/route.ts +14 -0
- package/src/modules/notifications/api/mark-all-read/route.ts +34 -0
- package/src/modules/notifications/api/openapi.ts +76 -0
- package/src/modules/notifications/api/role/route.ts +14 -0
- package/src/modules/notifications/api/route.ts +92 -0
- package/src/modules/notifications/api/settings/route.ts +157 -0
- package/src/modules/notifications/api/unread-count/route.ts +38 -0
- package/src/modules/notifications/backend/config/notifications/page.meta.ts +22 -0
- package/src/modules/notifications/backend/config/notifications/page.tsx +12 -0
- package/src/modules/notifications/cli.ts +18 -0
- package/src/modules/notifications/data/entities.ts +99 -0
- package/src/modules/notifications/data/validators.ts +115 -0
- package/src/modules/notifications/di.ts +11 -0
- package/src/modules/notifications/emails/NotificationEmail.tsx +98 -0
- package/src/modules/notifications/frontend/NotificationInboxPageClient.tsx +42 -0
- package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +233 -0
- package/src/modules/notifications/i18n/de.json +50 -0
- package/src/modules/notifications/i18n/en.json +50 -0
- package/src/modules/notifications/i18n/es.json +50 -0
- package/src/modules/notifications/i18n/pl.json +50 -0
- package/src/modules/notifications/index.ts +12 -0
- package/src/modules/notifications/lib/deliveryConfig.ts +153 -0
- package/src/modules/notifications/lib/deliveryStrategies.ts +50 -0
- package/src/modules/notifications/lib/events.ts +48 -0
- package/src/modules/notifications/lib/notificationBuilder.ts +121 -0
- package/src/modules/notifications/lib/notificationFactory.ts +76 -0
- package/src/modules/notifications/lib/notificationMapper.ts +33 -0
- package/src/modules/notifications/lib/notificationRecipients.ts +83 -0
- package/src/modules/notifications/lib/notificationService.ts +414 -0
- package/src/modules/notifications/lib/routeHelpers.ts +151 -0
- package/src/modules/notifications/lib/safeHref.ts +29 -0
- package/src/modules/notifications/migrations/.snapshot-open-mercato.json +336 -0
- package/src/modules/notifications/migrations/Migration20260123000001.ts +73 -0
- package/src/modules/notifications/migrations/Migration20260126150000.ts +39 -0
- package/src/modules/notifications/migrations/Migration20260129082610.ts +13 -0
- package/src/modules/notifications/subscribers/deliver-notification.ts +204 -0
- package/src/modules/notifications/workers/create-notification.worker.ts +122 -0
- package/src/modules/perspectives/setup.ts +10 -0
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +2 -2
- package/src/modules/planner/setup.ts +21 -0
- package/src/modules/query_index/cli.ts +82 -13
- package/src/modules/query_index/components/QueryIndexesTable.tsx +8 -2
- package/src/modules/query_index/setup.ts +9 -0
- package/src/modules/resources/backend/resources/resource-types/page.tsx +2 -2
- package/src/modules/resources/backend/resources/resources/page.tsx +2 -2
- package/src/modules/resources/setup.ts +21 -0
- package/src/modules/sales/acl.ts +0 -1
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +2 -0
- package/src/modules/sales/backend/sales/channels/page.tsx +2 -0
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +0 -16
- package/src/modules/sales/cli.ts +2 -43
- package/src/modules/sales/commands/documents.ts +62 -70
- package/src/modules/sales/commands/payments.ts +33 -0
- package/src/modules/sales/components/AdjustmentKindSettings.tsx +2 -2
- package/src/modules/sales/components/PaymentMethodsSettings.tsx +2 -2
- package/src/modules/sales/components/ShippingMethodsSettings.tsx +2 -2
- package/src/modules/sales/components/TaxRatesSettings.tsx +2 -2
- package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +2 -0
- package/src/modules/sales/components/documents/AdjustmentsSection.tsx +2 -0
- package/src/modules/sales/components/documents/PaymentsSection.tsx +2 -1
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +2 -0
- package/src/modules/sales/i18n/de.json +20 -0
- package/src/modules/sales/i18n/en.json +25 -1
- package/src/modules/sales/i18n/es.json +20 -0
- package/src/modules/sales/i18n/pl.json +20 -0
- package/src/modules/sales/lib/dictionaries.ts +0 -3
- package/src/modules/sales/lib/seeds.ts +53 -0
- package/src/modules/sales/notifications.client.ts +65 -0
- package/src/modules/sales/notifications.ts +82 -0
- package/src/modules/sales/setup.ts +108 -0
- package/src/modules/sales/subscribers/quote-expiring-notification.ts +53 -0
- package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +156 -0
- package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +156 -0
- package/src/modules/sales/widgets/notifications/index.ts +2 -0
- package/src/modules/sales/widgets/notifications/useSalesDocumentTotals.ts +81 -0
- package/src/modules/staff/backend/staff/team-members/page.tsx +1 -1
- package/src/modules/staff/backend/staff/team-roles/page.tsx +2 -2
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +2 -2
- package/src/modules/staff/backend/staff/teams/page.tsx +2 -2
- package/src/modules/staff/commands/leave-requests.ts +94 -0
- package/src/modules/staff/i18n/de.json +4 -0
- package/src/modules/staff/i18n/en.json +9 -1
- package/src/modules/staff/i18n/es.json +4 -0
- package/src/modules/staff/i18n/pl.json +4 -0
- package/src/modules/staff/notifications.ts +71 -0
- package/src/modules/staff/setup.ts +27 -0
- package/src/modules/workflows/acl.ts +0 -2
- package/src/modules/workflows/api/__tests__/instances.route.test.ts +2 -5
- package/src/modules/workflows/api/instances/route.ts +7 -21
- package/src/modules/workflows/api/tasks/route.ts +1 -7
- package/src/modules/workflows/backend/definitions/[id]/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/[id]/page.tsx +0 -9
- package/src/modules/workflows/backend/definitions/create/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/create/page.tsx +0 -9
- package/src/modules/workflows/backend/definitions/page.tsx +5 -0
- package/src/modules/workflows/backend/definitions/visual-editor/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +3 -21
- package/src/modules/workflows/backend/events/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/events/[id]/page.tsx +1 -1
- package/src/modules/workflows/backend/instances/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/instances/page.tsx +4 -1
- package/src/modules/workflows/backend/tasks/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +1 -1
- package/src/modules/workflows/backend/tasks/page.tsx +10 -6
- package/src/modules/workflows/cli.ts +12 -123
- package/src/modules/workflows/data/entities.ts +0 -124
- package/src/modules/workflows/data/validators.ts +0 -138
- package/src/modules/workflows/examples/checkout-demo-definition.json +5 -1
- package/src/modules/workflows/i18n/en.json +3 -72
- package/src/modules/workflows/lib/__tests__/activity-executor.test.ts +36 -43
- package/src/modules/workflows/lib/__tests__/transition-handler.test.ts +90 -170
- package/src/modules/workflows/lib/activity-executor.ts +16 -129
- package/src/modules/workflows/lib/graph-utils.ts +2 -117
- package/src/modules/workflows/lib/seeds.ts +12 -50
- package/src/modules/workflows/lib/start-validator.ts +28 -38
- package/src/modules/workflows/lib/transition-handler.ts +71 -212
- package/src/modules/workflows/migrations/Migration20251207131955.ts +77 -143
- package/src/modules/workflows/notifications.ts +25 -0
- package/src/modules/workflows/setup.ts +15 -0
- package/src/modules/workflows/subscribers/task-assigned-notification.ts +53 -0
- package/dist/generated/entities/workflow_event_trigger/index.js +0 -33
- package/dist/generated/entities/workflow_event_trigger/index.js.map +0 -7
- package/dist/modules/auth/events.js +0 -30
- package/dist/modules/auth/events.js.map +0 -7
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js +0 -145
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js.map +0 -7
- package/dist/modules/catalog/events.js +0 -34
- package/dist/modules/catalog/events.js.map +0 -7
- package/dist/modules/customers/events.js +0 -49
- package/dist/modules/customers/events.js.map +0 -7
- package/dist/modules/directory/events.js +0 -23
- package/dist/modules/directory/events.js.map +0 -7
- package/dist/modules/sales/events.js +0 -63
- package/dist/modules/sales/events.js.map +0 -7
- package/dist/modules/sales/lib/frontend/documentDataEvents.js +0 -25
- package/dist/modules/sales/lib/frontend/documentDataEvents.js.map +0 -7
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +0 -481
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +0 -7
- package/dist/modules/workflows/components/EventTriggersEditor.js +0 -553
- package/dist/modules/workflows/components/EventTriggersEditor.js.map +0 -7
- package/dist/modules/workflows/events.js +0 -38
- package/dist/modules/workflows/events.js.map +0 -7
- package/dist/modules/workflows/examples/order-approval-definition.json +0 -257
- package/dist/modules/workflows/examples/order-approval-guard-rules.json +0 -32
- package/dist/modules/workflows/lib/event-trigger-service.js +0 -308
- package/dist/modules/workflows/lib/event-trigger-service.js.map +0 -7
- package/dist/modules/workflows/migrations/Migration20260123143500.js +0 -36
- package/dist/modules/workflows/migrations/Migration20260123143500.js.map +0 -7
- package/dist/modules/workflows/subscribers/event-trigger.js +0 -78
- package/dist/modules/workflows/subscribers/event-trigger.js.map +0 -7
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js +0 -323
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js.map +0 -7
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js +0 -17
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js.map +0 -7
- package/dist/modules/workflows/widgets/injection-table.js +0 -19
- package/dist/modules/workflows/widgets/injection-table.js.map +0 -7
- package/generated/entities/workflow_event_trigger/index.ts +0 -15
- package/src/modules/auth/events.ts +0 -39
- package/src/modules/business_rules/api/execute/[ruleId]/route.ts +0 -163
- package/src/modules/catalog/events.ts +0 -45
- package/src/modules/customers/events.ts +0 -63
- package/src/modules/directory/events.ts +0 -31
- package/src/modules/sales/events.ts +0 -82
- package/src/modules/sales/lib/frontend/documentDataEvents.ts +0 -28
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +0 -581
- package/src/modules/workflows/components/EventTriggersEditor.tsx +0 -664
- package/src/modules/workflows/events.ts +0 -49
- package/src/modules/workflows/examples/order-approval-definition.json +0 -257
- package/src/modules/workflows/examples/order-approval-guard-rules.json +0 -32
- package/src/modules/workflows/lib/event-trigger-service.ts +0 -557
- package/src/modules/workflows/migrations/Migration20260123143500.ts +0 -38
- package/src/modules/workflows/subscribers/event-trigger.ts +0 -109
- package/src/modules/workflows/widgets/injection/order-approval/widget.client.tsx +0 -446
- package/src/modules/workflows/widgets/injection/order-approval/widget.ts +0 -16
- package/src/modules/workflows/widgets/injection-table.ts +0 -21
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/business_rules/lib/rule-engine.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/core'\nimport { BusinessRule, RuleExecutionLog, type RuleType } from '../data/entities'\nimport * as ruleEvaluator from './rule-evaluator'\nimport * as actionExecutor from './action-executor'\nimport type { RuleEvaluationContext } from './rule-evaluator'\nimport type { ActionContext, ActionExecutionOutcome } from './action-executor'\nimport { ruleEngineContextSchema, ruleDiscoveryOptionsSchema, directRuleExecutionContextSchema, ruleIdExecutionContextSchema } from '../data/validators'\n\n/**\n * Constants\n */\nconst DEFAULT_ENTITY_ID = 'unknown'\nconst RULE_TYPE_GUARD = 'GUARD'\nconst EXECUTION_RESULT_ERROR = 'ERROR'\nconst EXECUTION_RESULT_SUCCESS = 'SUCCESS'\nconst EXECUTION_RESULT_FAILURE = 'FAILURE'\n\n/**\n * Execution limits\n */\nconst MAX_RULES_PER_EXECUTION = 100\nconst MAX_SINGLE_RULE_TIMEOUT_MS = 30000 // 30 seconds\nconst MAX_TOTAL_EXECUTION_TIMEOUT_MS = 60000 // 60 seconds\n\n/**\n * Rule execution context\n */\nexport interface RuleEngineContext {\n entityType: string\n entityId?: string\n eventType?: string\n data: any\n user?: {\n id?: string\n email?: string\n role?: string\n [key: string]: any\n }\n tenant?: {\n id?: string\n [key: string]: any\n }\n organization?: {\n id?: string\n [key: string]: any\n }\n tenantId: string\n organizationId: string\n executedBy?: string\n dryRun?: boolean\n [key: string]: any\n}\n\n/**\n * Single rule execution result\n */\nexport interface RuleExecutionResult {\n rule: BusinessRule\n conditionResult: boolean\n actionsExecuted: ActionExecutionOutcome | null\n executionTime: number\n error?: string\n logId?: string // Database log ID (if logged)\n}\n\n/**\n * Overall rule engine result\n */\nexport interface RuleEngineResult {\n allowed: boolean\n executedRules: RuleExecutionResult[]\n totalExecutionTime: number\n errors?: string[]\n logIds?: string[]\n}\n\n/**\n * Rule discovery options\n */\nexport interface RuleDiscoveryOptions {\n entityType: string\n eventType?: string\n tenantId: string\n organizationId: string\n ruleType?: RuleType\n}\n\n/**\n * Direct rule execution context (for executing a specific rule by ID)\n */\nexport interface DirectRuleExecutionContext {\n ruleId: string // Database UUID of the rule\n data: any\n user?: {\n id?: string\n email?: string\n role?: string\n [key: string]: any\n }\n tenantId: string\n organizationId: string\n executedBy?: string\n dryRun?: boolean\n // Optional for logging (falls back to rule's entityType)\n entityType?: string\n entityId?: string\n eventType?: string\n}\n\n/**\n * Direct rule execution result\n */\nexport interface DirectRuleExecutionResult {\n success: boolean\n ruleId: string\n ruleName: string\n conditionResult: boolean\n actionsExecuted: ActionExecutionOutcome | null\n executionTime: number\n error?: string\n logId?: string\n}\n\n/**\n * Context for executing a rule by its string rule_id identifier\n * Unlike DirectRuleExecutionContext which uses database UUID,\n * this uses the string identifier (e.g., \"workflow_checkout_inventory_available\")\n */\nexport interface RuleIdExecutionContext {\n ruleId: string // String identifier (e.g., \"workflow_checkout_inventory_available\")\n data: any\n user?: {\n id?: string\n email?: string\n role?: string\n [key: string]: any\n }\n tenantId: string\n organizationId: string\n executedBy?: string\n dryRun?: boolean\n entityType?: string\n entityId?: string\n eventType?: string\n}\n\n/**\n * Execute a function with a timeout\n */\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n errorMessage: string\n): Promise<T> {\n let timeoutId: NodeJS.Timeout\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new Error(`${errorMessage} (timeout: ${timeoutMs}ms)`))\n }, timeoutMs)\n })\n\n try {\n return await Promise.race([promise, timeoutPromise])\n } finally {\n clearTimeout(timeoutId!)\n }\n}\n\n/**\n * Execute all applicable rules for the given context\n */\nexport async function executeRules(\n em: EntityManager,\n context: RuleEngineContext\n): Promise<RuleEngineResult> {\n // Validate input\n const validation = ruleEngineContextSchema.safeParse(context)\n if (!validation.success) {\n const validationErrors = validation.error.issues.map(e => `${e.path.join('.')}: ${e.message}`)\n return {\n allowed: false,\n executedRules: [],\n totalExecutionTime: 0,\n errors: validationErrors,\n }\n }\n\n const startTime = Date.now()\n const executedRules: RuleExecutionResult[] = []\n const errors: string[] = []\n const logIds: string[] = []\n\n try {\n // Discover applicable rules\n const rules = await findApplicableRules(em, {\n entityType: context.entityType,\n eventType: context.eventType,\n tenantId: context.tenantId,\n organizationId: context.organizationId,\n })\n\n // Check rule count limit\n if (rules.length > MAX_RULES_PER_EXECUTION) {\n errors.push(\n `Rule count limit exceeded: ${rules.length} rules found, maximum is ${MAX_RULES_PER_EXECUTION}`\n )\n return {\n allowed: false,\n executedRules: [],\n totalExecutionTime: Date.now() - startTime,\n errors,\n }\n }\n\n // Rules already sorted by database query (priority DESC, ruleId ASC)\n // Execute each rule with total timeout\n const executionPromise = (async () => {\n for (const rule of rules) {\n try {\n const ruleResult = await executeSingleRule(em, rule, context)\n executedRules.push(ruleResult)\n\n if (ruleResult.logId) {\n logIds.push(ruleResult.logId)\n }\n\n if (ruleResult.error) {\n errors.push(\n `Rule execution failed [ruleId=${rule.ruleId}, type=${rule.ruleType}, entityType=${context.entityType}]: ${ruleResult.error}`\n )\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n errors.push(\n `Unexpected error in rule execution [ruleId=${rule.ruleId}, type=${rule.ruleType}]: ${errorMessage}`\n )\n\n executedRules.push({\n rule,\n conditionResult: false,\n actionsExecuted: null,\n executionTime: 0,\n error: errorMessage,\n })\n }\n }\n })()\n\n // Execute with timeout\n await withTimeout(\n executionPromise,\n MAX_TOTAL_EXECUTION_TIMEOUT_MS,\n `Total rule execution timeout [entityType=${context.entityType}]`\n )\n\n // Determine overall allowed status\n // For GUARD rules: all must pass for operation to be allowed\n const guardRules = executedRules.filter((r) => r.rule.ruleType === RULE_TYPE_GUARD)\n const allowed = guardRules.length === 0 || guardRules.every((r) => r.conditionResult)\n\n const totalExecutionTime = Date.now() - startTime\n\n return {\n allowed,\n executedRules,\n totalExecutionTime,\n errors: errors.length > 0 ? errors : undefined,\n logIds: logIds.length > 0 ? logIds : undefined,\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n const stack = error instanceof Error ? error.stack : undefined\n errors.push(\n `Critical rule engine error [entityType=${context.entityType}, entityId=${context.entityId || 'unknown'}]: ${errorMessage}${stack ? `\\nStack: ${stack}` : ''}`\n )\n\n const totalExecutionTime = Date.now() - startTime\n\n return {\n allowed: false,\n executedRules,\n totalExecutionTime,\n errors,\n }\n }\n}\n\n/**\n * Execute a single rule\n */\nexport async function executeSingleRule(\n em: EntityManager,\n rule: BusinessRule,\n context: RuleEngineContext\n): Promise<RuleExecutionResult> {\n const startTime = Date.now()\n\n try {\n // Wrap execution in timeout\n const executeWithTimeout = async () => {\n // Build evaluation context\n const evalContext: RuleEvaluationContext = {\n entityType: context.entityType,\n entityId: context.entityId,\n eventType: context.eventType,\n user: context.user,\n tenant: context.tenant,\n organization: context.organization,\n }\n\n // Evaluate rule conditions\n const result = await ruleEvaluator.evaluateSingleRule(rule, context.data, evalContext)\n\n // Check if evaluation completed (not just if conditions passed)\n if (!result.evaluationCompleted) {\n const executionTime = Date.now() - startTime\n\n let logId: string | undefined\n\n // Log failure if not dry run\n if (!context.dryRun) {\n logId = await logRuleExecution(em, {\n rule,\n context,\n conditionResult: false,\n actionsExecuted: null,\n executionTime,\n error: result.error,\n })\n }\n\n return {\n rule,\n conditionResult: false,\n actionsExecuted: null,\n executionTime,\n error: result.error,\n logId,\n }\n }\n\n // Evaluation completed successfully - determine which actions to execute\n const actions = result.conditionsPassed ? rule.successActions : rule.failureActions\n\n let actionsExecuted: ActionExecutionOutcome | null = null\n\n if (actions && Array.isArray(actions) && actions.length > 0) {\n // Build action context\n const actionContext: ActionContext = {\n ...evalContext,\n data: context.data,\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n }\n\n // Execute actions\n actionsExecuted = await actionExecutor.executeActions(actions, actionContext)\n }\n\n const executionTime = Date.now() - startTime\n\n let logId: string | undefined\n\n // Log execution if not dry run\n if (!context.dryRun) {\n logId = await logRuleExecution(em, {\n rule,\n context,\n conditionResult: result.conditionsPassed,\n actionsExecuted,\n executionTime,\n })\n }\n\n return {\n rule,\n conditionResult: result.conditionsPassed,\n actionsExecuted,\n executionTime,\n logId,\n }\n }\n\n // Execute with single rule timeout\n return await withTimeout(\n executeWithTimeout(),\n MAX_SINGLE_RULE_TIMEOUT_MS,\n `Single rule execution timeout [ruleId=${rule.ruleId}]`\n )\n } catch (error) {\n const executionTime = Date.now() - startTime\n const errorMessage = error instanceof Error ? error.message : String(error)\n const enhancedError = `Failed to execute rule [ruleId=${rule.ruleId}, entityType=${context.entityType}]: ${errorMessage}`\n\n let logId: string | undefined\n\n // Log error if not dry run\n if (!context.dryRun) {\n logId = await logRuleExecution(em, {\n rule,\n context,\n conditionResult: false,\n actionsExecuted: null,\n executionTime,\n error: enhancedError,\n })\n }\n\n return {\n rule,\n conditionResult: false,\n actionsExecuted: null,\n executionTime,\n error: enhancedError,\n logId,\n }\n }\n}\n\n/**\n * Find all applicable rules for the given criteria\n */\nexport async function findApplicableRules(\n em: EntityManager,\n options: RuleDiscoveryOptions\n): Promise<BusinessRule[]> {\n // Validate input\n ruleDiscoveryOptionsSchema.parse(options)\n\n const { entityType, eventType, tenantId, organizationId, ruleType } = options\n\n const where: Partial<BusinessRule> = {\n entityType,\n tenantId,\n organizationId,\n enabled: true,\n deletedAt: null,\n }\n\n if (eventType) {\n where.eventType = eventType\n }\n\n if (ruleType) {\n where.ruleType = ruleType\n }\n\n const rules = await em.find(BusinessRule, where, {\n orderBy: { priority: 'DESC', ruleId: 'ASC' },\n })\n\n // Filter by effective date range\n const now = new Date()\n return rules.filter((rule) => {\n if (rule.effectiveFrom && rule.effectiveFrom > now) {\n return false\n }\n if (rule.effectiveTo && rule.effectiveTo < now) {\n return false\n }\n return true\n })\n}\n\n/**\n * Execute a specific rule by its database UUID\n * This bypasses the entityType/eventType discovery mechanism and directly executes the rule\n */\nexport async function executeRuleById(\n em: EntityManager,\n context: DirectRuleExecutionContext\n): Promise<DirectRuleExecutionResult> {\n const startTime = Date.now()\n\n // Validate input\n const validation = directRuleExecutionContextSchema.safeParse(context)\n if (!validation.success) {\n const validationErrors = validation.error.issues.map(e => `${e.path.join('.')}: ${e.message}`)\n return {\n success: false,\n ruleId: context.ruleId,\n ruleName: 'Unknown',\n conditionResult: false,\n actionsExecuted: null,\n executionTime: Date.now() - startTime,\n error: `Validation failed: ${validationErrors.join(', ')}`,\n }\n }\n\n // Fetch rule by ID with tenant/org validation\n const rule = await em.findOne(BusinessRule, {\n id: context.ruleId,\n tenantId: context.tenantId,\n organizationId: context.organizationId,\n deletedAt: null,\n })\n\n if (!rule) {\n return {\n success: false,\n ruleId: context.ruleId,\n ruleName: 'Unknown',\n conditionResult: false,\n actionsExecuted: null,\n executionTime: Date.now() - startTime,\n error: 'Rule not found',\n }\n }\n\n if (!rule.enabled) {\n return {\n success: false,\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n conditionResult: false,\n actionsExecuted: null,\n executionTime: Date.now() - startTime,\n error: 'Rule is disabled',\n }\n }\n\n // Check effective date range\n const now = new Date()\n if (rule.effectiveFrom && rule.effectiveFrom > now) {\n return {\n success: false,\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n conditionResult: false,\n actionsExecuted: null,\n executionTime: Date.now() - startTime,\n error: `Rule is not yet effective (starts ${rule.effectiveFrom.toISOString()})`,\n }\n }\n if (rule.effectiveTo && rule.effectiveTo < now) {\n return {\n success: false,\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n conditionResult: false,\n actionsExecuted: null,\n executionTime: Date.now() - startTime,\n error: `Rule has expired (ended ${rule.effectiveTo.toISOString()})`,\n }\n }\n\n // Build RuleEngineContext (use provided entityType or fall back to rule's)\n const engineContext: RuleEngineContext = {\n entityType: context.entityType || rule.entityType,\n entityId: context.entityId,\n eventType: context.eventType || rule.eventType || undefined,\n data: context.data,\n user: context.user,\n tenantId: context.tenantId,\n organizationId: context.organizationId,\n executedBy: context.executedBy,\n dryRun: context.dryRun,\n }\n\n // Execute via existing executeSingleRule\n const result = await executeSingleRule(em, rule, engineContext)\n\n return {\n success: !result.error,\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n conditionResult: result.conditionResult,\n actionsExecuted: result.actionsExecuted,\n executionTime: result.executionTime,\n error: result.error,\n logId: result.logId,\n }\n}\n\n/**\n * Execute a rule by its string rule_id identifier\n * Looks up rule by rule_id (string column) + tenant_id (unique constraint)\n * This is useful for workflow conditions that reference rules by their string identifiers\n */\nexport async function executeRuleByRuleId(\n em: EntityManager,\n context: RuleIdExecutionContext\n): Promise<DirectRuleExecutionResult> {\n const startTime = Date.now()\n\n // Validate input\n const validation = ruleIdExecutionContextSchema.safeParse(context)\n if (!validation.success) {\n const validationErrors = validation.error.issues.map(e => `${e.path.join('.')}: ${e.message}`)\n return {\n success: false,\n ruleId: context.ruleId || 'unknown',\n ruleName: 'Unknown',\n conditionResult: false,\n actionsExecuted: null,\n executionTime: Date.now() - startTime,\n error: `Validation failed: ${validationErrors.join(', ')}`,\n }\n }\n\n // Fetch rule by rule_id (string identifier) + tenant/org\n const rule = await em.findOne(BusinessRule, {\n ruleId: context.ruleId, // String identifier column\n tenantId: context.tenantId,\n organizationId: context.organizationId,\n deletedAt: null,\n })\n\n if (!rule) {\n return {\n success: false,\n ruleId: context.ruleId,\n ruleName: 'Unknown',\n conditionResult: false,\n actionsExecuted: null,\n executionTime: Date.now() - startTime,\n error: 'Rule not found',\n }\n }\n\n if (!rule.enabled) {\n return {\n success: false,\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n conditionResult: false,\n actionsExecuted: null,\n executionTime: Date.now() - startTime,\n error: 'Rule is disabled',\n }\n }\n\n // Check effective date range\n const now = new Date()\n if (rule.effectiveFrom && rule.effectiveFrom > now) {\n return {\n success: false,\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n conditionResult: false,\n actionsExecuted: null,\n executionTime: Date.now() - startTime,\n error: `Rule is not yet effective (starts ${rule.effectiveFrom.toISOString()})`,\n }\n }\n if (rule.effectiveTo && rule.effectiveTo < now) {\n return {\n success: false,\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n conditionResult: false,\n actionsExecuted: null,\n executionTime: Date.now() - startTime,\n error: `Rule has expired (ended ${rule.effectiveTo.toISOString()})`,\n }\n }\n\n // Build RuleEngineContext (use provided entityType or fall back to rule's)\n const engineContext: RuleEngineContext = {\n entityType: context.entityType || rule.entityType,\n entityId: context.entityId,\n eventType: context.eventType || rule.eventType || undefined,\n data: context.data,\n user: context.user,\n tenantId: context.tenantId,\n organizationId: context.organizationId,\n executedBy: context.executedBy,\n dryRun: context.dryRun,\n }\n\n // Execute via existing executeSingleRule\n const result = await executeSingleRule(em, rule, engineContext)\n\n return {\n success: !result.error,\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n conditionResult: result.conditionResult,\n actionsExecuted: result.actionsExecuted,\n executionTime: result.executionTime,\n error: result.error,\n logId: result.logId,\n }\n}\n\n/**\n * Sensitive field patterns to exclude from logs\n */\nconst SENSITIVE_FIELD_PATTERNS = [\n /password/i,\n /passwd/i,\n /pwd/i,\n /secret/i,\n /token/i,\n /api[_-]?key/i,\n /auth/i,\n /credit[_-]?card/i,\n /card[_-]?number/i,\n /cvv/i,\n /ssn/i,\n /social[_-]?security/i,\n /tax[_-]?id/i,\n /driver[_-]?license/i,\n /passport/i,\n]\n\n/**\n * Maximum depth for nested object sanitization\n */\nconst MAX_SANITIZATION_DEPTH = 5\n\n/**\n * Sanitize data for logging by removing sensitive fields\n */\nfunction sanitizeForLogging(data: any, depth: number = 0): any {\n // Prevent infinite recursion\n if (depth > MAX_SANITIZATION_DEPTH) {\n return '[Max depth exceeded]'\n }\n\n // Handle null/undefined\n if (data === null || data === undefined) {\n return data\n }\n\n // Handle primitives\n if (typeof data !== 'object') {\n return data\n }\n\n // Handle arrays\n if (Array.isArray(data)) {\n return data.map(item => sanitizeForLogging(item, depth + 1))\n }\n\n // Handle objects\n const sanitized: Record<string, any> = {}\n\n for (const [key, value] of Object.entries(data)) {\n // Check if field name matches sensitive patterns\n const isSensitive = SENSITIVE_FIELD_PATTERNS.some(pattern => pattern.test(key))\n\n if (isSensitive) {\n sanitized[key] = '[REDACTED]'\n } else if (typeof value === 'object' && value !== null) {\n sanitized[key] = sanitizeForLogging(value, depth + 1)\n } else {\n sanitized[key] = value\n }\n }\n\n return sanitized\n}\n\n/**\n * Sanitize user object for logging (keep only safe fields)\n */\nfunction sanitizeUser(user: any): any {\n if (!user) {\n return undefined\n }\n\n // Only log safe user fields\n return {\n id: user.id,\n role: user.role,\n // Don't log: email, name, phone, address, etc.\n }\n}\n\n/**\n * Log rule execution to database\n */\ninterface LogExecutionOptions {\n rule: BusinessRule\n context: RuleEngineContext\n conditionResult: boolean\n actionsExecuted: ActionExecutionOutcome | null\n executionTime: number\n error?: string\n}\n\nexport async function logRuleExecution(\n em: EntityManager,\n options: LogExecutionOptions\n): Promise<string> {\n const { rule, context, conditionResult, actionsExecuted, executionTime, error } = options\n\n const executionResult: 'SUCCESS' | 'FAILURE' | 'ERROR' = error\n ? EXECUTION_RESULT_ERROR\n : conditionResult\n ? EXECUTION_RESULT_SUCCESS\n : EXECUTION_RESULT_FAILURE\n\n const log = em.create(RuleExecutionLog, {\n rule,\n entityId: context.entityId || DEFAULT_ENTITY_ID,\n entityType: context.entityType,\n executionResult,\n inputContext: {\n data: sanitizeForLogging(context.data),\n eventType: context.eventType,\n user: sanitizeUser(context.user),\n },\n outputContext: actionsExecuted\n ? {\n conditionResult,\n actionsExecuted: actionsExecuted.results.map((r) => ({\n type: r.action.type,\n success: r.success,\n error: r.error,\n })),\n }\n : null,\n errorMessage: error || null,\n executionTimeMs: executionTime,\n tenantId: context.tenantId,\n organizationId: context.organizationId,\n executedBy: context.executedBy || null,\n })\n\n await em.persistAndFlush(log)\n\n return log.id\n}\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,cAAc,wBAAuC;AAC9D,YAAY,mBAAmB;AAC/B,YAAY,oBAAoB;AAGhC,SAAS,yBAAyB,4BAA4B,kCAAkC,oCAAoC;AAKpI,MAAM,oBAAoB;AAC1B,MAAM,kBAAkB;AACxB,MAAM,yBAAyB;AAC/B,MAAM,2BAA2B;AACjC,MAAM,2BAA2B;AAKjC,MAAM,0BAA0B;AAChC,MAAM,6BAA6B;AACnC,MAAM,iCAAiC;AA+HvC,eAAe,YACb,SACA,WACA,cACY;AACZ,MAAI;AAEJ,QAAM,iBAAiB,IAAI,QAAe,CAAC,GAAG,WAAW;AACvD,gBAAY,WAAW,MAAM;AAC3B,aAAO,IAAI,MAAM,GAAG,YAAY,cAAc,SAAS,KAAK,CAAC;AAAA,IAC/D,GAAG,SAAS;AAAA,EACd,CAAC;AAED,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK,CAAC,SAAS,cAAc,CAAC;AAAA,EACrD,UAAE;AACA,iBAAa,SAAU;AAAA,EACzB;AACF;AAKA,eAAsB,aACpB,IACA,SAC2B;AAE3B,QAAM,aAAa,wBAAwB,UAAU,OAAO;AAC5D,MAAI,CAAC,WAAW,SAAS;AACvB,UAAM,mBAAmB,WAAW,MAAM,OAAO,IAAI,OAAK,GAAG,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE;AAC7F,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe,CAAC;AAAA,MAChB,oBAAoB;AAAA,MACpB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,gBAAuC,CAAC;AAC9C,QAAM,SAAmB,CAAC;AAC1B,QAAM,SAAmB,CAAC;AAE1B,MAAI;AAEF,UAAM,QAAQ,MAAM,oBAAoB,IAAI;AAAA,MAC1C,YAAY,QAAQ;AAAA,MACpB,WAAW,QAAQ;AAAA,MACnB,UAAU,QAAQ;AAAA,MAClB,gBAAgB,QAAQ;AAAA,IAC1B,CAAC;AAGD,QAAI,MAAM,SAAS,yBAAyB;AAC1C,aAAO;AAAA,QACL,8BAA8B,MAAM,MAAM,4BAA4B,uBAAuB;AAAA,MAC/F;AACA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe,CAAC;AAAA,QAChB,oBAAoB,KAAK,IAAI,IAAI;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAIA,UAAM,oBAAoB,YAAY;AACpC,iBAAW,QAAQ,OAAO;AAC1B,YAAI;AACF,gBAAM,aAAa,MAAM,kBAAkB,IAAI,MAAM,OAAO;AAC5D,wBAAc,KAAK,UAAU;AAE7B,cAAI,WAAW,OAAO;AACpB,mBAAO,KAAK,WAAW,KAAK;AAAA,UAC9B;AAEA,cAAI,WAAW,OAAO;AACpB,mBAAO;AAAA,cACL,iCAAiC,KAAK,MAAM,UAAU,KAAK,QAAQ,gBAAgB,QAAQ,UAAU,MAAM,WAAW,KAAK;AAAA,YAC7H;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,gBAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,iBAAO;AAAA,YACL,8CAA8C,KAAK,MAAM,UAAU,KAAK,QAAQ,MAAM,YAAY;AAAA,UACpG;AAEA,wBAAc,KAAK;AAAA,YACjB;AAAA,YACA,iBAAiB;AAAA,YACjB,iBAAiB;AAAA,YACjB,eAAe;AAAA,YACf,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AAAA,MACA;AAAA,IACF,GAAG;AAGH,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,4CAA4C,QAAQ,UAAU;AAAA,IAChE;AAIA,UAAM,aAAa,cAAc,OAAO,CAAC,MAAM,EAAE,KAAK,aAAa,eAAe;AAClF,UAAM,UAAU,WAAW,WAAW,KAAK,WAAW,MAAM,CAAC,MAAM,EAAE,eAAe;AAEpF,UAAM,qBAAqB,KAAK,IAAI,IAAI;AAExC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,OAAO,SAAS,IAAI,SAAS;AAAA,MACrC,QAAQ,OAAO,SAAS,IAAI,SAAS;AAAA,IACvC;AAAA,EACF,SAAS,OAAO;AACd,UAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,UAAM,QAAQ,iBAAiB,QAAQ,MAAM,QAAQ;AACrD,WAAO;AAAA,MACL,0CAA0C,QAAQ,UAAU,cAAc,QAAQ,YAAY,SAAS,MAAM,YAAY,GAAG,QAAQ;AAAA,SAAY,KAAK,KAAK,EAAE;AAAA,IAC9J;AAEA,UAAM,qBAAqB,KAAK,IAAI,IAAI;AAExC,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAKA,eAAsB,kBACpB,IACA,MACA,SAC8B;AAC9B,QAAM,YAAY,KAAK,IAAI;AAE3B,MAAI;AAEF,UAAM,qBAAqB,YAAY;AAErC,YAAM,cAAqC;AAAA,QACzC,YAAY,QAAQ;AAAA,QACpB,UAAU,QAAQ;AAAA,QAClB,WAAW,QAAQ;AAAA,QACnB,MAAM,QAAQ;AAAA,QACd,QAAQ,QAAQ;AAAA,QAChB,cAAc,QAAQ;AAAA,MACxB;AAGA,YAAM,SAAS,MAAM,cAAc,mBAAmB,MAAM,QAAQ,MAAM,WAAW;AAGrF,UAAI,CAAC,OAAO,qBAAqB;AAC/B,cAAMA,iBAAgB,KAAK,IAAI,IAAI;AAEnC,YAAIC;AAGJ,YAAI,CAAC,QAAQ,QAAQ;AACnB,UAAAA,SAAQ,MAAM,iBAAiB,IAAI;AAAA,YACjC;AAAA,YACA;AAAA,YACA,iBAAiB;AAAA,YACjB,iBAAiB;AAAA,YACjB,eAAAD;AAAA,YACA,OAAO,OAAO;AAAA,UAChB,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,UACL;AAAA,UACA,iBAAiB;AAAA,UACjB,iBAAiB;AAAA,UACjB,eAAAA;AAAA,UACA,OAAO,OAAO;AAAA,UACd,OAAAC;AAAA,QACF;AAAA,MACF;AAGA,YAAM,UAAU,OAAO,mBAAmB,KAAK,iBAAiB,KAAK;AAErE,UAAI,kBAAiD;AAErD,UAAI,WAAW,MAAM,QAAQ,OAAO,KAAK,QAAQ,SAAS,GAAG;AAE3D,cAAM,gBAA+B;AAAA,UACnC,GAAG;AAAA,UACH,MAAM,QAAQ;AAAA,UACd,QAAQ,KAAK;AAAA,UACb,UAAU,KAAK;AAAA,QACjB;AAGA,0BAAkB,MAAM,eAAe,eAAe,SAAS,aAAa;AAAA,MAC9E;AAEA,YAAM,gBAAgB,KAAK,IAAI,IAAI;AAEnC,UAAI;AAGJ,UAAI,CAAC,QAAQ,QAAQ;AACnB,gBAAQ,MAAM,iBAAiB,IAAI;AAAA,UACjC;AAAA,UACA;AAAA,UACA,iBAAiB,OAAO;AAAA,UACxB;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,QACL;AAAA,QACA,iBAAiB,OAAO;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAGA,WAAO,MAAM;AAAA,MACX,mBAAmB;AAAA,MACnB;AAAA,MACA,yCAAyC,KAAK,MAAM;AAAA,IACtD;AAAA,EACF,SAAS,OAAO;AACd,UAAM,gBAAgB,KAAK,IAAI,IAAI;AACnC,UAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,UAAM,gBAAgB,kCAAkC,KAAK,MAAM,gBAAgB,QAAQ,UAAU,MAAM,YAAY;AAEvH,QAAI;AAGJ,QAAI,CAAC,QAAQ,QAAQ;AACnB,cAAQ,MAAM,iBAAiB,IAAI;AAAA,QACjC;AAAA,QACA;AAAA,QACA,iBAAiB;AAAA,QACjB,iBAAiB;AAAA,QACjB;AAAA,QACA,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL;AAAA,MACA,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACF;AAKA,eAAsB,oBACpB,IACA,SACyB;AAEzB,6BAA2B,MAAM,OAAO;AAExC,QAAM,EAAE,YAAY,WAAW,UAAU,gBAAgB,SAAS,IAAI;AAEtE,QAAM,QAA+B;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAEA,MAAI,WAAW;AACb,UAAM,YAAY;AAAA,EACpB;AAEA,MAAI,UAAU;AACZ,UAAM,WAAW;AAAA,EACnB;AAEA,QAAM,QAAQ,MAAM,GAAG,KAAK,cAAc,OAAO;AAAA,IAC/C,SAAS,EAAE,UAAU,QAAQ,QAAQ,MAAM;AAAA,EAC7C,CAAC;AAGD,QAAM,MAAM,oBAAI,KAAK;AACrB,SAAO,MAAM,OAAO,CAAC,SAAS;AAC5B,QAAI,KAAK,iBAAiB,KAAK,gBAAgB,KAAK;AAClD,aAAO;AAAA,IACT;AACA,QAAI,KAAK,eAAe,KAAK,cAAc,KAAK;AAC9C,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAMA,eAAsB,gBACpB,IACA,SACoC;AACpC,QAAM,YAAY,KAAK,IAAI;AAG3B,QAAM,aAAa,iCAAiC,UAAU,OAAO;AACrE,MAAI,CAAC,WAAW,SAAS;AACvB,UAAM,mBAAmB,WAAW,MAAM,OAAO,IAAI,OAAK,GAAG,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE;AAC7F,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,QAAQ;AAAA,MAChB,UAAU;AAAA,MACV,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,eAAe,KAAK,IAAI,IAAI;AAAA,MAC5B,OAAO,sBAAsB,iBAAiB,KAAK,IAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AAGA,QAAM,OAAO,MAAM,GAAG,QAAQ,cAAc;AAAA,IAC1C,IAAI,QAAQ;AAAA,IACZ,UAAU,QAAQ;AAAA,IAClB,gBAAgB,QAAQ;AAAA,IACxB,WAAW;AAAA,EACb,CAAC;AAED,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,QAAQ;AAAA,MAChB,UAAU;AAAA,MACV,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,eAAe,KAAK,IAAI,IAAI;AAAA,MAC5B,OAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,CAAC,KAAK,SAAS;AACjB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,eAAe,KAAK,IAAI,IAAI;AAAA,MAC5B,OAAO;AAAA,IACT;AAAA,EACF;AAGA,QAAM,MAAM,oBAAI,KAAK;AACrB,MAAI,KAAK,iBAAiB,KAAK,gBAAgB,KAAK;AAClD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,eAAe,KAAK,IAAI,IAAI;AAAA,MAC5B,OAAO,qCAAqC,KAAK,cAAc,YAAY,CAAC;AAAA,IAC9E;AAAA,EACF;AACA,MAAI,KAAK,eAAe,KAAK,cAAc,KAAK;AAC9C,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,eAAe,KAAK,IAAI,IAAI;AAAA,MAC5B,OAAO,2BAA2B,KAAK,YAAY,YAAY,CAAC;AAAA,IAClE;AAAA,EACF;AAGA,QAAM,gBAAmC;AAAA,IACvC,YAAY,QAAQ,cAAc,KAAK;AAAA,IACvC,UAAU,QAAQ;AAAA,IAClB,WAAW,QAAQ,aAAa,KAAK,aAAa;AAAA,IAClD,MAAM,QAAQ;AAAA,IACd,MAAM,QAAQ;AAAA,IACd,UAAU,QAAQ;AAAA,IAClB,gBAAgB,QAAQ;AAAA,IACxB,YAAY,QAAQ;AAAA,IACpB,QAAQ,QAAQ;AAAA,EAClB;AAGA,QAAM,SAAS,MAAM,kBAAkB,IAAI,MAAM,aAAa;AAE9D,SAAO;AAAA,IACL,SAAS,CAAC,OAAO;AAAA,IACjB,QAAQ,KAAK;AAAA,IACb,UAAU,KAAK;AAAA,IACf,iBAAiB,OAAO;AAAA,IACxB,iBAAiB,OAAO;AAAA,IACxB,eAAe,OAAO;AAAA,IACtB,OAAO,OAAO;AAAA,IACd,OAAO,OAAO;AAAA,EAChB;AACF;AAOA,eAAsB,oBACpB,IACA,SACoC;AACpC,QAAM,YAAY,KAAK,IAAI;AAG3B,QAAM,aAAa,6BAA6B,UAAU,OAAO;AACjE,MAAI,CAAC,WAAW,SAAS;AACvB,UAAM,mBAAmB,WAAW,MAAM,OAAO,IAAI,OAAK,GAAG,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE;AAC7F,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,QAAQ,UAAU;AAAA,MAC1B,UAAU;AAAA,MACV,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,eAAe,KAAK,IAAI,IAAI;AAAA,MAC5B,OAAO,sBAAsB,iBAAiB,KAAK,IAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AAGA,QAAM,OAAO,MAAM,GAAG,QAAQ,cAAc;AAAA,IAC1C,QAAQ,QAAQ;AAAA;AAAA,IAChB,UAAU,QAAQ;AAAA,IAClB,gBAAgB,QAAQ;AAAA,IACxB,WAAW;AAAA,EACb,CAAC;AAED,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,QAAQ;AAAA,MAChB,UAAU;AAAA,MACV,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,eAAe,KAAK,IAAI,IAAI;AAAA,MAC5B,OAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,CAAC,KAAK,SAAS;AACjB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,eAAe,KAAK,IAAI,IAAI;AAAA,MAC5B,OAAO;AAAA,IACT;AAAA,EACF;AAGA,QAAM,MAAM,oBAAI,KAAK;AACrB,MAAI,KAAK,iBAAiB,KAAK,gBAAgB,KAAK;AAClD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,eAAe,KAAK,IAAI,IAAI;AAAA,MAC5B,OAAO,qCAAqC,KAAK,cAAc,YAAY,CAAC;AAAA,IAC9E;AAAA,EACF;AACA,MAAI,KAAK,eAAe,KAAK,cAAc,KAAK;AAC9C,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,eAAe,KAAK,IAAI,IAAI;AAAA,MAC5B,OAAO,2BAA2B,KAAK,YAAY,YAAY,CAAC;AAAA,IAClE;AAAA,EACF;AAGA,QAAM,gBAAmC;AAAA,IACvC,YAAY,QAAQ,cAAc,KAAK;AAAA,IACvC,UAAU,QAAQ;AAAA,IAClB,WAAW,QAAQ,aAAa,KAAK,aAAa;AAAA,IAClD,MAAM,QAAQ;AAAA,IACd,MAAM,QAAQ;AAAA,IACd,UAAU,QAAQ;AAAA,IAClB,gBAAgB,QAAQ;AAAA,IACxB,YAAY,QAAQ;AAAA,IACpB,QAAQ,QAAQ;AAAA,EAClB;AAGA,QAAM,SAAS,MAAM,kBAAkB,IAAI,MAAM,aAAa;AAE9D,SAAO;AAAA,IACL,SAAS,CAAC,OAAO;AAAA,IACjB,QAAQ,KAAK;AAAA,IACb,UAAU,KAAK;AAAA,IACf,iBAAiB,OAAO;AAAA,IACxB,iBAAiB,OAAO;AAAA,IACxB,eAAe,OAAO;AAAA,IACtB,OAAO,OAAO;AAAA,IACd,OAAO,OAAO;AAAA,EAChB;AACF;AAKA,MAAM,2BAA2B;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKA,MAAM,yBAAyB;AAK/B,SAAS,mBAAmB,MAAW,QAAgB,GAAQ;AAE7D,MAAI,QAAQ,wBAAwB;AAClC,WAAO;AAAA,EACT;AAGA,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO;AAAA,EACT;AAGA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,WAAO,KAAK,IAAI,UAAQ,mBAAmB,MAAM,QAAQ,CAAC,CAAC;AAAA,EAC7D;AAGA,QAAM,YAAiC,CAAC;AAExC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAE/C,UAAM,cAAc,yBAAyB,KAAK,aAAW,QAAQ,KAAK,GAAG,CAAC;AAE9E,QAAI,aAAa;AACf,gBAAU,GAAG,IAAI;AAAA,IACnB,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACtD,gBAAU,GAAG,IAAI,mBAAmB,OAAO,QAAQ,CAAC;AAAA,IACtD,OAAO;AACL,gBAAU,GAAG,IAAI;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,aAAa,MAAgB;AACpC,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAGA,SAAO;AAAA,IACL,IAAI,KAAK;AAAA,IACT,MAAM,KAAK;AAAA;AAAA,EAEb;AACF;AAcA,eAAsB,iBACpB,IACA,SACiB;AACjB,QAAM,EAAE,MAAM,SAAS,iBAAiB,iBAAiB,eAAe,MAAM,IAAI;AAElF,QAAM,kBAAmD,QACrD,yBACA,kBACE,2BACA;AAEN,QAAM,MAAM,GAAG,OAAO,kBAAkB;AAAA,IACtC;AAAA,IACA,UAAU,QAAQ,YAAY;AAAA,IAC9B,YAAY,QAAQ;AAAA,IACpB;AAAA,IACA,cAAc;AAAA,MACZ,MAAM,mBAAmB,QAAQ,IAAI;AAAA,MACrC,WAAW,QAAQ;AAAA,MACnB,MAAM,aAAa,QAAQ,IAAI;AAAA,IACjC;AAAA,IACA,eAAe,kBACX;AAAA,MACE;AAAA,MACA,iBAAiB,gBAAgB,QAAQ,IAAI,CAAC,OAAO;AAAA,QACnD,MAAM,EAAE,OAAO;AAAA,QACf,SAAS,EAAE;AAAA,QACX,OAAO,EAAE;AAAA,MACX,EAAE;AAAA,IACJ,IACA;AAAA,IACJ,cAAc,SAAS;AAAA,IACvB,iBAAiB;AAAA,IACjB,UAAU,QAAQ;AAAA,IAClB,gBAAgB,QAAQ;AAAA,IACxB,YAAY,QAAQ,cAAc;AAAA,EACpC,CAAC;AAED,QAAM,GAAG,gBAAgB,GAAG;AAE5B,SAAO,IAAI;AACb;",
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/core'\nimport type { EventBus } from '@open-mercato/events'\nimport { BusinessRule, RuleExecutionLog, type RuleType } from '../data/entities'\nimport * as ruleEvaluator from './rule-evaluator'\nimport * as actionExecutor from './action-executor'\nimport type { RuleEvaluationContext } from './rule-evaluator'\nimport type { ActionContext, ActionExecutionOutcome } from './action-executor'\nimport { ruleEngineContextSchema, ruleDiscoveryOptionsSchema } from '../data/validators'\n\n/**\n * Constants\n */\nconst DEFAULT_ENTITY_ID = 'unknown'\nconst RULE_TYPE_GUARD = 'GUARD'\nconst EXECUTION_RESULT_ERROR = 'ERROR'\nconst EXECUTION_RESULT_SUCCESS = 'SUCCESS'\nconst EXECUTION_RESULT_FAILURE = 'FAILURE'\n\n/**\n * Execution limits\n */\nconst MAX_RULES_PER_EXECUTION = 100\nconst MAX_SINGLE_RULE_TIMEOUT_MS = 30000 // 30 seconds\nconst MAX_TOTAL_EXECUTION_TIMEOUT_MS = 60000 // 60 seconds\n\n/**\n * Rule execution context\n */\nexport interface RuleEngineContext {\n entityType: string\n entityId?: string\n eventType?: string\n data: any\n user?: {\n id?: string\n email?: string\n role?: string\n [key: string]: any\n }\n tenant?: {\n id?: string\n [key: string]: any\n }\n organization?: {\n id?: string\n [key: string]: any\n }\n tenantId: string\n organizationId: string\n executedBy?: string\n dryRun?: boolean\n [key: string]: any\n}\n\n/**\n * Single rule execution result\n */\nexport interface RuleExecutionResult {\n rule: BusinessRule\n conditionResult: boolean\n actionsExecuted: ActionExecutionOutcome | null\n executionTime: number\n error?: string\n logId?: string // Database log ID (if logged)\n}\n\n/**\n * Overall rule engine result\n */\nexport interface RuleEngineResult {\n allowed: boolean\n executedRules: RuleExecutionResult[]\n totalExecutionTime: number\n errors?: string[]\n logIds?: string[]\n}\n\n/**\n * Rule discovery options\n */\nexport interface RuleDiscoveryOptions {\n entityType: string\n eventType?: string\n tenantId: string\n organizationId: string\n ruleType?: RuleType\n}\n\nexport type RuleEngineExecutionOptions = {\n eventBus?: Pick<EventBus, 'emitEvent'> | null\n}\n\ntype RuleExecutionFailedPayload = {\n ruleId: string\n ruleName: string\n entityType?: string | null\n errorMessage?: string | null\n tenantId: string\n organizationId?: string | null\n}\n\n/**\n * Execute a function with a timeout\n */\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n errorMessage: string\n): Promise<T> {\n let timeoutId: NodeJS.Timeout\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new Error(`${errorMessage} (timeout: ${timeoutMs}ms)`))\n }, timeoutMs)\n })\n\n try {\n return await Promise.race([promise, timeoutPromise])\n } finally {\n clearTimeout(timeoutId!)\n }\n}\n\n/**\n * Execute all applicable rules for the given context\n */\nexport async function executeRules(\n em: EntityManager,\n context: RuleEngineContext,\n options: RuleEngineExecutionOptions = {}\n): Promise<RuleEngineResult> {\n // Validate input\n const validation = ruleEngineContextSchema.safeParse(context)\n if (!validation.success) {\n const validationErrors = validation.error.issues.map(e => `${e.path.join('.')}: ${e.message}`)\n return {\n allowed: false,\n executedRules: [],\n totalExecutionTime: 0,\n errors: validationErrors,\n }\n }\n\n const startTime = Date.now()\n const executedRules: RuleExecutionResult[] = []\n const errors: string[] = []\n const logIds: string[] = []\n\n try {\n // Discover applicable rules\n const rules = await findApplicableRules(em, {\n entityType: context.entityType,\n eventType: context.eventType,\n tenantId: context.tenantId,\n organizationId: context.organizationId,\n })\n\n // Check rule count limit\n if (rules.length > MAX_RULES_PER_EXECUTION) {\n errors.push(\n `Rule count limit exceeded: ${rules.length} rules found, maximum is ${MAX_RULES_PER_EXECUTION}`\n )\n return {\n allowed: false,\n executedRules: [],\n totalExecutionTime: Date.now() - startTime,\n errors,\n }\n }\n\n // Rules already sorted by database query (priority DESC, ruleId ASC)\n // Execute each rule with total timeout\n const executionPromise = (async () => {\n for (const rule of rules) {\n try {\n const ruleResult = await executeSingleRule(em, rule, context, options)\n executedRules.push(ruleResult)\n\n if (ruleResult.logId) {\n logIds.push(ruleResult.logId)\n }\n\n if (ruleResult.error) {\n errors.push(\n `Rule execution failed [ruleId=${rule.ruleId}, type=${rule.ruleType}, entityType=${context.entityType}]: ${ruleResult.error}`\n )\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n errors.push(\n `Unexpected error in rule execution [ruleId=${rule.ruleId}, type=${rule.ruleType}]: ${errorMessage}`\n )\n\n if (!context.dryRun) {\n await emitRuleExecutionFailed(options.eventBus, {\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n entityType: context.entityType ?? null,\n errorMessage,\n tenantId: context.tenantId,\n organizationId: context.organizationId ?? null,\n })\n }\n\n executedRules.push({\n rule,\n conditionResult: false,\n actionsExecuted: null,\n executionTime: 0,\n error: errorMessage,\n })\n }\n }\n })()\n\n // Execute with timeout\n await withTimeout(\n executionPromise,\n MAX_TOTAL_EXECUTION_TIMEOUT_MS,\n `Total rule execution timeout [entityType=${context.entityType}]`\n )\n\n // Determine overall allowed status\n // For GUARD rules: all must pass for operation to be allowed\n const guardRules = executedRules.filter((r) => r.rule.ruleType === RULE_TYPE_GUARD)\n const allowed = guardRules.length === 0 || guardRules.every((r) => r.conditionResult)\n\n const totalExecutionTime = Date.now() - startTime\n\n return {\n allowed,\n executedRules,\n totalExecutionTime,\n errors: errors.length > 0 ? errors : undefined,\n logIds: logIds.length > 0 ? logIds : undefined,\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n const stack = error instanceof Error ? error.stack : undefined\n errors.push(\n `Critical rule engine error [entityType=${context.entityType}, entityId=${context.entityId || 'unknown'}]: ${errorMessage}${stack ? `\\nStack: ${stack}` : ''}`\n )\n\n const totalExecutionTime = Date.now() - startTime\n\n return {\n allowed: false,\n executedRules,\n totalExecutionTime,\n errors,\n }\n }\n}\n\n/**\n * Execute a single rule\n */\nexport async function executeSingleRule(\n em: EntityManager,\n rule: BusinessRule,\n context: RuleEngineContext,\n options: RuleEngineExecutionOptions = {}\n): Promise<RuleExecutionResult> {\n const startTime = Date.now()\n\n try {\n // Wrap execution in timeout\n const executeWithTimeout = async () => {\n // Build evaluation context\n const evalContext: RuleEvaluationContext = {\n entityType: context.entityType,\n entityId: context.entityId,\n eventType: context.eventType,\n user: context.user,\n tenant: context.tenant,\n organization: context.organization,\n }\n\n // Evaluate rule conditions\n const result = await ruleEvaluator.evaluateSingleRule(rule, context.data, evalContext)\n\n // Check if evaluation completed (not just if conditions passed)\n if (!result.evaluationCompleted) {\n const executionTime = Date.now() - startTime\n\n let logId: string | undefined\n\n // Log failure if not dry run\n if (!context.dryRun) {\n logId = await logRuleExecution(em, {\n rule,\n context,\n conditionResult: false,\n actionsExecuted: null,\n executionTime,\n error: result.error,\n })\n\n await emitRuleExecutionFailed(options.eventBus, {\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n entityType: context.entityType ?? null,\n errorMessage: result.error ?? null,\n tenantId: context.tenantId,\n organizationId: context.organizationId ?? null,\n })\n }\n\n return {\n rule,\n conditionResult: false,\n actionsExecuted: null,\n executionTime,\n error: result.error,\n logId,\n }\n }\n\n // Evaluation completed successfully - determine which actions to execute\n const actions = result.conditionsPassed ? rule.successActions : rule.failureActions\n\n let actionsExecuted: ActionExecutionOutcome | null = null\n\n if (actions && Array.isArray(actions) && actions.length > 0) {\n // Build action context\n const actionContext: ActionContext = {\n ...evalContext,\n data: context.data,\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n }\n\n // Execute actions\n actionsExecuted = await actionExecutor.executeActions(actions, actionContext)\n }\n\n const executionTime = Date.now() - startTime\n\n let logId: string | undefined\n\n // Log execution if not dry run\n if (!context.dryRun) {\n logId = await logRuleExecution(em, {\n rule,\n context,\n conditionResult: result.conditionsPassed,\n actionsExecuted,\n executionTime,\n })\n }\n\n return {\n rule,\n conditionResult: result.conditionsPassed,\n actionsExecuted,\n executionTime,\n logId,\n }\n }\n\n // Execute with single rule timeout\n return await withTimeout(\n executeWithTimeout(),\n MAX_SINGLE_RULE_TIMEOUT_MS,\n `Single rule execution timeout [ruleId=${rule.ruleId}]`\n )\n } catch (error) {\n const executionTime = Date.now() - startTime\n const errorMessage = error instanceof Error ? error.message : String(error)\n const enhancedError = `Failed to execute rule [ruleId=${rule.ruleId}, entityType=${context.entityType}]: ${errorMessage}`\n\n let logId: string | undefined\n\n // Log error if not dry run\n if (!context.dryRun) {\n logId = await logRuleExecution(em, {\n rule,\n context,\n conditionResult: false,\n actionsExecuted: null,\n executionTime,\n error: enhancedError,\n })\n\n await emitRuleExecutionFailed(options.eventBus, {\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n entityType: context.entityType ?? null,\n errorMessage: enhancedError,\n tenantId: context.tenantId,\n organizationId: context.organizationId ?? null,\n })\n }\n\n return {\n rule,\n conditionResult: false,\n actionsExecuted: null,\n executionTime,\n error: enhancedError,\n logId,\n }\n }\n}\n\n/**\n * Find all applicable rules for the given criteria\n */\nexport async function findApplicableRules(\n em: EntityManager,\n options: RuleDiscoveryOptions\n): Promise<BusinessRule[]> {\n // Validate input\n ruleDiscoveryOptionsSchema.parse(options)\n\n const { entityType, eventType, tenantId, organizationId, ruleType } = options\n\n const where: Partial<BusinessRule> = {\n entityType,\n tenantId,\n organizationId,\n enabled: true,\n deletedAt: null,\n }\n\n if (eventType) {\n where.eventType = eventType\n }\n\n if (ruleType) {\n where.ruleType = ruleType\n }\n\n const rules = await em.find(BusinessRule, where, {\n orderBy: { priority: 'DESC', ruleId: 'ASC' },\n })\n\n // Filter by effective date range\n const now = new Date()\n return rules.filter((rule) => {\n if (rule.effectiveFrom && rule.effectiveFrom > now) {\n return false\n }\n if (rule.effectiveTo && rule.effectiveTo < now) {\n return false\n }\n return true\n })\n}\n\n/**\n * Sensitive field patterns to exclude from logs\n */\nconst SENSITIVE_FIELD_PATTERNS = [\n /password/i,\n /passwd/i,\n /pwd/i,\n /secret/i,\n /token/i,\n /api[_-]?key/i,\n /auth/i,\n /credit[_-]?card/i,\n /card[_-]?number/i,\n /cvv/i,\n /ssn/i,\n /social[_-]?security/i,\n /tax[_-]?id/i,\n /driver[_-]?license/i,\n /passport/i,\n]\n\n/**\n * Maximum depth for nested object sanitization\n */\nconst MAX_SANITIZATION_DEPTH = 5\n\n/**\n * Sanitize data for logging by removing sensitive fields\n */\nfunction sanitizeForLogging(data: any, depth: number = 0): any {\n // Prevent infinite recursion\n if (depth > MAX_SANITIZATION_DEPTH) {\n return '[Max depth exceeded]'\n }\n\n // Handle null/undefined\n if (data === null || data === undefined) {\n return data\n }\n\n // Handle primitives\n if (typeof data !== 'object') {\n return data\n }\n\n // Handle arrays\n if (Array.isArray(data)) {\n return data.map(item => sanitizeForLogging(item, depth + 1))\n }\n\n // Handle objects\n const sanitized: Record<string, any> = {}\n\n for (const [key, value] of Object.entries(data)) {\n // Check if field name matches sensitive patterns\n const isSensitive = SENSITIVE_FIELD_PATTERNS.some(pattern => pattern.test(key))\n\n if (isSensitive) {\n sanitized[key] = '[REDACTED]'\n } else if (typeof value === 'object' && value !== null) {\n sanitized[key] = sanitizeForLogging(value, depth + 1)\n } else {\n sanitized[key] = value\n }\n }\n\n return sanitized\n}\n\n/**\n * Sanitize user object for logging (keep only safe fields)\n */\nfunction sanitizeUser(user: any): any {\n if (!user) {\n return undefined\n }\n\n // Only log safe user fields\n return {\n id: user.id,\n role: user.role,\n // Don't log: email, name, phone, address, etc.\n }\n}\n\n/**\n * Log rule execution to database\n */\ninterface LogExecutionOptions {\n rule: BusinessRule\n context: RuleEngineContext\n conditionResult: boolean\n actionsExecuted: ActionExecutionOutcome | null\n executionTime: number\n error?: string\n}\n\nexport async function logRuleExecution(\n em: EntityManager,\n options: LogExecutionOptions\n): Promise<string> {\n const { rule, context, conditionResult, actionsExecuted, executionTime, error } = options\n\n const executionResult: 'SUCCESS' | 'FAILURE' | 'ERROR' = error\n ? EXECUTION_RESULT_ERROR\n : conditionResult\n ? EXECUTION_RESULT_SUCCESS\n : EXECUTION_RESULT_FAILURE\n\n const log = em.create(RuleExecutionLog, {\n rule,\n entityId: context.entityId || DEFAULT_ENTITY_ID,\n entityType: context.entityType,\n executionResult,\n inputContext: {\n data: sanitizeForLogging(context.data),\n eventType: context.eventType,\n user: sanitizeUser(context.user),\n },\n outputContext: actionsExecuted\n ? {\n conditionResult,\n actionsExecuted: actionsExecuted.results.map((r) => ({\n type: r.action.type,\n success: r.success,\n error: r.error,\n })),\n }\n : null,\n errorMessage: error || null,\n executionTimeMs: executionTime,\n tenantId: context.tenantId,\n organizationId: context.organizationId,\n executedBy: context.executedBy || null,\n })\n\n await em.persistAndFlush(log)\n\n return log.id\n}\n\nasync function emitRuleExecutionFailed(\n eventBus: Pick<EventBus, 'emitEvent'> | null | undefined,\n payload: RuleExecutionFailedPayload\n): Promise<void> {\n if (!eventBus?.emitEvent) return\n\n await eventBus.emitEvent('business_rules.rule.execution_failed', payload).catch(() => undefined)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["executionTime", "logId"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const notificationTypes = [
|
|
2
|
+
{
|
|
3
|
+
type: "business_rules.rule.execution_failed",
|
|
4
|
+
module: "business_rules",
|
|
5
|
+
titleKey: "businessRules.notifications.rule.executionFailed.title",
|
|
6
|
+
bodyKey: "businessRules.notifications.rule.executionFailed.body",
|
|
7
|
+
icon: "alert-triangle",
|
|
8
|
+
severity: "error",
|
|
9
|
+
actions: [
|
|
10
|
+
{
|
|
11
|
+
id: "view",
|
|
12
|
+
labelKey: "common.view",
|
|
13
|
+
variant: "outline",
|
|
14
|
+
href: "/backend/business-rules/{sourceEntityId}",
|
|
15
|
+
icon: "external-link"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
linkHref: "/backend/business-rules/{sourceEntityId}",
|
|
19
|
+
expiresAfterHours: 168
|
|
20
|
+
// 7 days
|
|
21
|
+
}
|
|
22
|
+
];
|
|
23
|
+
var notifications_default = notificationTypes;
|
|
24
|
+
export {
|
|
25
|
+
notifications_default as default,
|
|
26
|
+
notificationTypes
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=notifications.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/business_rules/notifications.ts"],
|
|
4
|
+
"sourcesContent": ["import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'\n\nexport const notificationTypes: NotificationTypeDefinition[] = [\n {\n type: 'business_rules.rule.execution_failed',\n module: 'business_rules',\n titleKey: 'businessRules.notifications.rule.executionFailed.title',\n bodyKey: 'businessRules.notifications.rule.executionFailed.body',\n icon: 'alert-triangle',\n severity: 'error',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/business-rules/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/business-rules/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n]\n\nexport default notificationTypes\n"],
|
|
5
|
+
"mappings": "AAEO,MAAM,oBAAkD;AAAA,EAC7D;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA;AAAA,EACrB;AACF;AAEA,IAAO,wBAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/business_rules/setup.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n admin: ['business_rules.*'],\n },\n}\n\nexport default setup\n"],
|
|
5
|
+
"mappings": "AAEO,MAAM,QAA2B;AAAA,EACtC,qBAAqB;AAAA,IACnB,OAAO,CAAC,kBAAkB;AAAA,EAC5B;AACF;AAEA,IAAO,gBAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { resolveNotificationService } from "../../notifications/lib/notificationService.js";
|
|
2
|
+
import { buildFeatureNotificationFromType } from "../../notifications/lib/notificationBuilder.js";
|
|
3
|
+
import { notificationTypes } from "../notifications.js";
|
|
4
|
+
const metadata = {
|
|
5
|
+
event: "business_rules.rule.execution_failed",
|
|
6
|
+
persistent: true,
|
|
7
|
+
id: "business_rules:rule-execution-failed-notification"
|
|
8
|
+
};
|
|
9
|
+
async function handle(payload, ctx) {
|
|
10
|
+
try {
|
|
11
|
+
const notificationService = resolveNotificationService(ctx);
|
|
12
|
+
const typeDef = notificationTypes.find((type) => type.type === "business_rules.rule.execution_failed");
|
|
13
|
+
if (!typeDef) return;
|
|
14
|
+
const notificationInput = buildFeatureNotificationFromType(typeDef, {
|
|
15
|
+
requiredFeature: "business_rules.manage",
|
|
16
|
+
bodyVariables: {
|
|
17
|
+
ruleName: payload.ruleName,
|
|
18
|
+
entityType: payload.entityType ?? "",
|
|
19
|
+
errorMessage: payload.errorMessage ?? "Unknown error"
|
|
20
|
+
},
|
|
21
|
+
sourceEntityType: "business_rules:rule",
|
|
22
|
+
sourceEntityId: payload.ruleId,
|
|
23
|
+
linkHref: `/backend/business-rules/${payload.ruleId}`
|
|
24
|
+
});
|
|
25
|
+
await notificationService.createForFeature(notificationInput, {
|
|
26
|
+
tenantId: payload.tenantId,
|
|
27
|
+
organizationId: payload.organizationId ?? null
|
|
28
|
+
});
|
|
29
|
+
} catch (err) {
|
|
30
|
+
console.error("[business_rules:rule-execution-failed-notification] Failed to create notification:", err);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
handle as default,
|
|
35
|
+
metadata
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=rule-execution-failed-notification.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/business_rules/subscribers/rule-execution-failed-notification.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { resolveNotificationService } from '../../notifications/lib/notificationService'\nimport { buildFeatureNotificationFromType } from '../../notifications/lib/notificationBuilder'\nimport { notificationTypes } from '../notifications'\n\nexport const metadata = {\n event: 'business_rules.rule.execution_failed',\n persistent: true,\n id: 'business_rules:rule-execution-failed-notification',\n}\n\ntype RuleExecutionFailedPayload = {\n ruleId: string\n ruleName: string\n entityType?: string | null\n errorMessage?: string | null\n tenantId: string\n organizationId?: string | null\n}\n\ntype ResolverContext = {\n resolve: <T = unknown>(name: string) => T\n}\n\nexport default async function handle(payload: RuleExecutionFailedPayload, ctx: ResolverContext) {\n try {\n const notificationService = resolveNotificationService(ctx)\n const typeDef = notificationTypes.find((type) => type.type === 'business_rules.rule.execution_failed')\n if (!typeDef) return\n\n const notificationInput = buildFeatureNotificationFromType(typeDef, {\n requiredFeature: 'business_rules.manage',\n bodyVariables: {\n ruleName: payload.ruleName,\n entityType: payload.entityType ?? '',\n errorMessage: payload.errorMessage ?? 'Unknown error',\n },\n sourceEntityType: 'business_rules:rule',\n sourceEntityId: payload.ruleId,\n linkHref: `/backend/business-rules/${payload.ruleId}`,\n })\n\n await notificationService.createForFeature(notificationInput, {\n tenantId: payload.tenantId,\n organizationId: payload.organizationId ?? null,\n })\n } catch (err) {\n console.error('[business_rules:rule-execution-failed-notification] Failed to create notification:', err)\n }\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,kCAAkC;AAC3C,SAAS,wCAAwC;AACjD,SAAS,yBAAyB;AAE3B,MAAM,WAAW;AAAA,EACtB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,IAAI;AACN;AAeA,eAAO,OAA8B,SAAqC,KAAsB;AAC9F,MAAI;AACF,UAAM,sBAAsB,2BAA2B,GAAG;AAC1D,UAAM,UAAU,kBAAkB,KAAK,CAAC,SAAS,KAAK,SAAS,sCAAsC;AACrG,QAAI,CAAC,QAAS;AAEd,UAAM,oBAAoB,iCAAiC,SAAS;AAAA,MAClE,iBAAiB;AAAA,MACjB,eAAe;AAAA,QACb,UAAU,QAAQ;AAAA,QAClB,YAAY,QAAQ,cAAc;AAAA,QAClC,cAAc,QAAQ,gBAAgB;AAAA,MACxC;AAAA,MACA,kBAAkB;AAAA,MAClB,gBAAgB,QAAQ;AAAA,MACxB,UAAU,2BAA2B,QAAQ,MAAM;AAAA,IACrD,CAAC;AAED,UAAM,oBAAoB,iBAAiB,mBAAmB;AAAA,MAC5D,UAAU,QAAQ;AAAA,MAClB,gBAAgB,QAAQ,kBAAkB;AAAA,IAC5C,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,YAAQ,MAAM,sFAAsF,GAAG;AAAA,EACzG;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -326,10 +326,12 @@ function PriceKindSettings() {
|
|
|
326
326
|
{
|
|
327
327
|
items: [
|
|
328
328
|
{
|
|
329
|
+
id: "edit",
|
|
329
330
|
label: t("catalog.priceKinds.actions.edit", "Edit"),
|
|
330
331
|
onSelect: () => openDialog({ mode: "edit", entry })
|
|
331
332
|
},
|
|
332
333
|
{
|
|
334
|
+
id: "delete",
|
|
333
335
|
label: t("catalog.priceKinds.actions.delete", "Delete"),
|
|
334
336
|
destructive: true,
|
|
335
337
|
onSelect: () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/catalog/components/PriceKindSettings.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { DictionaryEntrySelect } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport { useCurrencyDictionary } from '@open-mercato/core/modules/customers/components/detail/hooks/useCurrencyDictionary'\nimport type { DictionaryOption } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport type { CatalogPriceDisplayMode } from '../data/types'\n\ntype PriceKind = {\n id: string\n code: string\n title: string\n displayMode: CatalogPriceDisplayMode\n currencyCode: string | null\n isPromotion: boolean\n isActive: boolean\n createdAt: string\n updatedAt: string\n}\n\ntype DialogState =\n | { mode: 'create' }\n | { mode: 'edit'; entry: PriceKind }\n\ntype PriceKindApiPayload = Partial<PriceKind> & {\n display_mode?: PriceKind['displayMode']\n currency_code?: string | null\n is_promotion?: boolean\n is_active?: boolean\n created_at?: string\n updated_at?: string\n}\n\nconst DISPLAY_MODES: Array<{ value: 'including-tax' | 'excluding-tax'; label: string }> = [\n { value: 'excluding-tax', label: 'Excluding tax' },\n { value: 'including-tax', label: 'Including tax' },\n]\n\nconst PAGE_SIZE = 100\n\ntype PriceKindFormState = {\n code: string\n title: string\n displayMode: CatalogPriceDisplayMode\n currencyCode: string\n isPromotion: boolean\n isActive: boolean\n}\n\nconst DEFAULT_FORM: PriceKindFormState = {\n code: '',\n title: '',\n displayMode: 'excluding-tax' as const,\n currencyCode: '',\n isPromotion: false,\n isActive: true,\n}\n\nconst normalizePriceKind = (input: PriceKindApiPayload | null | undefined): PriceKind => {\n const raw = input ?? {}\n const toStringValue = (value: unknown): string | null => {\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'bigint') return String(value)\n return null\n }\n const toBooleanValue = (value: unknown): boolean | null => (typeof value === 'boolean' ? value : null)\n const resolveDisplayMode = (value: string | null): PriceKind['displayMode'] =>\n value === 'including-tax' ? 'including-tax' : value === 'excluding-tax' ? 'excluding-tax' : 'excluding-tax'\n\n const displayMode = resolveDisplayMode(\n toStringValue(raw.displayMode) ?? toStringValue(raw.display_mode),\n )\n const currencyCode = toStringValue(raw.currencyCode) ?? toStringValue(raw.currency_code)\n const isPromotion = toBooleanValue(raw.isPromotion) ?? toBooleanValue(raw.is_promotion)\n const isActive = toBooleanValue(raw.isActive) ?? toBooleanValue(raw.is_active)\n\n return {\n id: toStringValue(raw.id) ?? '',\n code: toStringValue(raw.code) ?? '',\n title: toStringValue(raw.title) ?? '',\n displayMode,\n currencyCode: currencyCode ?? null,\n isPromotion: isPromotion ?? false,\n isActive: isActive ?? true,\n createdAt: toStringValue(raw.createdAt) ?? toStringValue(raw.created_at) ?? '',\n updatedAt: toStringValue(raw.updatedAt) ?? toStringValue(raw.updated_at) ?? '',\n }\n}\n\nexport function PriceKindSettings() {\n const t = useT()\n const scopeVersion = useOrganizationScopeVersion()\n const [items, setItems] = React.useState<PriceKind[]>([])\n const [loading, setLoading] = React.useState(false)\n const [search, setSearch] = React.useState('')\n const [dialog, setDialog] = React.useState<DialogState | null>(null)\n const [form, setForm] = React.useState<PriceKindFormState>(DEFAULT_FORM)\n const [submitting, setSubmitting] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const { data: currencyDictionary, refetch: refetchCurrencyDictionary } = useCurrencyDictionary()\n\n const currencyOptionsLoader = React.useCallback(async (): Promise<DictionaryOption[]> => {\n if (currencyDictionary && Array.isArray(currencyDictionary.entries)) {\n return currencyDictionary.entries.map((entry) => ({\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n }))\n }\n const payload = await refetchCurrencyDictionary()\n return payload.entries.map((entry) => ({\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n }))\n }, [currencyDictionary, refetchCurrencyDictionary])\n\n const loadItems = React.useCallback(async () => {\n setLoading(true)\n const loadErrorMessage = t('catalog.priceKinds.errors.load', 'Failed to load price kinds.')\n try {\n const payload = await readApiResultOrThrow<{ items?: PriceKindApiPayload[] }>(\n `/api/catalog/price-kinds?pageSize=${PAGE_SIZE}`,\n undefined,\n { errorMessage: loadErrorMessage },\n )\n const normalized = Array.isArray(payload.items) ? payload.items.map((item) => normalizePriceKind(item)) : []\n setItems(normalized)\n } catch (err) {\n console.error('catalog.price-kinds.list failed', err)\n flash(loadErrorMessage, 'error')\n } finally {\n setLoading(false)\n }\n }, [t])\n\n React.useEffect(() => {\n loadItems().catch(() => {})\n }, [loadItems, scopeVersion])\n\n const openDialog = React.useCallback((state: DialogState) => {\n if (state.mode === 'edit') {\n setForm({\n code: state.entry.code,\n title: state.entry.title,\n displayMode: state.entry.displayMode,\n currencyCode: state.entry.currencyCode ?? '',\n isPromotion: state.entry.isPromotion,\n isActive: state.entry.isActive,\n })\n } else {\n setForm(DEFAULT_FORM)\n }\n setError(null)\n setDialog(state)\n }, [])\n\n const closeDialog = React.useCallback(() => {\n setDialog(null)\n setError(null)\n setSubmitting(false)\n setForm(DEFAULT_FORM)\n }, [])\n\n const handleSubmit = React.useCallback(async () => {\n if (!dialog) return\n const trimmedCode = form.code.trim().toLowerCase()\n const trimmedTitle = form.title.trim()\n if (!trimmedCode || !trimmedTitle) {\n setError(t('catalog.priceKinds.errors.required', 'Code and title are required.'))\n return\n }\n setSubmitting(true)\n setError(null)\n try {\n const payload = {\n code: trimmedCode,\n title: trimmedTitle,\n displayMode: form.displayMode,\n currencyCode: form.currencyCode.trim() || undefined,\n isPromotion: form.isPromotion,\n isActive: form.isActive,\n }\n const path = '/api/catalog/price-kinds'\n const method = dialog.mode === 'create' ? 'POST' : 'PUT'\n const body =\n dialog.mode === 'edit'\n ? JSON.stringify({ id: dialog.entry.id, ...payload })\n : JSON.stringify(payload)\n const call = await apiCall(path, {\n method,\n headers: { 'content-type': 'application/json' },\n body,\n })\n if (!call.ok) {\n await raiseCrudError(call.response, t('catalog.priceKinds.errors.save', 'Failed to save price kind.'))\n }\n flash(\n dialog.mode === 'create'\n ? t('catalog.priceKinds.messages.created', 'Price kind created.')\n : t('catalog.priceKinds.messages.updated', 'Price kind updated.'),\n 'success',\n )\n closeDialog()\n await loadItems()\n } catch (err) {\n console.error('catalog.price-kinds.save failed', err)\n const message =\n err instanceof Error ? err.message : t('catalog.priceKinds.errors.save', 'Failed to save price kind.')\n setError(message)\n } finally {\n setSubmitting(false)\n }\n }, [dialog, form, t, closeDialog, loadItems])\n\n const handleDelete = React.useCallback(\n async (entry: PriceKind) => {\n const confirmMessage = t('catalog.priceKinds.confirm.delete', 'Delete price kind \"{{code}}\"?').replace('{{code}}', entry.code)\n if (!window.confirm(confirmMessage)) return\n try {\n const call = await apiCall('/api/catalog/price-kinds', {\n method: 'DELETE',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id: entry.id }),\n })\n if (!call.ok) {\n await raiseCrudError(call.response, t('catalog.priceKinds.errors.delete', 'Failed to delete price kind.'))\n }\n flash(t('catalog.priceKinds.messages.deleted', 'Price kind deleted.'), 'success')\n await loadItems()\n } catch (err) {\n console.error('catalog.price-kinds.delete failed', err)\n const message =\n err instanceof Error ? err.message : t('catalog.priceKinds.errors.delete', 'Failed to delete price kind.')\n flash(message, 'error')\n }\n },\n [loadItems, t],\n )\n\n const formKeyHandler = React.useCallback(\n (event: React.KeyboardEvent<HTMLFormElement>) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n void handleSubmit()\n }\n },\n [handleSubmit],\n )\n\n const displayModeLabels = React.useMemo(() => ({\n 'including-tax': t('catalog.priceKinds.form.displayMode.include', 'Including tax'),\n 'excluding-tax': t('catalog.priceKinds.form.displayMode.exclude', 'Excluding tax'),\n }), [t])\n\n const displayModeOptions = React.useMemo(\n () =>\n DISPLAY_MODES.map((mode) => ({\n ...mode,\n label: displayModeLabels[mode.value],\n })),\n [displayModeLabels],\n )\n\n const currencyLabels = React.useMemo(() => ({\n placeholder: t('catalog.priceKinds.form.currency.placeholder', 'Select currency\u2026'),\n addLabel: t('catalog.priceKinds.form.currency.add', 'Add currency'),\n addPrompt: t('catalog.priceKinds.form.currency.addPrompt', 'Provide a currency code.'),\n dialogTitle: t('catalog.priceKinds.form.currency.dialogTitle', 'Add currency'),\n valueLabel: t('catalog.priceKinds.form.currency.valueLabel', 'Currency code'),\n valuePlaceholder: t('catalog.priceKinds.form.currency.valuePlaceholder', 'e.g. USD'),\n labelLabel: t('catalog.priceKinds.form.currency.labelLabel', 'Display label (optional)'),\n labelPlaceholder: t('catalog.priceKinds.form.currency.labelPlaceholder', 'e.g. US Dollar'),\n emptyError: t('catalog.priceKinds.form.currency.required', 'Currency code is required.'),\n cancelLabel: t('catalog.priceKinds.form.currency.cancel', 'Cancel'),\n saveLabel: t('catalog.priceKinds.form.currency.save', 'Save'),\n saveShortcutHint: t('catalog.priceKinds.form.currency.saveShortcut', 'Press Enter to save'),\n successCreateLabel: t('catalog.priceKinds.form.currency.success', 'Currency added.'),\n errorLoad: t('catalog.priceKinds.form.currency.loadError', 'Unable to load currencies.'),\n errorSave: t('catalog.priceKinds.form.currency.createError', 'Unable to add currency.'),\n loadingLabel: t('catalog.priceKinds.form.currency.loading', 'Loading currencies\u2026'),\n manageTitle: t('catalog.priceKinds.form.currency.manage', 'Manage currencies'),\n }), [t])\n\n const tableLabels = React.useMemo(() => ({\n code: t('catalog.priceKinds.table.code', 'Code'),\n title: t('catalog.priceKinds.table.title', 'Title'),\n displayMode: t('catalog.priceKinds.table.displayMode', 'Display mode'),\n currency: t('catalog.priceKinds.table.currency', 'Currency'),\n promotion: t('catalog.priceKinds.table.promotion', 'Promotion'),\n promotionYes: t('catalog.priceKinds.table.promotionYes', 'Yes'),\n promotionNo: t('catalog.priceKinds.table.promotionNo', 'No'),\n active: t('catalog.priceKinds.table.active', 'Active'),\n activeYes: t('catalog.priceKinds.table.activeYes', 'Active'),\n activeNo: t('catalog.priceKinds.table.activeNo', 'Inactive'),\n search: t('catalog.priceKinds.search.placeholder', 'Search by code or title\u2026'),\n empty: t('catalog.priceKinds.table.empty', 'No price kinds yet.'),\n }), [t])\n\n const columns = React.useMemo<ColumnDef<PriceKind>[]>(() => [\n {\n accessorKey: 'code',\n header: tableLabels.code,\n cell: ({ row }) => <span className=\"font-mono uppercase\">{row.original.code}</span>,\n },\n {\n accessorKey: 'title',\n header: tableLabels.title,\n cell: ({ row }) => <span className=\"font-medium\">{row.original.title}</span>,\n },\n {\n accessorKey: 'displayMode',\n header: tableLabels.displayMode,\n cell: ({ row }) => displayModeLabels[row.original.displayMode] ?? row.original.displayMode,\n },\n {\n accessorKey: 'currencyCode',\n header: tableLabels.currency,\n cell: ({ row }) => (row.original.currencyCode ? row.original.currencyCode.toUpperCase() : '\u2014'),\n },\n {\n id: 'promotion',\n header: tableLabels.promotion,\n cell: ({ row }) =>\n row.original.isPromotion ? (\n <span className=\"inline-flex items-center rounded-full border border-amber-200 bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-900 dark:border-amber-500/50 dark:bg-amber-500/10 dark:text-amber-100\">\n {tableLabels.promotionYes}\n </span>\n ) : (\n <span className=\"inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium\">\n {tableLabels.promotionNo}\n </span>\n ),\n },\n {\n id: 'active',\n header: tableLabels.active,\n cell: ({ row }) =>\n row.original.isActive ? (\n <span className=\"inline-flex items-center rounded-full border border-emerald-200 bg-emerald-50 px-2 py-0.5 text-xs font-medium text-emerald-900 dark:border-emerald-500/50 dark:bg-emerald-500/10 dark:text-emerald-100\">\n {tableLabels.activeYes}\n </span>\n ) : (\n <span className=\"inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium\">\n {tableLabels.activeNo}\n </span>\n ),\n },\n ], [displayModeLabels, tableLabels])\n\n const filteredItems = React.useMemo(() => {\n const term = search.trim().toLowerCase()\n if (!term) return items\n return items.filter((item) => {\n const currency = (item.currencyCode ?? '').toLowerCase()\n const modeLabel = (displayModeLabels[item.displayMode] ?? item.displayMode).toLowerCase()\n return (\n item.code.toLowerCase().includes(term) ||\n item.title.toLowerCase().includes(term) ||\n currency.includes(term) ||\n modeLabel.includes(term)\n )\n })\n }, [displayModeLabels, items, search])\n\n const handleRowClick = React.useCallback((entry: PriceKind) => {\n openDialog({ mode: 'edit', entry })\n }, [openDialog])\n\n return (\n <section className=\"border bg-card text-card-foreground shadow-sm\">\n <div className=\"border-b px-6 py-4 space-y-1\">\n <h2 className=\"text-lg font-semibold\">{t('catalog.priceKinds.title', 'Price kinds')}</h2>\n <p className=\"text-sm text-muted-foreground\">\n {t('catalog.priceKinds.description', 'Configure reusable price kinds that control pricing columns and tax display.')}\n </p>\n </div>\n <div className=\"px-2 py-4 sm:px-4\">\n <DataTable<PriceKind>\n data={filteredItems}\n columns={columns}\n embedded\n isLoading={loading}\n searchValue={search}\n onSearchChange={setSearch}\n searchPlaceholder={tableLabels.search}\n emptyState={<p className=\"py-8 text-center text-sm text-muted-foreground\">{tableLabels.empty}</p>}\n actions={(\n <Button size=\"sm\" onClick={() => openDialog({ mode: 'create' })}>\n {t('catalog.priceKinds.actions.add', 'Add price kind')}\n </Button>\n )}\n refreshButton={{\n label: t('catalog.priceKinds.actions.refresh', 'Refresh'),\n onRefresh: () => { void loadItems() },\n isRefreshing: loading,\n }}\n rowActions={(entry) => (\n <RowActions\n items={[\n {\n label: t('catalog.priceKinds.actions.edit', 'Edit'),\n onSelect: () => openDialog({ mode: 'edit', entry }),\n },\n {\n label: t('catalog.priceKinds.actions.delete', 'Delete'),\n destructive: true,\n onSelect: () => { void handleDelete(entry) },\n },\n ]}\n />\n )}\n onRowClick={handleRowClick}\n />\n </div>\n <Dialog open={dialog !== null} onOpenChange={(open) => { if (!open) closeDialog(); }}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {dialog?.mode === 'edit'\n ? t('catalog.priceKinds.dialog.editTitle', 'Edit price kind')\n : t('catalog.priceKinds.dialog.createTitle', 'Create price kind')}\n </DialogTitle>\n <DialogDescription>\n {dialog?.mode === 'edit'\n ? t('catalog.priceKinds.dialog.editDescription', 'Update labels or tax behavior for this price kind.')\n : t('catalog.priceKinds.dialog.createDescription', 'Define a reusable price kind for product pricing.')}\n </DialogDescription>\n </DialogHeader>\n <form className=\"space-y-4\" onKeyDown={formKeyHandler} onSubmit={(event) => { event.preventDefault(); void handleSubmit() }}>\n <div className=\"space-y-2\">\n <Label htmlFor=\"price-kind-code\">{t('catalog.priceKinds.form.codeLabel', 'Code')}</Label>\n <Input\n id=\"price-kind-code\"\n value={form.code}\n onChange={(event) => setForm((prev) => ({ ...prev, code: event.target.value }))}\n placeholder={t('catalog.priceKinds.form.codePlaceholder', 'e.g. regular')}\n className=\"font-mono uppercase\"\n disabled={dialog?.mode === 'edit'}\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"price-kind-title\">{t('catalog.priceKinds.form.titleLabel', 'Title')}</Label>\n <Input\n id=\"price-kind-title\"\n value={form.title}\n onChange={(event) => setForm((prev) => ({ ...prev, title: event.target.value }))}\n placeholder={t('catalog.priceKinds.form.titlePlaceholder', 'e.g. Regular price')}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>{t('catalog.priceKinds.form.displayModeLabel', 'Display mode')}</Label>\n <div className=\"grid gap-2 md:grid-cols-2\">\n {displayModeOptions.map((mode) => (\n <label\n key={mode.value}\n className={`flex cursor-pointer items-center gap-2 rounded-md border p-3 text-sm ${\n form.displayMode === mode.value ? 'border-primary bg-primary/5' : 'border-border'\n }`}\n >\n <input\n type=\"radio\"\n name=\"displayMode\"\n value={mode.value}\n checked={form.displayMode === mode.value}\n onChange={() => setForm((prev) => ({ ...prev, displayMode: mode.value }))}\n />\n <span>{mode.label}</span>\n </label>\n ))}\n </div>\n </div>\n <div className=\"space-y-2\">\n <Label>{t('catalog.priceKinds.form.currencyLabel', 'Currency (optional)')}</Label>\n <DictionaryEntrySelect\n value={form.currencyCode || undefined}\n onChange={(value) => setForm((prev) => ({ ...prev, currencyCode: value ?? '' }))}\n fetchOptions={currencyOptionsLoader}\n labels={currencyLabels}\n allowInlineCreate={false}\n />\n </div>\n <div className=\"flex flex-col gap-2\">\n <label className=\"flex items-center gap-2 text-sm font-medium\">\n <input\n type=\"checkbox\"\n className=\"h-4 w-4 rounded border\"\n checked={form.isPromotion}\n onChange={(event) => setForm((prev) => ({ ...prev, isPromotion: event.target.checked }))}\n />\n {t('catalog.priceKinds.form.promotionLabel', 'Mark as promotion')}\n </label>\n <label className=\"flex items-center gap-2 text-sm font-medium\">\n <input\n type=\"checkbox\"\n className=\"h-4 w-4 rounded border\"\n checked={form.isActive}\n onChange={(event) => setForm((prev) => ({ ...prev, isActive: event.target.checked }))}\n />\n {t('catalog.priceKinds.form.activeLabel', 'Active')}\n </label>\n </div>\n {error ? <p className=\"text-sm text-red-600\">{error}</p> : null}\n </form>\n <DialogFooter>\n <Button variant=\"ghost\" onClick={closeDialog}>\n {t('catalog.priceKinds.actions.cancel', 'Cancel')}\n </Button>\n <Button onClick={() => void handleSubmit()} disabled={submitting}>\n {dialog?.mode === 'edit'\n ? t('catalog.priceKinds.actions.saveChanges', 'Save changes')\n : t('catalog.priceKinds.actions.create', 'Create')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </section>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { DictionaryEntrySelect } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport { useCurrencyDictionary } from '@open-mercato/core/modules/customers/components/detail/hooks/useCurrencyDictionary'\nimport type { DictionaryOption } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport type { CatalogPriceDisplayMode } from '../data/types'\n\ntype PriceKind = {\n id: string\n code: string\n title: string\n displayMode: CatalogPriceDisplayMode\n currencyCode: string | null\n isPromotion: boolean\n isActive: boolean\n createdAt: string\n updatedAt: string\n}\n\ntype DialogState =\n | { mode: 'create' }\n | { mode: 'edit'; entry: PriceKind }\n\ntype PriceKindApiPayload = Partial<PriceKind> & {\n display_mode?: PriceKind['displayMode']\n currency_code?: string | null\n is_promotion?: boolean\n is_active?: boolean\n created_at?: string\n updated_at?: string\n}\n\nconst DISPLAY_MODES: Array<{ value: 'including-tax' | 'excluding-tax'; label: string }> = [\n { value: 'excluding-tax', label: 'Excluding tax' },\n { value: 'including-tax', label: 'Including tax' },\n]\n\nconst PAGE_SIZE = 100\n\ntype PriceKindFormState = {\n code: string\n title: string\n displayMode: CatalogPriceDisplayMode\n currencyCode: string\n isPromotion: boolean\n isActive: boolean\n}\n\nconst DEFAULT_FORM: PriceKindFormState = {\n code: '',\n title: '',\n displayMode: 'excluding-tax' as const,\n currencyCode: '',\n isPromotion: false,\n isActive: true,\n}\n\nconst normalizePriceKind = (input: PriceKindApiPayload | null | undefined): PriceKind => {\n const raw = input ?? {}\n const toStringValue = (value: unknown): string | null => {\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'bigint') return String(value)\n return null\n }\n const toBooleanValue = (value: unknown): boolean | null => (typeof value === 'boolean' ? value : null)\n const resolveDisplayMode = (value: string | null): PriceKind['displayMode'] =>\n value === 'including-tax' ? 'including-tax' : value === 'excluding-tax' ? 'excluding-tax' : 'excluding-tax'\n\n const displayMode = resolveDisplayMode(\n toStringValue(raw.displayMode) ?? toStringValue(raw.display_mode),\n )\n const currencyCode = toStringValue(raw.currencyCode) ?? toStringValue(raw.currency_code)\n const isPromotion = toBooleanValue(raw.isPromotion) ?? toBooleanValue(raw.is_promotion)\n const isActive = toBooleanValue(raw.isActive) ?? toBooleanValue(raw.is_active)\n\n return {\n id: toStringValue(raw.id) ?? '',\n code: toStringValue(raw.code) ?? '',\n title: toStringValue(raw.title) ?? '',\n displayMode,\n currencyCode: currencyCode ?? null,\n isPromotion: isPromotion ?? false,\n isActive: isActive ?? true,\n createdAt: toStringValue(raw.createdAt) ?? toStringValue(raw.created_at) ?? '',\n updatedAt: toStringValue(raw.updatedAt) ?? toStringValue(raw.updated_at) ?? '',\n }\n}\n\nexport function PriceKindSettings() {\n const t = useT()\n const scopeVersion = useOrganizationScopeVersion()\n const [items, setItems] = React.useState<PriceKind[]>([])\n const [loading, setLoading] = React.useState(false)\n const [search, setSearch] = React.useState('')\n const [dialog, setDialog] = React.useState<DialogState | null>(null)\n const [form, setForm] = React.useState<PriceKindFormState>(DEFAULT_FORM)\n const [submitting, setSubmitting] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const { data: currencyDictionary, refetch: refetchCurrencyDictionary } = useCurrencyDictionary()\n\n const currencyOptionsLoader = React.useCallback(async (): Promise<DictionaryOption[]> => {\n if (currencyDictionary && Array.isArray(currencyDictionary.entries)) {\n return currencyDictionary.entries.map((entry) => ({\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n }))\n }\n const payload = await refetchCurrencyDictionary()\n return payload.entries.map((entry) => ({\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n }))\n }, [currencyDictionary, refetchCurrencyDictionary])\n\n const loadItems = React.useCallback(async () => {\n setLoading(true)\n const loadErrorMessage = t('catalog.priceKinds.errors.load', 'Failed to load price kinds.')\n try {\n const payload = await readApiResultOrThrow<{ items?: PriceKindApiPayload[] }>(\n `/api/catalog/price-kinds?pageSize=${PAGE_SIZE}`,\n undefined,\n { errorMessage: loadErrorMessage },\n )\n const normalized = Array.isArray(payload.items) ? payload.items.map((item) => normalizePriceKind(item)) : []\n setItems(normalized)\n } catch (err) {\n console.error('catalog.price-kinds.list failed', err)\n flash(loadErrorMessage, 'error')\n } finally {\n setLoading(false)\n }\n }, [t])\n\n React.useEffect(() => {\n loadItems().catch(() => {})\n }, [loadItems, scopeVersion])\n\n const openDialog = React.useCallback((state: DialogState) => {\n if (state.mode === 'edit') {\n setForm({\n code: state.entry.code,\n title: state.entry.title,\n displayMode: state.entry.displayMode,\n currencyCode: state.entry.currencyCode ?? '',\n isPromotion: state.entry.isPromotion,\n isActive: state.entry.isActive,\n })\n } else {\n setForm(DEFAULT_FORM)\n }\n setError(null)\n setDialog(state)\n }, [])\n\n const closeDialog = React.useCallback(() => {\n setDialog(null)\n setError(null)\n setSubmitting(false)\n setForm(DEFAULT_FORM)\n }, [])\n\n const handleSubmit = React.useCallback(async () => {\n if (!dialog) return\n const trimmedCode = form.code.trim().toLowerCase()\n const trimmedTitle = form.title.trim()\n if (!trimmedCode || !trimmedTitle) {\n setError(t('catalog.priceKinds.errors.required', 'Code and title are required.'))\n return\n }\n setSubmitting(true)\n setError(null)\n try {\n const payload = {\n code: trimmedCode,\n title: trimmedTitle,\n displayMode: form.displayMode,\n currencyCode: form.currencyCode.trim() || undefined,\n isPromotion: form.isPromotion,\n isActive: form.isActive,\n }\n const path = '/api/catalog/price-kinds'\n const method = dialog.mode === 'create' ? 'POST' : 'PUT'\n const body =\n dialog.mode === 'edit'\n ? JSON.stringify({ id: dialog.entry.id, ...payload })\n : JSON.stringify(payload)\n const call = await apiCall(path, {\n method,\n headers: { 'content-type': 'application/json' },\n body,\n })\n if (!call.ok) {\n await raiseCrudError(call.response, t('catalog.priceKinds.errors.save', 'Failed to save price kind.'))\n }\n flash(\n dialog.mode === 'create'\n ? t('catalog.priceKinds.messages.created', 'Price kind created.')\n : t('catalog.priceKinds.messages.updated', 'Price kind updated.'),\n 'success',\n )\n closeDialog()\n await loadItems()\n } catch (err) {\n console.error('catalog.price-kinds.save failed', err)\n const message =\n err instanceof Error ? err.message : t('catalog.priceKinds.errors.save', 'Failed to save price kind.')\n setError(message)\n } finally {\n setSubmitting(false)\n }\n }, [dialog, form, t, closeDialog, loadItems])\n\n const handleDelete = React.useCallback(\n async (entry: PriceKind) => {\n const confirmMessage = t('catalog.priceKinds.confirm.delete', 'Delete price kind \"{{code}}\"?').replace('{{code}}', entry.code)\n if (!window.confirm(confirmMessage)) return\n try {\n const call = await apiCall('/api/catalog/price-kinds', {\n method: 'DELETE',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id: entry.id }),\n })\n if (!call.ok) {\n await raiseCrudError(call.response, t('catalog.priceKinds.errors.delete', 'Failed to delete price kind.'))\n }\n flash(t('catalog.priceKinds.messages.deleted', 'Price kind deleted.'), 'success')\n await loadItems()\n } catch (err) {\n console.error('catalog.price-kinds.delete failed', err)\n const message =\n err instanceof Error ? err.message : t('catalog.priceKinds.errors.delete', 'Failed to delete price kind.')\n flash(message, 'error')\n }\n },\n [loadItems, t],\n )\n\n const formKeyHandler = React.useCallback(\n (event: React.KeyboardEvent<HTMLFormElement>) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n void handleSubmit()\n }\n },\n [handleSubmit],\n )\n\n const displayModeLabels = React.useMemo(() => ({\n 'including-tax': t('catalog.priceKinds.form.displayMode.include', 'Including tax'),\n 'excluding-tax': t('catalog.priceKinds.form.displayMode.exclude', 'Excluding tax'),\n }), [t])\n\n const displayModeOptions = React.useMemo(\n () =>\n DISPLAY_MODES.map((mode) => ({\n ...mode,\n label: displayModeLabels[mode.value],\n })),\n [displayModeLabels],\n )\n\n const currencyLabels = React.useMemo(() => ({\n placeholder: t('catalog.priceKinds.form.currency.placeholder', 'Select currency\u2026'),\n addLabel: t('catalog.priceKinds.form.currency.add', 'Add currency'),\n addPrompt: t('catalog.priceKinds.form.currency.addPrompt', 'Provide a currency code.'),\n dialogTitle: t('catalog.priceKinds.form.currency.dialogTitle', 'Add currency'),\n valueLabel: t('catalog.priceKinds.form.currency.valueLabel', 'Currency code'),\n valuePlaceholder: t('catalog.priceKinds.form.currency.valuePlaceholder', 'e.g. USD'),\n labelLabel: t('catalog.priceKinds.form.currency.labelLabel', 'Display label (optional)'),\n labelPlaceholder: t('catalog.priceKinds.form.currency.labelPlaceholder', 'e.g. US Dollar'),\n emptyError: t('catalog.priceKinds.form.currency.required', 'Currency code is required.'),\n cancelLabel: t('catalog.priceKinds.form.currency.cancel', 'Cancel'),\n saveLabel: t('catalog.priceKinds.form.currency.save', 'Save'),\n saveShortcutHint: t('catalog.priceKinds.form.currency.saveShortcut', 'Press Enter to save'),\n successCreateLabel: t('catalog.priceKinds.form.currency.success', 'Currency added.'),\n errorLoad: t('catalog.priceKinds.form.currency.loadError', 'Unable to load currencies.'),\n errorSave: t('catalog.priceKinds.form.currency.createError', 'Unable to add currency.'),\n loadingLabel: t('catalog.priceKinds.form.currency.loading', 'Loading currencies\u2026'),\n manageTitle: t('catalog.priceKinds.form.currency.manage', 'Manage currencies'),\n }), [t])\n\n const tableLabels = React.useMemo(() => ({\n code: t('catalog.priceKinds.table.code', 'Code'),\n title: t('catalog.priceKinds.table.title', 'Title'),\n displayMode: t('catalog.priceKinds.table.displayMode', 'Display mode'),\n currency: t('catalog.priceKinds.table.currency', 'Currency'),\n promotion: t('catalog.priceKinds.table.promotion', 'Promotion'),\n promotionYes: t('catalog.priceKinds.table.promotionYes', 'Yes'),\n promotionNo: t('catalog.priceKinds.table.promotionNo', 'No'),\n active: t('catalog.priceKinds.table.active', 'Active'),\n activeYes: t('catalog.priceKinds.table.activeYes', 'Active'),\n activeNo: t('catalog.priceKinds.table.activeNo', 'Inactive'),\n search: t('catalog.priceKinds.search.placeholder', 'Search by code or title\u2026'),\n empty: t('catalog.priceKinds.table.empty', 'No price kinds yet.'),\n }), [t])\n\n const columns = React.useMemo<ColumnDef<PriceKind>[]>(() => [\n {\n accessorKey: 'code',\n header: tableLabels.code,\n cell: ({ row }) => <span className=\"font-mono uppercase\">{row.original.code}</span>,\n },\n {\n accessorKey: 'title',\n header: tableLabels.title,\n cell: ({ row }) => <span className=\"font-medium\">{row.original.title}</span>,\n },\n {\n accessorKey: 'displayMode',\n header: tableLabels.displayMode,\n cell: ({ row }) => displayModeLabels[row.original.displayMode] ?? row.original.displayMode,\n },\n {\n accessorKey: 'currencyCode',\n header: tableLabels.currency,\n cell: ({ row }) => (row.original.currencyCode ? row.original.currencyCode.toUpperCase() : '\u2014'),\n },\n {\n id: 'promotion',\n header: tableLabels.promotion,\n cell: ({ row }) =>\n row.original.isPromotion ? (\n <span className=\"inline-flex items-center rounded-full border border-amber-200 bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-900 dark:border-amber-500/50 dark:bg-amber-500/10 dark:text-amber-100\">\n {tableLabels.promotionYes}\n </span>\n ) : (\n <span className=\"inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium\">\n {tableLabels.promotionNo}\n </span>\n ),\n },\n {\n id: 'active',\n header: tableLabels.active,\n cell: ({ row }) =>\n row.original.isActive ? (\n <span className=\"inline-flex items-center rounded-full border border-emerald-200 bg-emerald-50 px-2 py-0.5 text-xs font-medium text-emerald-900 dark:border-emerald-500/50 dark:bg-emerald-500/10 dark:text-emerald-100\">\n {tableLabels.activeYes}\n </span>\n ) : (\n <span className=\"inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium\">\n {tableLabels.activeNo}\n </span>\n ),\n },\n ], [displayModeLabels, tableLabels])\n\n const filteredItems = React.useMemo(() => {\n const term = search.trim().toLowerCase()\n if (!term) return items\n return items.filter((item) => {\n const currency = (item.currencyCode ?? '').toLowerCase()\n const modeLabel = (displayModeLabels[item.displayMode] ?? item.displayMode).toLowerCase()\n return (\n item.code.toLowerCase().includes(term) ||\n item.title.toLowerCase().includes(term) ||\n currency.includes(term) ||\n modeLabel.includes(term)\n )\n })\n }, [displayModeLabels, items, search])\n\n const handleRowClick = React.useCallback((entry: PriceKind) => {\n openDialog({ mode: 'edit', entry })\n }, [openDialog])\n\n return (\n <section className=\"border bg-card text-card-foreground shadow-sm\">\n <div className=\"border-b px-6 py-4 space-y-1\">\n <h2 className=\"text-lg font-semibold\">{t('catalog.priceKinds.title', 'Price kinds')}</h2>\n <p className=\"text-sm text-muted-foreground\">\n {t('catalog.priceKinds.description', 'Configure reusable price kinds that control pricing columns and tax display.')}\n </p>\n </div>\n <div className=\"px-2 py-4 sm:px-4\">\n <DataTable<PriceKind>\n data={filteredItems}\n columns={columns}\n embedded\n isLoading={loading}\n searchValue={search}\n onSearchChange={setSearch}\n searchPlaceholder={tableLabels.search}\n emptyState={<p className=\"py-8 text-center text-sm text-muted-foreground\">{tableLabels.empty}</p>}\n actions={(\n <Button size=\"sm\" onClick={() => openDialog({ mode: 'create' })}>\n {t('catalog.priceKinds.actions.add', 'Add price kind')}\n </Button>\n )}\n refreshButton={{\n label: t('catalog.priceKinds.actions.refresh', 'Refresh'),\n onRefresh: () => { void loadItems() },\n isRefreshing: loading,\n }}\n rowActions={(entry) => (\n <RowActions\n items={[\n {\n id: 'edit',\n label: t('catalog.priceKinds.actions.edit', 'Edit'),\n onSelect: () => openDialog({ mode: 'edit', entry }),\n },\n {\n id: 'delete',\n label: t('catalog.priceKinds.actions.delete', 'Delete'),\n destructive: true,\n onSelect: () => { void handleDelete(entry) },\n },\n ]}\n />\n )}\n onRowClick={handleRowClick}\n />\n </div>\n <Dialog open={dialog !== null} onOpenChange={(open) => { if (!open) closeDialog(); }}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {dialog?.mode === 'edit'\n ? t('catalog.priceKinds.dialog.editTitle', 'Edit price kind')\n : t('catalog.priceKinds.dialog.createTitle', 'Create price kind')}\n </DialogTitle>\n <DialogDescription>\n {dialog?.mode === 'edit'\n ? t('catalog.priceKinds.dialog.editDescription', 'Update labels or tax behavior for this price kind.')\n : t('catalog.priceKinds.dialog.createDescription', 'Define a reusable price kind for product pricing.')}\n </DialogDescription>\n </DialogHeader>\n <form className=\"space-y-4\" onKeyDown={formKeyHandler} onSubmit={(event) => { event.preventDefault(); void handleSubmit() }}>\n <div className=\"space-y-2\">\n <Label htmlFor=\"price-kind-code\">{t('catalog.priceKinds.form.codeLabel', 'Code')}</Label>\n <Input\n id=\"price-kind-code\"\n value={form.code}\n onChange={(event) => setForm((prev) => ({ ...prev, code: event.target.value }))}\n placeholder={t('catalog.priceKinds.form.codePlaceholder', 'e.g. regular')}\n className=\"font-mono uppercase\"\n disabled={dialog?.mode === 'edit'}\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"price-kind-title\">{t('catalog.priceKinds.form.titleLabel', 'Title')}</Label>\n <Input\n id=\"price-kind-title\"\n value={form.title}\n onChange={(event) => setForm((prev) => ({ ...prev, title: event.target.value }))}\n placeholder={t('catalog.priceKinds.form.titlePlaceholder', 'e.g. Regular price')}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>{t('catalog.priceKinds.form.displayModeLabel', 'Display mode')}</Label>\n <div className=\"grid gap-2 md:grid-cols-2\">\n {displayModeOptions.map((mode) => (\n <label\n key={mode.value}\n className={`flex cursor-pointer items-center gap-2 rounded-md border p-3 text-sm ${\n form.displayMode === mode.value ? 'border-primary bg-primary/5' : 'border-border'\n }`}\n >\n <input\n type=\"radio\"\n name=\"displayMode\"\n value={mode.value}\n checked={form.displayMode === mode.value}\n onChange={() => setForm((prev) => ({ ...prev, displayMode: mode.value }))}\n />\n <span>{mode.label}</span>\n </label>\n ))}\n </div>\n </div>\n <div className=\"space-y-2\">\n <Label>{t('catalog.priceKinds.form.currencyLabel', 'Currency (optional)')}</Label>\n <DictionaryEntrySelect\n value={form.currencyCode || undefined}\n onChange={(value) => setForm((prev) => ({ ...prev, currencyCode: value ?? '' }))}\n fetchOptions={currencyOptionsLoader}\n labels={currencyLabels}\n allowInlineCreate={false}\n />\n </div>\n <div className=\"flex flex-col gap-2\">\n <label className=\"flex items-center gap-2 text-sm font-medium\">\n <input\n type=\"checkbox\"\n className=\"h-4 w-4 rounded border\"\n checked={form.isPromotion}\n onChange={(event) => setForm((prev) => ({ ...prev, isPromotion: event.target.checked }))}\n />\n {t('catalog.priceKinds.form.promotionLabel', 'Mark as promotion')}\n </label>\n <label className=\"flex items-center gap-2 text-sm font-medium\">\n <input\n type=\"checkbox\"\n className=\"h-4 w-4 rounded border\"\n checked={form.isActive}\n onChange={(event) => setForm((prev) => ({ ...prev, isActive: event.target.checked }))}\n />\n {t('catalog.priceKinds.form.activeLabel', 'Active')}\n </label>\n </div>\n {error ? <p className=\"text-sm text-red-600\">{error}</p> : null}\n </form>\n <DialogFooter>\n <Button variant=\"ghost\" onClick={closeDialog}>\n {t('catalog.priceKinds.actions.cancel', 'Cancel')}\n </Button>\n <Button onClick={() => void handleSubmit()} disabled={submitting}>\n {dialog?.mode === 'edit'\n ? t('catalog.priceKinds.actions.saveChanges', 'Save changes')\n : t('catalog.priceKinds.actions.create', 'Create')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </section>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -178,8 +178,8 @@ function CategoriesDataTable() {
|
|
|
178
178
|
RowActions,
|
|
179
179
|
{
|
|
180
180
|
items: [
|
|
181
|
-
{ label: t("catalog.categories.list.actions.edit", "Edit"), href: `/backend/catalog/categories/${row.id}/edit` },
|
|
182
|
-
{ label: t("catalog.categories.list.actions.delete", "Delete"), destructive: true, onSelect: () => handleDelete(row) }
|
|
181
|
+
{ id: "edit", label: t("catalog.categories.list.actions.edit", "Edit"), href: `/backend/catalog/categories/${row.id}/edit` },
|
|
182
|
+
{ id: "delete", label: t("catalog.categories.list.actions.delete", "Delete"), destructive: true, onSelect: () => handleDelete(row) }
|
|
183
183
|
]
|
|
184
184
|
}
|
|
185
185
|
) : null,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/catalog/components/categories/CategoriesDataTable.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'\nimport { apiCall, apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { formatCategoryTreeLabel } from '../../lib/categoryTree'\n\ntype CategoryRow = {\n id: string\n name: string\n slug: string | null\n description: string | null\n parentId: string | null\n parentName: string | null\n depth: number\n treePath: string\n pathLabel: string\n childCount: number\n descendantCount: number\n isActive: boolean\n}\n\ntype CategoriesResponse = {\n items: CategoryRow[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n}\n\nconst PAGE_SIZE = 50\nconst TREE_BASE_INDENT = 18\nconst TREE_STEP_INDENT = 14\n\nfunction computeIndent(depth: number): number {\n if (depth <= 0) return 0\n return TREE_BASE_INDENT + (depth - 1) * TREE_STEP_INDENT\n}\n\nexport default function CategoriesDataTable() {\n const t = useT()\n const queryClient = useQueryClient()\n const scopeVersion = useOrganizationScopeVersion()\n const [page, setPage] = React.useState(1)\n const [status, setStatus] = React.useState<'all' | 'active' | 'inactive'>('all')\n const [search, setSearch] = React.useState('')\n const [canManage, setCanManage] = React.useState(false)\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n try {\n const call = await apiCall<{ granted?: string[]; ok?: boolean }>('/api/auth/feature-check', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ features: ['catalog.categories.manage'] }),\n })\n if (!cancelled) {\n const granted = Array.isArray(call.result?.granted) ? call.result.granted : []\n setCanManage(call.result?.ok === true || granted.includes('catalog.categories.manage'))\n }\n } catch {\n if (!cancelled) setCanManage(false)\n }\n }\n load()\n return () => {\n cancelled = true\n }\n }, [])\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n params.set('view', 'manage')\n params.set('page', String(page))\n params.set('pageSize', String(PAGE_SIZE))\n params.set('status', status)\n if (search) params.set('search', search)\n return params.toString()\n }, [page, status, search])\n\n const { data, isLoading } = useQuery<CategoriesResponse>({\n queryKey: ['catalog-categories', queryParams, scopeVersion],\n queryFn: async () => {\n const payload = await readApiResultOrThrow<CategoriesResponse>(\n `/api/catalog/categories?${queryParams}`,\n undefined,\n { errorMessage: t('catalog.categories.list.error.load', 'Failed to load categories') },\n )\n return {\n items: Array.isArray(payload.items) ? payload.items : [],\n total: typeof payload.total === 'number' ? payload.total : 0,\n page: typeof payload.page === 'number' ? payload.page : 1,\n pageSize: typeof payload.pageSize === 'number' ? payload.pageSize : PAGE_SIZE,\n totalPages: typeof payload.totalPages === 'number' ? payload.totalPages : 1,\n }\n },\n })\n\n const rows = data?.items ?? []\n const total = data?.total ?? 0\n const totalPages = data?.totalPages ?? 1\n\n const columns = React.useMemo<ColumnDef<CategoryRow>[]>(() => [\n {\n accessorKey: 'name',\n header: t('catalog.categories.list.columns.category', 'Category'),\n meta: { priority: 1 },\n cell: ({ row }) => {\n const depth = row.original.depth ?? 0\n return (\n <div className=\"flex items-center text-sm font-medium leading-none text-foreground\">\n <span style={{ marginLeft: computeIndent(depth), whiteSpace: 'pre' }}>\n {formatCategoryTreeLabel(row.original.name, depth)}\n </span>\n </div>\n )\n },\n },\n {\n accessorKey: 'pathLabel',\n header: t('catalog.categories.list.columns.path', 'Path'),\n meta: { priority: 3 },\n cell: ({ getValue }) => {\n const value = getValue<string>()\n return <span className=\"text-xs text-muted-foreground\">{value || '\u2014'}</span>\n },\n },\n {\n accessorKey: 'parentName',\n header: t('catalog.categories.list.columns.parent', 'Parent'),\n meta: { priority: 4 },\n cell: ({ getValue }) => getValue<string>() || t('catalog.categories.list.none', '\u2014'),\n },\n {\n accessorKey: 'childCount',\n header: t('catalog.categories.list.columns.children', 'Children'),\n meta: { priority: 5 },\n },\n {\n accessorKey: 'isActive',\n header: t('catalog.categories.list.columns.active', 'Active'),\n enableSorting: false,\n meta: { priority: 2 },\n cell: ({ getValue }) => <BooleanIcon value={Boolean(getValue())} />,\n },\n ], [t])\n\n const handleDelete = React.useCallback(async (category: CategoryRow) => {\n const confirmLabel = t(\n 'catalog.categories.list.confirmDelete',\n 'Archive category \"{{name}}\"?',\n { name: category.name },\n )\n if (!window.confirm(confirmLabel)) return\n try {\n await apiCallOrThrow(\n `/api/catalog/categories?id=${encodeURIComponent(category.id)}`,\n { method: 'DELETE' },\n { errorMessage: t('catalog.categories.list.error.delete', 'Failed to delete category') },\n )\n await queryClient.invalidateQueries({ queryKey: ['catalog-categories'] })\n flash(t('catalog.categories.flash.deleted', 'Category archived'), 'success')\n } catch (err: unknown) {\n const fallback = t('catalog.categories.list.error.delete', 'Failed to delete category')\n const message = err instanceof Error ? err.message : fallback\n flash(message, 'error')\n }\n }, [queryClient, t])\n\n return (\n <DataTable\n title={t('catalog.categories.list.title', 'Categories')}\n actions={canManage ? (\n <Button asChild>\n <Link href=\"/backend/catalog/categories/create\">\n {t('catalog.categories.list.actions.create', 'Create')}\n </Link>\n </Button>\n ) : undefined}\n columns={columns}\n data={rows}\n searchValue={search}\n searchPlaceholder={t('catalog.categories.list.searchPlaceholder', 'Search categories')}\n onSearchChange={(value) => { setSearch(value); setPage(1) }}\n filters={[\n {\n id: 'status',\n label: t('catalog.categories.list.filters.status', 'Status'),\n type: 'select',\n options: [\n { value: 'all', label: t('catalog.categories.list.filters.all', 'All') },\n { value: 'active', label: t('catalog.categories.list.filters.active', 'Active') },\n { value: 'inactive', label: t('catalog.categories.list.filters.inactive', 'Inactive') },\n ],\n },\n ]}\n filterValues={status === 'all' ? {} : { status }}\n onFiltersApply={(values: FilterValues) => {\n const nextStatus = (values.status as 'all' | 'active' | 'inactive' | undefined) ?? 'all'\n setStatus(nextStatus)\n setPage(1)\n }}\n onFiltersClear={() => {\n setStatus('all')\n setPage(1)\n }}\n sortable={false}\n perspective={{ tableId: 'catalog.categories.list' }}\n rowActions={(row) => (\n canManage ? (\n <RowActions\n items={[\n { label: t('catalog.categories.list.actions.edit', 'Edit'), href: `/backend/catalog/categories/${row.id}/edit` },\n { label: t('catalog.categories.list.actions.delete', 'Delete'), destructive: true, onSelect: () => handleDelete(row) },\n ]}\n />\n ) : null\n )}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalPages,\n onPageChange: setPage,\n }}\n isLoading={isLoading}\n />\n )\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'\nimport { apiCall, apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { formatCategoryTreeLabel } from '../../lib/categoryTree'\n\ntype CategoryRow = {\n id: string\n name: string\n slug: string | null\n description: string | null\n parentId: string | null\n parentName: string | null\n depth: number\n treePath: string\n pathLabel: string\n childCount: number\n descendantCount: number\n isActive: boolean\n}\n\ntype CategoriesResponse = {\n items: CategoryRow[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n}\n\nconst PAGE_SIZE = 50\nconst TREE_BASE_INDENT = 18\nconst TREE_STEP_INDENT = 14\n\nfunction computeIndent(depth: number): number {\n if (depth <= 0) return 0\n return TREE_BASE_INDENT + (depth - 1) * TREE_STEP_INDENT\n}\n\nexport default function CategoriesDataTable() {\n const t = useT()\n const queryClient = useQueryClient()\n const scopeVersion = useOrganizationScopeVersion()\n const [page, setPage] = React.useState(1)\n const [status, setStatus] = React.useState<'all' | 'active' | 'inactive'>('all')\n const [search, setSearch] = React.useState('')\n const [canManage, setCanManage] = React.useState(false)\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n try {\n const call = await apiCall<{ granted?: string[]; ok?: boolean }>('/api/auth/feature-check', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ features: ['catalog.categories.manage'] }),\n })\n if (!cancelled) {\n const granted = Array.isArray(call.result?.granted) ? call.result.granted : []\n setCanManage(call.result?.ok === true || granted.includes('catalog.categories.manage'))\n }\n } catch {\n if (!cancelled) setCanManage(false)\n }\n }\n load()\n return () => {\n cancelled = true\n }\n }, [])\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n params.set('view', 'manage')\n params.set('page', String(page))\n params.set('pageSize', String(PAGE_SIZE))\n params.set('status', status)\n if (search) params.set('search', search)\n return params.toString()\n }, [page, status, search])\n\n const { data, isLoading } = useQuery<CategoriesResponse>({\n queryKey: ['catalog-categories', queryParams, scopeVersion],\n queryFn: async () => {\n const payload = await readApiResultOrThrow<CategoriesResponse>(\n `/api/catalog/categories?${queryParams}`,\n undefined,\n { errorMessage: t('catalog.categories.list.error.load', 'Failed to load categories') },\n )\n return {\n items: Array.isArray(payload.items) ? payload.items : [],\n total: typeof payload.total === 'number' ? payload.total : 0,\n page: typeof payload.page === 'number' ? payload.page : 1,\n pageSize: typeof payload.pageSize === 'number' ? payload.pageSize : PAGE_SIZE,\n totalPages: typeof payload.totalPages === 'number' ? payload.totalPages : 1,\n }\n },\n })\n\n const rows = data?.items ?? []\n const total = data?.total ?? 0\n const totalPages = data?.totalPages ?? 1\n\n const columns = React.useMemo<ColumnDef<CategoryRow>[]>(() => [\n {\n accessorKey: 'name',\n header: t('catalog.categories.list.columns.category', 'Category'),\n meta: { priority: 1 },\n cell: ({ row }) => {\n const depth = row.original.depth ?? 0\n return (\n <div className=\"flex items-center text-sm font-medium leading-none text-foreground\">\n <span style={{ marginLeft: computeIndent(depth), whiteSpace: 'pre' }}>\n {formatCategoryTreeLabel(row.original.name, depth)}\n </span>\n </div>\n )\n },\n },\n {\n accessorKey: 'pathLabel',\n header: t('catalog.categories.list.columns.path', 'Path'),\n meta: { priority: 3 },\n cell: ({ getValue }) => {\n const value = getValue<string>()\n return <span className=\"text-xs text-muted-foreground\">{value || '\u2014'}</span>\n },\n },\n {\n accessorKey: 'parentName',\n header: t('catalog.categories.list.columns.parent', 'Parent'),\n meta: { priority: 4 },\n cell: ({ getValue }) => getValue<string>() || t('catalog.categories.list.none', '\u2014'),\n },\n {\n accessorKey: 'childCount',\n header: t('catalog.categories.list.columns.children', 'Children'),\n meta: { priority: 5 },\n },\n {\n accessorKey: 'isActive',\n header: t('catalog.categories.list.columns.active', 'Active'),\n enableSorting: false,\n meta: { priority: 2 },\n cell: ({ getValue }) => <BooleanIcon value={Boolean(getValue())} />,\n },\n ], [t])\n\n const handleDelete = React.useCallback(async (category: CategoryRow) => {\n const confirmLabel = t(\n 'catalog.categories.list.confirmDelete',\n 'Archive category \"{{name}}\"?',\n { name: category.name },\n )\n if (!window.confirm(confirmLabel)) return\n try {\n await apiCallOrThrow(\n `/api/catalog/categories?id=${encodeURIComponent(category.id)}`,\n { method: 'DELETE' },\n { errorMessage: t('catalog.categories.list.error.delete', 'Failed to delete category') },\n )\n await queryClient.invalidateQueries({ queryKey: ['catalog-categories'] })\n flash(t('catalog.categories.flash.deleted', 'Category archived'), 'success')\n } catch (err: unknown) {\n const fallback = t('catalog.categories.list.error.delete', 'Failed to delete category')\n const message = err instanceof Error ? err.message : fallback\n flash(message, 'error')\n }\n }, [queryClient, t])\n\n return (\n <DataTable\n title={t('catalog.categories.list.title', 'Categories')}\n actions={canManage ? (\n <Button asChild>\n <Link href=\"/backend/catalog/categories/create\">\n {t('catalog.categories.list.actions.create', 'Create')}\n </Link>\n </Button>\n ) : undefined}\n columns={columns}\n data={rows}\n searchValue={search}\n searchPlaceholder={t('catalog.categories.list.searchPlaceholder', 'Search categories')}\n onSearchChange={(value) => { setSearch(value); setPage(1) }}\n filters={[\n {\n id: 'status',\n label: t('catalog.categories.list.filters.status', 'Status'),\n type: 'select',\n options: [\n { value: 'all', label: t('catalog.categories.list.filters.all', 'All') },\n { value: 'active', label: t('catalog.categories.list.filters.active', 'Active') },\n { value: 'inactive', label: t('catalog.categories.list.filters.inactive', 'Inactive') },\n ],\n },\n ]}\n filterValues={status === 'all' ? {} : { status }}\n onFiltersApply={(values: FilterValues) => {\n const nextStatus = (values.status as 'all' | 'active' | 'inactive' | undefined) ?? 'all'\n setStatus(nextStatus)\n setPage(1)\n }}\n onFiltersClear={() => {\n setStatus('all')\n setPage(1)\n }}\n sortable={false}\n perspective={{ tableId: 'catalog.categories.list' }}\n rowActions={(row) => (\n canManage ? (\n <RowActions\n items={[\n { id: 'edit', label: t('catalog.categories.list.actions.edit', 'Edit'), href: `/backend/catalog/categories/${row.id}/edit` },\n { id: 'delete', label: t('catalog.categories.list.actions.delete', 'Delete'), destructive: true, onSelect: () => handleDelete(row) },\n ]}\n />\n ) : null\n )}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalPages,\n onPageChange: setPage,\n }}\n isLoading={isLoading}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -509,10 +509,12 @@ function ProductsDataTable() {
|
|
|
509
509
|
{
|
|
510
510
|
items: [
|
|
511
511
|
{
|
|
512
|
+
id: "edit",
|
|
512
513
|
label: t("catalog.products.table.actions.edit", "Edit"),
|
|
513
514
|
href: `/backend/catalog/products/${row.id}`
|
|
514
515
|
},
|
|
515
516
|
{
|
|
517
|
+
id: "delete",
|
|
516
518
|
label: t("catalog.products.table.actions.delete", "Delete"),
|
|
517
519
|
destructive: true,
|
|
518
520
|
onSelect: () => {
|