@open-mercato/core 0.6.7 → 0.6.8-develop.6874.1.982d6097d8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +2 -2
- package/AGENTS.md +3 -3
- package/agentic/standalone-guide.md +13 -0
- package/dist/bootstrap.js +16 -1
- package/dist/bootstrap.js.map +2 -2
- package/dist/generated/entities/attachment_quota_reservation/index.js +33 -0
- package/dist/generated/entities/attachment_quota_reservation/index.js.map +7 -0
- package/dist/generated/entities/customer_deal_person_link/index.js +2 -0
- package/dist/generated/entities/customer_deal_person_link/index.js.map +2 -2
- package/dist/generated/entities/customer_user_invitation/index.js +2 -0
- package/dist/generated/entities/customer_user_invitation/index.js.map +2 -2
- package/dist/generated/entities/gateway_payment_operation/index.js +2 -0
- package/dist/generated/entities/gateway_payment_operation/index.js.map +2 -2
- package/dist/generated/entities/gateway_transaction/index.js +2 -0
- package/dist/generated/entities/gateway_transaction/index.js.map +2 -2
- package/dist/generated/entities/organization/index.js +2 -0
- package/dist/generated/entities/organization/index.js.map +2 -2
- package/dist/generated/entities/resources_resource/index.js +2 -0
- package/dist/generated/entities/resources_resource/index.js.map +2 -2
- package/dist/generated/entities.ids.generated.js +3 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +23 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/salesFixtures.js +31 -2
- package/dist/helpers/integration/salesFixtures.js.map +2 -2
- package/dist/helpers/integration/salesUi.js +5 -0
- package/dist/helpers/integration/salesUi.js.map +2 -2
- package/dist/modules/api_keys/backend/api-keys/page.js +2 -1
- package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
- package/dist/modules/api_keys/extension-points.js +16 -0
- package/dist/modules/api_keys/extension-points.js.map +7 -0
- package/dist/modules/attachments/api/route.js +120 -10
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/attachments/backend/config/attachments/page.js +1 -1
- package/dist/modules/attachments/backend/config/attachments/page.js.map +2 -2
- package/dist/modules/attachments/data/entities.js +67 -1
- package/dist/modules/attachments/data/entities.js.map +2 -2
- package/dist/modules/attachments/di.js +7 -1
- package/dist/modules/attachments/di.js.map +2 -2
- package/dist/modules/attachments/fields/attachment.js +1 -1
- package/dist/modules/attachments/fields/attachment.js.map +2 -2
- package/dist/modules/attachments/lib/drivers/index.js.map +1 -1
- package/dist/modules/attachments/lib/drivers/localDriver.js +19 -6
- package/dist/modules/attachments/lib/drivers/localDriver.js.map +2 -2
- package/dist/modules/attachments/lib/quota-recovery-queue.js +9 -0
- package/dist/modules/attachments/lib/quota-recovery-queue.js.map +7 -0
- package/dist/modules/attachments/lib/quota-service.js +224 -0
- package/dist/modules/attachments/lib/quota-service.js.map +7 -0
- package/dist/modules/attachments/lib/upload-limits.js +33 -0
- package/dist/modules/attachments/lib/upload-limits.js.map +2 -2
- package/dist/modules/attachments/migrations/Migration20260709234741_attachments.js +13 -0
- package/dist/modules/attachments/migrations/Migration20260709234741_attachments.js.map +7 -0
- package/dist/modules/attachments/workers/quota-recovery.js +45 -0
- package/dist/modules/attachments/workers/quota-recovery.js.map +7 -0
- package/dist/modules/audit_logs/api/audit-logs/access/route.js +5 -1
- package/dist/modules/audit_logs/api/audit-logs/access/route.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js +5 -1
- package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/actions/route.js +5 -1
- package/dist/modules/audit_logs/api/audit-logs/actions/route.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/readScope.js +12 -0
- package/dist/modules/audit_logs/api/audit-logs/readScope.js.map +7 -0
- package/dist/modules/audit_logs/components/AccessLogsTable.js +2 -1
- package/dist/modules/audit_logs/components/AccessLogsTable.js.map +2 -2
- package/dist/modules/audit_logs/components/AuditLogsActions.js +3 -2
- package/dist/modules/audit_logs/components/AuditLogsActions.js.map +2 -2
- package/dist/modules/audit_logs/extension-points.js +14 -0
- package/dist/modules/audit_logs/extension-points.js.map +7 -0
- package/dist/modules/auth/api/admin/nav.js +17 -4
- package/dist/modules/auth/api/admin/nav.js.map +2 -2
- package/dist/modules/auth/api/profile/route.js +8 -2
- package/dist/modules/auth/api/profile/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +8 -19
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/auth/profile/page.js.map +2 -2
- package/dist/modules/auth/backend/profile/change-password/page.js.map +2 -2
- package/dist/modules/auth/backend/roles/page.js +2 -1
- package/dist/modules/auth/backend/roles/page.js.map +2 -2
- package/dist/modules/auth/backend/settings/page.js +14 -9
- package/dist/modules/auth/backend/settings/page.js.map +2 -2
- package/dist/modules/auth/backend/users/page.js +2 -1
- package/dist/modules/auth/backend/users/page.js.map +2 -2
- package/dist/modules/auth/cli.js +1 -1
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/auth/components/UserConsentsPanel.js +9 -9
- package/dist/modules/auth/components/UserConsentsPanel.js.map +2 -2
- package/dist/modules/auth/extension-points.js +21 -0
- package/dist/modules/auth/extension-points.js.map +7 -0
- package/dist/modules/auth/frontend/login.js +7 -3
- package/dist/modules/auth/frontend/login.js.map +2 -2
- package/dist/modules/auth/frontend/reset.js +2 -2
- package/dist/modules/auth/frontend/reset.js.map +2 -2
- package/dist/modules/auth/lib/backendChrome.js +45 -29
- package/dist/modules/auth/lib/backendChrome.js.map +2 -2
- package/dist/modules/auth/lib/setup-app.js +17 -2
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/lib/tenantAccess.js +7 -0
- package/dist/modules/auth/lib/tenantAccess.js.map +2 -2
- package/dist/modules/auth/services/rbacService.js +29 -44
- package/dist/modules/auth/services/rbacService.js.map +2 -2
- package/dist/modules/business_rules/api/openmercato-call-options/route.js +85 -0
- package/dist/modules/business_rules/api/openmercato-call-options/route.js.map +7 -0
- package/dist/modules/business_rules/api/rules/route.js +71 -4
- package/dist/modules/business_rules/api/rules/route.js.map +2 -2
- package/dist/modules/business_rules/backend/rules/page.js +2 -1
- package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
- package/dist/modules/business_rules/components/ActionBuilder.js +47 -4
- package/dist/modules/business_rules/components/ActionBuilder.js.map +3 -3
- package/dist/modules/business_rules/components/ActionRow.js +106 -16
- package/dist/modules/business_rules/components/ActionRow.js.map +2 -2
- package/dist/modules/business_rules/components/ConditionRow.js +8 -4
- package/dist/modules/business_rules/components/ConditionRow.js.map +2 -2
- package/dist/modules/business_rules/components/utils/actionValidation.js +6 -0
- package/dist/modules/business_rules/components/utils/actionValidation.js.map +2 -2
- package/dist/modules/business_rules/events.js +13 -0
- package/dist/modules/business_rules/events.js.map +7 -0
- package/dist/modules/business_rules/extension-points.js +13 -0
- package/dist/modules/business_rules/extension-points.js.map +7 -0
- package/dist/modules/business_rules/lib/action-executor.js +148 -0
- package/dist/modules/business_rules/lib/action-executor.js.map +2 -2
- package/dist/modules/business_rules/lib/openmercato-call-options-types.js +5 -0
- package/dist/modules/business_rules/lib/openmercato-call-options-types.js.map +7 -0
- package/dist/modules/business_rules/lib/openmercato-call-options.js +231 -0
- package/dist/modules/business_rules/lib/openmercato-call-options.js.map +7 -0
- package/dist/modules/business_rules/lib/rule-engine.js +5 -1
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +6 -5
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/create/page.js +7 -6
- package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
- package/dist/modules/catalog/components/PriceKindSettings.js +3 -3
- package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -1
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductCategorizeSection.js +3 -3
- package/dist/modules/catalog/components/products/ProductCategorizeSection.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductMediaManager.js +1 -1
- package/dist/modules/catalog/components/products/ProductMediaManager.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js +3 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/VariantBuilder.js +5 -5
- package/dist/modules/catalog/components/products/VariantBuilder.js.map +2 -2
- package/dist/modules/catalog/events.js +1 -0
- package/dist/modules/catalog/events.js.map +2 -2
- package/dist/modules/catalog/extension-points.js +27 -0
- package/dist/modules/catalog/extension-points.js.map +7 -0
- package/dist/modules/catalog/widgets/injection/product-bulk-delete/widget.js +10 -5
- package/dist/modules/catalog/widgets/injection/product-bulk-delete/widget.js.map +2 -2
- package/dist/modules/catalog/widgets/injection/product-seo/widget.js +1 -1
- package/dist/modules/catalog/widgets/injection/product-seo/widget.js.map +2 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js +52 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +11 -1
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +11 -6
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +2 -2
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +2 -1
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +2 -2
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +8 -7
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
- package/dist/modules/communication_channels/data/enrichers.js +4 -4
- package/dist/modules/communication_channels/data/enrichers.js.map +2 -2
- package/dist/modules/communication_channels/extension-points.js +20 -0
- package/dist/modules/communication_channels/extension-points.js.map +7 -0
- package/dist/modules/communication_channels/lib/access-control.js +2 -2
- package/dist/modules/communication_channels/lib/access-control.js.map +2 -2
- package/dist/modules/configs/backend/config/system-status/page.js +2 -1
- package/dist/modules/configs/backend/config/system-status/page.js.map +2 -2
- package/dist/modules/configs/extension-points.js +18 -0
- package/dist/modules/configs/extension-points.js.map +7 -0
- package/dist/modules/configs/lib/upgrade-actions.js +12 -0
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +2 -1
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +2 -1
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/currencies/di.js +4 -0
- package/dist/modules/currencies/di.js.map +2 -2
- package/dist/modules/currencies/extension-points.js +14 -0
- package/dist/modules/currencies/extension-points.js.map +7 -0
- package/dist/modules/currencies/services/baseCurrencyService.js +42 -0
- package/dist/modules/currencies/services/baseCurrencyService.js.map +7 -0
- package/dist/modules/customer_accounts/api/admin/users/[id].js +10 -1
- package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/users-invite.js +63 -4
- package/dist/modules/customer_accounts/api/admin/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/api/invitations/accept.js +1 -2
- package/dist/modules/customer_accounts/api/invitations/accept.js.map +2 -2
- package/dist/modules/customer_accounts/api/login.js +4 -2
- package/dist/modules/customer_accounts/api/login.js.map +2 -2
- package/dist/modules/customer_accounts/api/magic-link/verify.js +4 -2
- package/dist/modules/customer_accounts/api/magic-link/verify.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/feature-check.js +5 -4
- package/dist/modules/customer_accounts/api/portal/feature-check.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/nav.js +6 -4
- package/dist/modules/customer_accounts/api/portal/nav.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/profile.js +5 -1
- package/dist/modules/customer_accounts/api/portal/profile.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/sessions-refresh.js +3 -3
- package/dist/modules/customer_accounts/api/portal/sessions-refresh.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js +22 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +2 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.js +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +2 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
- package/dist/modules/customer_accounts/data/entities.js +3 -0
- package/dist/modules/customer_accounts/data/entities.js.map +2 -2
- package/dist/modules/customer_accounts/data/validators.js +1 -0
- package/dist/modules/customer_accounts/data/validators.js.map +2 -2
- package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js +26 -0
- package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js.map +7 -0
- package/dist/modules/customer_accounts/extension-points.js +14 -0
- package/dist/modules/customer_accounts/extension-points.js.map +7 -0
- package/dist/modules/customer_accounts/lib/customerAuth.js +7 -2
- package/dist/modules/customer_accounts/lib/customerAuth.js.map +2 -2
- package/dist/modules/customer_accounts/lib/customerAuthServer.js +2 -1
- package/dist/modules/customer_accounts/lib/customerAuthServer.js.map +2 -2
- package/dist/modules/customer_accounts/lib/customerEntityOwnership.js +29 -3
- package/dist/modules/customer_accounts/lib/customerEntityOwnership.js.map +2 -2
- package/dist/modules/customer_accounts/lib/customerUrl.js +19 -10
- package/dist/modules/customer_accounts/lib/customerUrl.js.map +2 -2
- package/dist/modules/customer_accounts/lib/invitationEmail.js +35 -0
- package/dist/modules/customer_accounts/lib/invitationEmail.js.map +7 -0
- package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js +13 -0
- package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js.map +7 -0
- package/dist/modules/customer_accounts/services/customerInvitationService.js +32 -2
- package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
- package/dist/modules/customer_accounts/services/customerRbacService.js +12 -3
- package/dist/modules/customer_accounts/services/customerRbacService.js.map +2 -2
- package/dist/modules/customer_accounts/setup.js +6 -0
- package/dist/modules/customer_accounts/setup.js.map +2 -2
- package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js +47 -7
- package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +2 -2
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection/portal-ai-assistant-trigger/widget.client.js +1 -1
- package/dist/modules/customer_accounts/widgets/injection/portal-ai-assistant-trigger/widget.client.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection-table.js +1 -1
- package/dist/modules/customer_accounts/widgets/injection-table.js.map +2 -2
- package/dist/modules/customers/analytics.js +4 -1
- package/dist/modules/customers/analytics.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/route.js +3 -4
- package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +4 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/route.js +7 -3
- package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/deals/aggregate/route.js +5 -4
- package/dist/modules/customers/api/deals/aggregate/route.js.map +2 -2
- package/dist/modules/customers/api/deals/summary/route.js +14 -119
- package/dist/modules/customers/api/deals/summary/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +3 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
- package/dist/modules/customers/api/utils.js +21 -24
- package/dist/modules/customers/api/utils.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/[id]/page.js +2 -1
- package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +2 -1
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +16 -5
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +18 -11
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +2 -1
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js +17 -3
- package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js +8 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/[id]/page.js +2 -1
- package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/page.js +2 -1
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +26 -10
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/cli.js +28 -11
- package/dist/modules/customers/cli.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +48 -10
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/people.js +2 -0
- package/dist/modules/customers/commands/people.js.map +2 -2
- package/dist/modules/customers/components/CustomerTodosTable.js +2 -1
- package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js +1 -1
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js.map +2 -2
- package/dist/modules/customers/components/detail/ActiveDealCard.js +2 -1
- package/dist/modules/customers/components/detail/ActiveDealCard.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivitiesDayStrip.js +2 -3
- package/dist/modules/customers/components/detail/ActivitiesDayStrip.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js +26 -6
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyKpiBar.js +6 -5
- package/dist/modules/customers/components/detail/CompanyKpiBar.js.map +2 -2
- package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +2 -2
- package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/DealDetailTabs.js +30 -8
- package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/DealForm.js +2 -1
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/detail/DealsSection.js +1 -1
- package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
- package/dist/modules/customers/components/detail/MiniWeekCalendar.js +7 -52
- package/dist/modules/customers/components/detail/MiniWeekCalendar.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonDetailTabs.js +30 -8
- package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +231 -216
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/dashboard/helpers.js +4 -3
- package/dist/modules/customers/components/detail/dashboard/helpers.js.map +2 -2
- package/dist/modules/customers/components/detail/legacyActivities.js +69 -0
- package/dist/modules/customers/components/detail/legacyActivities.js.map +7 -0
- package/dist/modules/customers/components/formConfig.js +14 -10
- package/dist/modules/customers/components/formConfig.js.map +2 -2
- package/dist/modules/customers/data/entities.js +8 -0
- package/dist/modules/customers/data/entities.js.map +2 -2
- package/dist/modules/customers/data/validators.js +5 -2
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/extension-points.js +42 -0
- package/dist/modules/customers/extension-points.js.map +7 -0
- package/dist/modules/customers/lib/calendar/format.js +8 -4
- package/dist/modules/customers/lib/calendar/format.js.map +2 -2
- package/dist/modules/customers/lib/dealStatus.js +38 -0
- package/dist/modules/customers/lib/dealStatus.js.map +7 -0
- package/dist/modules/customers/lib/dealsSummaryQueries.js +144 -0
- package/dist/modules/customers/lib/dealsSummaryQueries.js.map +7 -0
- package/dist/modules/customers/lib/optionalBaseCurrency.js +19 -0
- package/dist/modules/customers/lib/optionalBaseCurrency.js.map +7 -0
- package/dist/modules/customers/lib/visibilityFilter.js +6 -4
- package/dist/modules/customers/lib/visibilityFilter.js.map +2 -2
- package/dist/modules/customers/migrations/Migration20260723210000_customers.js +15 -0
- package/dist/modules/customers/migrations/Migration20260723210000_customers.js.map +7 -0
- package/dist/modules/customers/search.js +50 -29
- package/dist/modules/customers/search.js.map +2 -2
- package/dist/modules/customers/utils/phoneDuplicates.js +1 -2
- package/dist/modules/customers/utils/phoneDuplicates.js.map +2 -2
- package/dist/modules/dashboards/api/layout/[itemId]/route.js +6 -3
- package/dist/modules/dashboards/api/layout/[itemId]/route.js.map +2 -2
- package/dist/modules/dashboards/api/layout/route.js +22 -9
- package/dist/modules/dashboards/api/layout/route.js.map +2 -2
- package/dist/modules/dashboards/api/roles/widgets/route.js +9 -3
- package/dist/modules/dashboards/api/roles/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/api/users/widgets/route.js +9 -3
- package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/catalog.js +6 -3
- package/dist/modules/dashboards/api/widgets/catalog.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/batch/route.js +12 -3
- package/dist/modules/dashboards/api/widgets/data/batch/route.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/route.js +28 -3
- package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/schema.js +28 -18
- package/dist/modules/dashboards/api/widgets/data/schema.js.map +2 -2
- package/dist/modules/dashboards/components/UnlabelledAmountNotice.js +33 -0
- package/dist/modules/dashboards/components/UnlabelledAmountNotice.js.map +7 -0
- package/dist/modules/dashboards/lib/access.js +5 -3
- package/dist/modules/dashboards/lib/access.js.map +2 -2
- package/dist/modules/dashboards/lib/aggregations.js +113 -46
- package/dist/modules/dashboards/lib/aggregations.js.map +2 -2
- package/dist/modules/dashboards/lib/exactDecimal.js +69 -0
- package/dist/modules/dashboards/lib/exactDecimal.js.map +7 -0
- package/dist/modules/dashboards/lib/formatters.js +84 -11
- package/dist/modules/dashboards/lib/formatters.js.map +2 -2
- package/dist/modules/dashboards/lib/optionalBaseCurrency.js +11 -0
- package/dist/modules/dashboards/lib/optionalBaseCurrency.js.map +7 -0
- package/dist/modules/dashboards/services/widgetDataService.js +316 -14
- package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
- package/dist/modules/dashboards/subscribers/invalidateWidgetDataCache.js +26 -0
- package/dist/modules/dashboards/subscribers/invalidateWidgetDataCache.js.map +7 -0
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js +9 -3
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/config.js +52 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/config.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js +52 -30
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js +9 -3
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js +8 -3
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js +26 -18
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js +22 -14
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js +10 -4
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js.map +2 -2
- package/dist/modules/data_sync/api/mappings/[id]/route.js +22 -9
- package/dist/modules/data_sync/api/mappings/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/mappings/route.js +13 -4
- package/dist/modules/data_sync/api/mappings/route.js.map +2 -2
- package/dist/modules/data_sync/api/options.js +7 -2
- package/dist/modules/data_sync/api/options.js.map +2 -2
- package/dist/modules/data_sync/api/run.js +7 -2
- package/dist/modules/data_sync/api/run.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/cancel.js +8 -3
- package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/retry.js +7 -2
- package/dist/modules/data_sync/api/runs/[id]/retry.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/route.js +8 -3
- package/dist/modules/data_sync/api/runs/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/runs.js +7 -2
- package/dist/modules/data_sync/api/runs.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/[id]/route.js +19 -6
- package/dist/modules/data_sync/api/schedules/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/route.js +13 -4
- package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
- package/dist/modules/data_sync/api/validate.js +9 -4
- package/dist/modules/data_sync/api/validate.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.js +5 -4
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js +5 -5
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
- package/dist/modules/data_sync/extension-points.js +13 -0
- package/dist/modules/data_sync/extension-points.js.map +7 -0
- package/dist/modules/data_sync/lib/queue-policy.js +15 -0
- package/dist/modules/data_sync/lib/queue-policy.js.map +7 -0
- package/dist/modules/data_sync/lib/queue.js +16 -1
- package/dist/modules/data_sync/lib/queue.js.map +2 -2
- package/dist/modules/data_sync/lib/start-run.js +2 -1
- package/dist/modules/data_sync/lib/start-run.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-engine.js +35 -2
- package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-run-service.js +70 -2
- package/dist/modules/data_sync/lib/sync-run-service.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-export.js +9 -2
- package/dist/modules/data_sync/workers/sync-export.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-import.js +9 -2
- package/dist/modules/data_sync/workers/sync-import.js.map +2 -2
- package/dist/modules/design_system/acl.js +9 -0
- package/dist/modules/design_system/acl.js.map +7 -0
- package/dist/modules/design_system/backend/design-system/page.js +11 -0
- package/dist/modules/design_system/backend/design-system/page.js.map +7 -0
- package/dist/modules/design_system/backend/design-system/page.meta.js +15 -0
- package/dist/modules/design_system/backend/design-system/page.meta.js.map +7 -0
- package/dist/modules/design_system/gallery/components/CodeSnippet.js +52 -0
- package/dist/modules/design_system/gallery/components/CodeSnippet.js.map +7 -0
- package/dist/modules/design_system/gallery/components/EntryCard.js +63 -0
- package/dist/modules/design_system/gallery/components/EntryCard.js.map +7 -0
- package/dist/modules/design_system/gallery/components/GalleryShell.js +163 -0
- package/dist/modules/design_system/gallery/components/GalleryShell.js.map +7 -0
- package/dist/modules/design_system/gallery/components/VariantPreview.js +9 -0
- package/dist/modules/design_system/gallery/components/VariantPreview.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/banners.js +186 -0
- package/dist/modules/design_system/gallery/entries/banners.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/buttons.js +361 -0
- package/dist/modules/design_system/gallery/entries/buttons.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/charts.js +457 -0
- package/dist/modules/design_system/gallery/entries/charts.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/dates.js +306 -0
- package/dist/modules/design_system/gallery/entries/dates.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/detail.js +358 -0
- package/dist/modules/design_system/gallery/entries/detail.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/display.js +785 -0
- package/dist/modules/design_system/gallery/entries/display.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/feedback.js +658 -0
- package/dist/modules/design_system/gallery/entries/feedback.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/filters.js +505 -0
- package/dist/modules/design_system/gallery/entries/filters.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/foundations.js +453 -0
- package/dist/modules/design_system/gallery/entries/foundations.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/icons.js +140 -0
- package/dist/modules/design_system/gallery/entries/icons.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/inputs.js +1217 -0
- package/dist/modules/design_system/gallery/entries/inputs.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/messages.js +334 -0
- package/dist/modules/design_system/gallery/entries/messages.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/navigation.js +475 -0
- package/dist/modules/design_system/gallery/entries/navigation.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/notifications.js +257 -0
- package/dist/modules/design_system/gallery/entries/notifications.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/overlays.js +576 -0
- package/dist/modules/design_system/gallery/entries/overlays.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/scaffolding.js +378 -0
- package/dist/modules/design_system/gallery/entries/scaffolding.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/schedule.js +297 -0
- package/dist/modules/design_system/gallery/entries/schedule.js.map +7 -0
- package/dist/modules/design_system/gallery/registry.js +139 -0
- package/dist/modules/design_system/gallery/registry.js.map +7 -0
- package/dist/modules/design_system/gallery/types.js +1 -0
- package/dist/modules/design_system/gallery/types.js.map +7 -0
- package/dist/modules/design_system/index.js +9 -0
- package/dist/modules/design_system/index.js.map +7 -0
- package/dist/modules/design_system/setup.js +14 -0
- package/dist/modules/design_system/setup.js.map +7 -0
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js +34 -12
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js.map +2 -2
- package/dist/modules/dictionaries/api/openapi.js +15 -2
- package/dist/modules/dictionaries/api/openapi.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryEntrySelect.js +1 -1
- package/dist/modules/dictionaries/components/DictionaryEntrySelect.js.map +2 -2
- package/dist/modules/dictionaries/components/hooks/useDictionaryEntries.js +30 -29
- package/dist/modules/dictionaries/components/hooks/useDictionaryEntries.js.map +2 -2
- package/dist/modules/dictionaries/data/validators.js +7 -0
- package/dist/modules/dictionaries/data/validators.js.map +2 -2
- package/dist/modules/dictionaries/lib/clientEntries.js +4 -3
- package/dist/modules/dictionaries/lib/clientEntries.js.map +2 -2
- package/dist/modules/dictionaries/lib/fetchAllEntries.js +43 -0
- package/dist/modules/dictionaries/lib/fetchAllEntries.js.map +7 -0
- package/dist/modules/directory/api/organization-branding/route.js +10 -3
- package/dist/modules/directory/api/organization-branding/route.js.map +2 -2
- package/dist/modules/directory/api/organization-switcher/route.js +84 -20
- package/dist/modules/directory/api/organization-switcher/route.js.map +2 -2
- package/dist/modules/directory/api/organizations/route.js +7 -0
- package/dist/modules/directory/api/organizations/route.js.map +3 -3
- package/dist/modules/directory/api/tenants/route.js +8 -2
- package/dist/modules/directory/api/tenants/route.js.map +2 -2
- package/dist/modules/directory/backend/directory/branding/page.js +31 -8
- package/dist/modules/directory/backend/directory/branding/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js +7 -16
- package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/organizations/page.js +2 -1
- package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js +2 -1
- package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
- package/dist/modules/directory/commands/organizations.js +8 -1
- package/dist/modules/directory/commands/organizations.js.map +2 -2
- package/dist/modules/directory/commands/tenants.js +6 -0
- package/dist/modules/directory/commands/tenants.js.map +2 -2
- package/dist/modules/directory/data/entities.js +4 -0
- package/dist/modules/directory/data/entities.js.map +2 -2
- package/dist/modules/directory/data/validators.js +2 -0
- package/dist/modules/directory/data/validators.js.map +2 -2
- package/dist/modules/directory/extension-points.js +14 -0
- package/dist/modules/directory/extension-points.js.map +7 -0
- package/dist/modules/directory/migrations/Migration20260626145500_directory_logo_preserve_aspect_ratio.js +13 -0
- package/dist/modules/directory/migrations/Migration20260626145500_directory_logo_preserve_aspect_ratio.js.map +7 -0
- package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js +5 -1
- package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js.map +2 -2
- package/dist/modules/directory/utils/organizationScope.js +11 -3
- package/dist/modules/directory/utils/organizationScope.js.map +2 -2
- package/dist/modules/entities/api/definitions.js +53 -3
- package/dist/modules/entities/api/definitions.js.map +2 -2
- package/dist/modules/entities/api/entities.js +21 -2
- package/dist/modules/entities/api/entities.js.map +2 -2
- package/dist/modules/entities/api/entity-settings.js +59 -9
- package/dist/modules/entities/api/entity-settings.js.map +2 -2
- package/dist/modules/entities/api/records.js +11 -28
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/api/sidebar-entities.js +34 -12
- package/dist/modules/entities/api/sidebar-entities.js.map +2 -2
- package/dist/modules/entities/backend/config/settings/page.js +10 -0
- package/dist/modules/entities/backend/config/settings/page.js.map +7 -0
- package/dist/modules/entities/backend/config/settings/page.meta.js +36 -0
- package/dist/modules/entities/backend/config/settings/page.meta.js.map +7 -0
- package/dist/modules/entities/backend/entities/user/[entityId]/page.js +1 -1
- package/dist/modules/entities/backend/entities/user/[entityId]/page.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +23 -4
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/create/page.js +16 -7
- package/dist/modules/entities/backend/entities/user/create/page.js.map +2 -2
- package/dist/modules/entities/cli.js +193 -19
- package/dist/modules/entities/cli.js.map +2 -2
- package/dist/modules/entities/components/EntitySettingsManager.js +136 -0
- package/dist/modules/entities/components/EntitySettingsManager.js.map +7 -0
- package/dist/modules/entities/components/RecordListRelationCell.js +63 -0
- package/dist/modules/entities/components/RecordListRelationCell.js.map +7 -0
- package/dist/modules/entities/components/SystemEntitiesTable.js +2 -1
- package/dist/modules/entities/components/SystemEntitiesTable.js.map +2 -2
- package/dist/modules/entities/components/UserEntitiesTable.js +2 -1
- package/dist/modules/entities/components/UserEntitiesTable.js.map +2 -2
- package/dist/modules/entities/components/recordListRelationDisplays.js +80 -0
- package/dist/modules/entities/components/recordListRelationDisplays.js.map +7 -0
- package/dist/modules/entities/extension-points.js +21 -0
- package/dist/modules/entities/extension-points.js.map +7 -0
- package/dist/modules/entities/lib/entityAcl.js +87 -9
- package/dist/modules/entities/lib/entityAcl.js.map +3 -3
- package/dist/modules/feature_toggles/components/FeatureGuard.js +3 -2
- package/dist/modules/feature_toggles/components/FeatureGuard.js.map +2 -2
- package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js +1 -1
- package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js.map +2 -2
- package/dist/modules/feature_toggles/components/hooks/staleTime.js +5 -0
- package/dist/modules/feature_toggles/components/hooks/staleTime.js.map +7 -0
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagBoolean.js +5 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagBoolean.js.map +2 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagJson.js +5 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagJson.js.map +2 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagNumber.js +5 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagNumber.js.map +2 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagString.js +5 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagString.js.map +2 -2
- package/dist/modules/inbox_ops/ai-tools.js +5 -2
- package/dist/modules/inbox_ops/ai-tools.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js +14 -1
- package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/route.js +16 -1
- package/dist/modules/inbox_ops/api/proposals/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/webhook/inbound.js +14 -10
- package/dist/modules/inbox_ops/api/webhook/inbound.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js +6 -6
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js.map +2 -2
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +25 -20
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
- package/dist/modules/inbox_ops/search.js +15 -4
- package/dist/modules/inbox_ops/search.js.map +2 -2
- package/dist/modules/inbox_ops/subscribers/search-reindex-proposal-created.js +32 -0
- package/dist/modules/inbox_ops/subscribers/search-reindex-proposal-created.js.map +7 -0
- package/dist/modules/integrations/api/[id]/credentials/route.js +11 -5
- package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/health/route.js +6 -3
- package/dist/modules/integrations/api/[id]/health/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/route.js +6 -3
- package/dist/modules/integrations/api/[id]/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/state/route.js +6 -3
- package/dist/modules/integrations/api/[id]/state/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/version/route.js +6 -3
- package/dist/modules/integrations/api/[id]/version/route.js.map +2 -2
- package/dist/modules/integrations/api/logs/route.js +6 -3
- package/dist/modules/integrations/api/logs/route.js.map +2 -2
- package/dist/modules/integrations/api/route.js +6 -3
- package/dist/modules/integrations/api/route.js.map +2 -2
- package/dist/modules/integrations/api/umes-read.js +2 -2
- package/dist/modules/integrations/api/umes-read.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js +2 -4
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/extension-points.js +30 -0
- package/dist/modules/integrations/extension-points.js.map +7 -0
- package/dist/modules/integrations/lib/organization-scope.js +2 -9
- package/dist/modules/integrations/lib/organization-scope.js.map +2 -2
- package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js +0 -5
- package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js.map +2 -2
- package/dist/modules/integrations/widgets/injection/external-ids/widget.js +14 -0
- package/dist/modules/integrations/widgets/injection/external-ids/widget.js.map +7 -0
- package/dist/modules/messages/api/[id]/route.js +15 -0
- package/dist/modules/messages/api/[id]/route.js.map +2 -2
- package/dist/modules/messages/api/route.js +77 -8
- package/dist/modules/messages/api/route.js.map +2 -2
- package/dist/modules/messages/components/ComposeMessagePageClient.js +2 -1
- package/dist/modules/messages/components/ComposeMessagePageClient.js.map +2 -2
- package/dist/modules/messages/components/MessageDetailPageClient.js +3 -2
- package/dist/modules/messages/components/MessageDetailPageClient.js.map +2 -2
- package/dist/modules/messages/components/MessagesInboxPageClient.js +2 -1
- package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/dialogs.js +1 -1
- package/dist/modules/messages/components/message-detail/panels/dialogs.js.map +1 -1
- package/dist/modules/messages/extension-points.js +16 -0
- package/dist/modules/messages/extension-points.js.map +7 -0
- package/dist/modules/messages/lib/participantScope.js +15 -0
- package/dist/modules/messages/lib/participantScope.js.map +7 -0
- package/dist/modules/messages/lib/routeHelpers.js +1 -3
- package/dist/modules/messages/lib/routeHelpers.js.map +2 -2
- package/dist/modules/messages/lib/searchLookup.js +8 -16
- package/dist/modules/messages/lib/searchLookup.js.map +2 -2
- package/dist/modules/messages/search.js +10 -5
- package/dist/modules/messages/search.js.map +2 -2
- package/dist/modules/notifications/api/route.js +83 -4
- package/dist/modules/notifications/api/route.js.map +2 -2
- package/dist/modules/notifications/api/unread-count/route.js +25 -6
- package/dist/modules/notifications/api/unread-count/route.js.map +2 -2
- package/dist/modules/notifications/di.js +1 -1
- package/dist/modules/notifications/di.js.map +2 -2
- package/dist/modules/notifications/events.js +4 -2
- package/dist/modules/notifications/events.js.map +2 -2
- package/dist/modules/notifications/lib/notificationRecipients.js +6 -7
- package/dist/modules/notifications/lib/notificationRecipients.js.map +2 -2
- package/dist/modules/notifications/lib/notificationScope.js +26 -0
- package/dist/modules/notifications/lib/notificationScope.js.map +7 -0
- package/dist/modules/notifications/lib/notificationService.js +48 -4
- package/dist/modules/notifications/lib/notificationService.js.map +2 -2
- package/dist/modules/notifications/lib/routeHelpers.js +16 -2
- package/dist/modules/notifications/lib/routeHelpers.js.map +2 -2
- package/dist/modules/payment_gateways/api/capture/route.js +1 -1
- package/dist/modules/payment_gateways/api/capture/route.js.map +2 -2
- package/dist/modules/payment_gateways/api/sessions/route.js +6 -3
- package/dist/modules/payment_gateways/api/sessions/route.js.map +2 -2
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +11 -1
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js +3 -2
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +2 -2
- package/dist/modules/payment_gateways/data/entities.js +11 -0
- package/dist/modules/payment_gateways/data/entities.js.map +2 -2
- package/dist/modules/payment_gateways/di.js +17 -1
- package/dist/modules/payment_gateways/di.js.map +2 -2
- package/dist/modules/payment_gateways/extension-points.js +19 -0
- package/dist/modules/payment_gateways/extension-points.js.map +7 -0
- package/dist/modules/payment_gateways/lib/capture-ledger.js +183 -0
- package/dist/modules/payment_gateways/lib/capture-ledger.js.map +7 -0
- package/dist/modules/payment_gateways/lib/gateway-service.js +93 -14
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
- package/dist/modules/payment_gateways/lib/order-amount-reconciliation.js +58 -0
- package/dist/modules/payment_gateways/lib/order-amount-reconciliation.js.map +7 -0
- package/dist/modules/payment_gateways/lib/payment-operation-idempotency.js +1 -0
- package/dist/modules/payment_gateways/lib/payment-operation-idempotency.js.map +2 -2
- package/dist/modules/payment_gateways/lib/session-idempotency.js +33 -0
- package/dist/modules/payment_gateways/lib/session-idempotency.js.map +2 -2
- package/dist/modules/payment_gateways/migrations/Migration20260725101500_payment_gateways.js +16 -0
- package/dist/modules/payment_gateways/migrations/Migration20260725101500_payment_gateways.js.map +7 -0
- package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js +18 -0
- package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js.map +7 -0
- package/dist/modules/payment_gateways/setup.js +47 -0
- package/dist/modules/payment_gateways/setup.js.map +2 -2
- package/dist/modules/payment_gateways/workers/session-initialization-prune.js +50 -0
- package/dist/modules/payment_gateways/workers/session-initialization-prune.js.map +7 -0
- package/dist/modules/planner/components/AvailabilityRulesEditor.js +4 -4
- package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
- package/dist/modules/planner/components/unavailabilityReasons.js +3 -3
- package/dist/modules/planner/components/unavailabilityReasons.js.map +2 -2
- package/dist/modules/portal/extension-points.js +32 -0
- package/dist/modules/portal/extension-points.js.map +7 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js +3 -3
- package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js +134 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js.map +7 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js +11 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js.map +7 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/login/page.js +4 -4
- package/dist/modules/portal/frontend/[orgSlug]/portal/login/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/page.js +3 -3
- package/dist/modules/portal/frontend/[orgSlug]/portal/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/profile/page.js +3 -3
- package/dist/modules/portal/frontend/[orgSlug]/portal/profile/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/reset-password/page.js +4 -4
- package/dist/modules/portal/frontend/[orgSlug]/portal/reset-password/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/signup/page.js +4 -4
- package/dist/modules/portal/frontend/[orgSlug]/portal/signup/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/verify/page.js +1 -1
- package/dist/modules/portal/frontend/[orgSlug]/portal/verify/page.js.map +2 -2
- package/dist/modules/portal/lib/navigation.js +7 -0
- package/dist/modules/portal/lib/navigation.js.map +7 -0
- package/dist/modules/progress/lib/progressService.js +2 -0
- package/dist/modules/progress/lib/progressService.js.map +2 -2
- package/dist/modules/progress/lib/progressServiceImpl.js +322 -104
- package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
- package/dist/modules/query_index/api/openapi.js +13 -1
- package/dist/modules/query_index/api/openapi.js.map +2 -2
- package/dist/modules/query_index/api/reindex.js +10 -0
- package/dist/modules/query_index/api/reindex.js.map +2 -2
- package/dist/modules/query_index/api/status.js +165 -105
- package/dist/modules/query_index/api/status.js.map +2 -2
- package/dist/modules/query_index/cli.js +125 -1
- package/dist/modules/query_index/cli.js.map +2 -2
- package/dist/modules/query_index/components/QueryIndexesTable.js +130 -42
- package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
- package/dist/modules/query_index/data/entities.js +2 -1
- package/dist/modules/query_index/data/entities.js.map +2 -2
- package/dist/modules/query_index/di.js +3 -0
- package/dist/modules/query_index/di.js.map +2 -2
- package/dist/modules/query_index/events.js +20 -0
- package/dist/modules/query_index/events.js.map +7 -0
- package/dist/modules/query_index/extension-points.js +13 -0
- package/dist/modules/query_index/extension-points.js.map +7 -0
- package/dist/modules/query_index/lib/batch.js +11 -4
- package/dist/modules/query_index/lib/batch.js.map +2 -2
- package/dist/modules/query_index/lib/coverage.js +21 -9
- package/dist/modules/query_index/lib/coverage.js.map +2 -2
- package/dist/modules/query_index/lib/document.js +12 -5
- package/dist/modules/query_index/lib/document.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +105 -48
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/lib/indexer.js +95 -19
- package/dist/modules/query_index/lib/indexer.js.map +2 -2
- package/dist/modules/query_index/lib/reindexer.js +43 -37
- package/dist/modules/query_index/lib/reindexer.js.map +2 -2
- package/dist/modules/query_index/lib/search-tokens.js +34 -15
- package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
- package/dist/modules/query_index/lib/subscriber-scope.js +2 -3
- package/dist/modules/query_index/lib/subscriber-scope.js.map +2 -2
- package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js +17 -0
- package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js.map +7 -0
- package/dist/modules/query_index/subscribers/coverage_refresh.js +4 -0
- package/dist/modules/query_index/subscribers/coverage_refresh.js.map +2 -2
- package/dist/modules/query_index/subscribers/delete_one.js +53 -1
- package/dist/modules/query_index/subscribers/delete_one.js.map +3 -3
- package/dist/modules/query_index/subscribers/upsert_one.js +60 -0
- package/dist/modules/query_index/subscribers/upsert_one.js.map +3 -3
- package/dist/modules/resources/api/resources.js +2 -0
- package/dist/modules/resources/api/resources.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js +2 -1
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js +3 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js +2 -1
- package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
- package/dist/modules/resources/commands/resources.js +9 -0
- package/dist/modules/resources/commands/resources.js.map +2 -2
- package/dist/modules/resources/components/detail/dictionaries.js +3 -3
- package/dist/modules/resources/components/detail/dictionaries.js.map +2 -2
- package/dist/modules/resources/data/entities.js +3 -0
- package/dist/modules/resources/data/entities.js.map +2 -2
- package/dist/modules/resources/data/validators.js +6 -2
- package/dist/modules/resources/data/validators.js.map +2 -2
- package/dist/modules/resources/extension-points.js +14 -0
- package/dist/modules/resources/extension-points.js.map +7 -0
- package/dist/modules/resources/lib/seeds.js +16 -9
- package/dist/modules/resources/lib/seeds.js.map +2 -2
- package/dist/modules/resources/migrations/Migration20260608231000.js +13 -0
- package/dist/modules/resources/migrations/Migration20260608231000.js.map +7 -0
- package/dist/modules/sales/analytics.js +7 -3
- package/dist/modules/sales/analytics.js.map +2 -2
- package/dist/modules/sales/api/document-history/route.js +2 -1
- package/dist/modules/sales/api/document-history/route.js.map +2 -2
- package/dist/modules/sales/api/documents/factory.js +14 -3
- package/dist/modules/sales/api/documents/factory.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +11 -3
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/create/page.js +11 -14
- package/dist/modules/sales/backend/sales/documents/create/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +184 -23
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +31 -11
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +12 -5
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js +48 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +4 -1
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js +167 -0
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js.map +7 -0
- package/dist/modules/sales/components/useSalesChannelsEnabled.js +2 -35
- package/dist/modules/sales/components/useSalesChannelsEnabled.js.map +2 -2
- package/dist/modules/sales/data/validators.js +32 -5
- package/dist/modules/sales/data/validators.js.map +2 -2
- package/dist/modules/sales/di.js +7 -0
- package/dist/modules/sales/di.js.map +2 -2
- package/dist/modules/sales/events.js +1 -0
- package/dist/modules/sales/events.js.map +2 -2
- package/dist/modules/sales/extension-points.js +36 -0
- package/dist/modules/sales/extension-points.js.map +7 -0
- package/dist/modules/sales/lib/historyHelpers.js +69 -1
- package/dist/modules/sales/lib/historyHelpers.js.map +2 -2
- package/dist/modules/sales/services/paymentOrderTotalResolver.js +52 -0
- package/dist/modules/sales/services/paymentOrderTotalResolver.js.map +7 -0
- package/dist/modules/sales/widgets/injection/document-history/widget.client.js +51 -2
- package/dist/modules/sales/widgets/injection/document-history/widget.client.js.map +2 -2
- package/dist/modules/sales/workflows.js +10 -7
- package/dist/modules/sales/workflows.js.map +2 -2
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +11 -1
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/shipping_carriers/lib/shipment-wizard/components/PackageEditor.js +1 -1
- package/dist/modules/shipping_carriers/lib/shipment-wizard/components/PackageEditor.js.map +1 -1
- package/dist/modules/staff/api/interceptors.js +5 -3
- package/dist/modules/staff/api/interceptors.js.map +2 -2
- package/dist/modules/staff/api/leave-requests.js +45 -42
- package/dist/modules/staff/api/leave-requests.js.map +2 -2
- package/dist/modules/staff/components/detail/dictionaries.js +3 -3
- package/dist/modules/staff/components/detail/dictionaries.js.map +2 -2
- package/dist/modules/sync_excel/api/upload/route.js +15 -2
- package/dist/modules/sync_excel/api/upload/route.js.map +2 -2
- package/dist/modules/sync_excel/widgets/injection/upload-config/widget.client.js +1 -1
- package/dist/modules/sync_excel/widgets/injection/upload-config/widget.client.js.map +2 -2
- package/dist/modules/wms/components/backend/ReleaseReservationDialog.js +1 -1
- package/dist/modules/wms/components/backend/ReleaseReservationDialog.js.map +1 -1
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js +5 -4
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js +4 -3
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLocationDetailPage.js +3 -2
- package/dist/modules/wms/components/backend/WmsLocationDetailPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLotDetailPage.js +3 -2
- package/dist/modules/wms/components/backend/WmsLotDetailPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLotsListPage.js +2 -1
- package/dist/modules/wms/components/backend/WmsLotsListPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsSkuDetailPage.js +3 -2
- package/dist/modules/wms/components/backend/WmsSkuDetailPage.js.map +2 -2
- package/dist/modules/wms/extension-points.js +26 -0
- package/dist/modules/wms/extension-points.js.map +7 -0
- package/dist/modules/workflows/backend/definitions/[id]/page.js +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.js +1 -1
- package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/page.js +3 -2
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +9 -6
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.js +10 -9
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +8 -7
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/components/ActivitiesEditor.js +69 -13
- package/dist/modules/workflows/components/ActivitiesEditor.js.map +2 -2
- package/dist/modules/workflows/components/BusinessRulesSelector.js +1 -1
- package/dist/modules/workflows/components/BusinessRulesSelector.js.map +2 -2
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +3 -3
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
- package/dist/modules/workflows/components/EdgeEditDialogCrudForm.js +1 -2
- package/dist/modules/workflows/components/EdgeEditDialogCrudForm.js.map +2 -2
- package/dist/modules/workflows/components/NodeEditDialog.js +3 -3
- package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
- package/dist/modules/workflows/components/NodeEditDialogCrudForm.js +4 -5
- package/dist/modules/workflows/components/NodeEditDialogCrudForm.js.map +2 -2
- package/dist/modules/workflows/components/StepsEditor.js +2 -2
- package/dist/modules/workflows/components/StepsEditor.js.map +2 -2
- package/dist/modules/workflows/components/TransitionsEditor.js +207 -165
- package/dist/modules/workflows/components/TransitionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowGraphImpl.js +1 -1
- package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowLegend.js +1 -1
- package/dist/modules/workflows/components/WorkflowLegend.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowSelector.js +1 -1
- package/dist/modules/workflows/components/WorkflowSelector.js.map +2 -2
- package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js +1 -1
- package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js +2 -2
- package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/MappingArrayEditor.js +1 -1
- package/dist/modules/workflows/components/fields/MappingArrayEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js +1 -1
- package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/WorkflowSelectorField.js +4 -4
- package/dist/modules/workflows/components/fields/WorkflowSelectorField.js.map +2 -2
- package/dist/modules/workflows/data/validators.js +34 -1
- package/dist/modules/workflows/data/validators.js.map +3 -3
- package/dist/modules/workflows/events.js +1 -0
- package/dist/modules/workflows/events.js.map +2 -2
- package/dist/modules/workflows/extension-points.js +15 -0
- package/dist/modules/workflows/extension-points.js.map +7 -0
- package/dist/modules/workflows/lib/activity-executor.js +59 -14
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/format-validation-error.js +46 -1
- package/dist/modules/workflows/lib/format-validation-error.js.map +2 -2
- package/dist/modules/workflows/widgets/injection/order-approval/context-keys.js +10 -0
- package/dist/modules/workflows/widgets/injection/order-approval/context-keys.js.map +7 -0
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js +21 -10
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js.map +2 -2
- package/generated/entities/attachment_quota_reservation/index.ts +15 -0
- package/generated/entities/customer_deal_person_link/index.ts +1 -0
- package/generated/entities/customer_user_invitation/index.ts +1 -0
- package/generated/entities/gateway_payment_operation/index.ts +1 -0
- package/generated/entities/gateway_transaction/index.ts +1 -0
- package/generated/entities/organization/index.ts +1 -0
- package/generated/entities/resources_resource/index.ts +1 -0
- package/generated/entities.ids.generated.ts +3 -1
- package/generated/entity-fields-registry.ts +23 -0
- package/package.json +19 -18
- package/src/bootstrap.ts +17 -2
- package/src/helpers/integration/salesFixtures.ts +34 -2
- package/src/helpers/integration/salesUi.ts +8 -0
- package/src/modules/api_keys/backend/api-keys/page.tsx +2 -1
- package/src/modules/api_keys/extension-points.ts +13 -0
- package/src/modules/api_keys/i18n/ko.json +42 -0
- package/src/modules/attachments/api/route.ts +130 -9
- package/src/modules/attachments/backend/config/attachments/page.tsx +1 -1
- package/src/modules/attachments/data/entities.ts +59 -0
- package/src/modules/attachments/di.ts +9 -1
- package/src/modules/attachments/fields/attachment.tsx +1 -1
- package/src/modules/attachments/i18n/de.json +15 -0
- package/src/modules/attachments/i18n/en.json +15 -0
- package/src/modules/attachments/i18n/es.json +15 -0
- package/src/modules/attachments/i18n/ko.json +175 -0
- package/src/modules/attachments/i18n/pl.json +15 -0
- package/src/modules/attachments/lib/drivers/index.ts +1 -1
- package/src/modules/attachments/lib/drivers/localDriver.ts +23 -8
- package/src/modules/attachments/lib/drivers/types.ts +5 -0
- package/src/modules/attachments/lib/quota-recovery-queue.ts +16 -0
- package/src/modules/attachments/lib/quota-service.ts +442 -0
- package/src/modules/attachments/lib/upload-limits.ts +35 -0
- package/src/modules/attachments/migrations/.snapshot-open-mercato.json +648 -120
- package/src/modules/attachments/migrations/Migration20260709234741_attachments.ts +12 -0
- package/src/modules/attachments/workers/quota-recovery.ts +68 -0
- package/src/modules/audit_logs/api/audit-logs/access/route.ts +5 -0
- package/src/modules/audit_logs/api/audit-logs/actions/export/route.ts +5 -0
- package/src/modules/audit_logs/api/audit-logs/actions/route.ts +5 -0
- package/src/modules/audit_logs/api/audit-logs/readScope.ts +28 -0
- package/src/modules/audit_logs/components/AccessLogsTable.tsx +2 -1
- package/src/modules/audit_logs/components/AuditLogsActions.tsx +3 -2
- package/src/modules/audit_logs/extension-points.ts +11 -0
- package/src/modules/audit_logs/i18n/ko.json +66 -0
- package/src/modules/auth/AGENTS.md +12 -8
- package/src/modules/auth/api/admin/nav.ts +28 -4
- package/src/modules/auth/api/profile/route.ts +8 -2
- package/src/modules/auth/api/users/route.ts +8 -28
- package/src/modules/auth/backend/auth/profile/page.tsx +1 -0
- package/src/modules/auth/backend/profile/change-password/page.tsx +1 -0
- package/src/modules/auth/backend/roles/page.tsx +2 -1
- package/src/modules/auth/backend/settings/page.tsx +17 -8
- package/src/modules/auth/backend/users/page.tsx +2 -1
- package/src/modules/auth/cli.ts +1 -1
- package/src/modules/auth/components/UserConsentsPanel.tsx +9 -9
- package/src/modules/auth/extension-points.ts +18 -0
- package/src/modules/auth/frontend/login.tsx +7 -3
- package/src/modules/auth/frontend/reset.tsx +2 -2
- package/src/modules/auth/i18n/de.json +1 -0
- package/src/modules/auth/i18n/en.json +1 -0
- package/src/modules/auth/i18n/es.json +1 -0
- package/src/modules/auth/i18n/ko.json +255 -0
- package/src/modules/auth/i18n/pl.json +1 -0
- package/src/modules/auth/lib/backendChrome.tsx +71 -33
- package/src/modules/auth/lib/setup-app.ts +21 -2
- package/src/modules/auth/lib/tenantAccess.ts +8 -0
- package/src/modules/auth/services/rbacService.ts +41 -46
- package/src/modules/business_rules/api/openmercato-call-options/route.ts +94 -0
- package/src/modules/business_rules/api/rules/route.ts +92 -4
- package/src/modules/business_rules/backend/rules/page.tsx +2 -1
- package/src/modules/business_rules/components/ActionBuilder.tsx +54 -5
- package/src/modules/business_rules/components/ActionRow.tsx +156 -18
- package/src/modules/business_rules/components/ConditionRow.tsx +9 -6
- package/src/modules/business_rules/components/utils/actionValidation.ts +6 -0
- package/src/modules/business_rules/events.ts +10 -0
- package/src/modules/business_rules/extension-points.ts +10 -0
- package/src/modules/business_rules/i18n/de.json +12 -0
- package/src/modules/business_rules/i18n/en.json +12 -0
- package/src/modules/business_rules/i18n/es.json +12 -0
- package/src/modules/business_rules/i18n/ko.json +396 -0
- package/src/modules/business_rules/i18n/pl.json +12 -0
- package/src/modules/business_rules/lib/action-executor.ts +198 -0
- package/src/modules/business_rules/lib/openmercato-call-options-types.ts +31 -0
- package/src/modules/business_rules/lib/openmercato-call-options.ts +297 -0
- package/src/modules/business_rules/lib/rule-engine.ts +4 -0
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +6 -5
- package/src/modules/catalog/backend/catalog/products/create/page.tsx +7 -6
- package/src/modules/catalog/components/PriceKindSettings.tsx +3 -3
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +2 -1
- package/src/modules/catalog/components/products/ProductCategorizeSection.tsx +3 -3
- package/src/modules/catalog/components/products/ProductMediaManager.tsx +1 -1
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +3 -2
- package/src/modules/catalog/components/products/VariantBuilder.tsx +5 -5
- package/src/modules/catalog/events.ts +1 -0
- package/src/modules/catalog/extension-points.ts +24 -0
- package/src/modules/catalog/i18n/de.json +18 -0
- package/src/modules/catalog/i18n/en.json +18 -0
- package/src/modules/catalog/i18n/es.json +18 -0
- package/src/modules/catalog/i18n/ko.json +723 -0
- package/src/modules/catalog/i18n/pl.json +18 -0
- package/src/modules/catalog/widgets/injection/product-bulk-delete/widget.ts +15 -5
- package/src/modules/catalog/widgets/injection/product-seo/widget.ts +1 -1
- package/src/modules/communication_channels/api/post/test-seed/route.ts +69 -2
- package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +11 -1
- package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +17 -11
- package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +2 -1
- package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +8 -7
- package/src/modules/communication_channels/data/enrichers.ts +6 -26
- package/src/modules/communication_channels/extension-points.ts +17 -0
- package/src/modules/communication_channels/i18n/de.json +2 -2
- package/src/modules/communication_channels/i18n/en.json +2 -2
- package/src/modules/communication_channels/i18n/es.json +2 -2
- package/src/modules/communication_channels/i18n/ko.json +138 -0
- package/src/modules/communication_channels/i18n/pl.json +2 -2
- package/src/modules/communication_channels/lib/access-control.ts +3 -3
- package/src/modules/configs/backend/config/system-status/page.tsx +2 -1
- package/src/modules/configs/extension-points.ts +15 -0
- package/src/modules/configs/i18n/ko.json +197 -0
- package/src/modules/configs/lib/upgrade-actions.ts +14 -0
- package/src/modules/currencies/backend/currencies/page.tsx +2 -1
- package/src/modules/currencies/backend/exchange-rates/page.tsx +2 -1
- package/src/modules/currencies/di.ts +4 -1
- package/src/modules/currencies/extension-points.ts +11 -0
- package/src/modules/currencies/i18n/de.json +1 -0
- package/src/modules/currencies/i18n/en.json +1 -0
- package/src/modules/currencies/i18n/es.json +1 -0
- package/src/modules/currencies/i18n/ko.json +160 -0
- package/src/modules/currencies/i18n/pl.json +1 -0
- package/src/modules/currencies/services/baseCurrencyService.ts +59 -0
- package/src/modules/customer_accounts/AGENTS.md +3 -3
- package/src/modules/customer_accounts/api/admin/users/[id].ts +16 -1
- package/src/modules/customer_accounts/api/admin/users-invite.ts +81 -3
- package/src/modules/customer_accounts/api/invitations/accept.ts +1 -2
- package/src/modules/customer_accounts/api/login.ts +4 -2
- package/src/modules/customer_accounts/api/magic-link/verify.ts +4 -2
- package/src/modules/customer_accounts/api/portal/feature-check.ts +5 -7
- package/src/modules/customer_accounts/api/portal/nav.ts +5 -3
- package/src/modules/customer_accounts/api/portal/profile.ts +5 -1
- package/src/modules/customer_accounts/api/portal/sessions-refresh.ts +3 -3
- package/src/modules/customer_accounts/api/portal/users-invite.ts +25 -1
- package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +2 -1
- package/src/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.tsx +2 -2
- package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +2 -1
- package/src/modules/customer_accounts/data/entities.ts +3 -0
- package/src/modules/customer_accounts/data/validators.ts +1 -0
- package/src/modules/customer_accounts/emails/CustomerInvitationEmail.tsx +45 -0
- package/src/modules/customer_accounts/extension-points.ts +11 -0
- package/src/modules/customer_accounts/i18n/de.json +6 -0
- package/src/modules/customer_accounts/i18n/en.json +6 -0
- package/src/modules/customer_accounts/i18n/es.json +6 -0
- package/src/modules/customer_accounts/i18n/ko.json +354 -0
- package/src/modules/customer_accounts/i18n/pl.json +6 -0
- package/src/modules/customer_accounts/lib/customerAuth.ts +8 -2
- package/src/modules/customer_accounts/lib/customerAuthServer.ts +1 -0
- package/src/modules/customer_accounts/lib/customerEntityOwnership.ts +68 -2
- package/src/modules/customer_accounts/lib/customerUrl.ts +27 -11
- package/src/modules/customer_accounts/lib/invitationEmail.ts +42 -0
- package/src/modules/customer_accounts/migrations/.snapshot-open-mercato.json +16 -0
- package/src/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.ts +13 -0
- package/src/modules/customer_accounts/services/customerInvitationService.ts +56 -3
- package/src/modules/customer_accounts/services/customerRbacService.ts +16 -3
- package/src/modules/customer_accounts/setup.ts +7 -0
- package/src/modules/customer_accounts/subscribers/autoLinkCrm.ts +75 -8
- package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +2 -2
- package/src/modules/customer_accounts/widgets/injection/portal-ai-assistant-trigger/widget.client.tsx +1 -3
- package/src/modules/customer_accounts/widgets/injection-table.ts +4 -1
- package/src/modules/customers/analytics.ts +3 -0
- package/src/modules/customers/api/companies/[id]/route.ts +3 -4
- package/src/modules/customers/api/deals/[id]/people/route.ts +3 -0
- package/src/modules/customers/api/deals/[id]/route.ts +10 -2
- package/src/modules/customers/api/deals/aggregate/route.ts +5 -4
- package/src/modules/customers/api/deals/summary/route.ts +15 -162
- package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +3 -2
- package/src/modules/customers/api/utils.ts +25 -37
- package/src/modules/customers/backend/customers/companies/[id]/page.tsx +2 -1
- package/src/modules/customers/backend/customers/companies/page.tsx +2 -1
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +17 -5
- package/src/modules/customers/backend/customers/deals/[id]/hooks/types.ts +1 -0
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +19 -12
- package/src/modules/customers/backend/customers/deals/page.tsx +2 -1
- package/src/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.tsx +35 -3
- package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +11 -2
- package/src/modules/customers/backend/customers/people/[id]/page.tsx +2 -1
- package/src/modules/customers/backend/customers/people/page.tsx +2 -1
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +29 -10
- package/src/modules/customers/cli.ts +28 -11
- package/src/modules/customers/commands/deals.ts +50 -9
- package/src/modules/customers/commands/people.ts +3 -0
- package/src/modules/customers/components/CustomerTodosTable.tsx +2 -1
- package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +1 -1
- package/src/modules/customers/components/detail/ActiveDealCard.tsx +2 -1
- package/src/modules/customers/components/detail/ActivitiesDayStrip.tsx +2 -3
- package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +30 -7
- package/src/modules/customers/components/detail/CompanyKpiBar.tsx +6 -5
- package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +2 -2
- package/src/modules/customers/components/detail/DealDetailTabs.tsx +34 -9
- package/src/modules/customers/components/detail/DealForm.tsx +5 -1
- package/src/modules/customers/components/detail/DealsSection.tsx +1 -1
- package/src/modules/customers/components/detail/MiniWeekCalendar.tsx +8 -57
- package/src/modules/customers/components/detail/PersonDetailTabs.tsx +34 -9
- package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +29 -14
- package/src/modules/customers/components/detail/dashboard/helpers.ts +4 -3
- package/src/modules/customers/components/detail/legacyActivities.ts +79 -0
- package/src/modules/customers/components/formConfig.tsx +12 -8
- package/src/modules/customers/data/entities.ts +9 -1
- package/src/modules/customers/data/validators.ts +6 -1
- package/src/modules/customers/extension-points.ts +40 -0
- package/src/modules/customers/i18n/de.json +72 -0
- package/src/modules/customers/i18n/en.json +72 -0
- package/src/modules/customers/i18n/es.json +72 -0
- package/src/modules/customers/i18n/ko.json +2855 -0
- package/src/modules/customers/i18n/pl.json +72 -0
- package/src/modules/customers/lib/calendar/format.ts +10 -4
- package/src/modules/customers/lib/dealStatus.ts +48 -0
- package/src/modules/customers/lib/dealsSummaryQueries.ts +211 -0
- package/src/modules/customers/lib/optionalBaseCurrency.ts +34 -0
- package/src/modules/customers/lib/visibilityFilter.ts +7 -5
- package/src/modules/customers/migrations/.snapshot-open-mercato.json +27 -1
- package/src/modules/customers/migrations/Migration20260723210000_customers.ts +15 -0
- package/src/modules/customers/search.ts +59 -27
- package/src/modules/customers/utils/phoneDuplicates.ts +6 -3
- package/src/modules/dashboards/api/layout/[itemId]/route.ts +6 -3
- package/src/modules/dashboards/api/layout/route.ts +22 -9
- package/src/modules/dashboards/api/roles/widgets/route.ts +9 -3
- package/src/modules/dashboards/api/users/widgets/route.ts +9 -3
- package/src/modules/dashboards/api/widgets/catalog.ts +6 -3
- package/src/modules/dashboards/api/widgets/data/batch/route.ts +12 -1
- package/src/modules/dashboards/api/widgets/data/route.ts +29 -1
- package/src/modules/dashboards/api/widgets/data/schema.ts +49 -19
- package/src/modules/dashboards/components/UnlabelledAmountNotice.tsx +43 -0
- package/src/modules/dashboards/i18n/de.json +5 -0
- package/src/modules/dashboards/i18n/en.json +5 -0
- package/src/modules/dashboards/i18n/es.json +5 -0
- package/src/modules/dashboards/i18n/ko.json +118 -0
- package/src/modules/dashboards/i18n/pl.json +5 -0
- package/src/modules/dashboards/lib/access.ts +5 -3
- package/src/modules/dashboards/lib/aggregations.ts +198 -48
- package/src/modules/dashboards/lib/exactDecimal.ts +96 -0
- package/src/modules/dashboards/lib/formatters.ts +137 -12
- package/src/modules/dashboards/lib/optionalBaseCurrency.ts +22 -0
- package/src/modules/dashboards/services/widgetDataService.ts +453 -12
- package/src/modules/dashboards/subscribers/invalidateWidgetDataCache.ts +32 -0
- package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.tsx +9 -3
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/config.ts +86 -0
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.tsx +42 -21
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.tsx +9 -3
- package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.tsx +7 -2
- package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.tsx +25 -15
- package/src/modules/dashboards/widgets/dashboard/top-customers/widget.client.tsx +21 -11
- package/src/modules/dashboards/widgets/dashboard/top-products/widget.client.tsx +9 -3
- package/src/modules/data_sync/AGENTS.md +1 -0
- package/src/modules/data_sync/api/mappings/[id]/route.ts +22 -9
- package/src/modules/data_sync/api/mappings/route.ts +13 -4
- package/src/modules/data_sync/api/options.ts +7 -2
- package/src/modules/data_sync/api/run.ts +7 -2
- package/src/modules/data_sync/api/runs/[id]/cancel.ts +8 -3
- package/src/modules/data_sync/api/runs/[id]/retry.ts +7 -2
- package/src/modules/data_sync/api/runs/[id]/route.ts +8 -3
- package/src/modules/data_sync/api/runs.ts +7 -2
- package/src/modules/data_sync/api/schedules/[id]/route.ts +19 -6
- package/src/modules/data_sync/api/schedules/route.ts +13 -4
- package/src/modules/data_sync/api/validate.ts +9 -4
- package/src/modules/data_sync/backend/data-sync/page.tsx +5 -4
- package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +5 -5
- package/src/modules/data_sync/extension-points.ts +10 -0
- package/src/modules/data_sync/i18n/ko.json +125 -0
- package/src/modules/data_sync/lib/adapter.ts +18 -0
- package/src/modules/data_sync/lib/queue-policy.ts +30 -0
- package/src/modules/data_sync/lib/queue.ts +19 -1
- package/src/modules/data_sync/lib/start-run.ts +2 -1
- package/src/modules/data_sync/lib/sync-engine.ts +46 -0
- package/src/modules/data_sync/lib/sync-run-service.ts +82 -1
- package/src/modules/data_sync/workers/sync-export.ts +8 -1
- package/src/modules/data_sync/workers/sync-import.ts +8 -1
- package/src/modules/design_system/AGENTS.md +34 -0
- package/src/modules/design_system/acl.ts +5 -0
- package/src/modules/design_system/backend/design-system/page.meta.ts +11 -0
- package/src/modules/design_system/backend/design-system/page.tsx +14 -0
- package/src/modules/design_system/gallery/components/CodeSnippet.tsx +55 -0
- package/src/modules/design_system/gallery/components/EntryCard.tsx +95 -0
- package/src/modules/design_system/gallery/components/GalleryShell.tsx +206 -0
- package/src/modules/design_system/gallery/components/VariantPreview.tsx +15 -0
- package/src/modules/design_system/gallery/entries/banners.tsx +226 -0
- package/src/modules/design_system/gallery/entries/buttons.tsx +422 -0
- package/src/modules/design_system/gallery/entries/charts.tsx +518 -0
- package/src/modules/design_system/gallery/entries/dates.tsx +325 -0
- package/src/modules/design_system/gallery/entries/detail.tsx +403 -0
- package/src/modules/design_system/gallery/entries/display.tsx +893 -0
- package/src/modules/design_system/gallery/entries/feedback.tsx +746 -0
- package/src/modules/design_system/gallery/entries/filters.tsx +570 -0
- package/src/modules/design_system/gallery/entries/foundations.tsx +529 -0
- package/src/modules/design_system/gallery/entries/icons.tsx +168 -0
- package/src/modules/design_system/gallery/entries/inputs.tsx +1516 -0
- package/src/modules/design_system/gallery/entries/messages.tsx +339 -0
- package/src/modules/design_system/gallery/entries/navigation.tsx +573 -0
- package/src/modules/design_system/gallery/entries/notifications.tsx +285 -0
- package/src/modules/design_system/gallery/entries/overlays.tsx +677 -0
- package/src/modules/design_system/gallery/entries/scaffolding.tsx +430 -0
- package/src/modules/design_system/gallery/entries/schedule.tsx +307 -0
- package/src/modules/design_system/gallery/registry.ts +152 -0
- package/src/modules/design_system/gallery/types.ts +32 -0
- package/src/modules/design_system/i18n/.hardcoded-allowlist.json +71 -0
- package/src/modules/design_system/i18n/de.json +58 -0
- package/src/modules/design_system/i18n/en.json +58 -0
- package/src/modules/design_system/i18n/es.json +58 -0
- package/src/modules/design_system/i18n/ko.json +58 -0
- package/src/modules/design_system/i18n/pl.json +58 -0
- package/src/modules/design_system/index.ts +7 -0
- package/src/modules/design_system/setup.ts +12 -0
- package/src/modules/dictionaries/api/[dictionaryId]/entries/route.ts +39 -11
- package/src/modules/dictionaries/api/openapi.ts +19 -0
- package/src/modules/dictionaries/components/DictionaryEntrySelect.tsx +1 -1
- package/src/modules/dictionaries/components/hooks/useDictionaryEntries.ts +35 -36
- package/src/modules/dictionaries/data/validators.ts +14 -0
- package/src/modules/dictionaries/i18n/ko.json +130 -0
- package/src/modules/dictionaries/lib/clientEntries.ts +4 -3
- package/src/modules/dictionaries/lib/fetchAllEntries.ts +72 -0
- package/src/modules/directory/api/organization-branding/route.ts +12 -1
- package/src/modules/directory/api/organization-switcher/route.ts +97 -26
- package/src/modules/directory/api/organizations/route.ts +7 -0
- package/src/modules/directory/api/tenants/route.ts +9 -1
- package/src/modules/directory/backend/directory/branding/page.tsx +34 -9
- package/src/modules/directory/backend/directory/organizations/[id]/edit/page.tsx +10 -14
- package/src/modules/directory/backend/directory/organizations/page.tsx +2 -1
- package/src/modules/directory/backend/directory/tenants/page.tsx +2 -1
- package/src/modules/directory/commands/organizations.ts +9 -1
- package/src/modules/directory/commands/tenants.ts +6 -0
- package/src/modules/directory/data/entities.ts +3 -0
- package/src/modules/directory/data/validators.ts +2 -0
- package/src/modules/directory/extension-points.ts +11 -0
- package/src/modules/directory/i18n/de.json +4 -1
- package/src/modules/directory/i18n/en.json +4 -1
- package/src/modules/directory/i18n/es.json +4 -1
- package/src/modules/directory/i18n/ko.json +105 -0
- package/src/modules/directory/i18n/pl.json +4 -1
- package/src/modules/directory/migrations/.snapshot-open-mercato.json +18 -1
- package/src/modules/directory/migrations/Migration20260626145500_directory_logo_preserve_aspect_ratio.ts +13 -0
- package/src/modules/directory/subscribers/invalidateOrgScopeCache.ts +4 -1
- package/src/modules/directory/utils/organizationScope.ts +9 -3
- package/src/modules/entities/api/definitions.ts +55 -3
- package/src/modules/entities/api/entities.ts +30 -2
- package/src/modules/entities/api/entity-settings.ts +66 -22
- package/src/modules/entities/api/records.ts +15 -31
- package/src/modules/entities/api/sidebar-entities.ts +43 -14
- package/src/modules/entities/backend/config/settings/page.meta.ts +34 -0
- package/src/modules/entities/backend/config/settings/page.tsx +12 -0
- package/src/modules/entities/backend/entities/user/[entityId]/page.tsx +1 -1
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +96 -75
- package/src/modules/entities/backend/entities/user/create/page.tsx +16 -7
- package/src/modules/entities/cli.ts +238 -21
- package/src/modules/entities/components/EntitySettingsManager.tsx +160 -0
- package/src/modules/entities/components/RecordListRelationCell.tsx +90 -0
- package/src/modules/entities/components/SystemEntitiesTable.tsx +2 -1
- package/src/modules/entities/components/UserEntitiesTable.tsx +2 -1
- package/src/modules/entities/components/recordListRelationDisplays.ts +109 -0
- package/src/modules/entities/extension-points.ts +18 -0
- package/src/modules/entities/i18n/de.json +9 -0
- package/src/modules/entities/i18n/en.json +9 -0
- package/src/modules/entities/i18n/es.json +9 -0
- package/src/modules/entities/i18n/ko.json +260 -0
- package/src/modules/entities/i18n/pl.json +9 -0
- package/src/modules/entities/lib/entityAcl.ts +98 -11
- package/src/modules/feature_toggles/components/FeatureGuard.tsx +9 -2
- package/src/modules/feature_toggles/components/FeatureToggleOverrideCard.tsx +1 -1
- package/src/modules/feature_toggles/components/hooks/staleTime.ts +5 -0
- package/src/modules/feature_toggles/components/hooks/useFeatureFlagBoolean.ts +13 -1
- package/src/modules/feature_toggles/components/hooks/useFeatureFlagJson.ts +12 -3
- package/src/modules/feature_toggles/components/hooks/useFeatureFlagNumber.ts +10 -1
- package/src/modules/feature_toggles/components/hooks/useFeatureFlagString.ts +10 -1
- package/src/modules/feature_toggles/i18n/ko.json +96 -0
- package/src/modules/inbox_ops/ai-tools.ts +5 -3
- package/src/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.ts +17 -1
- package/src/modules/inbox_ops/api/proposals/route.ts +20 -1
- package/src/modules/inbox_ops/api/webhook/inbound.ts +14 -12
- package/src/modules/inbox_ops/backend/inbox-ops/log/page.tsx +6 -6
- package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +24 -19
- package/src/modules/inbox_ops/components/proposals/types.ts +1 -0
- package/src/modules/inbox_ops/i18n/de.json +3 -0
- package/src/modules/inbox_ops/i18n/en.json +3 -0
- package/src/modules/inbox_ops/i18n/es.json +3 -0
- package/src/modules/inbox_ops/i18n/ko.json +196 -0
- package/src/modules/inbox_ops/i18n/pl.json +3 -0
- package/src/modules/inbox_ops/search.ts +20 -4
- package/src/modules/inbox_ops/subscribers/search-reindex-proposal-created.ts +39 -0
- package/src/modules/integrations/api/[id]/credentials/route.ts +11 -5
- package/src/modules/integrations/api/[id]/health/route.ts +6 -3
- package/src/modules/integrations/api/[id]/route.ts +6 -3
- package/src/modules/integrations/api/[id]/state/route.ts +6 -3
- package/src/modules/integrations/api/[id]/version/route.ts +6 -3
- package/src/modules/integrations/api/logs/route.ts +6 -3
- package/src/modules/integrations/api/route.ts +6 -3
- package/src/modules/integrations/api/umes-read.ts +2 -2
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +2 -2
- package/src/modules/integrations/extension-points.ts +27 -0
- package/src/modules/integrations/i18n/ko.json +129 -0
- package/src/modules/integrations/lib/organization-scope.ts +5 -25
- package/src/modules/integrations/widgets/injection/external-ids/widget.client.tsx +0 -5
- package/src/modules/integrations/widgets/injection/external-ids/widget.ts +13 -0
- package/src/modules/messages/api/[id]/route.ts +21 -0
- package/src/modules/messages/api/route.ts +109 -9
- package/src/modules/messages/components/ComposeMessagePageClient.tsx +2 -1
- package/src/modules/messages/components/MessageDetailPageClient.tsx +3 -2
- package/src/modules/messages/components/MessagesInboxPageClient.tsx +2 -1
- package/src/modules/messages/components/message-detail/panels/dialogs.tsx +1 -1
- package/src/modules/messages/extension-points.ts +13 -0
- package/src/modules/messages/i18n/de.json +2 -0
- package/src/modules/messages/i18n/en.json +2 -0
- package/src/modules/messages/i18n/es.json +2 -0
- package/src/modules/messages/i18n/ko.json +263 -0
- package/src/modules/messages/i18n/pl.json +2 -0
- package/src/modules/messages/lib/participantScope.ts +64 -0
- package/src/modules/messages/lib/routeHelpers.ts +4 -6
- package/src/modules/messages/lib/searchLookup.ts +11 -34
- package/src/modules/messages/search.ts +11 -5
- package/src/modules/notifications/api/route.ts +123 -3
- package/src/modules/notifications/api/unread-count/route.ts +42 -5
- package/src/modules/notifications/di.ts +1 -1
- package/src/modules/notifications/events.ts +2 -0
- package/src/modules/notifications/i18n/ko.json +55 -0
- package/src/modules/notifications/lib/notificationRecipients.ts +6 -8
- package/src/modules/notifications/lib/notificationScope.ts +40 -0
- package/src/modules/notifications/lib/notificationService.ts +63 -1
- package/src/modules/notifications/lib/routeHelpers.ts +19 -2
- package/src/modules/payment_gateways/api/capture/route.ts +1 -1
- package/src/modules/payment_gateways/api/sessions/route.ts +6 -3
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +13 -1
- package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +3 -2
- package/src/modules/payment_gateways/data/entities.ts +13 -2
- package/src/modules/payment_gateways/di.ts +28 -2
- package/src/modules/payment_gateways/extension-points.ts +16 -0
- package/src/modules/payment_gateways/i18n/de.json +8 -1
- package/src/modules/payment_gateways/i18n/en.json +8 -1
- package/src/modules/payment_gateways/i18n/es.json +8 -1
- package/src/modules/payment_gateways/i18n/ko.json +87 -0
- package/src/modules/payment_gateways/i18n/pl.json +8 -1
- package/src/modules/payment_gateways/lib/capture-ledger.ts +260 -0
- package/src/modules/payment_gateways/lib/gateway-service.ts +114 -18
- package/src/modules/payment_gateways/lib/order-amount-reconciliation.ts +93 -0
- package/src/modules/payment_gateways/lib/payment-operation-idempotency.ts +1 -0
- package/src/modules/payment_gateways/lib/session-idempotency.ts +36 -0
- package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +44 -1
- package/src/modules/payment_gateways/migrations/Migration20260725101500_payment_gateways.ts +21 -0
- package/src/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.ts +17 -0
- package/src/modules/payment_gateways/setup.ts +62 -0
- package/src/modules/payment_gateways/workers/session-initialization-prune.ts +63 -0
- package/src/modules/planner/components/AvailabilityRulesEditor.tsx +4 -4
- package/src/modules/planner/components/unavailabilityReasons.ts +3 -3
- package/src/modules/planner/i18n/ko.json +565 -0
- package/src/modules/portal/extension-points.ts +30 -0
- package/src/modules/portal/frontend/[orgSlug]/portal/dashboard/page.tsx +3 -3
- package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.ts +9 -0
- package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.tsx +164 -0
- package/src/modules/portal/frontend/[orgSlug]/portal/login/page.tsx +4 -4
- package/src/modules/portal/frontend/[orgSlug]/portal/page.tsx +3 -3
- package/src/modules/portal/frontend/[orgSlug]/portal/profile/page.tsx +3 -3
- package/src/modules/portal/frontend/[orgSlug]/portal/reset-password/page.tsx +5 -5
- package/src/modules/portal/frontend/[orgSlug]/portal/signup/page.tsx +4 -4
- package/src/modules/portal/frontend/[orgSlug]/portal/verify/page.tsx +1 -1
- package/src/modules/portal/i18n/de.json +18 -0
- package/src/modules/portal/i18n/en.json +18 -0
- package/src/modules/portal/i18n/es.json +18 -0
- package/src/modules/portal/i18n/ko.json +143 -0
- package/src/modules/portal/i18n/pl.json +18 -0
- package/src/modules/portal/lib/navigation.ts +3 -0
- package/src/modules/progress/AGENTS.md +11 -1
- package/src/modules/progress/i18n/ko.json +20 -0
- package/src/modules/progress/lib/progressService.ts +1 -0
- package/src/modules/progress/lib/progressServiceImpl.ts +385 -117
- package/src/modules/query_index/api/openapi.ts +12 -0
- package/src/modules/query_index/api/reindex.ts +15 -0
- package/src/modules/query_index/api/status.ts +238 -136
- package/src/modules/query_index/cli.ts +180 -1
- package/src/modules/query_index/components/QueryIndexesTable.tsx +194 -47
- package/src/modules/query_index/data/entities.ts +7 -0
- package/src/modules/query_index/di.ts +6 -0
- package/src/modules/query_index/events.ts +17 -0
- package/src/modules/query_index/extension-points.ts +10 -0
- package/src/modules/query_index/i18n/de.json +5 -3
- package/src/modules/query_index/i18n/en.json +5 -3
- package/src/modules/query_index/i18n/es.json +5 -3
- package/src/modules/query_index/i18n/ko.json +69 -0
- package/src/modules/query_index/i18n/pl.json +5 -3
- package/src/modules/query_index/lib/batch.ts +11 -4
- package/src/modules/query_index/lib/coverage.ts +47 -14
- package/src/modules/query_index/lib/document.ts +35 -4
- package/src/modules/query_index/lib/engine.ts +136 -59
- package/src/modules/query_index/lib/indexer.ts +130 -21
- package/src/modules/query_index/lib/reindexer.ts +62 -40
- package/src/modules/query_index/lib/search-tokens.ts +48 -16
- package/src/modules/query_index/lib/subscriber-scope.ts +2 -7
- package/src/modules/query_index/migrations/.snapshot-open-mercato.json +12 -0
- package/src/modules/query_index/migrations/Migration20260731105052_query_index.ts +35 -0
- package/src/modules/query_index/subscribers/coverage_refresh.ts +4 -0
- package/src/modules/query_index/subscribers/delete_one.ts +65 -1
- package/src/modules/query_index/subscribers/upsert_one.ts +68 -1
- package/src/modules/resources/api/resources.ts +2 -0
- package/src/modules/resources/backend/resources/resource-types/page.tsx +2 -1
- package/src/modules/resources/backend/resources/resources/[id]/page.tsx +9 -3
- package/src/modules/resources/backend/resources/resources/page.tsx +2 -1
- package/src/modules/resources/commands/resources.ts +10 -0
- package/src/modules/resources/components/detail/dictionaries.ts +3 -3
- package/src/modules/resources/data/entities.ts +3 -0
- package/src/modules/resources/data/validators.ts +5 -0
- package/src/modules/resources/extension-points.ts +11 -0
- package/src/modules/resources/i18n/ko.json +770 -0
- package/src/modules/resources/lib/seeds.ts +16 -9
- package/src/modules/resources/migrations/.snapshot-open-mercato.json +17 -1
- package/src/modules/resources/migrations/Migration20260608231000.ts +13 -0
- package/src/modules/sales/analytics.ts +4 -0
- package/src/modules/sales/api/document-history/route.ts +1 -0
- package/src/modules/sales/api/documents/factory.ts +28 -3
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +11 -3
- package/src/modules/sales/backend/sales/documents/create/page.tsx +2 -4
- package/src/modules/sales/commands/documents.ts +298 -31
- package/src/modules/sales/components/documents/ItemsSection.tsx +34 -11
- package/src/modules/sales/components/documents/LineItemDialog.tsx +13 -5
- package/src/modules/sales/components/documents/SalesDocumentForm.tsx +48 -6
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +6 -1
- package/src/modules/sales/components/documents/SalesOrderDraftLines.tsx +198 -0
- package/src/modules/sales/components/documents/lineItemTypes.ts +1 -0
- package/src/modules/sales/components/useSalesChannelsEnabled.ts +2 -48
- package/src/modules/sales/data/validators.ts +59 -6
- package/src/modules/sales/di.ts +9 -0
- package/src/modules/sales/events.ts +1 -0
- package/src/modules/sales/extension-points.ts +33 -0
- package/src/modules/sales/i18n/de.json +22 -0
- package/src/modules/sales/i18n/en.json +22 -0
- package/src/modules/sales/i18n/es.json +22 -0
- package/src/modules/sales/i18n/ko.json +1442 -0
- package/src/modules/sales/i18n/pl.json +22 -0
- package/src/modules/sales/lib/historyHelpers.ts +88 -1
- package/src/modules/sales/services/paymentOrderTotalResolver.ts +67 -0
- package/src/modules/sales/widgets/injection/document-history/widget.client.tsx +64 -3
- package/src/modules/sales/workflows.ts +10 -7
- package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +11 -1
- package/src/modules/shipping_carriers/i18n/ko.json +85 -0
- package/src/modules/shipping_carriers/lib/shipment-wizard/components/PackageEditor.tsx +1 -1
- package/src/modules/staff/api/interceptors.ts +6 -4
- package/src/modules/staff/api/leave-requests.ts +54 -47
- package/src/modules/staff/components/detail/dictionaries.ts +3 -3
- package/src/modules/staff/i18n/ko.json +1162 -0
- package/src/modules/sync_excel/api/upload/route.ts +15 -2
- package/src/modules/sync_excel/i18n/ko.json +107 -0
- package/src/modules/sync_excel/widgets/injection/upload-config/widget.client.tsx +1 -1
- package/src/modules/translations/i18n/ko.json +45 -0
- package/src/modules/wms/components/backend/ReleaseReservationDialog.tsx +1 -1
- package/src/modules/wms/components/backend/WmsConfigurationPage.tsx +5 -4
- package/src/modules/wms/components/backend/WmsInventoryConsolePage.tsx +4 -3
- package/src/modules/wms/components/backend/WmsLocationDetailPage.tsx +3 -2
- package/src/modules/wms/components/backend/WmsLotDetailPage.tsx +3 -2
- package/src/modules/wms/components/backend/WmsLotsListPage.tsx +2 -1
- package/src/modules/wms/components/backend/WmsSkuDetailPage.tsx +3 -2
- package/src/modules/wms/extension-points.ts +23 -0
- package/src/modules/wms/i18n/de.json +2 -0
- package/src/modules/wms/i18n/en.json +2 -0
- package/src/modules/wms/i18n/es.json +2 -0
- package/src/modules/wms/i18n/ko.json +1053 -0
- package/src/modules/wms/i18n/pl.json +2 -0
- package/src/modules/workflows/backend/definitions/[id]/page.tsx +2 -2
- package/src/modules/workflows/backend/definitions/create/page.tsx +1 -1
- package/src/modules/workflows/backend/definitions/page.tsx +3 -2
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +16 -7
- package/src/modules/workflows/backend/instances/page.tsx +10 -9
- package/src/modules/workflows/backend/tasks/page.tsx +8 -7
- package/src/modules/workflows/components/ActivitiesEditor.tsx +98 -14
- package/src/modules/workflows/components/BusinessRulesSelector.tsx +1 -1
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +3 -3
- package/src/modules/workflows/components/EdgeEditDialogCrudForm.tsx +1 -2
- package/src/modules/workflows/components/NodeEditDialog.tsx +3 -3
- package/src/modules/workflows/components/NodeEditDialogCrudForm.tsx +4 -5
- package/src/modules/workflows/components/StepsEditor.tsx +2 -2
- package/src/modules/workflows/components/TransitionsEditor.tsx +78 -20
- package/src/modules/workflows/components/WorkflowGraphImpl.tsx +1 -1
- package/src/modules/workflows/components/WorkflowLegend.tsx +1 -1
- package/src/modules/workflows/components/WorkflowSelector.tsx +1 -1
- package/src/modules/workflows/components/fields/BusinessRuleConditionsEditor.tsx +1 -1
- package/src/modules/workflows/components/fields/FormFieldArrayEditor.tsx +2 -2
- package/src/modules/workflows/components/fields/MappingArrayEditor.tsx +1 -1
- package/src/modules/workflows/components/fields/StartPreConditionsEditor.tsx +1 -1
- package/src/modules/workflows/components/fields/WorkflowSelectorField.tsx +4 -4
- package/src/modules/workflows/data/validators.ts +52 -1
- package/src/modules/workflows/events.ts +1 -0
- package/src/modules/workflows/extension-points.ts +12 -0
- package/src/modules/workflows/i18n/de.json +3 -0
- package/src/modules/workflows/i18n/en.json +3 -0
- package/src/modules/workflows/i18n/es.json +3 -0
- package/src/modules/workflows/i18n/ko.json +1204 -0
- package/src/modules/workflows/i18n/pl.json +3 -0
- package/src/modules/workflows/lib/activity-executor.ts +99 -20
- package/src/modules/workflows/lib/format-validation-error.ts +60 -0
- package/src/modules/workflows/widgets/injection/order-approval/context-keys.ts +18 -0
- package/src/modules/workflows/widgets/injection/order-approval/widget.client.tsx +27 -11
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/modules/customers/search.ts"],
|
|
4
|
-
"sourcesContent": ["import type { QueryCustomFieldSource, QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport type {\n SearchModuleConfig,\n SearchBuildContext,\n SearchResultPresenter,\n SearchResultLink,\n SearchIndexSource,\n} from '@open-mercato/shared/modules/search'\nimport { CUSTOMER_INTERACTION_TASK_SOURCE, EXAMPLE_TODO_SOURCE } from './lib/interactionCompatibility'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('customers')\n\n// =============================================================================\n// Context Types\n// =============================================================================\n\ntype SearchContext = SearchBuildContext & {\n tenantId: string\n queryEngine?: QueryEngine\n}\n\nfunction assertTenantContext(ctx: SearchBuildContext): asserts ctx is SearchContext {\n if (typeof ctx.tenantId !== 'string' || ctx.tenantId.length === 0) {\n throw new Error('[search.customers] Missing tenantId in search build context')\n }\n}\n\ntype CustomerProfileKind = 'person' | 'company'\n\ntype LoadedCustomerEntity = {\n entity: Record<string, unknown> | null\n customFields: Record<string, unknown>\n}\n\n// =============================================================================\n// Caching\n// =============================================================================\n\nconst entityIdCache = new Map<string, LoadedCustomerEntity | null>()\nconst profileEntityCache = new WeakMap<Record<string, unknown>, Partial<Record<CustomerProfileKind, LoadedCustomerEntity | null>>>()\nconst todoCache = new WeakMap<Record<string, unknown>, unknown>()\n\n// =============================================================================\n// Query Configuration\n// =============================================================================\n\nconst CUSTOMER_ENTITY_FIELDS = [\n 'id',\n 'kind',\n 'display_name',\n 'description',\n 'primary_email',\n 'primary_phone',\n 'status',\n 'lifecycle_stage',\n 'owner_user_id',\n 'source',\n 'next_interaction_at',\n 'next_interaction_name',\n 'next_interaction_ref_id',\n 'next_interaction_icon',\n 'next_interaction_color',\n 'organization_id',\n 'tenant_id',\n 'created_at',\n 'updated_at',\n 'deleted_at',\n] satisfies string[]\n\nconst CUSTOMER_CUSTOM_FIELD_SOURCES: QueryCustomFieldSource[] = [\n {\n entityId: 'customers:customer_person_profile',\n table: 'customer_people',\n alias: 'person_profile',\n recordIdColumn: 'id',\n join: { fromField: 'id', toField: 'entity_id' },\n },\n {\n entityId: 'customers:customer_company_profile',\n table: 'customer_companies',\n alias: 'company_profile',\n recordIdColumn: 'id',\n join: { fromField: 'id', toField: 'entity_id' },\n },\n]\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\nfunction extractCustomFieldMap(source: Record<string, unknown> | null | undefined): Record<string, unknown> {\n if (!source) return {}\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(source)) {\n if (value === undefined) continue\n if (key.startsWith('cf:')) {\n result[key.slice(3)] = value\n } else if (key.startsWith('cf_')) {\n result[key.slice(3)] = value\n }\n }\n return result\n}\n\nfunction normalizeCustomerEntity(row: Record<string, unknown>): Record<string, unknown> {\n const normalized: Record<string, unknown> = {\n id: row.id ?? row.entity_id ?? row.entityId ?? null,\n kind: row.kind ?? null,\n }\n const assign = (snake: string, camel?: string) => {\n const value = row[snake] ?? (camel ? row[camel] : undefined)\n if (value !== undefined) {\n normalized[snake] = value\n if (camel) normalized[camel] = value\n }\n }\n assign('display_name', 'displayName')\n assign('description')\n assign('primary_email', 'primaryEmail')\n assign('primary_phone', 'primaryPhone')\n assign('status')\n assign('lifecycle_stage', 'lifecycleStage')\n assign('owner_user_id', 'ownerUserId')\n assign('source')\n assign('next_interaction_at', 'nextInteractionAt')\n assign('next_interaction_name', 'nextInteractionName')\n assign('next_interaction_ref_id', 'nextInteractionRefId')\n assign('next_interaction_icon', 'nextInteractionIcon')\n assign('next_interaction_color', 'nextInteractionColor')\n assign('organization_id', 'organizationId')\n assign('tenant_id', 'tenantId')\n assign('created_at', 'createdAt')\n assign('updated_at', 'updatedAt')\n assign('deleted_at', 'deletedAt')\n return normalized\n}\n\nfunction getProfileCache(record: Record<string, unknown>): Partial<Record<CustomerProfileKind, LoadedCustomerEntity | null>> {\n let cache = profileEntityCache.get(record)\n if (!cache) {\n cache = {}\n profileEntityCache.set(record, cache)\n }\n return cache\n}\n\nfunction subtractCustomFields(\n primary: Record<string, unknown>,\n secondary: Record<string, unknown>,\n): Record<string, unknown> {\n if (!secondary || Object.keys(secondary).length === 0) return {}\n const primaryKeys = new Set(Object.keys(primary))\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(secondary)) {\n if (!primaryKeys.has(key)) {\n result[key] = value\n }\n }\n return result\n}\n\n// =============================================================================\n// Entity Loading Functions\n// =============================================================================\n\ntype CustomerEntityQueryOptions = {\n entityId?: string | null\n profileKind?: CustomerProfileKind\n profileId?: string | null\n}\n\nasync function loadCustomerEntityBundle(ctx: SearchContext, opts: CustomerEntityQueryOptions): Promise<LoadedCustomerEntity | null> {\n if (!ctx.queryEngine) return null\n const filters: Record<string, unknown> = {}\n const resolvedEntityId = typeof opts.entityId === 'string' && opts.entityId.length ? opts.entityId : null\n const resolvedProfileId =\n opts.profileId != null && String(opts.profileId).trim().length > 0 ? String(opts.profileId).trim() : null\n const shouldJoinProfileSource = Boolean(opts.profileKind && resolvedProfileId && !resolvedEntityId)\n if (resolvedEntityId) {\n filters.id = { $eq: resolvedEntityId }\n }\n if (shouldJoinProfileSource) {\n const alias = opts.profileKind === 'person' ? 'person_profile' : 'company_profile'\n filters[`${alias}.id`] = { $eq: resolvedProfileId }\n }\n if (!Object.keys(filters).length) return null\n try {\n const result = await ctx.queryEngine.query('customers:customer_entity', {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId ?? undefined,\n filters,\n includeCustomFields: true,\n ...(shouldJoinProfileSource ? { customFieldSources: CUSTOMER_CUSTOM_FIELD_SOURCES } : {}),\n fields: CUSTOMER_ENTITY_FIELDS,\n page: { page: 1, pageSize: 1 },\n })\n const row = result.items[0] as Record<string, unknown> | undefined\n if (!row) return null\n const entity = normalizeCustomerEntity(row)\n const customFields = extractCustomFieldMap(row)\n return { entity, customFields }\n } catch (error) {\n logger.warn('Failed to load customer entity via QueryEngine', {\n component: 'search',\n entityId: resolvedEntityId ?? null,\n profileKind: opts.profileKind ?? null,\n profileId: resolvedProfileId ?? null,\n err: error,\n })\n return null\n }\n}\n\nasync function loadCustomerEntityForProfile(ctx: SearchContext, kind: CustomerProfileKind): Promise<LoadedCustomerEntity | null> {\n const cache = getProfileCache(ctx.record)\n if (cache[kind] !== undefined) return cache[kind] ?? null\n const entityIdHint = resolveCustomerEntityId(ctx.record)\n const profileIdRaw = ctx.record.id ?? null\n const profileId = profileIdRaw != null ? String(profileIdRaw) : null\n if (!entityIdHint && !profileId) {\n cache[kind] = null\n return null\n }\n const loaded = await loadCustomerEntityBundle(ctx, {\n entityId: entityIdHint,\n profileKind: kind,\n profileId,\n })\n cache[kind] = loaded ?? null\n const resolvedId = loaded?.entity?.id ?? entityIdHint\n if (resolvedId && typeof resolvedId === 'string') {\n ctx.record.entity_id ??= resolvedId\n ctx.record.entityId ??= resolvedId\n entityIdCache.set(resolvedId, loaded ?? null)\n }\n if (loaded?.entity) {\n if (!ctx.record.entity) ctx.record.entity = loaded.entity\n if (!ctx.record.customer_entity) ctx.record.customer_entity = loaded.entity\n }\n return loaded ?? null\n}\n\nasync function loadCustomerEntityById(ctx: SearchContext, entityId: string | null | undefined): Promise<LoadedCustomerEntity | null> {\n const resolvedId = typeof entityId === 'string' && entityId.length ? entityId : null\n if (!resolvedId) return null\n if (entityIdCache.has(resolvedId)) {\n return entityIdCache.get(resolvedId) ?? null\n }\n const loaded = await loadCustomerEntityBundle(ctx, { entityId: resolvedId })\n entityIdCache.set(resolvedId, loaded ?? null)\n return loaded ?? null\n}\n\nasync function getCustomerEntity(ctx: SearchContext, entityId?: string | null): Promise<Record<string, unknown> | null> {\n const profileCache = profileEntityCache.get(ctx.record)\n if (profileCache) {\n const cached = Object.values(profileCache).find((entry) => {\n if (!entry?.entity) return false\n if (!entityId) return true\n return entry.entity.id === entityId\n })\n if (cached?.entity) return cached.entity\n }\n const inline = getInlineCustomerEntity(ctx.record)\n if (inline && (!entityId || inline.id === entityId)) {\n if (inline.id && typeof inline.id === 'string') {\n entityIdCache.set(inline.id, { entity: inline, customFields: {} })\n }\n return inline\n }\n const resolvedId = entityId ?? resolveCustomerEntityId(ctx.record)\n const loaded = await loadCustomerEntityById(ctx, resolvedId)\n return loaded?.entity ?? null\n}\n\ntype HydratedProfileContext = {\n entity: Record<string, unknown> | null\n entityId: string | null\n profileCustomFields: Record<string, unknown>\n entityCustomFields: Record<string, unknown>\n entityOnlyCustomFields: Record<string, unknown>\n}\n\nasync function hydrateProfileContext(ctx: SearchContext, kind: CustomerProfileKind): Promise<HydratedProfileContext> {\n const profileCustomFields = ctx.customFields ?? {}\n const loaded = await loadCustomerEntityForProfile(ctx, kind)\n let entity = loaded?.entity ?? getInlineCustomerEntity(ctx.record)\n let entityCustomFields = loaded?.customFields ?? {}\n let entityId = (entity?.id as string | undefined) ?? resolveCustomerEntityId(ctx.record)\n if (!entity && entityId) {\n const fetched = await loadCustomerEntityById(ctx, entityId)\n entity = fetched?.entity ?? null\n if (fetched?.customFields) {\n entityCustomFields = Object.keys(entityCustomFields).length ? entityCustomFields : fetched.customFields\n }\n }\n if (!entity && !entityId) {\n entityId = resolveCustomerEntityId(ctx.record)\n }\n if (entity?.id && typeof entity.id === 'string') {\n entityId = entity.id\n ctx.record.entity_id ??= entity.id\n ctx.record.entityId ??= entity.id\n if (!ctx.record.entity) ctx.record.entity = entity\n if (!ctx.record.customer_entity) ctx.record.customer_entity = entity\n }\n const entityOnlyCustomFields = subtractCustomFields(profileCustomFields, entityCustomFields)\n return {\n entity: entity ?? null,\n entityId: entityId ?? null,\n profileCustomFields,\n entityCustomFields,\n entityOnlyCustomFields,\n }\n}\n\nasync function loadRecord(ctx: SearchContext, entityId: string, recordId?: string | null) {\n if (!recordId || !ctx.queryEngine) return null\n const res = await ctx.queryEngine.query(entityId, {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId ?? undefined,\n filters: { id: recordId },\n includeCustomFields: true,\n page: { page: 1, pageSize: 1 },\n })\n return res.items[0] as Record<string, unknown> | undefined\n}\n\nfunction resolveCustomerEntityId(record: Record<string, unknown>): string | null {\n const direct =\n record.customer_entity_id ??\n record.entityId ??\n record.entity_id ??\n record.customerEntityId ??\n record.customerEntityID ??\n (typeof record.entity === 'object' && record.entity ? (record.entity as Record<string, unknown>).id : undefined) ??\n (typeof record.customer_entity === 'object' && record.customer_entity ? (record.customer_entity as Record<string, unknown>).id : undefined)\n const value = typeof direct === 'string' && direct.length ? direct : null\n return value\n}\n\nfunction getInlineCustomerEntity(record: Record<string, unknown>): Record<string, unknown> | null {\n const inline =\n (typeof record.entity === 'object' && record.entity) ||\n (typeof record.customer_entity === 'object' && record.customer_entity) ||\n null\n return inline as Record<string, unknown> | null\n}\n\nasync function getLinkedTodo(ctx: SearchContext) {\n if (todoCache.has(ctx.record)) {\n return todoCache.get(ctx.record)\n }\n const sourceRaw = typeof ctx.record.todo_source === 'string' ? ctx.record.todo_source : EXAMPLE_TODO_SOURCE\n const [moduleId, entityName] = sourceRaw.split(':')\n const entityId = moduleId && entityName ? `${moduleId}:${entityName}` : CUSTOMER_INTERACTION_TASK_SOURCE\n const todo = await loadRecord(ctx, entityId, ctx.record.todo_id as string ?? ctx.record.todoId as string)\n todoCache.set(ctx.record, todo ?? null)\n return todo ?? null\n}\n\n// =============================================================================\n// URL and Formatting Helpers\n// =============================================================================\n\nfunction buildCustomerUrl(kind: string | null | undefined, id?: string | null): string | null {\n if (!id) return null\n const encoded = encodeURIComponent(id)\n if (kind === 'person') return `/backend/customers/people-v2/${encoded}`\n if (kind === 'company') return `/backend/customers/companies-v2/${encoded}`\n return `/backend/customers/companies-v2/${encoded}`\n}\n\nfunction formatDealValue(record: Record<string, unknown>): string | undefined {\n const amount = record.value_amount ?? record.valueAmount\n if (!amount) return undefined\n const currency = record.value_currency ?? record.valueCurrency ?? ''\n return currency ? `${amount} ${currency}` : String(amount)\n}\n\nfunction snippet(text: unknown, max = 140): string | undefined {\n if (typeof text !== 'string') return undefined\n const trimmed = text.trim()\n if (!trimmed.length) return undefined\n if (trimmed.length <= max) return trimmed\n return `${trimmed.slice(0, max - 3)}...`\n}\n\nfunction appendLine(lines: string[], label: string, value: unknown) {\n if (value === null || value === undefined) return\n const text = Array.isArray(value)\n ? value.map((item) => (item === null || item === undefined ? '' : String(item))).filter(Boolean).join(', ')\n : (typeof value === 'object' ? JSON.stringify(value) : String(value))\n if (!text.trim()) return\n lines.push(`${label}: ${text}`)\n}\n\nfunction friendlyLabel(input: string): string {\n return input\n .replace(/^cf:/, '')\n .replace(/_/g, ' ')\n .replace(/([a-z])([A-Z])/g, (_, a, b) => `${a} ${b}`)\n .replace(/\\b\\w/g, (char) => char.toUpperCase())\n}\n\nfunction appendCustomFieldLines(lines: string[], customFields: Record<string, unknown>, prefix: string) {\n for (const [key, value] of Object.entries(customFields)) {\n if (value === null || value === undefined) continue\n const label = prefix ? `${prefix} ${friendlyLabel(key)}` : friendlyLabel(key)\n appendLine(lines, label, value)\n }\n}\n\nfunction pickValue(source: Record<string, unknown> | null | undefined, ...keys: string[]): unknown {\n if (!source) return undefined\n for (const key of keys) {\n if (key in source && source[key] != null) return source[key]\n }\n return undefined\n}\n\nfunction pickString(...candidates: unknown[]): string | null {\n for (const candidate of candidates) {\n if (typeof candidate === 'string' && candidate.trim().length) {\n return candidate.trim()\n }\n }\n return null\n}\n\nfunction pickLabel(...candidates: Array<unknown>): string | null {\n for (const candidate of candidates) {\n if (candidate === null || candidate === undefined) continue\n const value = typeof candidate === 'string' ? candidate : String(candidate)\n const trimmed = value.trim()\n if (trimmed.length) return trimmed\n }\n return null\n}\n\nfunction appendCustomerEntityLines(\n lines: string[],\n entity: Record<string, unknown> | null,\n contactLabel: 'Customer' | 'Primary' = 'Customer',\n) {\n if (!entity) return\n appendLine(lines, 'Customer', pickValue(entity, 'display_name', 'displayName') ?? entity.id)\n appendLine(lines, `${contactLabel} email`, pickValue(entity, 'primary_email', 'primaryEmail'))\n appendLine(lines, `${contactLabel} phone`, pickValue(entity, 'primary_phone', 'primaryPhone'))\n appendLine(lines, 'Lifecycle stage', pickValue(entity, 'lifecycle_stage', 'lifecycleStage'))\n appendLine(lines, 'Status', pickValue(entity, 'status'))\n}\n\nfunction ensureFallbackLines(lines: string[], record: Record<string, unknown>, options: { includeId?: boolean } = {}) {\n if (lines.length) return\n const excluded = new Set(['tenant_id', 'organization_id', 'created_at', 'updated_at', 'deleted_at'])\n for (const [key, value] of Object.entries(record)) {\n if (value === null || value === undefined) continue\n if (excluded.has(key)) continue\n if (key === 'id') continue\n appendLine(lines, friendlyLabel(key), value)\n }\n if (!lines.length && options.includeId !== false) {\n const fallbackId =\n record.id ??\n record.entity_id ??\n record.customer_entity_id ??\n record.entityId ??\n record.customerEntityId ??\n null\n if (fallbackId) {\n appendLine(lines, 'Record ID', fallbackId)\n }\n }\n}\n\n// =============================================================================\n// Presenter Functions\n// =============================================================================\n\nfunction resolvePersonPresenter(\n record: Record<string, unknown>,\n entity: Record<string, unknown> | null,\n customFields: Record<string, unknown>,\n): SearchResultPresenter {\n const fallbackEntityId = resolveCustomerEntityId(record)\n const firstName = record.first_name ?? record.firstName ?? customFields.first_name ?? customFields.firstName ?? ''\n const lastName = record.last_name ?? record.lastName ?? customFields.last_name ?? customFields.lastName ?? ''\n const nameParts = [firstName, lastName].filter(Boolean).join(' ')\n const title =\n (pickValue(entity, 'display_name', 'displayName') as string | undefined) ??\n (record.preferred_name as string | undefined) ??\n (record.preferredName as string | undefined) ??\n (nameParts.length ? nameParts : undefined) ??\n fallbackEntityId ??\n (record.id as string | undefined) ??\n 'Person'\n const subtitlePieces: string[] = []\n const jobTitle = record.job_title ?? record.jobTitle ?? customFields.job_title ?? customFields.jobTitle\n if (jobTitle) subtitlePieces.push(String(jobTitle))\n const department = record.department ?? customFields.department\n if (department) subtitlePieces.push(String(department))\n const primaryEmail = pickValue(entity, 'primary_email', 'primaryEmail')\n if (primaryEmail) subtitlePieces.push(String(primaryEmail))\n const primaryPhone = pickValue(entity, 'primary_phone', 'primaryPhone')\n if (primaryPhone) subtitlePieces.push(String(primaryPhone))\n const summary = snippet(\n (pickValue(entity, 'description') as string | undefined) ??\n (customFields.summary as string | undefined) ??\n (customFields.description as string | undefined),\n )\n if (summary) subtitlePieces.push(summary)\n return {\n title: String(title),\n subtitle: subtitlePieces.length ? subtitlePieces.join(' \u00B7 ') : undefined,\n icon: 'user',\n badge: pickValue(entity, 'display_name', 'displayName') ? 'Person' : undefined,\n }\n}\n\nfunction resolveCompanyPresenter(\n record: Record<string, unknown>,\n entity: Record<string, unknown> | null,\n customFields: Record<string, unknown>,\n): SearchResultPresenter {\n const fallbackEntityId = resolveCustomerEntityId(record)\n const title =\n (pickValue(entity, 'display_name', 'displayName') as string | undefined) ??\n (customFields.display_name as string | undefined) ??\n (customFields.displayName as string | undefined) ??\n (record.brand_name as string | undefined) ??\n (record.legal_name as string | undefined) ??\n (record.domain as string | undefined) ??\n (record.brandName as string | undefined) ??\n (record.legalName as string | undefined) ??\n (entity?.id && entity?.display_name ? entity.display_name as string : undefined) ??\n fallbackEntityId ??\n (record.id as string | undefined) ??\n 'Company'\n const subtitlePieces: string[] = []\n const industry = record.industry\n if (industry) subtitlePieces.push(String(industry))\n const sizeBucket = record.size_bucket ?? record.sizeBucket\n if (sizeBucket) subtitlePieces.push(String(sizeBucket))\n if (entity) {\n const primaryEmail = pickValue(entity, 'primary_email', 'primaryEmail')\n if (primaryEmail) subtitlePieces.push(String(primaryEmail))\n }\n const summary = snippet(\n (pickValue(entity, 'description') as string | undefined) ??\n (customFields.summary as string | undefined) ??\n (customFields.description as string | undefined) ??\n (record.summary as string | undefined) ??\n (record.description as string | undefined),\n )\n if (summary) subtitlePieces.push(summary)\n if (!entity && (!title || title === fallbackEntityId)) {\n logger.warn('Missing customer entity during company presenter build', {\n component: 'search',\n recordId: record.id ?? null,\n entityId: fallbackEntityId,\n recordKeys: Object.keys(record),\n })\n }\n return {\n title: String(title),\n subtitle: subtitlePieces.length ? subtitlePieces.join(' \u00B7 ') : undefined,\n icon: 'building',\n badge: pickValue(entity, 'display_name', 'displayName') ? 'Company' : undefined,\n }\n}\n\nfunction logMissingPresenterTitle(\n kind: 'person' | 'company',\n record: Record<string, unknown>,\n entity: Record<string, unknown> | null,\n presenter: SearchResultPresenter,\n) {\n const fallbackId = record.id ?? record.entity_id ?? resolveCustomerEntityId(record)\n if (!fallbackId) return\n if (presenter.title && presenter.title !== String(fallbackId)) return\n logger.warn('Presenter fell back to record id', {\n component: 'search',\n kind,\n recordId: fallbackId,\n entityId: resolveCustomerEntityId(record),\n hasEntityDisplayName: entity?.display_name != null,\n })\n}\n\n// =============================================================================\n// Search Module Configuration\n// =============================================================================\n\nexport const searchConfig: SearchModuleConfig = {\n entities: [\n // =========================================================================\n // Person Profile\n // =========================================================================\n {\n entityId: 'customers:customer_person_profile',\n enabled: true,\n priority: 10,\n\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n assertTenantContext(ctx)\n const lines: string[] = []\n const record = ctx.record\n appendLine(lines, 'Preferred name', record.preferred_name ?? record.preferredName ?? ctx.customFields.preferred_name)\n appendLine(lines, 'First name', record.first_name ?? record.firstName ?? ctx.customFields.first_name)\n appendLine(lines, 'Last name', record.last_name ?? record.lastName ?? ctx.customFields.last_name)\n appendLine(lines, 'Job title', record.job_title ?? record.jobTitle ?? ctx.customFields.job_title)\n appendLine(lines, 'Department', record.department ?? record.department_name ?? record.departmentName ?? ctx.customFields.department)\n appendLine(lines, 'Seniority', record.seniority ?? record.seniority_level ?? record.seniorityLevel ?? ctx.customFields.seniority)\n appendLine(lines, 'Timezone', record.timezone ?? record.time_zone ?? record.timeZone ?? ctx.customFields.timezone)\n appendLine(lines, 'LinkedIn', record.linked_in_url ?? record.linkedInUrl ?? ctx.customFields.linked_in_url)\n appendLine(lines, 'Twitter', record.twitter_url ?? record.twitterUrl ?? ctx.customFields.twitter_url)\n\n const { entity, entityId, profileCustomFields, entityCustomFields, entityOnlyCustomFields } =\n await hydrateProfileContext(ctx, 'person')\n appendCustomFieldLines(lines, profileCustomFields, 'Person custom')\n if (Object.keys(entityOnlyCustomFields).length) {\n appendCustomFieldLines(lines, entityOnlyCustomFields, 'Customer custom')\n }\n if (!entity) {\n logger.warn('Failed to load customer entity for person profile', {\n component: 'search',\n recordId: record.id,\n entityId,\n recordKeys: Object.keys(record),\n })\n }\n appendCustomerEntityLines(lines, entity, 'Customer')\n ensureFallbackLines(lines, record)\n if (!lines.length) return null\n\n if (!entityId) {\n logger.warn('Person profile missing entity id', {\n component: 'search',\n recordId: record.id,\n recordKeys: Object.keys(record),\n })\n }\n\n const presenter = resolvePersonPresenter(record, entity, ctx.customFields)\n logMissingPresenterTitle('person', record, entity, presenter)\n const presenterLabel = pickLabel(presenter.title) ?? 'Open person'\n const links: SearchResultLink[] = []\n if (entityId) {\n const href = buildCustomerUrl('person', entityId)\n if (href) {\n links.push({ href, label: presenterLabel, kind: 'primary' })\n }\n }\n\n return {\n text: lines,\n presenter,\n links,\n checksumSource: {\n record: ctx.record,\n customFields: profileCustomFields,\n entity,\n entityCustomFields,\n },\n }\n },\n\n formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {\n assertTenantContext(ctx)\n const entity = await getCustomerEntity(ctx, resolveCustomerEntityId(ctx.record))\n return resolvePersonPresenter(ctx.record, entity, ctx.customFields)\n },\n\n resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {\n const entityId = resolveCustomerEntityId(ctx.record)\n return buildCustomerUrl('person', entityId)\n },\n\n resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {\n const entityId = resolveCustomerEntityId(ctx.record)\n if (!entityId) return null\n const href = buildCustomerUrl('person', entityId)\n if (!href) return null\n return [{ href: `${href}/edit`, label: 'Edit', kind: 'secondary' }]\n },\n\n fieldPolicy: {\n searchable: [\n 'preferred_name',\n 'first_name',\n 'last_name',\n 'job_title',\n 'department',\n 'seniority',\n 'timezone',\n 'linked_in_url',\n 'twitter_url',\n ],\n hashOnly: ['primary_email', 'primary_phone', 'personal_email'],\n excluded: ['date_of_birth', 'government_id', 'ssn', 'tax_id'],\n },\n aclFeatures: ['customers.people.view'],\n },\n\n // =========================================================================\n // Company Profile\n // =========================================================================\n {\n entityId: 'customers:customer_company_profile',\n enabled: true,\n priority: 10,\n\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n assertTenantContext(ctx)\n const lines: string[] = []\n const record = ctx.record\n appendLine(lines, 'Legal name', record.legal_name ?? record.legalName ?? ctx.customFields.legal_name)\n appendLine(lines, 'Brand name', record.brand_name ?? record.brandName ?? ctx.customFields.brand_name)\n appendLine(lines, 'Domain', record.domain ?? record.website_domain ?? record.websiteDomain ?? ctx.customFields.domain)\n appendLine(lines, 'Website', record.website_url ?? record.websiteUrl ?? ctx.customFields.website_url)\n appendLine(lines, 'Industry', record.industry ?? ctx.customFields.industry)\n appendLine(lines, 'Company size', record.size_bucket ?? record.sizeBucket ?? ctx.customFields.size_bucket)\n appendLine(lines, 'Annual revenue', record.annual_revenue ?? record.annualRevenue ?? ctx.customFields.annual_revenue)\n\n const { entity, entityId, profileCustomFields, entityCustomFields, entityOnlyCustomFields } =\n await hydrateProfileContext(ctx, 'company')\n appendCustomFieldLines(lines, profileCustomFields, 'Company custom')\n if (Object.keys(entityOnlyCustomFields).length) {\n appendCustomFieldLines(lines, entityOnlyCustomFields, 'Customer custom')\n }\n appendCustomerEntityLines(lines, entity, 'Primary')\n ensureFallbackLines(lines, record)\n if (!lines.length) return null\n\n const presenter = resolveCompanyPresenter(record, entity, ctx.customFields)\n logMissingPresenterTitle('company', record, entity, presenter)\n const primaryLabel = pickLabel(presenter.title) ?? 'Open company'\n const links: SearchResultLink[] = []\n if (entityId) {\n const href = buildCustomerUrl('company', entityId)\n if (href) {\n links.push({ href, label: primaryLabel, kind: 'primary' })\n }\n }\n\n return {\n text: lines,\n presenter,\n links,\n checksumSource: {\n record: ctx.record,\n customFields: profileCustomFields,\n entity,\n entityCustomFields,\n },\n }\n },\n\n formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {\n assertTenantContext(ctx)\n const entity = await getCustomerEntity(ctx, resolveCustomerEntityId(ctx.record))\n return resolveCompanyPresenter(ctx.record, entity, ctx.customFields)\n },\n\n resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {\n const entityId = resolveCustomerEntityId(ctx.record)\n return buildCustomerUrl('company', entityId)\n },\n\n resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {\n const entityId = resolveCustomerEntityId(ctx.record)\n if (!entityId) return null\n const href = buildCustomerUrl('company', entityId)\n if (!href) return null\n return [{ href: `${href}/edit`, label: 'Edit', kind: 'secondary' }]\n },\n\n fieldPolicy: {\n searchable: [\n 'legal_name',\n 'brand_name',\n 'display_name',\n 'domain',\n 'website_url',\n 'industry',\n 'size_bucket',\n 'description',\n ],\n hashOnly: ['tax_id', 'registration_number'],\n excluded: ['bank_account', 'billing_info', 'credit_info'],\n },\n aclFeatures: ['customers.companies.view'],\n },\n\n // =========================================================================\n // Customer Comment\n // =========================================================================\n {\n entityId: 'customers:customer_comment',\n enabled: true,\n priority: 6,\n\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n assertTenantContext(ctx)\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const lines: string[] = []\n if (parent?.display_name) lines.push(`Customer: ${parent.display_name}`)\n lines.push(`Note: ${ctx.record.body ?? ''}`)\n if (ctx.record.appearance_icon) lines.push(`Icon: ${ctx.record.appearance_icon}`)\n if (ctx.record.appearance_color) lines.push(`Color: ${ctx.record.appearance_color}`)\n\n const presenter: SearchResultPresenter | undefined = parent?.display_name\n ? {\n title: parent.display_name as string,\n subtitle: snippet(ctx.record.body),\n icon: parent.kind === 'person' ? 'user' : 'building',\n }\n : undefined\n\n return {\n text: lines,\n presenter,\n checksumSource: {\n body: ctx.record.body,\n entityId: ctx.record.entity_id ?? null,\n updatedAt: ctx.record.updated_at ?? ctx.record.updatedAt ?? null,\n },\n }\n },\n\n formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {\n assertTenantContext(ctx)\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const title = (parent?.display_name as string | undefined) ?? 'Customer note'\n return {\n title,\n subtitle: snippet(ctx.record.body),\n icon: 'sticky-note',\n }\n },\n\n resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {\n assertTenantContext(ctx)\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const base = buildCustomerUrl(parent?.kind as string ?? null, (parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId) as string)\n return base ? `${base}#notes` : null\n },\n\n resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {\n assertTenantContext(ctx)\n const links: SearchResultLink[] = []\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const parentUrl = buildCustomerUrl(parent?.kind as string ?? null, (parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId) as string)\n if (parentUrl) {\n links.push({ href: parentUrl, label: (parent?.display_name as string | undefined) ?? 'View customer', kind: 'primary' })\n }\n if (ctx.record.deal_id) {\n const dealUrl = `/backend/customers/deals/${encodeURIComponent(ctx.record.deal_id as string)}`\n links.push({ href: dealUrl, label: 'Open deal', kind: 'secondary' })\n }\n return links.length ? links : null\n },\n\n fieldPolicy: {\n searchable: ['body'],\n hashOnly: [],\n excluded: [],\n },\n aclFeatures: ['customers.activities.view'],\n },\n\n // =========================================================================\n // Customer Deal\n // =========================================================================\n {\n entityId: 'customers:customer_deal',\n enabled: true,\n priority: 8,\n\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n const lines: string[] = []\n const record = ctx.record\n appendLine(lines, 'Title', record.title)\n appendLine(lines, 'Stage', record.pipeline_stage)\n appendLine(lines, 'Status', record.status)\n appendLine(lines, 'Source', record.source)\n const value = formatDealValue(record)\n if (value) appendLine(lines, 'Value', value)\n if (!lines.length) return null\n\n const subtitleParts: string[] = []\n if (record.pipeline_stage) subtitleParts.push(String(record.pipeline_stage))\n if (record.status) subtitleParts.push(String(record.status))\n if (value) subtitleParts.push(value)\n\n return {\n text: lines,\n presenter: {\n title: String(record.title ?? 'Deal'),\n subtitle: subtitleParts.join(' \u00B7 ') || undefined,\n icon: 'briefcase',\n badge: 'Deal',\n },\n checksumSource: {\n title: record.title,\n status: record.status,\n stage: record.pipeline_stage,\n value: value,\n },\n }\n },\n\n formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {\n const { record } = ctx\n const title = pickString(record.title as string, 'Deal')\n const subtitleParts: string[] = []\n if (record.pipeline_stage) subtitleParts.push(String(record.pipeline_stage))\n if (record.status) subtitleParts.push(String(record.status))\n const amount = record.value_amount ?? record.valueAmount\n const currency = record.value_currency ?? record.valueCurrency\n if (amount) {\n subtitleParts.push(currency ? `${amount} ${currency}` : String(amount))\n }\n\n return {\n title: title ?? 'Deal',\n subtitle: subtitleParts.length ? subtitleParts.join(' \u00B7 ') : undefined,\n icon: 'briefcase',\n badge: 'Deal',\n }\n },\n\n resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {\n const id = ctx.record.id\n if (!id) return null\n return `/backend/customers/deals/${encodeURIComponent(String(id))}`\n },\n\n resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {\n const id = ctx.record.id\n if (!id) return null\n return [\n {\n href: `/backend/customers/deals/${encodeURIComponent(String(id))}/edit`,\n label: 'Edit',\n kind: 'secondary',\n },\n ]\n },\n\n fieldPolicy: {\n searchable: ['title', 'description', 'pipeline_stage', 'status', 'source'],\n hashOnly: [],\n excluded: ['value_amount', 'value_currency'],\n },\n aclFeatures: ['customers.deals.view'],\n },\n\n // =========================================================================\n // Customer Activity\n // =========================================================================\n {\n entityId: 'customers:customer_activity',\n enabled: true,\n priority: 5,\n\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n assertTenantContext(ctx)\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const lines: string[] = []\n if (parent?.display_name) lines.push(`Customer: ${parent.display_name}`)\n if (ctx.record.activity_type) lines.push(`Type: ${ctx.record.activity_type}`)\n if (ctx.record.subject) lines.push(`Subject: ${ctx.record.subject}`)\n if (ctx.record.body) lines.push(`Body: ${ctx.record.body}`)\n\n const presenter: SearchResultPresenter = {\n title: ctx.record.subject ? String(ctx.record.subject) : `Activity: ${ctx.record.activity_type ?? 'update'}`,\n subtitle: (parent?.display_name as string | undefined) ?? snippet(ctx.record.body),\n icon: 'bolt',\n }\n\n return {\n text: lines,\n presenter,\n checksumSource: {\n subject: ctx.record.subject,\n body: ctx.record.body,\n entityId: ctx.record.entity_id ?? null,\n updatedAt: ctx.record.updated_at ?? ctx.record.updatedAt ?? null,\n },\n }\n },\n\n formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {\n assertTenantContext(ctx)\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n return {\n title: ctx.record.subject ? String(ctx.record.subject) : `Activity: ${ctx.record.activity_type ?? 'update'}`,\n subtitle: (parent?.display_name as string | undefined) ?? snippet(ctx.record.body),\n icon: 'bolt',\n badge: 'Activity',\n }\n },\n\n resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {\n assertTenantContext(ctx)\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const base = buildCustomerUrl(parent?.kind as string ?? null, (parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId) as string)\n return base ? `${base}#activity-${ctx.record.id ?? ctx.record.activity_id ?? ''}` : null\n },\n\n resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {\n const links: SearchResultLink[] = []\n if (ctx.record.deal_id) {\n links.push({\n href: `/backend/customers/deals/${encodeURIComponent(ctx.record.deal_id as string)}`,\n label: 'Open deal',\n kind: 'secondary',\n })\n }\n return links.length ? links : null\n },\n\n fieldPolicy: {\n searchable: ['subject', 'body', 'activity_type'],\n hashOnly: [],\n excluded: [],\n },\n aclFeatures: ['customers.activities.view'],\n },\n\n // =========================================================================\n // Customer Todo Link\n // =========================================================================\n {\n entityId: 'customers:customer_todo_link',\n enabled: true,\n priority: 4,\n\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n assertTenantContext(ctx)\n const todo = await getLinkedTodo(ctx) as Record<string, unknown> | null\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const lines: string[] = []\n if (todo?.title) lines.push(`Todo: ${todo.title}`)\n if (todo?.is_done !== undefined) lines.push(`Status: ${todo.is_done ? 'Done' : 'Open'}`)\n if (parent?.display_name) lines.push(`Customer: ${parent.display_name}`)\n if (!lines.length) return null\n\n return {\n text: lines,\n presenter: todo?.title\n ? { title: todo.title as string, subtitle: parent?.display_name as string | undefined, icon: 'check-square' }\n : undefined,\n checksumSource: {\n todoId: ctx.record.todo_id ?? ctx.record.todoId,\n todoSource: ctx.record.todo_source ?? ctx.record.todoSource,\n entityId: ctx.record.entity_id ?? ctx.record.entityId,\n },\n }\n },\n\n formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {\n assertTenantContext(ctx)\n const todo = await getLinkedTodo(ctx) as Record<string, unknown> | null\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n return {\n title: (todo?.title as string | undefined) ?? 'Customer task',\n subtitle: parent?.display_name as string | undefined,\n icon: 'check-square',\n }\n },\n\n resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {\n assertTenantContext(ctx)\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const base = buildCustomerUrl(parent?.kind as string ?? null, (parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId) as string)\n return base ? `${base}#tasks` : null\n },\n\n resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {\n const todoId = ctx.record.todo_id ?? ctx.record.todoId\n if (!todoId) return null\n return [{\n href: `/backend/todos/${encodeURIComponent(todoId as string)}/edit`,\n label: 'Open todo',\n kind: 'secondary',\n }]\n },\n\n fieldPolicy: {\n searchable: [],\n hashOnly: [],\n excluded: [],\n },\n aclFeatures: ['customers.activities.view'],\n },\n ],\n}\n\nexport default searchConfig\nexport const config = searchConfig\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { QueryCustomFieldSource, QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport type {\n SearchModuleConfig,\n SearchBuildContext,\n SearchResultPresenter,\n SearchResultLink,\n SearchIndexSource,\n} from '@open-mercato/shared/modules/search'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CUSTOMER_INTERACTION_TASK_SOURCE, EXAMPLE_TODO_SOURCE } from './lib/interactionCompatibility'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('customers')\n\n// =============================================================================\n// Context Types\n// =============================================================================\n\ntype SearchContext = SearchBuildContext & {\n tenantId: string\n queryEngine?: QueryEngine\n}\n\nfunction assertTenantContext(ctx: SearchBuildContext): asserts ctx is SearchContext {\n if (typeof ctx.tenantId !== 'string' || ctx.tenantId.length === 0) {\n throw new Error('[search.customers] Missing tenantId in search build context')\n }\n}\n\ntype CustomerProfileKind = 'person' | 'company'\n\ntype LoadedCustomerEntity = {\n entity: Record<string, unknown> | null\n customFields: Record<string, unknown>\n}\n\n// =============================================================================\n// Caching\n// =============================================================================\n\nconst entityIdCache = new Map<string, LoadedCustomerEntity | null>()\nconst profileEntityCache = new WeakMap<Record<string, unknown>, Partial<Record<CustomerProfileKind, LoadedCustomerEntity | null>>>()\nconst todoCache = new WeakMap<Record<string, unknown>, unknown>()\n\n// =============================================================================\n// Query Configuration\n// =============================================================================\n\nconst CUSTOMER_ENTITY_FIELDS = [\n 'id',\n 'kind',\n 'display_name',\n 'description',\n 'primary_email',\n 'primary_phone',\n 'status',\n 'lifecycle_stage',\n 'owner_user_id',\n 'source',\n 'next_interaction_at',\n 'next_interaction_name',\n 'next_interaction_ref_id',\n 'next_interaction_icon',\n 'next_interaction_color',\n 'organization_id',\n 'tenant_id',\n 'created_at',\n 'updated_at',\n 'deleted_at',\n] satisfies string[]\n\nconst CUSTOMER_CUSTOM_FIELD_SOURCES: QueryCustomFieldSource[] = [\n {\n entityId: 'customers:customer_person_profile',\n table: 'customer_people',\n alias: 'person_profile',\n recordIdColumn: 'id',\n join: { fromField: 'id', toField: 'entity_id' },\n },\n {\n entityId: 'customers:customer_company_profile',\n table: 'customer_companies',\n alias: 'company_profile',\n recordIdColumn: 'id',\n join: { fromField: 'id', toField: 'entity_id' },\n },\n]\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\nfunction extractCustomFieldMap(source: Record<string, unknown> | null | undefined): Record<string, unknown> {\n if (!source) return {}\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(source)) {\n if (value === undefined) continue\n if (key.startsWith('cf:')) {\n result[key.slice(3)] = value\n } else if (key.startsWith('cf_')) {\n result[key.slice(3)] = value\n }\n }\n return result\n}\n\nfunction normalizeCustomerEntity(row: Record<string, unknown>): Record<string, unknown> {\n const normalized: Record<string, unknown> = {\n id: row.id ?? row.entity_id ?? row.entityId ?? null,\n kind: row.kind ?? null,\n }\n const assign = (snake: string, camel?: string) => {\n const value = row[snake] ?? (camel ? row[camel] : undefined)\n if (value !== undefined) {\n normalized[snake] = value\n if (camel) normalized[camel] = value\n }\n }\n assign('display_name', 'displayName')\n assign('description')\n assign('primary_email', 'primaryEmail')\n assign('primary_phone', 'primaryPhone')\n assign('status')\n assign('lifecycle_stage', 'lifecycleStage')\n assign('owner_user_id', 'ownerUserId')\n assign('source')\n assign('next_interaction_at', 'nextInteractionAt')\n assign('next_interaction_name', 'nextInteractionName')\n assign('next_interaction_ref_id', 'nextInteractionRefId')\n assign('next_interaction_icon', 'nextInteractionIcon')\n assign('next_interaction_color', 'nextInteractionColor')\n assign('organization_id', 'organizationId')\n assign('tenant_id', 'tenantId')\n assign('created_at', 'createdAt')\n assign('updated_at', 'updatedAt')\n assign('deleted_at', 'deletedAt')\n return normalized\n}\n\nfunction getProfileCache(record: Record<string, unknown>): Partial<Record<CustomerProfileKind, LoadedCustomerEntity | null>> {\n let cache = profileEntityCache.get(record)\n if (!cache) {\n cache = {}\n profileEntityCache.set(record, cache)\n }\n return cache\n}\n\nfunction subtractCustomFields(\n primary: Record<string, unknown>,\n secondary: Record<string, unknown>,\n): Record<string, unknown> {\n if (!secondary || Object.keys(secondary).length === 0) return {}\n const primaryKeys = new Set(Object.keys(primary))\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(secondary)) {\n if (!primaryKeys.has(key)) {\n result[key] = value\n }\n }\n return result\n}\n\n// =============================================================================\n// Entity Loading Functions\n// =============================================================================\n\ntype CustomerEntityQueryOptions = {\n entityId?: string | null\n profileKind?: CustomerProfileKind\n profileId?: string | null\n}\n\nasync function loadCustomerEntityBundle(ctx: SearchContext, opts: CustomerEntityQueryOptions): Promise<LoadedCustomerEntity | null> {\n if (!ctx.queryEngine) return null\n const filters: Record<string, unknown> = {}\n const resolvedEntityId = typeof opts.entityId === 'string' && opts.entityId.length ? opts.entityId : null\n const resolvedProfileId =\n opts.profileId != null && String(opts.profileId).trim().length > 0 ? String(opts.profileId).trim() : null\n const shouldJoinProfileSource = Boolean(opts.profileKind && resolvedProfileId && !resolvedEntityId)\n if (resolvedEntityId) {\n filters.id = { $eq: resolvedEntityId }\n }\n if (shouldJoinProfileSource) {\n const alias = opts.profileKind === 'person' ? 'person_profile' : 'company_profile'\n filters[`${alias}.id`] = { $eq: resolvedProfileId }\n }\n if (!Object.keys(filters).length) return null\n try {\n const result = await ctx.queryEngine.query('customers:customer_entity', {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId ?? undefined,\n filters,\n includeCustomFields: true,\n ...(shouldJoinProfileSource ? { customFieldSources: CUSTOMER_CUSTOM_FIELD_SOURCES } : {}),\n fields: CUSTOMER_ENTITY_FIELDS,\n page: { page: 1, pageSize: 1 },\n })\n const row = result.items[0] as Record<string, unknown> | undefined\n if (!row) return null\n const entity = normalizeCustomerEntity(row)\n const customFields = extractCustomFieldMap(row)\n return { entity, customFields }\n } catch (error) {\n logger.warn('Failed to load customer entity via QueryEngine', {\n component: 'search',\n entityId: resolvedEntityId ?? null,\n profileKind: opts.profileKind ?? null,\n profileId: resolvedProfileId ?? null,\n err: error,\n })\n return null\n }\n}\n\nasync function loadCustomerEntityForProfile(ctx: SearchContext, kind: CustomerProfileKind): Promise<LoadedCustomerEntity | null> {\n const cache = getProfileCache(ctx.record)\n if (cache[kind] !== undefined) return cache[kind] ?? null\n const entityIdHint = resolveCustomerEntityId(ctx.record)\n const profileIdRaw = ctx.record.id ?? null\n const profileId = profileIdRaw != null ? String(profileIdRaw) : null\n if (!entityIdHint && !profileId) {\n cache[kind] = null\n return null\n }\n const loaded = await loadCustomerEntityBundle(ctx, {\n entityId: entityIdHint,\n profileKind: kind,\n profileId,\n })\n cache[kind] = loaded ?? null\n const resolvedId = loaded?.entity?.id ?? entityIdHint\n if (resolvedId && typeof resolvedId === 'string') {\n ctx.record.entity_id ??= resolvedId\n ctx.record.entityId ??= resolvedId\n entityIdCache.set(resolvedId, loaded ?? null)\n }\n if (loaded?.entity) {\n if (!ctx.record.entity) ctx.record.entity = loaded.entity\n if (!ctx.record.customer_entity) ctx.record.customer_entity = loaded.entity\n }\n return loaded ?? null\n}\n\nasync function loadCustomerEntityById(ctx: SearchContext, entityId: string | null | undefined): Promise<LoadedCustomerEntity | null> {\n const resolvedId = typeof entityId === 'string' && entityId.length ? entityId : null\n if (!resolvedId) return null\n if (entityIdCache.has(resolvedId)) {\n return entityIdCache.get(resolvedId) ?? null\n }\n const loaded = await loadCustomerEntityBundle(ctx, { entityId: resolvedId })\n entityIdCache.set(resolvedId, loaded ?? null)\n return loaded ?? null\n}\n\nasync function getCustomerEntity(ctx: SearchContext, entityId?: string | null): Promise<Record<string, unknown> | null> {\n const profileCache = profileEntityCache.get(ctx.record)\n if (profileCache) {\n const cached = Object.values(profileCache).find((entry) => {\n if (!entry?.entity) return false\n if (!entityId) return true\n return entry.entity.id === entityId\n })\n if (cached?.entity) return cached.entity\n }\n const inline = getInlineCustomerEntity(ctx.record)\n if (inline && (!entityId || inline.id === entityId)) {\n if (inline.id && typeof inline.id === 'string') {\n entityIdCache.set(inline.id, { entity: inline, customFields: {} })\n }\n return inline\n }\n const resolvedId = entityId ?? resolveCustomerEntityId(ctx.record)\n const loaded = await loadCustomerEntityById(ctx, resolvedId)\n return loaded?.entity ?? null\n}\n\ntype HydratedProfileContext = {\n entity: Record<string, unknown> | null\n entityId: string | null\n profileCustomFields: Record<string, unknown>\n entityCustomFields: Record<string, unknown>\n entityOnlyCustomFields: Record<string, unknown>\n}\n\nasync function hydrateProfileContext(ctx: SearchContext, kind: CustomerProfileKind): Promise<HydratedProfileContext> {\n const profileCustomFields = ctx.customFields ?? {}\n const loaded = await loadCustomerEntityForProfile(ctx, kind)\n let entity = loaded?.entity ?? getInlineCustomerEntity(ctx.record)\n let entityCustomFields = loaded?.customFields ?? {}\n let entityId = (entity?.id as string | undefined) ?? resolveCustomerEntityId(ctx.record)\n if (!entity && entityId) {\n const fetched = await loadCustomerEntityById(ctx, entityId)\n entity = fetched?.entity ?? null\n if (fetched?.customFields) {\n entityCustomFields = Object.keys(entityCustomFields).length ? entityCustomFields : fetched.customFields\n }\n }\n if (!entity && !entityId) {\n entityId = resolveCustomerEntityId(ctx.record)\n }\n if (entity?.id && typeof entity.id === 'string') {\n entityId = entity.id\n ctx.record.entity_id ??= entity.id\n ctx.record.entityId ??= entity.id\n if (!ctx.record.entity) ctx.record.entity = entity\n if (!ctx.record.customer_entity) ctx.record.customer_entity = entity\n }\n const entityOnlyCustomFields = subtractCustomFields(profileCustomFields, entityCustomFields)\n return {\n entity: entity ?? null,\n entityId: entityId ?? null,\n profileCustomFields,\n entityCustomFields,\n entityOnlyCustomFields,\n }\n}\n\nasync function loadRecord(ctx: SearchContext, entityId: string, recordId?: string | null) {\n if (!recordId || !ctx.queryEngine) return null\n const res = await ctx.queryEngine.query(entityId, {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId ?? undefined,\n filters: { id: recordId },\n includeCustomFields: true,\n page: { page: 1, pageSize: 1 },\n })\n return res.items[0] as Record<string, unknown> | undefined\n}\n\nfunction resolveCustomerEntityId(record: Record<string, unknown>): string | null {\n const direct =\n record.customer_entity_id ??\n record.entityId ??\n record.entity_id ??\n record.customerEntityId ??\n record.customerEntityID ??\n (typeof record.entity === 'object' && record.entity ? (record.entity as Record<string, unknown>).id : undefined) ??\n (typeof record.customer_entity === 'object' && record.customer_entity ? (record.customer_entity as Record<string, unknown>).id : undefined)\n const value = typeof direct === 'string' && direct.length ? direct : null\n return value\n}\n\nfunction getInlineCustomerEntity(record: Record<string, unknown>): Record<string, unknown> | null {\n const inline =\n (typeof record.entity === 'object' && record.entity) ||\n (typeof record.customer_entity === 'object' && record.customer_entity) ||\n null\n return inline as Record<string, unknown> | null\n}\n\nasync function getLinkedTodo(ctx: SearchContext) {\n if (todoCache.has(ctx.record)) {\n return todoCache.get(ctx.record)\n }\n const sourceRaw = typeof ctx.record.todo_source === 'string' ? ctx.record.todo_source : EXAMPLE_TODO_SOURCE\n const [moduleId, entityName] = sourceRaw.split(':')\n const entityId = moduleId && entityName ? `${moduleId}:${entityName}` : CUSTOMER_INTERACTION_TASK_SOURCE\n const todo = await loadRecord(ctx, entityId, ctx.record.todo_id as string ?? ctx.record.todoId as string)\n todoCache.set(ctx.record, todo ?? null)\n return todo ?? null\n}\n\n// =============================================================================\n// URL and Formatting Helpers\n// =============================================================================\n\nfunction buildCustomerUrl(kind: string | null | undefined, id?: string | null): string | null {\n if (!id) return null\n const encoded = encodeURIComponent(id)\n if (kind === 'person') return `/backend/customers/people-v2/${encoded}`\n if (kind === 'company') return `/backend/customers/companies-v2/${encoded}`\n return `/backend/customers/companies-v2/${encoded}`\n}\n\nfunction formatDealValue(record: Record<string, unknown>): string | undefined {\n const amount = record.value_amount ?? record.valueAmount\n if (!amount) return undefined\n const currency = record.value_currency ?? record.valueCurrency ?? ''\n return currency ? `${amount} ${currency}` : String(amount)\n}\n\nfunction snippet(text: unknown, max = 140): string | undefined {\n if (typeof text !== 'string') return undefined\n const trimmed = text.trim()\n if (!trimmed.length) return undefined\n if (trimmed.length <= max) return trimmed\n return `${trimmed.slice(0, max - 3)}...`\n}\n\nfunction appendLine(lines: string[], label: string, value: unknown) {\n if (value === null || value === undefined) return\n const text = Array.isArray(value)\n ? value.map((item) => (item === null || item === undefined ? '' : String(item))).filter(Boolean).join(', ')\n : (typeof value === 'object' ? JSON.stringify(value) : String(value))\n if (!text.trim()) return\n lines.push(`${label}: ${text}`)\n}\n\nfunction friendlyLabel(input: string): string {\n return input\n .replace(/^cf:/, '')\n .replace(/_/g, ' ')\n .replace(/([a-z])([A-Z])/g, (_, a, b) => `${a} ${b}`)\n .replace(/\\b\\w/g, (char) => char.toUpperCase())\n}\n\nfunction appendCustomFieldLines(lines: string[], customFields: Record<string, unknown>, prefix: string) {\n for (const [key, value] of Object.entries(customFields)) {\n if (value === null || value === undefined) continue\n const label = prefix ? `${prefix} ${friendlyLabel(key)}` : friendlyLabel(key)\n appendLine(lines, label, value)\n }\n}\n\nfunction pickValue(source: Record<string, unknown> | null | undefined, ...keys: string[]): unknown {\n if (!source) return undefined\n for (const key of keys) {\n if (key in source && source[key] != null) return source[key]\n }\n return undefined\n}\n\nfunction pickString(...candidates: unknown[]): string | null {\n for (const candidate of candidates) {\n if (typeof candidate === 'string' && candidate.trim().length) {\n return candidate.trim()\n }\n }\n return null\n}\n\nfunction pickLabel(...candidates: Array<unknown>): string | null {\n for (const candidate of candidates) {\n if (candidate === null || candidate === undefined) continue\n const value = typeof candidate === 'string' ? candidate : String(candidate)\n const trimmed = value.trim()\n if (trimmed.length) return trimmed\n }\n return null\n}\n\nfunction appendCustomerEntityLines(\n lines: string[],\n entity: Record<string, unknown> | null,\n contactLabel: 'Customer' | 'Primary' = 'Customer',\n) {\n if (!entity) return\n appendLine(lines, 'Customer', pickValue(entity, 'display_name', 'displayName') ?? entity.id)\n appendLine(lines, `${contactLabel} email`, pickValue(entity, 'primary_email', 'primaryEmail'))\n appendLine(lines, `${contactLabel} phone`, pickValue(entity, 'primary_phone', 'primaryPhone'))\n appendLine(lines, 'Lifecycle stage', pickValue(entity, 'lifecycle_stage', 'lifecycleStage'))\n appendLine(lines, 'Status', pickValue(entity, 'status'))\n}\n\nfunction ensureFallbackLines(lines: string[], record: Record<string, unknown>, options: { includeId?: boolean } = {}) {\n if (lines.length) return\n const excluded = new Set(['tenant_id', 'organization_id', 'created_at', 'updated_at', 'deleted_at'])\n for (const [key, value] of Object.entries(record)) {\n if (value === null || value === undefined) continue\n if (excluded.has(key)) continue\n if (key === 'id') continue\n appendLine(lines, friendlyLabel(key), value)\n }\n if (!lines.length && options.includeId !== false) {\n const fallbackId =\n record.id ??\n record.entity_id ??\n record.customer_entity_id ??\n record.entityId ??\n record.customerEntityId ??\n null\n if (fallbackId) {\n appendLine(lines, 'Record ID', fallbackId)\n }\n }\n}\n\n// =============================================================================\n// Presenter Functions\n// =============================================================================\n\nfunction resolvePersonPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n entity: Record<string, unknown> | null,\n customFields: Record<string, unknown>,\n): SearchResultPresenter {\n const fallbackEntityId = resolveCustomerEntityId(record)\n const firstName = record.first_name ?? record.firstName ?? customFields.first_name ?? customFields.firstName ?? ''\n const lastName = record.last_name ?? record.lastName ?? customFields.last_name ?? customFields.lastName ?? ''\n const nameParts = [firstName, lastName].filter(Boolean).join(' ')\n const title =\n (pickValue(entity, 'display_name', 'displayName') as string | undefined) ??\n (record.preferred_name as string | undefined) ??\n (record.preferredName as string | undefined) ??\n (nameParts.length ? nameParts : undefined) ??\n fallbackEntityId ??\n (record.id as string | undefined) ??\n translate('customers.search.fallback.person', 'Person')\n const subtitlePieces: string[] = []\n const jobTitle = record.job_title ?? record.jobTitle ?? customFields.job_title ?? customFields.jobTitle\n if (jobTitle) subtitlePieces.push(String(jobTitle))\n const department = record.department ?? customFields.department\n if (department) subtitlePieces.push(String(department))\n const primaryEmail = pickValue(entity, 'primary_email', 'primaryEmail')\n if (primaryEmail) subtitlePieces.push(String(primaryEmail))\n const primaryPhone = pickValue(entity, 'primary_phone', 'primaryPhone')\n if (primaryPhone) subtitlePieces.push(String(primaryPhone))\n const summary = snippet(\n (pickValue(entity, 'description') as string | undefined) ??\n (customFields.summary as string | undefined) ??\n (customFields.description as string | undefined),\n )\n if (summary) subtitlePieces.push(summary)\n return {\n title: String(title),\n subtitle: subtitlePieces.length ? subtitlePieces.join(' \u00B7 ') : undefined,\n icon: 'user',\n badge: pickValue(entity, 'display_name', 'displayName')\n ? translate('customers.search.badge.person', 'Person')\n : undefined,\n }\n}\n\nfunction resolveCompanyPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n entity: Record<string, unknown> | null,\n customFields: Record<string, unknown>,\n): SearchResultPresenter {\n const fallbackEntityId = resolveCustomerEntityId(record)\n const title =\n (pickValue(entity, 'display_name', 'displayName') as string | undefined) ??\n (customFields.display_name as string | undefined) ??\n (customFields.displayName as string | undefined) ??\n (record.brand_name as string | undefined) ??\n (record.legal_name as string | undefined) ??\n (record.domain as string | undefined) ??\n (record.brandName as string | undefined) ??\n (record.legalName as string | undefined) ??\n (entity?.id && entity?.display_name ? entity.display_name as string : undefined) ??\n fallbackEntityId ??\n (record.id as string | undefined) ??\n translate('customers.search.fallback.company', 'Company')\n const subtitlePieces: string[] = []\n const industry = record.industry\n if (industry) subtitlePieces.push(String(industry))\n const sizeBucket = record.size_bucket ?? record.sizeBucket\n if (sizeBucket) subtitlePieces.push(String(sizeBucket))\n if (entity) {\n const primaryEmail = pickValue(entity, 'primary_email', 'primaryEmail')\n if (primaryEmail) subtitlePieces.push(String(primaryEmail))\n }\n const summary = snippet(\n (pickValue(entity, 'description') as string | undefined) ??\n (customFields.summary as string | undefined) ??\n (customFields.description as string | undefined) ??\n (record.summary as string | undefined) ??\n (record.description as string | undefined),\n )\n if (summary) subtitlePieces.push(summary)\n if (!entity && (!title || title === fallbackEntityId)) {\n logger.warn('Missing customer entity during company presenter build', {\n component: 'search',\n recordId: record.id ?? null,\n entityId: fallbackEntityId,\n recordKeys: Object.keys(record),\n })\n }\n return {\n title: String(title),\n subtitle: subtitlePieces.length ? subtitlePieces.join(' \u00B7 ') : undefined,\n icon: 'building',\n badge: pickValue(entity, 'display_name', 'displayName')\n ? translate('customers.search.badge.company', 'Company')\n : undefined,\n }\n}\n\nfunction logMissingPresenterTitle(\n kind: 'person' | 'company',\n record: Record<string, unknown>,\n entity: Record<string, unknown> | null,\n presenter: SearchResultPresenter,\n) {\n const fallbackId = record.id ?? record.entity_id ?? resolveCustomerEntityId(record)\n if (!fallbackId) return\n if (presenter.title && presenter.title !== String(fallbackId)) return\n logger.warn('Presenter fell back to record id', {\n component: 'search',\n kind,\n recordId: fallbackId,\n entityId: resolveCustomerEntityId(record),\n hasEntityDisplayName: entity?.display_name != null,\n })\n}\n\n// =============================================================================\n// Search Module Configuration\n// =============================================================================\n\nexport const searchConfig: SearchModuleConfig = {\n entities: [\n // =========================================================================\n // Person Profile\n // =========================================================================\n {\n entityId: 'customers:customer_person_profile',\n enabled: true,\n priority: 10,\n\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n assertTenantContext(ctx)\n const { t } = await resolveTranslations()\n const lines: string[] = []\n const record = ctx.record\n appendLine(lines, 'Preferred name', record.preferred_name ?? record.preferredName ?? ctx.customFields.preferred_name)\n appendLine(lines, 'First name', record.first_name ?? record.firstName ?? ctx.customFields.first_name)\n appendLine(lines, 'Last name', record.last_name ?? record.lastName ?? ctx.customFields.last_name)\n appendLine(lines, 'Job title', record.job_title ?? record.jobTitle ?? ctx.customFields.job_title)\n appendLine(lines, 'Department', record.department ?? record.department_name ?? record.departmentName ?? ctx.customFields.department)\n appendLine(lines, 'Seniority', record.seniority ?? record.seniority_level ?? record.seniorityLevel ?? ctx.customFields.seniority)\n appendLine(lines, 'Timezone', record.timezone ?? record.time_zone ?? record.timeZone ?? ctx.customFields.timezone)\n appendLine(lines, 'LinkedIn', record.linked_in_url ?? record.linkedInUrl ?? ctx.customFields.linked_in_url)\n appendLine(lines, 'Twitter', record.twitter_url ?? record.twitterUrl ?? ctx.customFields.twitter_url)\n\n const { entity, entityId, profileCustomFields, entityCustomFields, entityOnlyCustomFields } =\n await hydrateProfileContext(ctx, 'person')\n appendCustomFieldLines(lines, profileCustomFields, 'Person custom')\n if (Object.keys(entityOnlyCustomFields).length) {\n appendCustomFieldLines(lines, entityOnlyCustomFields, 'Customer custom')\n }\n if (!entity) {\n logger.warn('Failed to load customer entity for person profile', {\n component: 'search',\n recordId: record.id,\n entityId,\n recordKeys: Object.keys(record),\n })\n }\n appendCustomerEntityLines(lines, entity, 'Customer')\n ensureFallbackLines(lines, record)\n if (!lines.length) return null\n\n if (!entityId) {\n logger.warn('Person profile missing entity id', {\n component: 'search',\n recordId: record.id,\n recordKeys: Object.keys(record),\n })\n }\n\n const presenter = resolvePersonPresenter(t, record, entity, ctx.customFields)\n logMissingPresenterTitle('person', record, entity, presenter)\n const presenterLabel = pickLabel(presenter.title) ?? t('customers.search.link.openPerson', 'Open person')\n const links: SearchResultLink[] = []\n if (entityId) {\n const href = buildCustomerUrl('person', entityId)\n if (href) {\n links.push({ href, label: presenterLabel, kind: 'primary' })\n }\n }\n\n return {\n text: lines,\n presenter,\n links,\n checksumSource: {\n record: ctx.record,\n customFields: profileCustomFields,\n entity,\n entityCustomFields,\n },\n }\n },\n\n formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {\n assertTenantContext(ctx)\n const { t } = await resolveTranslations()\n const entity = await getCustomerEntity(ctx, resolveCustomerEntityId(ctx.record))\n return resolvePersonPresenter(t, ctx.record, entity, ctx.customFields)\n },\n\n resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {\n const entityId = resolveCustomerEntityId(ctx.record)\n return buildCustomerUrl('person', entityId)\n },\n\n resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {\n const { t } = await resolveTranslations()\n const entityId = resolveCustomerEntityId(ctx.record)\n if (!entityId) return null\n const href = buildCustomerUrl('person', entityId)\n if (!href) return null\n return [{ href: `${href}/edit`, label: t('customers.search.link.edit', 'Edit'), kind: 'secondary' }]\n },\n\n fieldPolicy: {\n searchable: [\n 'preferred_name',\n 'first_name',\n 'last_name',\n 'job_title',\n 'department',\n 'seniority',\n 'timezone',\n 'linked_in_url',\n 'twitter_url',\n ],\n hashOnly: ['primary_email', 'primary_phone', 'personal_email'],\n excluded: ['date_of_birth', 'government_id', 'ssn', 'tax_id'],\n },\n aclFeatures: ['customers.people.view'],\n },\n\n // =========================================================================\n // Company Profile\n // =========================================================================\n {\n entityId: 'customers:customer_company_profile',\n enabled: true,\n priority: 10,\n\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n assertTenantContext(ctx)\n const { t } = await resolveTranslations()\n const lines: string[] = []\n const record = ctx.record\n appendLine(lines, 'Legal name', record.legal_name ?? record.legalName ?? ctx.customFields.legal_name)\n appendLine(lines, 'Brand name', record.brand_name ?? record.brandName ?? ctx.customFields.brand_name)\n appendLine(lines, 'Domain', record.domain ?? record.website_domain ?? record.websiteDomain ?? ctx.customFields.domain)\n appendLine(lines, 'Website', record.website_url ?? record.websiteUrl ?? ctx.customFields.website_url)\n appendLine(lines, 'Industry', record.industry ?? ctx.customFields.industry)\n appendLine(lines, 'Company size', record.size_bucket ?? record.sizeBucket ?? ctx.customFields.size_bucket)\n appendLine(lines, 'Annual revenue', record.annual_revenue ?? record.annualRevenue ?? ctx.customFields.annual_revenue)\n\n const { entity, entityId, profileCustomFields, entityCustomFields, entityOnlyCustomFields } =\n await hydrateProfileContext(ctx, 'company')\n appendCustomFieldLines(lines, profileCustomFields, 'Company custom')\n if (Object.keys(entityOnlyCustomFields).length) {\n appendCustomFieldLines(lines, entityOnlyCustomFields, 'Customer custom')\n }\n appendCustomerEntityLines(lines, entity, 'Primary')\n ensureFallbackLines(lines, record)\n if (!lines.length) return null\n\n const presenter = resolveCompanyPresenter(t, record, entity, ctx.customFields)\n logMissingPresenterTitle('company', record, entity, presenter)\n const primaryLabel = pickLabel(presenter.title) ?? t('customers.search.link.openCompany', 'Open company')\n const links: SearchResultLink[] = []\n if (entityId) {\n const href = buildCustomerUrl('company', entityId)\n if (href) {\n links.push({ href, label: primaryLabel, kind: 'primary' })\n }\n }\n\n return {\n text: lines,\n presenter,\n links,\n checksumSource: {\n record: ctx.record,\n customFields: profileCustomFields,\n entity,\n entityCustomFields,\n },\n }\n },\n\n formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {\n assertTenantContext(ctx)\n const { t } = await resolveTranslations()\n const entity = await getCustomerEntity(ctx, resolveCustomerEntityId(ctx.record))\n return resolveCompanyPresenter(t, ctx.record, entity, ctx.customFields)\n },\n\n resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {\n const entityId = resolveCustomerEntityId(ctx.record)\n return buildCustomerUrl('company', entityId)\n },\n\n resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {\n const { t } = await resolveTranslations()\n const entityId = resolveCustomerEntityId(ctx.record)\n if (!entityId) return null\n const href = buildCustomerUrl('company', entityId)\n if (!href) return null\n return [{ href: `${href}/edit`, label: t('customers.search.link.edit', 'Edit'), kind: 'secondary' }]\n },\n\n fieldPolicy: {\n searchable: [\n 'legal_name',\n 'brand_name',\n 'display_name',\n 'domain',\n 'website_url',\n 'industry',\n 'size_bucket',\n 'description',\n ],\n hashOnly: ['tax_id', 'registration_number'],\n excluded: ['bank_account', 'billing_info', 'credit_info'],\n },\n aclFeatures: ['customers.companies.view'],\n },\n\n // =========================================================================\n // Customer Comment\n // =========================================================================\n {\n entityId: 'customers:customer_comment',\n enabled: true,\n priority: 6,\n\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n assertTenantContext(ctx)\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const lines: string[] = []\n if (parent?.display_name) lines.push(`Customer: ${parent.display_name}`)\n lines.push(`Note: ${ctx.record.body ?? ''}`)\n if (ctx.record.appearance_icon) lines.push(`Icon: ${ctx.record.appearance_icon}`)\n if (ctx.record.appearance_color) lines.push(`Color: ${ctx.record.appearance_color}`)\n\n const presenter: SearchResultPresenter | undefined = parent?.display_name\n ? {\n title: parent.display_name as string,\n subtitle: snippet(ctx.record.body),\n icon: parent.kind === 'person' ? 'user' : 'building',\n }\n : undefined\n\n return {\n text: lines,\n presenter,\n checksumSource: {\n body: ctx.record.body,\n entityId: ctx.record.entity_id ?? null,\n updatedAt: ctx.record.updated_at ?? ctx.record.updatedAt ?? null,\n },\n }\n },\n\n formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {\n assertTenantContext(ctx)\n const { t } = await resolveTranslations()\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const title = (parent?.display_name as string | undefined) ?? t('customers.search.fallback.customerNote', 'Customer note')\n return {\n title,\n subtitle: snippet(ctx.record.body),\n icon: 'sticky-note',\n }\n },\n\n resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {\n assertTenantContext(ctx)\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const base = buildCustomerUrl(parent?.kind as string ?? null, (parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId) as string)\n return base ? `${base}#notes` : null\n },\n\n resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {\n assertTenantContext(ctx)\n const { t } = await resolveTranslations()\n const links: SearchResultLink[] = []\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const parentUrl = buildCustomerUrl(parent?.kind as string ?? null, (parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId) as string)\n if (parentUrl) {\n links.push({ href: parentUrl, label: (parent?.display_name as string | undefined) ?? t('customers.search.link.viewCustomer', 'View customer'), kind: 'primary' })\n }\n if (ctx.record.deal_id) {\n const dealUrl = `/backend/customers/deals/${encodeURIComponent(ctx.record.deal_id as string)}`\n links.push({ href: dealUrl, label: t('customers.search.link.openDeal', 'Open deal'), kind: 'secondary' })\n }\n return links.length ? links : null\n },\n\n fieldPolicy: {\n searchable: ['body'],\n hashOnly: [],\n excluded: [],\n },\n aclFeatures: ['customers.activities.view'],\n },\n\n // =========================================================================\n // Customer Deal\n // =========================================================================\n {\n entityId: 'customers:customer_deal',\n enabled: true,\n priority: 8,\n\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n const { t } = await resolveTranslations()\n const lines: string[] = []\n const record = ctx.record\n appendLine(lines, 'Title', record.title)\n appendLine(lines, 'Stage', record.pipeline_stage)\n appendLine(lines, 'Status', record.status)\n appendLine(lines, 'Source', record.source)\n const value = formatDealValue(record)\n if (value) appendLine(lines, 'Value', value)\n if (!lines.length) return null\n\n const subtitleParts: string[] = []\n if (record.pipeline_stage) subtitleParts.push(String(record.pipeline_stage))\n if (record.status) subtitleParts.push(String(record.status))\n if (value) subtitleParts.push(value)\n\n return {\n text: lines,\n presenter: {\n title: String(record.title ?? t('customers.search.fallback.deal', 'Deal')),\n subtitle: subtitleParts.join(' \u00B7 ') || undefined,\n icon: 'briefcase',\n badge: t('customers.search.badge.deal', 'Deal'),\n },\n checksumSource: {\n title: record.title,\n status: record.status,\n stage: record.pipeline_stage,\n value: value,\n },\n }\n },\n\n formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {\n const { t } = await resolveTranslations()\n const { record } = ctx\n const title = pickString(record.title as string, t('customers.search.fallback.deal', 'Deal'))\n const subtitleParts: string[] = []\n if (record.pipeline_stage) subtitleParts.push(String(record.pipeline_stage))\n if (record.status) subtitleParts.push(String(record.status))\n const amount = record.value_amount ?? record.valueAmount\n const currency = record.value_currency ?? record.valueCurrency\n if (amount) {\n subtitleParts.push(currency ? `${amount} ${currency}` : String(amount))\n }\n\n return {\n title: title ?? t('customers.search.fallback.deal', 'Deal'),\n subtitle: subtitleParts.length ? subtitleParts.join(' \u00B7 ') : undefined,\n icon: 'briefcase',\n badge: t('customers.search.badge.deal', 'Deal'),\n }\n },\n\n resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {\n const id = ctx.record.id\n if (!id) return null\n return `/backend/customers/deals/${encodeURIComponent(String(id))}`\n },\n\n resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {\n const { t } = await resolveTranslations()\n const id = ctx.record.id\n if (!id) return null\n return [\n {\n href: `/backend/customers/deals/${encodeURIComponent(String(id))}/edit`,\n label: t('customers.search.link.edit', 'Edit'),\n kind: 'secondary',\n },\n ]\n },\n\n fieldPolicy: {\n searchable: ['title', 'description', 'pipeline_stage', 'status', 'source'],\n hashOnly: [],\n excluded: ['value_amount', 'value_currency'],\n },\n aclFeatures: ['customers.deals.view'],\n },\n\n // =========================================================================\n // Customer Activity\n // =========================================================================\n {\n entityId: 'customers:customer_activity',\n enabled: true,\n priority: 5,\n\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n assertTenantContext(ctx)\n const { t } = await resolveTranslations()\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const lines: string[] = []\n if (parent?.display_name) lines.push(`Customer: ${parent.display_name}`)\n if (ctx.record.activity_type) lines.push(`Type: ${ctx.record.activity_type}`)\n if (ctx.record.subject) lines.push(`Subject: ${ctx.record.subject}`)\n if (ctx.record.body) lines.push(`Body: ${ctx.record.body}`)\n\n const presenter: SearchResultPresenter = {\n title: ctx.record.subject\n ? String(ctx.record.subject)\n : t('customers.search.fallback.activity', 'Activity: {{type}}', {\n type: String(ctx.record.activity_type ?? t('customers.search.fallback.activityUpdate', 'update')),\n }),\n subtitle: (parent?.display_name as string | undefined) ?? snippet(ctx.record.body),\n icon: 'bolt',\n }\n\n return {\n text: lines,\n presenter,\n checksumSource: {\n subject: ctx.record.subject,\n body: ctx.record.body,\n entityId: ctx.record.entity_id ?? null,\n updatedAt: ctx.record.updated_at ?? ctx.record.updatedAt ?? null,\n },\n }\n },\n\n formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {\n assertTenantContext(ctx)\n const { t } = await resolveTranslations()\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n return {\n title: ctx.record.subject\n ? String(ctx.record.subject)\n : t('customers.search.fallback.activity', 'Activity: {{type}}', {\n type: String(ctx.record.activity_type ?? t('customers.search.fallback.activityUpdate', 'update')),\n }),\n subtitle: (parent?.display_name as string | undefined) ?? snippet(ctx.record.body),\n icon: 'bolt',\n badge: t('customers.search.badge.activity', 'Activity'),\n }\n },\n\n resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {\n assertTenantContext(ctx)\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const base = buildCustomerUrl(parent?.kind as string ?? null, (parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId) as string)\n return base ? `${base}#activity-${ctx.record.id ?? ctx.record.activity_id ?? ''}` : null\n },\n\n resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {\n const { t } = await resolveTranslations()\n const links: SearchResultLink[] = []\n if (ctx.record.deal_id) {\n links.push({\n href: `/backend/customers/deals/${encodeURIComponent(ctx.record.deal_id as string)}`,\n label: t('customers.search.link.openDeal', 'Open deal'),\n kind: 'secondary',\n })\n }\n return links.length ? links : null\n },\n\n fieldPolicy: {\n searchable: ['subject', 'body', 'activity_type'],\n hashOnly: [],\n excluded: [],\n },\n aclFeatures: ['customers.activities.view'],\n },\n\n // =========================================================================\n // Customer Todo Link\n // =========================================================================\n {\n entityId: 'customers:customer_todo_link',\n enabled: true,\n priority: 4,\n\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n assertTenantContext(ctx)\n const todo = await getLinkedTodo(ctx) as Record<string, unknown> | null\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const lines: string[] = []\n if (todo?.title) lines.push(`Todo: ${todo.title}`)\n if (todo?.is_done !== undefined) lines.push(`Status: ${todo.is_done ? 'Done' : 'Open'}`)\n if (parent?.display_name) lines.push(`Customer: ${parent.display_name}`)\n if (!lines.length) return null\n\n return {\n text: lines,\n presenter: todo?.title\n ? { title: todo.title as string, subtitle: parent?.display_name as string | undefined, icon: 'check-square' }\n : undefined,\n checksumSource: {\n todoId: ctx.record.todo_id ?? ctx.record.todoId,\n todoSource: ctx.record.todo_source ?? ctx.record.todoSource,\n entityId: ctx.record.entity_id ?? ctx.record.entityId,\n },\n }\n },\n\n formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {\n assertTenantContext(ctx)\n const { t } = await resolveTranslations()\n const todo = await getLinkedTodo(ctx) as Record<string, unknown> | null\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n return {\n title: (todo?.title as string | undefined) ?? t('customers.search.fallback.customerTask', 'Customer task'),\n subtitle: parent?.display_name as string | undefined,\n icon: 'check-square',\n }\n },\n\n resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {\n assertTenantContext(ctx)\n const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)\n const base = buildCustomerUrl(parent?.kind as string ?? null, (parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId) as string)\n return base ? `${base}#tasks` : null\n },\n\n resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {\n const { t } = await resolveTranslations()\n const todoId = ctx.record.todo_id ?? ctx.record.todoId\n if (!todoId) return null\n return [{\n href: `/backend/todos/${encodeURIComponent(todoId as string)}/edit`,\n label: t('customers.search.link.openTodo', 'Open todo'),\n kind: 'secondary',\n }]\n },\n\n fieldPolicy: {\n searchable: [],\n hashOnly: [],\n excluded: [],\n },\n aclFeatures: ['customers.activities.view'],\n },\n ],\n}\n\nexport default searchConfig\nexport const config = searchConfig\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -32,8 +32,7 @@ async function lookupPhoneDuplicate(rawDigits, { recordId } = {}) {
|
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
if (total !== null && page * PAGE_SIZE >= total) {
|
|
35
|
+
if (items.length < PAGE_SIZE) {
|
|
37
36
|
break;
|
|
38
37
|
}
|
|
39
38
|
} catch {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/customers/utils/phoneDuplicates.ts"],
|
|
4
|
-
"sourcesContent": ["import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport type { PhoneDuplicateMatch } from '@open-mercato/ui/backend/inputs/PhoneNumberField'\n\ntype LookupOptions = {\n recordId?: string | null\n}\n\nconst normalizeDigits = (value: string): string => value.replace(/\\D+/g, '')\n\nconst MAX_PAGES = 3\nconst PAGE_SIZE = 50\n\nexport async function lookupPhoneDuplicate(\n rawDigits: string,\n { recordId }: LookupOptions = {}\n): Promise<PhoneDuplicateMatch | null> {\n const digits = normalizeDigits(rawDigits)\n if (!digits) return null\n\n const seen = new Set<string>()\n\n for (let page = 1; page <= MAX_PAGES; page += 1) {\n try {\n const url = `/api/customers/people?hasPhone=true&page=${page}&pageSize=${PAGE_SIZE}&sortField=createdAt&sortDir=desc`\n const call = await apiCall<{ items?: unknown[]
|
|
5
|
-
"mappings": "AAAA,SAAS,eAAe;AAOxB,MAAM,kBAAkB,CAAC,UAA0B,MAAM,QAAQ,QAAQ,EAAE;AAE3E,MAAM,YAAY;AAClB,MAAM,YAAY;AAElB,eAAsB,qBACpB,WACA,EAAE,SAAS,IAAmB,CAAC,GACM;AACrC,QAAM,SAAS,gBAAgB,SAAS;AACxC,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,OAAO,oBAAI,IAAY;AAE7B,WAAS,OAAO,GAAG,QAAQ,WAAW,QAAQ,GAAG;AAC/C,QAAI;AACF,YAAM,MAAM,4CAA4C,IAAI,aAAa,SAAS;AAClF,YAAM,OAAO,MAAM,QAA+
|
|
4
|
+
"sourcesContent": ["import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport type { PhoneDuplicateMatch } from '@open-mercato/ui/backend/inputs/PhoneNumberField'\n\ntype LookupOptions = {\n recordId?: string | null\n}\n\nconst normalizeDigits = (value: string): string => value.replace(/\\D+/g, '')\n\nconst MAX_PAGES = 3\nconst PAGE_SIZE = 50\n\nexport async function lookupPhoneDuplicate(\n rawDigits: string,\n { recordId }: LookupOptions = {}\n): Promise<PhoneDuplicateMatch | null> {\n const digits = normalizeDigits(rawDigits)\n if (!digits) return null\n\n const seen = new Set<string>()\n\n for (let page = 1; page <= MAX_PAGES; page += 1) {\n try {\n const url = `/api/customers/people?hasPhone=true&page=${page}&pageSize=${PAGE_SIZE}&sortField=createdAt&sortDir=desc`\n const call = await apiCall<{ items?: unknown[] }>(url)\n if (!call.ok) continue\n const payload = call.result ?? {}\n const items = Array.isArray(payload?.items) ? payload.items : []\n for (const item of items) {\n if (!item || typeof item !== 'object') continue\n const record = item as { id?: unknown; display_name?: unknown; primary_phone?: unknown }\n const id = typeof record.id === 'string' ? record.id : null\n if (!id || seen.has(id)) continue\n seen.add(id)\n if (recordId && id === recordId) continue\n const displayName = typeof record.display_name === 'string' ? record.display_name : null\n const phoneRaw = typeof record.primary_phone === 'string' ? record.primary_phone : ''\n const itemDigits = normalizeDigits(phoneRaw)\n if (!displayName || !itemDigits) continue\n if (itemDigits === digits) {\n return {\n id,\n label: displayName,\n href: `/backend/customers/people/${id}`,\n }\n }\n }\n // Short-page termination: a page shorter than requested is the end of the result\n // set. `total` is a display value and may under-report (capped counts), so it is\n // no longer consulted. MAX_PAGES stays as the deliberate best-effort bound \u2014 this\n // is a duplicate hint, not an exhaustive check.\n if (items.length < PAGE_SIZE) {\n break\n }\n } catch {\n // ignore and try next page\n }\n }\n\n return null\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,eAAe;AAOxB,MAAM,kBAAkB,CAAC,UAA0B,MAAM,QAAQ,QAAQ,EAAE;AAE3E,MAAM,YAAY;AAClB,MAAM,YAAY;AAElB,eAAsB,qBACpB,WACA,EAAE,SAAS,IAAmB,CAAC,GACM;AACrC,QAAM,SAAS,gBAAgB,SAAS;AACxC,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,OAAO,oBAAI,IAAY;AAE7B,WAAS,OAAO,GAAG,QAAQ,WAAW,QAAQ,GAAG;AAC/C,QAAI;AACF,YAAM,MAAM,4CAA4C,IAAI,aAAa,SAAS;AAClF,YAAM,OAAO,MAAM,QAA+B,GAAG;AACrD,UAAI,CAAC,KAAK,GAAI;AACd,YAAM,UAAU,KAAK,UAAU,CAAC;AAChC,YAAM,QAAQ,MAAM,QAAQ,SAAS,KAAK,IAAI,QAAQ,QAAQ,CAAC;AAC/D,iBAAW,QAAQ,OAAO;AACxB,YAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,cAAM,SAAS;AACf,cAAM,KAAK,OAAO,OAAO,OAAO,WAAW,OAAO,KAAK;AACvD,YAAI,CAAC,MAAM,KAAK,IAAI,EAAE,EAAG;AACzB,aAAK,IAAI,EAAE;AACX,YAAI,YAAY,OAAO,SAAU;AACjC,cAAM,cAAc,OAAO,OAAO,iBAAiB,WAAW,OAAO,eAAe;AACpF,cAAM,WAAW,OAAO,OAAO,kBAAkB,WAAW,OAAO,gBAAgB;AACnF,cAAM,aAAa,gBAAgB,QAAQ;AAC3C,YAAI,CAAC,eAAe,CAAC,WAAY;AACjC,YAAI,eAAe,QAAQ;AACzB,iBAAO;AAAA,YACL;AAAA,YACA,OAAO;AAAA,YACP,MAAM,6BAA6B,EAAE;AAAA,UACvC;AAAA,QACF;AAAA,MACF;AAKA,UAAI,MAAM,SAAS,WAAW;AAC5B;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -4,7 +4,6 @@ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
|
|
|
4
4
|
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
5
5
|
import { DashboardLayout } from "@open-mercato/core/modules/dashboards/data/entities";
|
|
6
6
|
import { dashboardLayoutItemPatchSchema } from "@open-mercato/core/modules/dashboards/data/validators";
|
|
7
|
-
import { hasFeature } from "@open-mercato/shared/security/features";
|
|
8
7
|
import {
|
|
9
8
|
runCrudMutationGuardAfterSuccess,
|
|
10
9
|
validateCrudMutationGuard
|
|
@@ -47,8 +46,12 @@ async function PATCH(req, ctx) {
|
|
|
47
46
|
tenantId: auth.tenantId ?? null,
|
|
48
47
|
organizationId: auth.orgId ?? null
|
|
49
48
|
};
|
|
50
|
-
const
|
|
51
|
-
|
|
49
|
+
const canConfigure = await rbac.userHasAllFeatures(
|
|
50
|
+
scope.userId,
|
|
51
|
+
["dashboards.configure"],
|
|
52
|
+
{ tenantId: scope.tenantId, organizationId: scope.organizationId }
|
|
53
|
+
);
|
|
54
|
+
if (!canConfigure) {
|
|
52
55
|
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
|
53
56
|
}
|
|
54
57
|
const guardResult = await validateCrudMutationGuard(container, {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/dashboards/api/layout/%5BitemId%5D/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { DashboardLayout } from '@open-mercato/core/modules/dashboards/data/entities'\nimport { dashboardLayoutItemPatchSchema } from '@open-mercato/core/modules/dashboards/data/validators'\nimport {
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAClB,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC,SAAS,uBAAuB;AAChC,SAAS,sCAAsC;AAC/C
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { DashboardLayout } from '@open-mercato/core/modules/dashboards/data/entities'\nimport { dashboardLayoutItemPatchSchema } from '@open-mercato/core/modules/dashboards/data/validators'\nimport {\n runCrudMutationGuardAfterSuccess,\n validateCrudMutationGuard,\n} from '@open-mercato/shared/lib/crud/mutation-guard'\nimport type { OpenApiMethodDoc, OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport {\n dashboardsTag,\n dashboardsErrorSchema,\n dashboardsOkSchema,\n dashboardLayoutItemUpdateSchema,\n} from '../../openapi'\n\nconst DEFAULT_SIZE = 'md'\nconst RESOURCE_KIND = 'dashboards.layout'\n\nexport const metadata = {\n PATCH: { requireAuth: true, requireFeatures: ['dashboards.configure'] },\n}\n\nexport async function PATCH(req: Request, ctx: { params?: { itemId?: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n const layoutItemId = ctx.params?.itemId\n if (!layoutItemId) return NextResponse.json({ error: 'Missing layout item id' }, { status: 400 })\n\n let body: unknown\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 })\n }\n if (!body || typeof body !== 'object' || Array.isArray(body)) {\n return NextResponse.json({ error: 'Invalid payload' }, { status: 400 })\n }\n const parsed = dashboardLayoutItemPatchSchema.safeParse({ ...(body as Record<string, unknown>), id: layoutItemId })\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid payload', issues: parsed.error.issues }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const { resolve } = container\n const em = resolve('em') as any\n const rbac = resolve('rbacService') as any\n\n const scope = {\n userId: String(auth.sub),\n tenantId: auth.tenantId ?? null,\n organizationId: auth.orgId ?? null,\n }\n\n const canConfigure = await rbac.userHasAllFeatures(\n scope.userId,\n ['dashboards.configure'],\n { tenantId: scope.tenantId, organizationId: scope.organizationId },\n )\n if (!canConfigure) {\n return NextResponse.json({ error: 'Forbidden' }, { status: 403 })\n }\n\n const guardResult = await validateCrudMutationGuard(container, {\n tenantId: scope.tenantId ?? '',\n organizationId: scope.organizationId,\n userId: scope.userId,\n resourceKind: RESOURCE_KIND,\n resourceId: layoutItemId,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: { id: layoutItemId, size: parsed.data.size, settings: parsed.data.settings },\n })\n if (guardResult && !guardResult.ok) {\n return NextResponse.json(guardResult.body, { status: guardResult.status })\n }\n\n const layout = await em.findOne(DashboardLayout, {\n userId: scope.userId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n })\n if (!layout) {\n return NextResponse.json({ error: 'Layout not found' }, { status: 404 })\n }\n\n const idx = layout.layoutJson.findIndex((item: { id?: string | null }) => item?.id === layoutItemId)\n if (idx === -1) {\n return NextResponse.json({ error: 'Layout item not found' }, { status: 404 })\n }\n\n const current = layout.layoutJson[idx]\n layout.layoutJson[idx] = {\n ...current,\n size: parsed.data.size ?? current.size ?? DEFAULT_SIZE,\n settings: parsed.data.settings ?? current.settings,\n }\n await em.flush()\n\n if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {\n await runCrudMutationGuardAfterSuccess(container, {\n tenantId: scope.tenantId ?? '',\n organizationId: scope.organizationId,\n userId: scope.userId,\n resourceKind: RESOURCE_KIND,\n resourceId: layoutItemId,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n metadata: guardResult.metadata ?? null,\n })\n }\n\n return NextResponse.json({ ok: true })\n}\n\nconst layoutItemParamsSchema = z.object({\n itemId: z.string().uuid(),\n})\n\nconst layoutItemPatchDoc: OpenApiMethodDoc = {\n summary: 'Update a dashboard layout item',\n description: 'Adjusts the size or settings for a single widget within the dashboard layout.',\n tags: [dashboardsTag],\n requestBody: {\n contentType: 'application/json',\n schema: dashboardLayoutItemUpdateSchema,\n description: 'Payload containing the new size or settings for the widget.',\n },\n responses: [\n { status: 200, description: 'Layout item updated.', schema: dashboardsOkSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid payload or missing item id', schema: dashboardsErrorSchema },\n { status: 401, description: 'Authentication required', schema: dashboardsErrorSchema },\n { status: 403, description: 'Missing dashboards.configure feature', schema: dashboardsErrorSchema },\n { status: 404, description: 'Item not found', schema: dashboardsErrorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: dashboardsTag,\n summary: 'Update dashboard layout item',\n pathParams: layoutItemParamsSchema,\n methods: {\n PATCH: layoutItemPatchDoc,\n },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -6,7 +6,7 @@ import { DashboardLayout } from "@open-mercato/core/modules/dashboards/data/enti
|
|
|
6
6
|
import { dashboardLayoutSchema } from "@open-mercato/core/modules/dashboards/data/validators";
|
|
7
7
|
import { loadAllWidgets } from "@open-mercato/core/modules/dashboards/lib/widgets";
|
|
8
8
|
import { resolveAllowedWidgetIds } from "@open-mercato/core/modules/dashboards/lib/access";
|
|
9
|
-
import {
|
|
9
|
+
import { authorizeFeatures } from "@open-mercato/shared/security/featurePolicy";
|
|
10
10
|
import { User } from "@open-mercato/core/modules/auth/data/entities";
|
|
11
11
|
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
12
12
|
import {
|
|
@@ -67,7 +67,10 @@ async function GET(req) {
|
|
|
67
67
|
tenantId: auth.tenantId ?? null,
|
|
68
68
|
organizationId: auth.orgId ?? null
|
|
69
69
|
};
|
|
70
|
-
const
|
|
70
|
+
const effectiveFeatures = await rbac.getEffectiveFeatures(scope.userId, {
|
|
71
|
+
tenantId: scope.tenantId,
|
|
72
|
+
organizationId: scope.organizationId
|
|
73
|
+
});
|
|
71
74
|
const widgets = await loadAllWidgets();
|
|
72
75
|
const allowedIds = await resolveAllowedWidgetIds(
|
|
73
76
|
em,
|
|
@@ -75,8 +78,8 @@ async function GET(req) {
|
|
|
75
78
|
userId: scope.userId,
|
|
76
79
|
tenantId: scope.tenantId,
|
|
77
80
|
organizationId: scope.organizationId,
|
|
78
|
-
features:
|
|
79
|
-
isSuperAdmin:
|
|
81
|
+
features: effectiveFeatures,
|
|
82
|
+
isSuperAdmin: false
|
|
80
83
|
},
|
|
81
84
|
widgets
|
|
82
85
|
);
|
|
@@ -119,7 +122,9 @@ async function GET(req) {
|
|
|
119
122
|
if (hasChanged) {
|
|
120
123
|
await em.flush();
|
|
121
124
|
}
|
|
122
|
-
const canConfigure =
|
|
125
|
+
const canConfigure = authorizeFeatures(["dashboards.configure"], {
|
|
126
|
+
grantedFeatures: effectiveFeatures
|
|
127
|
+
});
|
|
123
128
|
let userEmail = null;
|
|
124
129
|
let userName = null;
|
|
125
130
|
let userLabel = null;
|
|
@@ -186,8 +191,12 @@ async function PUT(req) {
|
|
|
186
191
|
tenantId: auth.tenantId ?? null,
|
|
187
192
|
organizationId: auth.orgId ?? null
|
|
188
193
|
};
|
|
189
|
-
const
|
|
190
|
-
|
|
194
|
+
const canConfigure = await rbac.userHasAllFeatures(
|
|
195
|
+
scope.userId,
|
|
196
|
+
["dashboards.configure"],
|
|
197
|
+
{ tenantId: scope.tenantId, organizationId: scope.organizationId }
|
|
198
|
+
);
|
|
199
|
+
if (!canConfigure) {
|
|
191
200
|
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
|
192
201
|
}
|
|
193
202
|
const guardResult = await validateCrudMutationGuard(container, {
|
|
@@ -205,14 +214,18 @@ async function PUT(req) {
|
|
|
205
214
|
return NextResponse.json(guardResult.body, { status: guardResult.status });
|
|
206
215
|
}
|
|
207
216
|
const widgets = await loadAllWidgets();
|
|
217
|
+
const effectiveFeatures = await rbac.getEffectiveFeatures(scope.userId, {
|
|
218
|
+
tenantId: scope.tenantId,
|
|
219
|
+
organizationId: scope.organizationId
|
|
220
|
+
});
|
|
208
221
|
const allowedIds = await resolveAllowedWidgetIds(
|
|
209
222
|
em,
|
|
210
223
|
{
|
|
211
224
|
userId: scope.userId,
|
|
212
225
|
tenantId: scope.tenantId,
|
|
213
226
|
organizationId: scope.organizationId,
|
|
214
|
-
features:
|
|
215
|
-
isSuperAdmin:
|
|
227
|
+
features: effectiveFeatures,
|
|
228
|
+
isSuperAdmin: false
|
|
216
229
|
},
|
|
217
230
|
widgets
|
|
218
231
|
);
|