@open-mercato/core 0.7.0 → 0.7.1-develop.7102.1.b41f7e3e51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/helpers/integration/api.js +13 -1
- package/dist/helpers/integration/api.js.map +2 -2
- package/dist/helpers/integration/communicationChannelsFixtures.js +19 -0
- package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
- package/dist/modules/api_keys/api/keys/route.js +1 -1
- package/dist/modules/api_keys/api/keys/route.js.map +2 -2
- package/dist/modules/api_keys/backend/api-keys/page.js +3 -1
- package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
- package/dist/modules/api_keys/di.js +9 -0
- package/dist/modules/api_keys/di.js.map +7 -0
- package/dist/modules/api_keys/services/principalService.js +31 -0
- package/dist/modules/api_keys/services/principalService.js.map +7 -0
- package/dist/modules/attachments/api/route.js +2 -2
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentLibrary.js +2 -0
- package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
- package/dist/modules/attachments/di.js +11 -1
- package/dist/modules/attachments/di.js.map +2 -2
- package/dist/modules/attachments/index.js.map +1 -1
- package/dist/modules/attachments/lib/attachment-service.js +313 -0
- package/dist/modules/attachments/lib/attachment-service.js.map +7 -0
- package/dist/modules/attachments/lib/scoped-upload-service.js +15 -2
- package/dist/modules/attachments/lib/scoped-upload-service.js.map +2 -2
- package/dist/modules/attachments/lib/upload-limits.js +6 -2
- package/dist/modules/attachments/lib/upload-limits.js.map +2 -2
- package/dist/modules/audit_logs/backend/audit-logs/page.js +6 -0
- package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
- package/dist/modules/audit_logs/lib/display-helpers.js +19 -11
- package/dist/modules/audit_logs/lib/display-helpers.js.map +2 -2
- package/dist/modules/audit_logs/services/actionLogService.js +57 -12
- package/dist/modules/audit_logs/services/actionLogService.js.map +3 -3
- package/dist/modules/auth/acl.js +30 -5
- package/dist/modules/auth/acl.js.map +2 -2
- package/dist/modules/auth/api/feature-check.js +8 -2
- package/dist/modules/auth/api/feature-check.js.map +2 -2
- package/dist/modules/auth/api/login.js +4 -1
- package/dist/modules/auth/api/login.js.map +2 -2
- package/dist/modules/auth/api/reset/validate.js +55 -0
- package/dist/modules/auth/api/reset/validate.js.map +7 -0
- package/dist/modules/auth/api/roles/acl/route.js +28 -33
- package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
- package/dist/modules/auth/api/session/refresh.js +25 -1
- package/dist/modules/auth/api/session/refresh.js.map +2 -2
- package/dist/modules/auth/api/users/acl/route.js +96 -51
- package/dist/modules/auth/api/users/acl/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +13 -5
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/roles/[id]/edit/page.meta.js +5 -1
- package/dist/modules/auth/backend/roles/[id]/edit/page.meta.js.map +2 -2
- package/dist/modules/auth/backend/roles/page.js +3 -1
- package/dist/modules/auth/backend/roles/page.js.map +2 -2
- package/dist/modules/auth/backend/users/[id]/edit/page.meta.js +5 -1
- package/dist/modules/auth/backend/users/[id]/edit/page.meta.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/commands/acl.js +254 -0
- package/dist/modules/auth/commands/acl.js.map +7 -0
- package/dist/modules/auth/components/AclEditor.js +39 -30
- package/dist/modules/auth/components/AclEditor.js.map +2 -2
- package/dist/modules/auth/data/entities.js.map +2 -2
- package/dist/modules/auth/data/validators.js +5 -1
- package/dist/modules/auth/data/validators.js.map +2 -2
- package/dist/modules/auth/di.js +35 -9
- package/dist/modules/auth/di.js.map +2 -2
- package/dist/modules/auth/frontend/reset/[token]/page.js +46 -0
- package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
- package/dist/modules/auth/lib/grantChecks.js.map +2 -2
- package/dist/modules/auth/lib/userIdFilter.js +16 -0
- package/dist/modules/auth/lib/userIdFilter.js.map +7 -0
- package/dist/modules/auth/services/authService.js +16 -2
- package/dist/modules/auth/services/authService.js.map +2 -2
- package/dist/modules/auth/services/principalService.js +200 -0
- package/dist/modules/auth/services/principalService.js.map +7 -0
- package/dist/modules/auth/services/rbacService.js +67 -24
- package/dist/modules/auth/services/rbacService.js.map +3 -3
- package/dist/modules/auth/services/roleOrganizationScope.js +41 -0
- package/dist/modules/auth/services/roleOrganizationScope.js.map +7 -0
- package/dist/modules/business_rules/backend/logs/page.js +3 -1
- package/dist/modules/business_rules/backend/logs/page.js.map +2 -2
- package/dist/modules/business_rules/backend/rules/page.js +3 -1
- package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
- package/dist/modules/business_rules/backend/sets/page.js +3 -1
- package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
- package/dist/modules/business_rules/lib/expression-evaluator.js +9 -9
- package/dist/modules/business_rules/lib/expression-evaluator.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-evaluator.js +10 -9
- package/dist/modules/business_rules/lib/rule-evaluator.js.map +2 -2
- package/dist/modules/catalog/ai-agents.js +1 -1
- package/dist/modules/catalog/ai-agents.js.map +1 -1
- package/dist/modules/catalog/ai-tools/merchandising-pack.js +2 -2
- package/dist/modules/catalog/ai-tools/merchandising-pack.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js +5 -2
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js.map +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -0
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js +7 -1
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js +2 -0
- package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js +9 -1
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js +95 -10
- package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +3 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +2 -2
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js +14 -1
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +2 -2
- package/dist/modules/communication_channels/di.js +7 -1
- package/dist/modules/communication_channels/di.js.map +2 -2
- package/dist/modules/communication_channels/lib/email-capabilities.js +4 -1
- package/dist/modules/communication_channels/lib/email-capabilities.js.map +2 -2
- package/dist/modules/communication_channels/lib/outbound-recipient.js +33 -0
- package/dist/modules/communication_channels/lib/outbound-recipient.js.map +7 -0
- package/dist/modules/communication_channels/lib/resolve-channel-type.js +51 -0
- package/dist/modules/communication_channels/lib/resolve-channel-type.js.map +7 -0
- package/dist/modules/communication_channels/lib/test-seed.js +41 -2
- package/dist/modules/communication_channels/lib/test-seed.js.map +2 -2
- package/dist/modules/configs/lib/system-status.js +9 -0
- package/dist/modules/configs/lib/system-status.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +3 -1
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +3 -1
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/currencies/services/rateFetchingService.js +6 -1
- package/dist/modules/currencies/services/rateFetchingService.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/domain-mappings.js +9 -0
- package/dist/modules/customer_accounts/api/admin/domain-mappings.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +3 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js +3 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js.map +2 -2
- package/dist/modules/customer_accounts/services/domainMappingService.js +10 -0
- package/dist/modules/customer_accounts/services/domainMappingService.js.map +2 -2
- package/dist/modules/customers/ai-tools/companies-pack.js +4 -1
- package/dist/modules/customers/ai-tools/companies-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/deal-analyzer-pack.js +13 -2
- package/dist/modules/customers/ai-tools/deal-analyzer-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/deals-pack.js +52 -6
- package/dist/modules/customers/ai-tools/deals-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/people-pack.js +4 -1
- package/dist/modules/customers/ai-tools/people-pack.js.map +2 -2
- package/dist/modules/customers/api/activities/route.js +48 -6
- package/dist/modules/customers/api/activities/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/people/route.js +20 -64
- package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/route.js +17 -94
- package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js +8 -5
- package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/companies/route.js +1 -1
- package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +1 -1
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/route.js +8 -25
- package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/stats/route.js +3 -22
- package/dist/modules/customers/api/deals/[id]/stats/route.js.map +2 -2
- package/dist/modules/customers/api/deals/aggregate/route.js +11 -4
- package/dist/modules/customers/api/deals/aggregate/route.js.map +2 -2
- package/dist/modules/customers/api/deals/map/route.js +2 -1
- package/dist/modules/customers/api/deals/map/route.js.map +2 -2
- package/dist/modules/customers/api/deals/route.js +38 -1
- package/dist/modules/customers/api/deals/route.js.map +2 -2
- package/dist/modules/customers/api/entity-roles-factory.js +4 -4
- package/dist/modules/customers/api/entity-roles-factory.js.map +2 -2
- package/dist/modules/customers/api/interactions/route.js +3 -1
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/tasks/route.js +27 -4
- package/dist/modules/customers/api/interactions/tasks/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +4 -3
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/context.js +1 -1
- package/dist/modules/customers/api/people/[id]/companies/context.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +1 -1
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/route.js +11 -10
- package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/people/check-phone/route.js +51 -9
- package/dist/modules/customers/api/people/check-phone/route.js.map +2 -2
- package/dist/modules/customers/api/todos/route.js +30 -5
- package/dist/modules/customers/api/todos/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +4 -2
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +6 -1
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +5 -2
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js +4 -13
- package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js +85 -14
- package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/toneClasses.js +18 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/toneClasses.js.map +7 -0
- package/dist/modules/customers/backend/customers/people/page.js +4 -2
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/backend/hooks/useEmailDuplicateCheck.js +9 -3
- package/dist/modules/customers/backend/hooks/useEmailDuplicateCheck.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +21 -34
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js.map +1 -1
- package/dist/modules/customers/commands/personCompanyLinks.js +131 -2
- package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
- package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
- package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
- package/dist/modules/customers/components/DealsKpiStrip.js +7 -6
- package/dist/modules/customers/components/DealsKpiStrip.js.map +2 -2
- package/dist/modules/customers/components/calendar/AgendaList.js +2 -2
- package/dist/modules/customers/components/calendar/AgendaList.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/calendar/CalendarScreen.js +1 -1
- package/dist/modules/customers/components/calendar/CalendarScreen.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js +1 -1
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js.map +2 -2
- package/dist/modules/customers/components/calendar/EventBlock.js +1 -1
- package/dist/modules/customers/components/calendar/EventBlock.js.map +2 -2
- package/dist/modules/customers/components/calendar/EventPeekPopover.js +3 -2
- package/dist/modules/customers/components/calendar/EventPeekPopover.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/PeopleField.js +40 -5
- package/dist/modules/customers/components/calendar/editor/PeopleField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/hooks.js +2 -1
- package/dist/modules/customers/components/calendar/editor/hooks.js.map +2 -2
- package/dist/modules/customers/components/calendar/types.js +1 -1
- package/dist/modules/customers/components/calendar/types.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyKpiBar.js +5 -4
- package/dist/modules/customers/components/detail/CompanyKpiBar.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js +3 -1
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
- package/dist/modules/customers/components/detail/DealForm.js +19 -7
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/detail/DealsSection.js +6 -5
- package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
- package/dist/modules/customers/components/detail/EntityTagsDialog.js +35 -11
- package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js +3 -1
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
- package/dist/modules/customers/components/detail/hooks/usePersonTasks.js +19 -13
- package/dist/modules/customers/components/detail/hooks/usePersonTasks.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js +4 -4
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +3 -3
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
- package/dist/modules/customers/components/detail/utils.js +5 -5
- package/dist/modules/customers/components/detail/utils.js.map +2 -2
- package/dist/modules/customers/data/entities.js.map +1 -1
- package/dist/modules/customers/data/validators.js +32 -3
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/events.js +5 -0
- package/dist/modules/customers/events.js.map +2 -2
- package/dist/modules/customers/lib/calendar/conflicts.js +8 -2
- package/dist/modules/customers/lib/calendar/conflicts.js.map +2 -2
- package/dist/modules/customers/lib/calendar/editorPayload.js +3 -2
- package/dist/modules/customers/lib/calendar/editorPayload.js.map +2 -2
- package/dist/modules/customers/lib/calendar/mapItem.js +8 -3
- package/dist/modules/customers/lib/calendar/mapItem.js.map +2 -2
- package/dist/modules/customers/lib/calendar/participantIdentity.js +9 -0
- package/dist/modules/customers/lib/calendar/participantIdentity.js.map +7 -0
- package/dist/modules/customers/lib/closureStage.js +45 -0
- package/dist/modules/customers/lib/closureStage.js.map +7 -0
- package/dist/modules/customers/lib/dealStatus.js +30 -0
- package/dist/modules/customers/lib/dealStatus.js.map +2 -2
- package/dist/modules/customers/lib/detailReadAccess.js +12 -0
- package/dist/modules/customers/lib/detailReadAccess.js.map +7 -0
- package/dist/modules/customers/lib/findPeopleByAddresses.js +1 -0
- package/dist/modules/customers/lib/findPeopleByAddresses.js.map +2 -2
- package/dist/modules/customers/lib/personCompanies.js +100 -2
- package/dist/modules/customers/lib/personCompanies.js.map +2 -2
- package/dist/modules/customers/lib/todoCompatibility.js +12 -0
- package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
- package/dist/modules/dashboards/lib/widgetScope.js +6 -1
- package/dist/modules/dashboards/lib/widgetScope.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.js +3 -1
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/data_sync/lib/abandoned-run.js +19 -0
- package/dist/modules/data_sync/lib/abandoned-run.js.map +7 -0
- package/dist/modules/data_sync/lib/sync-engine.js +72 -6
- package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-export.js +5 -1
- package/dist/modules/data_sync/workers/sync-export.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-import.js +5 -1
- package/dist/modules/data_sync/workers/sync-import.js.map +2 -2
- package/dist/modules/devices/acl.js +9 -1
- package/dist/modules/devices/acl.js.map +2 -2
- package/dist/modules/devices/api/admin/devices/[id]/route.js +5 -32
- package/dist/modules/devices/api/admin/devices/[id]/route.js.map +2 -2
- package/dist/modules/devices/api/admin/devices/route.js +14 -1
- package/dist/modules/devices/api/admin/devices/route.js.map +2 -2
- package/dist/modules/devices/api/deviceList.js +99 -12
- package/dist/modules/devices/api/deviceList.js.map +2 -2
- package/dist/modules/devices/api/deviceSerialization.js +46 -0
- package/dist/modules/devices/api/deviceSerialization.js.map +7 -0
- package/dist/modules/devices/api/openapi.js +3 -1
- package/dist/modules/devices/api/openapi.js.map +2 -2
- package/dist/modules/devices/api/route.js +9 -1
- package/dist/modules/devices/api/route.js.map +2 -2
- package/dist/modules/devices/backend/devices/[id]/page.js +10 -26
- package/dist/modules/devices/backend/devices/[id]/page.js.map +2 -2
- package/dist/modules/devices/backend/devices/create/page.js +17 -1
- package/dist/modules/devices/backend/devices/create/page.js.map +2 -2
- package/dist/modules/devices/backend/devices/page.js +28 -34
- package/dist/modules/devices/backend/devices/page.js.map +2 -2
- package/dist/modules/devices/backend/devices/useDeviceUserLabels.js +34 -0
- package/dist/modules/devices/backend/devices/useDeviceUserLabels.js.map +7 -0
- package/dist/modules/devices/backend/devices/userOptions.js +52 -0
- package/dist/modules/devices/backend/devices/userOptions.js.map +7 -0
- package/dist/modules/devices/setup.js +6 -2
- package/dist/modules/devices/setup.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/di.js +9 -0
- package/dist/modules/directory/di.js.map +2 -2
- package/dist/modules/directory/services/organizationHierarchyService.js +29 -0
- package/dist/modules/directory/services/organizationHierarchyService.js.map +7 -0
- package/dist/modules/directory/services/organizationScopeService.js +56 -0
- package/dist/modules/directory/services/organizationScopeService.js.map +7 -0
- package/dist/modules/directory/utils/organizationScope.js.map +2 -2
- package/dist/modules/entities/api/records.js +4 -2
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +3 -1
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- package/dist/modules/eudr/api/plots/route.js +5 -1
- package/dist/modules/eudr/api/plots/route.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/plots/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/plots/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/statements/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/statements/page.js.map +2 -2
- package/dist/modules/eudr/commands/statements.js +0 -3
- package/dist/modules/eudr/commands/statements.js.map +2 -2
- package/dist/modules/eudr/data/validators.js +4 -1
- package/dist/modules/eudr/data/validators.js.map +2 -2
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +1 -0
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
- package/dist/modules/feature_toggles/components/OverridesTable.js +1 -0
- package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
- package/dist/modules/feature_toggles/defaults.json +0 -8
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js +3 -0
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js +3 -0
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js.map +2 -2
- package/dist/modules/inbox_ops/lib/htmlToPlainText.js +1 -12
- package/dist/modules/inbox_ops/lib/htmlToPlainText.js.map +2 -2
- package/dist/modules/integrations/api/[id]/credentials/route.js +6 -1
- package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js +38 -29
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +36 -9
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/credential-secret-fields.js +55 -0
- package/dist/modules/integrations/backend/integrations/credential-secret-fields.js.map +7 -0
- package/dist/modules/integrations/data/validators.js +11 -3
- package/dist/modules/integrations/data/validators.js.map +2 -2
- package/dist/modules/integrations/lib/credentials-masking.js +6 -2
- package/dist/modules/integrations/lib/credentials-masking.js.map +2 -2
- package/dist/modules/messages/api/[id]/route.js +29 -1
- package/dist/modules/messages/api/[id]/route.js.map +2 -2
- package/dist/modules/messages/api/openapi.js +17 -2
- package/dist/modules/messages/api/openapi.js.map +2 -2
- package/dist/modules/messages/api/route.js +17 -2
- package/dist/modules/messages/api/route.js.map +2 -2
- package/dist/modules/messages/components/MessagesInboxPageClient.js +7 -14
- package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
- package/dist/modules/messages/components/inboxFilters.js +15 -0
- package/dist/modules/messages/components/inboxFilters.js.map +2 -2
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js +11 -1
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/MessageHeader.js +3 -1
- package/dist/modules/messages/components/message-detail/panels/MessageHeader.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/thread-panel.js +2 -1
- package/dist/modules/messages/components/message-detail/panels/thread-panel.js.map +2 -2
- package/dist/modules/messages/components/messageListLabels.js +14 -2
- package/dist/modules/messages/components/messageListLabels.js.map +2 -2
- package/dist/modules/messages/data/validators.js +18 -4
- package/dist/modules/messages/data/validators.js.map +2 -2
- package/dist/modules/messages/lib/channel-sender-identity.js +26 -0
- package/dist/modules/messages/lib/channel-sender-identity.js.map +7 -0
- package/dist/modules/messages/lib/composeSourceChannelType.js +41 -0
- package/dist/modules/messages/lib/composeSourceChannelType.js.map +7 -0
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +4 -6
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js +3 -1
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +2 -2
- package/dist/modules/payment_gateways/lib/webhook-processor.js +7 -0
- package/dist/modules/payment_gateways/lib/webhook-processor.js.map +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js +3 -0
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
- package/dist/modules/push_notifications/backend/push_notifications/page.js +3 -1
- package/dist/modules/push_notifications/backend/push_notifications/page.js.map +2 -2
- package/dist/modules/push_notifications/backend/push_notifications/send/page.js +1 -1
- package/dist/modules/push_notifications/backend/push_notifications/send/page.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +150 -51
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/lib/search-entity-policy.js +14 -0
- package/dist/modules/query_index/lib/search-entity-policy.js.map +7 -0
- package/dist/modules/query_index/lib/search-tokens.js +79 -3
- package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js +3 -1
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js +3 -1
- package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +3 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +3 -0
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +10 -8
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +79 -1
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/components/PriceWithCurrency.js +7 -5
- package/dist/modules/sales/components/PriceWithCurrency.js.map +2 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +3 -0
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js +8 -6
- package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +51 -22
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +83 -18
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js +23 -9
- package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ReturnsSection.js +8 -6
- package/dist/modules/sales/components/documents/ReturnsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +68 -14
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js +6 -5
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentDialog.js +5 -4
- package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentsSection.js +8 -6
- package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/lineItemShipmentLock.js +54 -0
- package/dist/modules/sales/components/documents/lineItemShipmentLock.js.map +7 -0
- package/dist/modules/sales/components/documents/lineItemUtils.js +2 -2
- package/dist/modules/sales/components/documents/lineItemUtils.js.map +2 -2
- package/dist/modules/sales/data/entities.js +8 -2
- package/dist/modules/sales/data/entities.js.map +2 -2
- package/dist/modules/sales/extension-points.js +1 -0
- package/dist/modules/sales/extension-points.js.map +2 -2
- package/dist/modules/sales/lib/salesChannelsToggleSeed.js +33 -0
- package/dist/modules/sales/lib/salesChannelsToggleSeed.js.map +7 -0
- package/dist/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.js +32 -0
- package/dist/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.js.map +7 -0
- package/dist/modules/sales/setup.js +2 -0
- package/dist/modules/sales/setup.js.map +2 -2
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js +10 -2
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js.map +2 -2
- package/dist/modules/sales/widgets/injection-table.js +4 -7
- package/dist/modules/sales/widgets/injection-table.js.map +2 -2
- package/dist/modules/staff/backend/staff/leave-requests/page.js +3 -0
- package/dist/modules/staff/backend/staff/leave-requests/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/my-leave-requests/page.js +3 -0
- package/dist/modules/staff/backend/staff/my-leave-requests/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/page.js +3 -0
- package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js +3 -0
- package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +3 -0
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js +3 -0
- package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/page.js +29 -18
- package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js +3 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
- package/dist/modules/sync_excel/lib/adapters/customers.js +1 -0
- package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
- package/dist/modules/warranty_claims/api/assignees/route.js +3 -3
- package/dist/modules/warranty_claims/api/assignees/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/attachments/route.js +2 -2
- package/dist/modules/warranty_claims/api/portal/attachments/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/route.js +12 -9
- package/dist/modules/warranty_claims/api/portal/claims/route.js.map +2 -2
- package/dist/modules/warranty_claims/backend/page.js +3 -0
- package/dist/modules/warranty_claims/backend/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js.map +2 -2
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js +3 -0
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js.map +2 -2
- package/dist/modules/wms/api/warehouseSearch.js +21 -0
- package/dist/modules/wms/api/warehouseSearch.js.map +7 -0
- package/dist/modules/wms/api/warehouses/route.js +13 -9
- package/dist/modules/wms/api/warehouses/route.js.map +2 -2
- package/dist/modules/wms/api/zones/route.js +15 -2
- package/dist/modules/wms/api/zones/route.js.map +2 -2
- package/dist/modules/wms/commands/configuration.js +121 -9
- package/dist/modules/wms/commands/configuration.js.map +2 -2
- package/dist/modules/wms/commands/inventory-actions.js +3 -0
- package/dist/modules/wms/commands/inventory-actions.js.map +2 -2
- package/dist/modules/wms/commands/shared.js +9 -1
- package/dist/modules/wms/commands/shared.js.map +2 -2
- package/dist/modules/wms/components/backend/WarehouseEditDialog.js +158 -0
- package/dist/modules/wms/components/backend/WarehouseEditDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js +76 -111
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js.map +3 -3
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js +1 -0
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLotsListPage.js +1 -0
- package/dist/modules/wms/components/backend/WmsLotsListPage.js.map +2 -2
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js +27 -20
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js.map +2 -2
- package/dist/modules/wms/components/backend/warehouseFormOptions.js +66 -0
- package/dist/modules/wms/components/backend/warehouseFormOptions.js.map +7 -0
- package/dist/modules/workflows/backend/definitions/page.js +3 -1
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/events/page.js +3 -1
- package/dist/modules/workflows/backend/events/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.js +3 -1
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +3 -1
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/lib/activity-executor.js +4 -0
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/package.json +9 -10
- package/src/helpers/integration/api.ts +33 -1
- package/src/helpers/integration/communicationChannelsFixtures.ts +69 -1
- package/src/modules/api_keys/api/keys/route.ts +3 -1
- package/src/modules/api_keys/backend/api-keys/page.tsx +4 -1
- package/src/modules/api_keys/di.ts +7 -0
- package/src/modules/api_keys/services/principalService.ts +33 -0
- package/src/modules/attachments/AGENTS.md +15 -0
- package/src/modules/attachments/api/route.ts +2 -2
- package/src/modules/attachments/components/AttachmentLibrary.tsx +3 -0
- package/src/modules/attachments/di.ts +16 -0
- package/src/modules/attachments/i18n/de.json +5 -0
- package/src/modules/attachments/i18n/en.json +5 -0
- package/src/modules/attachments/i18n/es.json +5 -0
- package/src/modules/attachments/i18n/ko.json +5 -0
- package/src/modules/attachments/i18n/pl.json +5 -0
- package/src/modules/attachments/index.ts +10 -0
- package/src/modules/attachments/lib/attachment-service.ts +468 -0
- package/src/modules/attachments/lib/scoped-upload-service.ts +46 -0
- package/src/modules/attachments/lib/upload-limits.ts +6 -2
- package/src/modules/audit_logs/backend/audit-logs/page.tsx +8 -0
- package/src/modules/audit_logs/lib/display-helpers.tsx +42 -32
- package/src/modules/audit_logs/services/actionLogService.ts +74 -11
- package/src/modules/auth/acl.ts +30 -6
- package/src/modules/auth/api/feature-check.ts +10 -3
- package/src/modules/auth/api/login.ts +9 -1
- package/src/modules/auth/api/reset/validate.ts +57 -0
- package/src/modules/auth/api/roles/acl/route.ts +42 -39
- package/src/modules/auth/api/session/refresh.ts +32 -1
- package/src/modules/auth/api/users/acl/route.ts +177 -53
- package/src/modules/auth/api/users/route.ts +18 -5
- package/src/modules/auth/backend/roles/[id]/edit/page.meta.ts +5 -2
- package/src/modules/auth/backend/roles/page.tsx +4 -2
- package/src/modules/auth/backend/users/[id]/edit/page.meta.ts +5 -2
- package/src/modules/auth/backend/users/page.tsx +3 -2
- package/src/modules/auth/commands/acl.ts +495 -0
- package/src/modules/auth/components/AclEditor.tsx +63 -33
- package/src/modules/auth/data/entities.ts +4 -1
- package/src/modules/auth/data/validators.ts +5 -0
- package/src/modules/auth/di.ts +46 -16
- package/src/modules/auth/frontend/reset/[token]/page.tsx +74 -0
- package/src/modules/auth/i18n/de.json +389 -0
- package/src/modules/auth/i18n/en.json +389 -0
- package/src/modules/auth/i18n/es.json +389 -0
- package/src/modules/auth/i18n/ko.json +389 -0
- package/src/modules/auth/i18n/pl.json +391 -2
- package/src/modules/auth/lib/grantChecks.ts +6 -0
- package/src/modules/auth/lib/userIdFilter.ts +31 -0
- package/src/modules/auth/services/authService.ts +18 -2
- package/src/modules/auth/services/principalService.ts +266 -0
- package/src/modules/auth/services/rbacService.ts +110 -24
- package/src/modules/auth/services/roleOrganizationScope.ts +70 -0
- package/src/modules/business_rules/backend/logs/page.tsx +4 -1
- package/src/modules/business_rules/backend/rules/page.tsx +4 -1
- package/src/modules/business_rules/backend/sets/page.tsx +4 -1
- package/src/modules/business_rules/lib/expression-evaluator.ts +9 -9
- package/src/modules/business_rules/lib/rule-evaluator.ts +10 -9
- package/src/modules/catalog/ai-agents.ts +1 -1
- package/src/modules/catalog/ai-tools/merchandising-pack.ts +2 -2
- package/src/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.tsx +12 -5
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +3 -0
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +7 -0
- package/src/modules/catalog/i18n/de.json +1 -0
- package/src/modules/catalog/i18n/en.json +1 -0
- package/src/modules/catalog/i18n/es.json +1 -0
- package/src/modules/catalog/i18n/ko.json +1 -0
- package/src/modules/catalog/i18n/pl.json +1 -0
- package/src/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.tsx +4 -0
- package/src/modules/communication_channels/api/post/channels/[id]/test-send/route.ts +17 -1
- package/src/modules/communication_channels/api/post/test-seed/route.ts +155 -16
- package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +4 -0
- package/src/modules/communication_channels/commands/ingest-inbound-message.ts +38 -1
- package/src/modules/communication_channels/di.ts +7 -0
- package/src/modules/communication_channels/lib/adapter.ts +14 -0
- package/src/modules/communication_channels/lib/email-capabilities.ts +4 -0
- package/src/modules/communication_channels/lib/outbound-recipient.ts +71 -0
- package/src/modules/communication_channels/lib/resolve-channel-type.ts +99 -0
- package/src/modules/communication_channels/lib/test-seed.ts +64 -4
- package/src/modules/configs/i18n/de.json +2 -0
- package/src/modules/configs/i18n/en.json +2 -0
- package/src/modules/configs/i18n/es.json +2 -0
- package/src/modules/configs/i18n/ko.json +2 -0
- package/src/modules/configs/i18n/pl.json +2 -0
- package/src/modules/configs/lib/system-status.ts +9 -0
- package/src/modules/currencies/AGENTS.md +3 -0
- package/src/modules/currencies/backend/currencies/page.tsx +4 -1
- package/src/modules/currencies/backend/exchange-rates/page.tsx +4 -1
- package/src/modules/currencies/services/README.md +45 -0
- package/src/modules/currencies/services/rateFetchingService.ts +6 -1
- package/src/modules/customer_accounts/api/admin/domain-mappings.ts +7 -0
- package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +4 -1
- package/src/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.tsx +4 -1
- package/src/modules/customer_accounts/services/domainMappingService.ts +10 -0
- package/src/modules/customers/ai-tools/companies-pack.ts +4 -1
- package/src/modules/customers/ai-tools/deal-analyzer-pack.ts +17 -2
- package/src/modules/customers/ai-tools/deals-pack.ts +66 -1
- package/src/modules/customers/ai-tools/people-pack.ts +4 -1
- package/src/modules/customers/api/activities/route.ts +45 -0
- package/src/modules/customers/api/companies/[id]/people/route.ts +24 -73
- package/src/modules/customers/api/companies/[id]/route.ts +24 -107
- package/src/modules/customers/api/dashboard/widgets/customer-todos/route.ts +16 -8
- package/src/modules/customers/api/deals/[id]/companies/route.ts +4 -1
- package/src/modules/customers/api/deals/[id]/people/route.ts +4 -1
- package/src/modules/customers/api/deals/[id]/route.ts +17 -28
- package/src/modules/customers/api/deals/[id]/stats/route.ts +10 -25
- package/src/modules/customers/api/deals/aggregate/route.ts +14 -4
- package/src/modules/customers/api/deals/map/route.ts +1 -0
- package/src/modules/customers/api/deals/route.ts +50 -1
- package/src/modules/customers/api/entity-roles-factory.ts +8 -4
- package/src/modules/customers/api/interactions/route.ts +8 -2
- package/src/modules/customers/api/interactions/tasks/route.ts +24 -1
- package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +12 -4
- package/src/modules/customers/api/people/[id]/companies/context.ts +4 -1
- package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +4 -1
- package/src/modules/customers/api/people/[id]/route.ts +16 -11
- package/src/modules/customers/api/people/check-phone/route.ts +75 -10
- package/src/modules/customers/api/todos/route.ts +27 -2
- package/src/modules/customers/backend/customers/companies/page.tsx +5 -2
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +7 -2
- package/src/modules/customers/backend/customers/deals/page.tsx +8 -2
- package/src/modules/customers/backend/customers/deals/pipeline/components/Lane.tsx +5 -14
- package/src/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.tsx +109 -27
- package/src/modules/customers/backend/customers/deals/pipeline/components/toneClasses.ts +21 -0
- package/src/modules/customers/backend/customers/people/page.tsx +5 -2
- package/src/modules/customers/backend/hooks/useEmailDuplicateCheck.ts +12 -4
- package/src/modules/customers/commands/deals.ts +34 -59
- package/src/modules/customers/commands/interactions.ts +1 -1
- package/src/modules/customers/commands/personCompanyLinks.ts +224 -8
- package/src/modules/customers/components/CustomerTodosTable.tsx +2 -0
- package/src/modules/customers/components/DealsKpiStrip.tsx +7 -7
- package/src/modules/customers/components/calendar/AgendaList.tsx +3 -3
- package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +1 -1
- package/src/modules/customers/components/calendar/CalendarScreen.tsx +1 -1
- package/src/modules/customers/components/calendar/CalendarSettingsModal.tsx +1 -1
- package/src/modules/customers/components/calendar/EventBlock.tsx +2 -2
- package/src/modules/customers/components/calendar/EventPeekPopover.tsx +4 -2
- package/src/modules/customers/components/calendar/editor/PeopleField.tsx +61 -5
- package/src/modules/customers/components/calendar/editor/hooks.ts +7 -1
- package/src/modules/customers/components/calendar/types.ts +2 -2
- package/src/modules/customers/components/detail/CompanyKpiBar.tsx +5 -4
- package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +8 -1
- package/src/modules/customers/components/detail/DealForm.tsx +22 -2
- package/src/modules/customers/components/detail/DealsSection.tsx +11 -5
- package/src/modules/customers/components/detail/EntityTagsDialog.tsx +58 -12
- package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +8 -1
- package/src/modules/customers/components/detail/hooks/usePersonTasks.ts +23 -14
- package/src/modules/customers/components/detail/schedule/ParticipantsField.tsx +5 -5
- package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +5 -5
- package/src/modules/customers/components/detail/types.ts +1 -1
- package/src/modules/customers/components/detail/utils.ts +15 -5
- package/src/modules/customers/data/entities.ts +1 -1
- package/src/modules/customers/data/validators.ts +50 -9
- package/src/modules/customers/events.ts +5 -0
- package/src/modules/customers/i18n/de.json +9 -1
- package/src/modules/customers/i18n/en.json +9 -1
- package/src/modules/customers/i18n/es.json +9 -1
- package/src/modules/customers/i18n/ko.json +9 -1
- package/src/modules/customers/i18n/pl.json +9 -1
- package/src/modules/customers/lib/calendar/conflicts.ts +10 -2
- package/src/modules/customers/lib/calendar/editorPayload.ts +4 -3
- package/src/modules/customers/lib/calendar/mapItem.ts +8 -3
- package/src/modules/customers/lib/calendar/participantIdentity.ts +17 -0
- package/src/modules/customers/lib/closureStage.ts +76 -0
- package/src/modules/customers/lib/dealStatus.ts +42 -0
- package/src/modules/customers/lib/detailReadAccess.ts +35 -0
- package/src/modules/customers/lib/findPeopleByAddresses.ts +8 -6
- package/src/modules/customers/lib/personCompanies.ts +136 -1
- package/src/modules/customers/lib/todoCompatibility.ts +19 -1
- package/src/modules/dashboards/i18n/es.json +4 -4
- package/src/modules/dashboards/i18n/pl.json +7 -7
- package/src/modules/dashboards/lib/widgetScope.ts +6 -0
- package/src/modules/data_sync/AGENTS.md +1 -1
- package/src/modules/data_sync/backend/data-sync/page.tsx +4 -1
- package/src/modules/data_sync/lib/abandoned-run.ts +56 -0
- package/src/modules/data_sync/lib/adapter.ts +36 -0
- package/src/modules/data_sync/lib/sync-engine.ts +113 -5
- package/src/modules/data_sync/workers/sync-export.ts +4 -0
- package/src/modules/data_sync/workers/sync-import.ts +4 -0
- package/src/modules/devices/AGENTS.md +20 -1
- package/src/modules/devices/acl.ts +9 -1
- package/src/modules/devices/api/admin/devices/[id]/route.ts +5 -34
- package/src/modules/devices/api/admin/devices/route.ts +14 -1
- package/src/modules/devices/api/deviceList.ts +135 -11
- package/src/modules/devices/api/deviceSerialization.ts +50 -0
- package/src/modules/devices/api/openapi.ts +9 -1
- package/src/modules/devices/api/route.ts +9 -1
- package/src/modules/devices/backend/devices/[id]/page.tsx +18 -32
- package/src/modules/devices/backend/devices/create/page.tsx +17 -1
- package/src/modules/devices/backend/devices/page.tsx +44 -45
- package/src/modules/devices/backend/devices/useDeviceUserLabels.ts +45 -0
- package/src/modules/devices/backend/devices/userOptions.ts +99 -0
- package/src/modules/devices/i18n/de.json +3 -2
- package/src/modules/devices/i18n/en.json +3 -2
- package/src/modules/devices/i18n/es.json +3 -2
- package/src/modules/devices/i18n/ko.json +3 -2
- package/src/modules/devices/i18n/pl.json +3 -2
- package/src/modules/devices/setup.ts +6 -2
- package/src/modules/directory/backend/directory/organizations/page.tsx +3 -1
- package/src/modules/directory/backend/directory/tenants/page.tsx +3 -1
- package/src/modules/directory/di.ts +14 -2
- package/src/modules/directory/services/organizationHierarchyService.ts +34 -0
- package/src/modules/directory/services/organizationScopeService.ts +85 -0
- package/src/modules/directory/utils/organizationScope.ts +4 -15
- package/src/modules/entities/api/records.ts +2 -0
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +4 -1
- package/src/modules/eudr/api/plots/route.ts +4 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/plots/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/statements/page.tsx +4 -0
- package/src/modules/eudr/commands/statements.ts +0 -3
- package/src/modules/eudr/data/validators.ts +16 -1
- package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +2 -1
- package/src/modules/feature_toggles/components/OverridesTable.tsx +2 -1
- package/src/modules/feature_toggles/defaults.json +0 -8
- package/src/modules/inbox_ops/backend/inbox-ops/log/page.tsx +4 -0
- package/src/modules/inbox_ops/backend/inbox-ops/page.tsx +4 -0
- package/src/modules/inbox_ops/lib/htmlToPlainText.ts +1 -17
- package/src/modules/integrations/api/[id]/credentials/route.ts +6 -4
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +61 -31
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +44 -9
- package/src/modules/integrations/backend/integrations/credential-secret-fields.ts +84 -0
- package/src/modules/integrations/data/validators.ts +12 -2
- package/src/modules/integrations/i18n/de.json +1 -0
- package/src/modules/integrations/i18n/en.json +1 -0
- package/src/modules/integrations/i18n/es.json +1 -0
- package/src/modules/integrations/i18n/ko.json +1 -0
- package/src/modules/integrations/i18n/pl.json +1 -0
- package/src/modules/integrations/lib/credentials-masking.ts +10 -6
- package/src/modules/messages/api/[id]/route.ts +55 -1
- package/src/modules/messages/api/openapi.ts +20 -0
- package/src/modules/messages/api/route.ts +31 -2
- package/src/modules/messages/components/MessagesInboxPageClient.tsx +9 -16
- package/src/modules/messages/components/inboxFilters.ts +36 -0
- package/src/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.ts +14 -1
- package/src/modules/messages/components/message-detail/panels/MessageHeader.tsx +3 -1
- package/src/modules/messages/components/message-detail/panels/thread-panel.tsx +2 -1
- package/src/modules/messages/components/message-detail/types.ts +3 -0
- package/src/modules/messages/components/messageListLabels.ts +52 -3
- package/src/modules/messages/data/validators.ts +43 -4
- package/src/modules/messages/lib/channel-sender-identity.ts +55 -0
- package/src/modules/messages/lib/composeSourceChannelType.ts +95 -0
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +4 -6
- package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +4 -1
- package/src/modules/payment_gateways/lib/webhook-processor.ts +11 -0
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +4 -0
- package/src/modules/push_notifications/backend/push_notifications/page.tsx +4 -1
- package/src/modules/push_notifications/backend/push_notifications/send/page.tsx +4 -4
- package/src/modules/query_index/lib/engine.ts +249 -61
- package/src/modules/query_index/lib/search-entity-policy.ts +46 -0
- package/src/modules/query_index/lib/search-tokens.ts +135 -3
- package/src/modules/resources/backend/resources/resource-types/page.tsx +4 -1
- package/src/modules/resources/backend/resources/resources/page.tsx +4 -1
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +4 -0
- package/src/modules/sales/backend/sales/channels/page.tsx +4 -0
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +14 -8
- package/src/modules/sales/commands/documents.ts +93 -0
- package/src/modules/sales/components/PriceWithCurrency.tsx +17 -5
- package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +4 -0
- package/src/modules/sales/components/documents/AdjustmentsSection.tsx +6 -5
- package/src/modules/sales/components/documents/ItemsSection.tsx +56 -18
- package/src/modules/sales/components/documents/LineItemDialog.tsx +137 -20
- package/src/modules/sales/components/documents/PaymentsSection.tsx +20 -9
- package/src/modules/sales/components/documents/ReturnsSection.tsx +6 -5
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +106 -14
- package/src/modules/sales/components/documents/SalesOrderDraftLines.tsx +6 -5
- package/src/modules/sales/components/documents/ShipmentDialog.tsx +5 -4
- package/src/modules/sales/components/documents/ShipmentsSection.tsx +6 -5
- package/src/modules/sales/components/documents/lineItemShipmentLock.ts +74 -0
- package/src/modules/sales/components/documents/lineItemUtils.ts +7 -2
- package/src/modules/sales/data/entities.ts +6 -0
- package/src/modules/sales/extension-points.ts +1 -0
- package/src/modules/sales/i18n/de.json +8 -0
- package/src/modules/sales/i18n/en.json +8 -0
- package/src/modules/sales/i18n/es.json +8 -0
- package/src/modules/sales/i18n/ko.json +8 -0
- package/src/modules/sales/i18n/pl.json +8 -0
- package/src/modules/sales/lib/salesChannelsToggleSeed.ts +42 -0
- package/src/modules/sales/migrations/.snapshot-open-mercato.json +60 -0
- package/src/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.ts +87 -0
- package/src/modules/sales/setup.ts +2 -0
- package/src/modules/sales/widgets/injection/payment-gateway-status-column/widget.ts +9 -1
- package/src/modules/sales/widgets/injection-table.ts +4 -7
- package/src/modules/staff/backend/staff/leave-requests/page.tsx +4 -0
- package/src/modules/staff/backend/staff/my-leave-requests/page.tsx +4 -0
- package/src/modules/staff/backend/staff/team-members/page.tsx +6 -0
- package/src/modules/staff/backend/staff/team-roles/page.tsx +4 -0
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +4 -0
- package/src/modules/staff/backend/staff/teams/page.tsx +4 -0
- package/src/modules/staff/backend/staff/timesheets/page.tsx +12 -1
- package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +4 -0
- package/src/modules/sync_excel/lib/adapters/customers.ts +5 -0
- package/src/modules/warranty_claims/api/assignees/route.ts +3 -3
- package/src/modules/warranty_claims/api/portal/attachments/route.ts +2 -2
- package/src/modules/warranty_claims/api/portal/claims/route.ts +12 -9
- package/src/modules/warranty_claims/backend/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/registrations/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.tsx +4 -0
- package/src/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.tsx +4 -0
- package/src/modules/wms/api/warehouseSearch.ts +23 -0
- package/src/modules/wms/api/warehouses/route.ts +13 -9
- package/src/modules/wms/api/zones/route.ts +16 -0
- package/src/modules/wms/commands/configuration.ts +159 -10
- package/src/modules/wms/commands/inventory-actions.ts +3 -0
- package/src/modules/wms/commands/shared.ts +17 -0
- package/src/modules/wms/components/backend/WarehouseEditDialog.tsx +216 -0
- package/src/modules/wms/components/backend/WmsConfigurationPage.tsx +95 -141
- package/src/modules/wms/components/backend/WmsInventoryConsolePage.tsx +2 -0
- package/src/modules/wms/components/backend/WmsLotsListPage.tsx +2 -0
- package/src/modules/wms/components/backend/inventoryMutationLoaders.ts +36 -20
- package/src/modules/wms/components/backend/warehouseFormOptions.ts +72 -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 +2 -0
- package/src/modules/wms/i18n/pl.json +2 -0
- package/src/modules/workflows/backend/definitions/page.tsx +4 -1
- package/src/modules/workflows/backend/events/page.tsx +4 -1
- package/src/modules/workflows/backend/instances/page.tsx +4 -1
- package/src/modules/workflows/backend/tasks/page.tsx +4 -1
- package/src/modules/workflows/lib/activity-executor.ts +9 -0
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { getChannelAdapterRegistry } from './lib/adapter-registry-singleton'
|
|
12
12
|
import { ensureTestSeedAdapterRegistered } from './lib/test-seed'
|
|
13
13
|
import { sendAsUser } from './lib/send-as-user'
|
|
14
|
+
import { resolveChannelTypeSafely } from './lib/resolve-channel-type'
|
|
14
15
|
|
|
15
16
|
export function register(container: AppContainer) {
|
|
16
17
|
// Test-only: register the network-free stub channel adapter when
|
|
@@ -36,5 +37,11 @@ export function register(container: AppContainer) {
|
|
|
36
37
|
// In-process send-as-user facade. Cross-module callers (e.g. the customers
|
|
37
38
|
// compose route) resolve this instead of making an HTTP self-call.
|
|
38
39
|
communicationChannelsSendAsUser: asValue(sendAsUser),
|
|
40
|
+
|
|
41
|
+
// Cross-module channel-type lookup. The messages compose route resolves this
|
|
42
|
+
// to decide whether an external correspondent must carry an email address
|
|
43
|
+
// (#4975); absent module or failed lookup reads as "unknown", which the
|
|
44
|
+
// messages validator handles fail-closed.
|
|
45
|
+
communicationChannelsResolveChannelType: asValue(resolveChannelTypeSafely),
|
|
39
46
|
})
|
|
40
47
|
}
|
|
@@ -48,6 +48,20 @@ export interface ChannelCapabilities {
|
|
|
48
48
|
* Optional; existing chat providers (Slack, WhatsApp) omit and are treated as `true`.
|
|
49
49
|
*/
|
|
50
50
|
realtimePush?: boolean
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Shape of the outbound recipient this provider's `sendMessage` accepts as
|
|
54
|
+
* `metadata.to`. Optional; when absent the hub validates recipients as email
|
|
55
|
+
* addresses, so every provider that predates this field keeps its exact
|
|
56
|
+
* behavior.
|
|
57
|
+
*
|
|
58
|
+
* Declare `'provider-native'` when recipients are provider-issued identifiers
|
|
59
|
+
* rather than email addresses (e.g. a Discord channel snowflake). The hub then
|
|
60
|
+
* applies transport-safety checks only (see `validateOutboundRecipient`) and
|
|
61
|
+
* the adapter owns the provider-specific format — it MUST treat the value as
|
|
62
|
+
* untrusted input.
|
|
63
|
+
*/
|
|
64
|
+
recipientFormat?: 'email' | 'provider-native'
|
|
51
65
|
}
|
|
52
66
|
|
|
53
67
|
// ── Send / status / sender listing ────────────────────────────
|
|
@@ -57,4 +57,8 @@ export const baseEmailCapabilities: ChannelCapabilities = {
|
|
|
57
57
|
|
|
58
58
|
// Polling (real-time push deferred to v2 for all email providers)
|
|
59
59
|
realtimePush: false,
|
|
60
|
+
|
|
61
|
+
// Stated rather than left to the default so the email baseline reads as an
|
|
62
|
+
// explicit choice: outbound recipients here are addresses, not provider ids.
|
|
63
|
+
recipientFormat: 'email',
|
|
60
64
|
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import type { ChannelCapabilities } from './adapter'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Upper bound shared by both recipient shapes. 320 is the RFC 5321 maximum for
|
|
6
|
+
* an email address (64 local + `@` + 255 domain); provider-native identifiers
|
|
7
|
+
* are far shorter, so one ceiling covers both.
|
|
8
|
+
*/
|
|
9
|
+
export const MAX_OUTBOUND_RECIPIENT_LENGTH = 320
|
|
10
|
+
|
|
11
|
+
const emailRecipientSchema = z.string().email()
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Characters a provider-native recipient may contain. This is an allowlist, not a
|
|
15
|
+
* denylist, because the recipient reaches adapters that interpolate it into a REST
|
|
16
|
+
* path (Discord posts to `/channels/{recipient}/messages`), and a denylist fails
|
|
17
|
+
* open on every character nobody thought of — percent-encoded separators
|
|
18
|
+
* (`%2F`, `%2e%2e%2f`) and control bytes (NUL, DEL) all walked through the
|
|
19
|
+
* previous `[\r\n\s/\\?#]` class. An allowlist fails closed instead: the worst
|
|
20
|
+
* case is a provider whose identifier alphabet needs widening, which is a
|
|
21
|
+
* reviewable one-line change rather than a silent path-steering primitive.
|
|
22
|
+
*
|
|
23
|
+
* The set covers every provider-native identifier shape the hub has to carry
|
|
24
|
+
* today — Discord snowflakes (digits), Slack-style ids (alphanumerics), and email
|
|
25
|
+
* addresses, since `'provider-native'` must never narrow what `'email'` accepts.
|
|
26
|
+
*/
|
|
27
|
+
const PROVIDER_NATIVE_ALLOWED = /^[A-Za-z0-9._:@+-]+$/
|
|
28
|
+
|
|
29
|
+
export type OutboundRecipientCheck = { ok: true } | { ok: false; error: string }
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Validate an outbound recipient against the provider's declared recipient
|
|
33
|
+
* shape.
|
|
34
|
+
*
|
|
35
|
+
* The hub used to hard-wire `z.string().email()` on every outbound endpoint,
|
|
36
|
+
* which left providers whose recipients are not email addresses with no product
|
|
37
|
+
* path to send at all (#4976). Validation now follows the adapter's
|
|
38
|
+
* `capabilities.recipientFormat`, defaulting to `'email'` so every existing
|
|
39
|
+
* provider keeps byte-identical behavior.
|
|
40
|
+
*/
|
|
41
|
+
export function validateOutboundRecipient(
|
|
42
|
+
recipient: unknown,
|
|
43
|
+
capabilities: Pick<ChannelCapabilities, 'recipientFormat'> | null | undefined,
|
|
44
|
+
): OutboundRecipientCheck {
|
|
45
|
+
if (typeof recipient !== 'string' || recipient.length === 0) {
|
|
46
|
+
return { ok: false, error: 'Recipient is required' }
|
|
47
|
+
}
|
|
48
|
+
if (recipient.length > MAX_OUTBOUND_RECIPIENT_LENGTH) {
|
|
49
|
+
return {
|
|
50
|
+
ok: false,
|
|
51
|
+
error: `Recipient must be at most ${MAX_OUTBOUND_RECIPIENT_LENGTH} characters`,
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (capabilities?.recipientFormat !== 'provider-native') {
|
|
55
|
+
return emailRecipientSchema.safeParse(recipient).success
|
|
56
|
+
? { ok: true }
|
|
57
|
+
: { ok: false, error: 'Recipient must be a valid email address' }
|
|
58
|
+
}
|
|
59
|
+
if (!PROVIDER_NATIVE_ALLOWED.test(recipient)) {
|
|
60
|
+
return {
|
|
61
|
+
ok: false,
|
|
62
|
+
error: 'Recipient may only contain letters, digits, and the characters . _ : @ + -',
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// `.` is allowed (email addresses need it), so traversal still has to be
|
|
66
|
+
// rejected explicitly even though the separators it would need are not.
|
|
67
|
+
if (recipient.includes('..')) {
|
|
68
|
+
return { ok: false, error: 'Recipient must not contain ".."' }
|
|
69
|
+
}
|
|
70
|
+
return { ok: true }
|
|
71
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
2
|
+
import type { AppContainer } from '@open-mercato/shared/lib/di/container'
|
|
3
|
+
import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
4
|
+
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
5
|
+
import { CommunicationChannel, ExternalConversation, MessageChannelLink } from '../data/entities'
|
|
6
|
+
|
|
7
|
+
const logger = createLogger('communication_channels').child({ component: 'resolve-channel-type' })
|
|
8
|
+
|
|
9
|
+
export type ChannelTypeScope = {
|
|
10
|
+
tenantId: string
|
|
11
|
+
organizationId: string | null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type ChannelTypeReference = {
|
|
15
|
+
/** `ExternalConversation.id`, as carried by a message's `sourceEntityId`. */
|
|
16
|
+
externalConversationId?: string | null
|
|
17
|
+
/** A platform `messages.message` id that may be linked to a channel. */
|
|
18
|
+
messageId?: string | null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Resolve the channel type behind a platform message or conversation (#4975).
|
|
23
|
+
*
|
|
24
|
+
* Cross-module callers (the `messages` compose route) need to know whether an
|
|
25
|
+
* external correspondent is reachable by email before validating a compose
|
|
26
|
+
* payload, but `messages` may not reach into this module's entities. They
|
|
27
|
+
* resolve this facade from DI instead — mirroring `communicationChannelsSendAsUser`
|
|
28
|
+
* — and treat a `null` result as "unknown", which the messages validator
|
|
29
|
+
* handles fail-closed.
|
|
30
|
+
*
|
|
31
|
+
* Always tenant/organization scoped: a reference that does not resolve inside
|
|
32
|
+
* the caller's scope is reported as unknown rather than looked up globally.
|
|
33
|
+
*/
|
|
34
|
+
export async function resolveChannelType(
|
|
35
|
+
container: AppContainer,
|
|
36
|
+
scope: ChannelTypeScope,
|
|
37
|
+
reference: ChannelTypeReference,
|
|
38
|
+
): Promise<string | null> {
|
|
39
|
+
const em = (container.resolve('em') as EntityManager).fork()
|
|
40
|
+
const dscope = { tenantId: scope.tenantId, organizationId: scope.organizationId ?? null }
|
|
41
|
+
const baseFilter = { tenantId: scope.tenantId, organizationId: scope.organizationId ?? null }
|
|
42
|
+
|
|
43
|
+
let externalConversationId = reference.externalConversationId ?? null
|
|
44
|
+
|
|
45
|
+
if (!externalConversationId && reference.messageId) {
|
|
46
|
+
// The message is linked to a channel directly — `MessageChannelLink` carries
|
|
47
|
+
// a denormalized channel type, so this is the cheapest hop when it exists.
|
|
48
|
+
const link = await findOneWithDecryption(
|
|
49
|
+
em,
|
|
50
|
+
MessageChannelLink,
|
|
51
|
+
{ messageId: reference.messageId, ...baseFilter },
|
|
52
|
+
undefined,
|
|
53
|
+
dscope,
|
|
54
|
+
)
|
|
55
|
+
if (link?.channelType) return link.channelType
|
|
56
|
+
externalConversationId = link?.externalConversationId ?? null
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!externalConversationId) return null
|
|
60
|
+
|
|
61
|
+
const conversation = await findOneWithDecryption(
|
|
62
|
+
em,
|
|
63
|
+
ExternalConversation,
|
|
64
|
+
{ id: externalConversationId, ...baseFilter },
|
|
65
|
+
undefined,
|
|
66
|
+
dscope,
|
|
67
|
+
)
|
|
68
|
+
if (!conversation?.channelId) return null
|
|
69
|
+
|
|
70
|
+
const channel = await findOneWithDecryption(
|
|
71
|
+
em,
|
|
72
|
+
CommunicationChannel,
|
|
73
|
+
{ id: conversation.channelId, ...baseFilter, deletedAt: null },
|
|
74
|
+
undefined,
|
|
75
|
+
dscope,
|
|
76
|
+
)
|
|
77
|
+
return channel?.channelType ?? null
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Same contract, but never throws: a lookup failure degrades to "unknown" so a
|
|
82
|
+
* transient database error cannot turn into a 500 on an otherwise valid compose.
|
|
83
|
+
* Unknown is the safe answer — the messages validator fails closed on it.
|
|
84
|
+
*/
|
|
85
|
+
export async function resolveChannelTypeSafely(
|
|
86
|
+
container: AppContainer,
|
|
87
|
+
scope: ChannelTypeScope,
|
|
88
|
+
reference: ChannelTypeReference,
|
|
89
|
+
): Promise<string | null> {
|
|
90
|
+
try {
|
|
91
|
+
return await resolveChannelType(container, scope, reference)
|
|
92
|
+
} catch (err) {
|
|
93
|
+
logger.warn('channel type resolution failed, treating the channel as unknown', { err })
|
|
94
|
+
return null
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** DI service type for cross-module callers (resolve `communicationChannelsResolveChannelType`). */
|
|
99
|
+
export type ResolveChannelTypeService = typeof resolveChannelTypeSafely
|
|
@@ -41,6 +41,19 @@ import { hasChannelAdapter, registerChannelAdapter } from './adapter-registry-si
|
|
|
41
41
|
/** Provider key for the network-free test stub adapter. */
|
|
42
42
|
export const TEST_SEED_PROVIDER_KEY = '__test_seed__'
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Provider key for the network-free stub adapter that stands in for a CHAT
|
|
46
|
+
* provider — one whose senders are identified by an opaque handle and have no
|
|
47
|
+
* email address at all (Discord, Slack, Telegram…).
|
|
48
|
+
*
|
|
49
|
+
* It exists because the email-shaped stub above can only ever prove the hub
|
|
50
|
+
* accepts email-shaped data. That is precisely how CI stayed green while every
|
|
51
|
+
* real inbound Discord message was rejected (#4975): the fixture invented an
|
|
52
|
+
* address the provider can never produce. Tests that need to prove the hub's
|
|
53
|
+
* non-email identity contract MUST drive this provider instead.
|
|
54
|
+
*/
|
|
55
|
+
export const TEST_SEED_CHAT_PROVIDER_KEY = '__test_seed_chat__'
|
|
56
|
+
|
|
44
57
|
/** Env flag that unlocks test-only channel seeding. Off in production. */
|
|
45
58
|
export const TEST_CHANNEL_SEEDING_ENV = 'OM_ENABLE_TEST_CHANNEL_SEEDING'
|
|
46
59
|
|
|
@@ -72,8 +85,10 @@ const testSeedCapabilities: ChannelCapabilities = {
|
|
|
72
85
|
* delivery worker reach its success path and emit `communication_channels.message.sent`.
|
|
73
86
|
*/
|
|
74
87
|
class TestSeedChannelAdapter implements ChannelAdapter {
|
|
75
|
-
|
|
76
|
-
|
|
88
|
+
// Widened to `string` rather than inferred as a literal so the chat-flavoured
|
|
89
|
+
// subclass below can override both with its own provider key / channel type.
|
|
90
|
+
readonly providerKey: string = TEST_SEED_PROVIDER_KEY
|
|
91
|
+
readonly channelType: string = 'email'
|
|
77
92
|
readonly capabilities = testSeedCapabilities
|
|
78
93
|
|
|
79
94
|
async sendMessage(input: SendMessageInput): Promise<SendMessageResult> {
|
|
@@ -121,13 +136,54 @@ class TestSeedChannelAdapter implements ChannelAdapter {
|
|
|
121
136
|
}
|
|
122
137
|
}
|
|
123
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Chat-flavoured twin of {@link TestSeedChannelAdapter}: same network-free
|
|
141
|
+
* behaviour, but it declares a non-email `channelType`, so a channel connected
|
|
142
|
+
* through it is shaped like a real chat channel — including an
|
|
143
|
+
* `externalIdentifier` of NULL when no email-ish credential key is supplied.
|
|
144
|
+
*/
|
|
145
|
+
class TestSeedChatChannelAdapter extends TestSeedChannelAdapter {
|
|
146
|
+
readonly providerKey: string = TEST_SEED_CHAT_PROVIDER_KEY
|
|
147
|
+
readonly channelType: string = 'discord'
|
|
148
|
+
|
|
149
|
+
async normalizeInbound(raw: InboundMessage): Promise<NormalizedInboundMessage> {
|
|
150
|
+
// Unlike the email stub, this one is reachable: the test-seed ingest action
|
|
151
|
+
// feeds it a chat-shaped frame so the message travels the real ingest path
|
|
152
|
+
// (and therefore the real compose validation) rather than a SQL shortcut.
|
|
153
|
+
const frame = (raw.raw ?? {}) as Record<string, unknown>
|
|
154
|
+
const senderIdentifier = String(frame.senderIdentifier ?? '')
|
|
155
|
+
if (!senderIdentifier) {
|
|
156
|
+
throw new Error('[internal] TestSeedChatChannelAdapter requires a senderIdentifier')
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
externalMessageId: String(frame.externalMessageId ?? ''),
|
|
160
|
+
externalConversationId: String(frame.externalConversationId ?? ''),
|
|
161
|
+
senderIdentifier,
|
|
162
|
+
senderDisplayName:
|
|
163
|
+
typeof frame.senderDisplayName === 'string' ? frame.senderDisplayName : undefined,
|
|
164
|
+
body: typeof frame.body === 'string' ? frame.body : '',
|
|
165
|
+
bodyFormat: 'text',
|
|
166
|
+
timestamp: new Date(),
|
|
167
|
+
channelPayload: {},
|
|
168
|
+
channelContentType: 'text/plain',
|
|
169
|
+
channelMetadata: {},
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
124
174
|
let cachedTestSeedAdapter: TestSeedChannelAdapter | null = null
|
|
175
|
+
let cachedTestSeedChatAdapter: TestSeedChatChannelAdapter | null = null
|
|
125
176
|
|
|
126
177
|
function getTestSeedChannelAdapter(): TestSeedChannelAdapter {
|
|
127
178
|
if (!cachedTestSeedAdapter) cachedTestSeedAdapter = new TestSeedChannelAdapter()
|
|
128
179
|
return cachedTestSeedAdapter
|
|
129
180
|
}
|
|
130
181
|
|
|
182
|
+
function getTestSeedChatChannelAdapter(): TestSeedChatChannelAdapter {
|
|
183
|
+
if (!cachedTestSeedChatAdapter) cachedTestSeedChatAdapter = new TestSeedChatChannelAdapter()
|
|
184
|
+
return cachedTestSeedChatAdapter
|
|
185
|
+
}
|
|
186
|
+
|
|
131
187
|
/**
|
|
132
188
|
* Register the test-seed adapter exactly once, but ONLY when the env flag is set.
|
|
133
189
|
* Idempotent and safe to call from every container creation (`di.register`) — a
|
|
@@ -135,6 +191,10 @@ function getTestSeedChannelAdapter(): TestSeedChannelAdapter {
|
|
|
135
191
|
*/
|
|
136
192
|
export function ensureTestSeedAdapterRegistered(): void {
|
|
137
193
|
if (!isTestChannelSeedingEnabled()) return
|
|
138
|
-
if (hasChannelAdapter(TEST_SEED_PROVIDER_KEY))
|
|
139
|
-
|
|
194
|
+
if (!hasChannelAdapter(TEST_SEED_PROVIDER_KEY)) {
|
|
195
|
+
registerChannelAdapter(getTestSeedChannelAdapter())
|
|
196
|
+
}
|
|
197
|
+
if (!hasChannelAdapter(TEST_SEED_CHAT_PROVIDER_KEY)) {
|
|
198
|
+
registerChannelAdapter(getTestSeedChatChannelAdapter())
|
|
199
|
+
}
|
|
140
200
|
}
|
|
@@ -155,6 +155,8 @@
|
|
|
155
155
|
"configs.systemStatus.variables.entitiesBackcompatEav.label": "Legacy-EAV-Schreibvorgänge",
|
|
156
156
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.description": "Query-Index-Ergebnisse auch bei unvollständiger Abdeckung bereitstellen.",
|
|
157
157
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.label": "Teilindex-Nutzung erzwingen",
|
|
158
|
+
"configs.systemStatus.variables.listCountCap.description": "Maximal gemeldete Gesamtzahl einer Liste; die Zählung stoppt an der Obergrenze und begrenzte Summen werden z. B. als „10 000+“ angezeigt. 0 deaktiviert die Begrenzung.",
|
|
159
|
+
"configs.systemStatus.variables.listCountCap.label": "Obergrenze für Listenzählung",
|
|
158
160
|
"configs.systemStatus.variables.logLevel.description": "Fallback-Log-Level, wenn die Verbosität nicht gesetzt ist.",
|
|
159
161
|
"configs.systemStatus.variables.logLevel.label": "Log-Level",
|
|
160
162
|
"configs.systemStatus.variables.logVerbosity.description": "Überschreibt die strukturierte Log-Verbosität wie Debug oder Trace.",
|
|
@@ -155,6 +155,8 @@
|
|
|
155
155
|
"configs.systemStatus.variables.entitiesBackcompatEav.label": "Legacy EAV writes",
|
|
156
156
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.description": "Serve query index results even when coverage is partial.",
|
|
157
157
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.label": "Force partial index usage",
|
|
158
|
+
"configs.systemStatus.variables.listCountCap.description": "Maximum reported list total; counting stops at the cap and capped totals render as e.g. “10 000+”. 0 disables capping.",
|
|
159
|
+
"configs.systemStatus.variables.listCountCap.label": "List count cap",
|
|
158
160
|
"configs.systemStatus.variables.logLevel.description": "Fallback log level applied when verbosity is not set.",
|
|
159
161
|
"configs.systemStatus.variables.logLevel.label": "Log level",
|
|
160
162
|
"configs.systemStatus.variables.logVerbosity.description": "Overrides structured log verbosity such as debug or trace.",
|
|
@@ -155,6 +155,8 @@
|
|
|
155
155
|
"configs.systemStatus.variables.entitiesBackcompatEav.label": "Escrituras EAV heredadas",
|
|
156
156
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.description": "Servir resultados del índice de consultas incluso cuando la cobertura es parcial.",
|
|
157
157
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.label": "Forzar uso de índice parcial",
|
|
158
|
+
"configs.systemStatus.variables.listCountCap.description": "Total máximo informado en listas; el conteo se detiene en el límite y los totales limitados se muestran p. ej. como «10 000+». 0 desactiva el límite.",
|
|
159
|
+
"configs.systemStatus.variables.listCountCap.label": "Límite del conteo de listas",
|
|
158
160
|
"configs.systemStatus.variables.logLevel.description": "Nivel de registro de respaldo cuando la verbosidad no está configurada.",
|
|
159
161
|
"configs.systemStatus.variables.logLevel.label": "Nivel de registro",
|
|
160
162
|
"configs.systemStatus.variables.logVerbosity.description": "Anula la verbosidad del registro estructurado, como debug o trace.",
|
|
@@ -155,6 +155,8 @@
|
|
|
155
155
|
"configs.systemStatus.variables.entitiesBackcompatEav.label": "레거시 EAV 쓰기",
|
|
156
156
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.description": "커버리지가 부분적이어도 쿼리 인덱스 결과를 제공합니다.",
|
|
157
157
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.label": "부분 인덱스 사용 강제",
|
|
158
|
+
"configs.systemStatus.variables.listCountCap.description": "목록 총계의 최대 보고 값입니다. 카운트는 상한에서 멈추며 제한된 총계는 예를 들어 “10 000+”로 표시됩니다. 0이면 상한이 비활성화됩니다.",
|
|
159
|
+
"configs.systemStatus.variables.listCountCap.label": "목록 카운트 상한",
|
|
158
160
|
"configs.systemStatus.variables.logLevel.description": "상세 수준이 설정되지 않았을 때 적용되는 대체 로그 레벨입니다.",
|
|
159
161
|
"configs.systemStatus.variables.logLevel.label": "로그 레벨",
|
|
160
162
|
"configs.systemStatus.variables.logVerbosity.description": "debug나 trace와 같은 구조화된 로그 상세 수준을 재정의합니다.",
|
|
@@ -155,6 +155,8 @@
|
|
|
155
155
|
"configs.systemStatus.variables.entitiesBackcompatEav.label": "Zapis do legacy EAV",
|
|
156
156
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.description": "Pozwala korzystać z wyników indeksu zapytań nawet przy częściowym pokryciu.",
|
|
157
157
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.label": "Wymuś użycie częściowego indeksu",
|
|
158
|
+
"configs.systemStatus.variables.listCountCap.description": "Maksymalna raportowana liczba wyników listy; zliczanie zatrzymuje się na limicie, a ograniczone sumy są pokazywane np. jako „10 000+”. 0 wyłącza limit.",
|
|
159
|
+
"configs.systemStatus.variables.listCountCap.label": "Limit licznika list",
|
|
158
160
|
"configs.systemStatus.variables.logLevel.description": "Domyślny poziom logowania używany, gdy nie ustawiono szczegółowości.",
|
|
159
161
|
"configs.systemStatus.variables.logLevel.label": "Poziom logowania",
|
|
160
162
|
"configs.systemStatus.variables.logVerbosity.description": "Nadpisuje poziom szczegółowości logów, np. debug lub trace.",
|
|
@@ -267,6 +267,15 @@ export const SYSTEM_STATUS_VARIABLES: SystemStatusVariableDefinition[] = [
|
|
|
267
267
|
docUrl: `${SYSTEM_STATUS_DOC_BASE}#optimize_index_coverage_stats`,
|
|
268
268
|
defaultValue: 'false',
|
|
269
269
|
},
|
|
270
|
+
{
|
|
271
|
+
key: 'OM_LIST_COUNT_CAP',
|
|
272
|
+
category: 'query_index',
|
|
273
|
+
kind: 'string',
|
|
274
|
+
labelKey: 'configs.systemStatus.variables.listCountCap.label',
|
|
275
|
+
descriptionKey: 'configs.systemStatus.variables.listCountCap.description',
|
|
276
|
+
docUrl: `${SYSTEM_STATUS_DOC_BASE}#om_list_count_cap`,
|
|
277
|
+
defaultValue: '10000',
|
|
278
|
+
},
|
|
270
279
|
{
|
|
271
280
|
key: 'FORCE_QUERY_INDEX_ON_PARTIAL_INDEXES',
|
|
272
281
|
category: 'query_index',
|
|
@@ -9,6 +9,9 @@ Use the currencies module for multi-currency support, exchange rates, and curren
|
|
|
9
9
|
3. **MUST record both transaction currency and base currency amounts** — dual recording is mandatory for reporting
|
|
10
10
|
4. **MUST calculate realized gains/losses** on payment: `(payment rate - invoice rate) × foreign amount`
|
|
11
11
|
5. **MUST keep financial postings atomic** — full transaction rollback on error
|
|
12
|
+
6. **MUST NOT filter rate fetching by `isActive`** — that flag decides whether a currency can be
|
|
13
|
+
picked for something new, not whether it still needs a live rate. Rates are fetched for every
|
|
14
|
+
currency in scope that is not soft-deleted. See `services/README.md` → "Which Currencies Get Rates"
|
|
12
15
|
|
|
13
16
|
## Ask First
|
|
14
17
|
|
|
@@ -41,6 +41,7 @@ type ResponsePayload = {
|
|
|
41
41
|
total: number
|
|
42
42
|
page: number
|
|
43
43
|
totalPages: number
|
|
44
|
+
totalIsCapped?: boolean
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
export default function CurrenciesPage() {
|
|
@@ -50,6 +51,7 @@ export default function CurrenciesPage() {
|
|
|
50
51
|
const [page, setPage] = React.useState(1)
|
|
51
52
|
const [total, setTotal] = React.useState(0)
|
|
52
53
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
54
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
53
55
|
const [search, setSearch] = React.useState('')
|
|
54
56
|
const [filters, setFilters] = React.useState<FilterValues>({})
|
|
55
57
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
@@ -96,6 +98,7 @@ export default function CurrenciesPage() {
|
|
|
96
98
|
setRows(Array.isArray(payload.items) ? payload.items : [])
|
|
97
99
|
setTotal(payload.total || 0)
|
|
98
100
|
setTotalPages(payload.totalPages || 1)
|
|
101
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
99
102
|
}
|
|
100
103
|
} catch (error) {
|
|
101
104
|
if (!cancelled) {
|
|
@@ -342,7 +345,7 @@ export default function CurrenciesPage() {
|
|
|
342
345
|
createLabel={t('currencies.list.actions.create')}
|
|
343
346
|
/>
|
|
344
347
|
)}
|
|
345
|
-
pagination={{ page, pageSize: 50, total, totalPages, onPageChange: setPage }}
|
|
348
|
+
pagination={{ page, pageSize: 50, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
346
349
|
isLoading={isLoading}
|
|
347
350
|
perspective={{ tableId: extensionPoints.hosts.currenciesTable.tableId }}
|
|
348
351
|
/>
|
|
@@ -42,6 +42,7 @@ type ResponsePayload = {
|
|
|
42
42
|
total: number
|
|
43
43
|
page: number
|
|
44
44
|
totalPages: number
|
|
45
|
+
totalIsCapped?: boolean
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
export default function ExchangeRatesPage() {
|
|
@@ -51,6 +52,7 @@ export default function ExchangeRatesPage() {
|
|
|
51
52
|
const [page, setPage] = React.useState(1)
|
|
52
53
|
const [total, setTotal] = React.useState(0)
|
|
53
54
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
55
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
54
56
|
const [search, setSearch] = React.useState('')
|
|
55
57
|
const [filters, setFilters] = React.useState<FilterValues>({})
|
|
56
58
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
@@ -100,6 +102,7 @@ export default function ExchangeRatesPage() {
|
|
|
100
102
|
setRows(Array.isArray(payload.items) ? payload.items : [])
|
|
101
103
|
setTotal(payload.total || 0)
|
|
102
104
|
setTotalPages(payload.totalPages || 1)
|
|
105
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
103
106
|
}
|
|
104
107
|
} catch (error) {
|
|
105
108
|
if (!cancelled) {
|
|
@@ -332,7 +335,7 @@ export default function ExchangeRatesPage() {
|
|
|
332
335
|
createLabel={t('exchangeRates.list.actions.create')}
|
|
333
336
|
/>
|
|
334
337
|
)}
|
|
335
|
-
pagination={{ page, pageSize: 50, total, totalPages, onPageChange: setPage }}
|
|
338
|
+
pagination={{ page, pageSize: 50, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
336
339
|
isLoading={isLoading}
|
|
337
340
|
perspective={{ tableId: extensionPoints.hosts.exchangeRatesTable.tableId }}
|
|
338
341
|
/>
|
|
@@ -282,6 +282,51 @@ console.log(`By provider:`, result.byProvider)
|
|
|
282
282
|
console.log(`Errors:`, result.errors)
|
|
283
283
|
```
|
|
284
284
|
|
|
285
|
+
### Which Currencies Get Rates
|
|
286
|
+
|
|
287
|
+
`fetchRatesForDate` first resolves the set of currency codes worth storing rates for, then filters
|
|
288
|
+
every provider response against it — a rate is kept only when **both** legs of its pair are in the
|
|
289
|
+
set. The set is every currency in the tenant/organization scope that is not soft-deleted.
|
|
290
|
+
|
|
291
|
+
`isActive` deliberately plays no part here. That flag answers whether a currency may be **selected**
|
|
292
|
+
for something new (it gates `api/currencies/options`, the `?isActive` list filter and the
|
|
293
|
+
exchange-rate form's currency select), which says nothing about whether records already denominated
|
|
294
|
+
in it must stay convertible. Deactivating a currency while existing records still reference it is
|
|
295
|
+
the normal way to grandfather it, and those records keep needing a rate — otherwise conversions out
|
|
296
|
+
of the currency start failing once the stored rates fall outside the consumer's lookback window.
|
|
297
|
+
`ExchangeRateService` defaults to `maxDaysBack: 30`, but consumers override it — the deal-value
|
|
298
|
+
conversions in `customers/api/deals/{aggregate,summary}` pass `maxDaysBack: 60`, so a currency that
|
|
299
|
+
stopped accruing rates drops out of pipeline totals (`convertedAll: false`, no error surfaced)
|
|
300
|
+
roughly 60 days later.
|
|
301
|
+
|
|
302
|
+
**Soft delete is the only thing that stops a currency from accruing rates.** `deletedAt` excludes it
|
|
303
|
+
from the set; nothing else does, `isActive` included.
|
|
304
|
+
|
|
305
|
+
Reaching `deletedAt` takes two steps, in this order, because `deleteCurrencyCommand` refuses the
|
|
306
|
+
delete while the currency still has live rates — the very rates fetching keeps writing
|
|
307
|
+
(`storeRates` stores each one with `isActive: true`):
|
|
308
|
+
|
|
309
|
+
1. Delete or deactivate every `exchange_rates` row whose `fromCurrencyCode` or `toCurrencyCode` is
|
|
310
|
+
the currency, otherwise `DELETE /api/currencies/currencies` answers
|
|
311
|
+
`400 Cannot delete currency XXX because it has N active exchange rate(s)`.
|
|
312
|
+
2. Soft-delete the currency, with no fetch in between. Any fetch in that window — the "Fetch rates"
|
|
313
|
+
button, `mercato currencies fetch-rates`, or `ExchangeRateService`'s `autoFetch` (which defaults
|
|
314
|
+
to `true`) — recreates the rates and re-blocks the delete.
|
|
315
|
+
|
|
316
|
+
There is deliberately **no reversible way to pause rate accrual for a single currency**. An earlier
|
|
317
|
+
draft of this change added a `Currency.fetchRatesWhenInactive` opt-in column for exactly that and it
|
|
318
|
+
was dropped: an extra column to express "grandfathered but still convertible" is the state
|
|
319
|
+
`isActive: false` already describes, and the cost of keeping a currency in the set is bounded (see
|
|
320
|
+
below). Soft delete is the terminal off-switch, not a pause.
|
|
321
|
+
|
|
322
|
+
Note that both bundled providers (NBP, Raiffeisen) return `[]` outright when `PLN` is missing from
|
|
323
|
+
the set, so a `PLN` that fell out of it silenced the entire provider rather than just `PLN`'s own
|
|
324
|
+
pairs — another reason the set is not narrowed by selectability.
|
|
325
|
+
|
|
326
|
+
Keeping the set wide costs no extra provider calls: both providers fetch a full table in a single
|
|
327
|
+
request per date and the set is applied locally. The only cost is additional `exchange_rates` rows,
|
|
328
|
+
bounded by what the provider returns anyway.
|
|
329
|
+
|
|
285
330
|
### When to Use RateFetchingService Directly
|
|
286
331
|
|
|
287
332
|
- Scheduled/batch fetching of rates
|
|
@@ -131,6 +131,12 @@ export class RateFetchingService {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Currencies whose rates are worth storing. Deliberately not filtered by `isActive`: that flag
|
|
136
|
+
* answers whether a currency may be picked for something new, which says nothing about whether
|
|
137
|
+
* records already denominated in it must stay convertible. Soft delete is what takes a currency
|
|
138
|
+
* out of rate fetching.
|
|
139
|
+
*/
|
|
134
140
|
private async getExistingCurrencies(scope: {
|
|
135
141
|
tenantId: string
|
|
136
142
|
organizationId: string
|
|
@@ -138,7 +144,6 @@ export class RateFetchingService {
|
|
|
138
144
|
return this.em.find(Currency, {
|
|
139
145
|
tenantId: scope.tenantId,
|
|
140
146
|
organizationId: scope.organizationId,
|
|
141
|
-
isActive: true,
|
|
142
147
|
deletedAt: null,
|
|
143
148
|
})
|
|
144
149
|
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import { registerDomainSchema } from '@open-mercato/core/modules/customer_accounts/data/validators'
|
|
15
15
|
import {
|
|
16
16
|
DomainMappingService,
|
|
17
|
+
DomainMappingOrgScopeError,
|
|
17
18
|
type ResolveResult,
|
|
18
19
|
} from '@open-mercato/core/modules/customer_accounts/services/domainMappingService'
|
|
19
20
|
import { DomainMapping } from '@open-mercato/core/modules/customer_accounts/data/entities'
|
|
@@ -142,6 +143,12 @@ export async function POST(req: Request) {
|
|
|
142
143
|
{ status: 409 },
|
|
143
144
|
)
|
|
144
145
|
}
|
|
146
|
+
if (err instanceof DomainMappingOrgScopeError) {
|
|
147
|
+
return NextResponse.json(
|
|
148
|
+
{ ok: false, error: 'Organization was not found in the current tenant.' },
|
|
149
|
+
{ status: 400 },
|
|
150
|
+
)
|
|
151
|
+
}
|
|
145
152
|
const message = err instanceof Error ? err.message : 'Failed to register domain'
|
|
146
153
|
return NextResponse.json({ ok: false, error: message }, { status: 500 })
|
|
147
154
|
}
|
|
@@ -34,6 +34,7 @@ type RolesResponse = {
|
|
|
34
34
|
items?: RoleRow[]
|
|
35
35
|
total?: number
|
|
36
36
|
totalPages?: number
|
|
37
|
+
totalIsCapped?: boolean
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export default function CustomerRolesPage() {
|
|
@@ -45,6 +46,7 @@ export default function CustomerRolesPage() {
|
|
|
45
46
|
const [pageSize] = React.useState(50)
|
|
46
47
|
const [total, setTotal] = React.useState(0)
|
|
47
48
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
49
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
48
50
|
const [search, setSearch] = React.useState('')
|
|
49
51
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
50
52
|
const [reloadToken, setReloadToken] = React.useState(0)
|
|
@@ -88,6 +90,7 @@ export default function CustomerRolesPage() {
|
|
|
88
90
|
setRows(items)
|
|
89
91
|
setTotal(typeof payload?.total === 'number' ? payload.total : items.length)
|
|
90
92
|
setTotalPages(typeof payload?.totalPages === 'number' ? payload.totalPages : 1)
|
|
93
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
91
94
|
} catch (err) {
|
|
92
95
|
if (!cancelled) {
|
|
93
96
|
const message = err instanceof Error ? err.message : t('customer_accounts.admin.roles.error.load', 'Failed to load roles')
|
|
@@ -240,7 +243,7 @@ export default function CustomerRolesPage() {
|
|
|
240
243
|
]}
|
|
241
244
|
/>
|
|
242
245
|
)}
|
|
243
|
-
pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}
|
|
246
|
+
pagination={{ page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
244
247
|
isLoading={isLoading}
|
|
245
248
|
/>
|
|
246
249
|
</PageBody>
|
package/src/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.tsx
CHANGED
|
@@ -41,6 +41,7 @@ type UsersResponse = {
|
|
|
41
41
|
items?: UserRow[]
|
|
42
42
|
total?: number
|
|
43
43
|
totalPages?: number
|
|
44
|
+
totalIsCapped?: boolean
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
function formatDate(value: string | null | undefined, fallback: string): string {
|
|
@@ -239,6 +240,7 @@ export function PortalUsersPageClient({ portalOrigin }: PortalUsersPageClientPro
|
|
|
239
240
|
const [pageSize] = React.useState(50)
|
|
240
241
|
const [total, setTotal] = React.useState(0)
|
|
241
242
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
243
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
242
244
|
const [search, setSearch] = React.useState('')
|
|
243
245
|
const [filterValues, setFilterValues] = React.useState<FilterValues>({})
|
|
244
246
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
@@ -318,6 +320,7 @@ export function PortalUsersPageClient({ portalOrigin }: PortalUsersPageClientPro
|
|
|
318
320
|
setRows(items)
|
|
319
321
|
setTotal(typeof payload?.total === 'number' ? payload.total : items.length)
|
|
320
322
|
setTotalPages(typeof payload?.totalPages === 'number' ? payload.totalPages : 1)
|
|
323
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
321
324
|
} catch (err) {
|
|
322
325
|
if (!cancelled) {
|
|
323
326
|
const message = err instanceof Error ? err.message : t('customer_accounts.admin.error.loadUsers', 'Failed to load customer users')
|
|
@@ -582,7 +585,7 @@ export function PortalUsersPageClient({ portalOrigin }: PortalUsersPageClientPro
|
|
|
582
585
|
]}
|
|
583
586
|
/>
|
|
584
587
|
)}
|
|
585
|
-
pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}
|
|
588
|
+
pagination={{ page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
586
589
|
isLoading={isLoading}
|
|
587
590
|
/>
|
|
588
591
|
<CreateUserDialog
|