@open-mercato/core 0.7.0 → 0.7.1-develop.7103.1.41ff100d93
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 +14 -9
- package/dist/modules/customers/api/deals/aggregate/route.js.map +2 -2
- package/dist/modules/customers/api/deals/map/route.js +5 -5
- 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 +17 -9
- package/src/modules/customers/api/deals/map/route.ts +4 -4
- 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
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
2
|
+
import { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
3
|
+
import { CustomerPipelineStage } from '../data/entities'
|
|
4
|
+
|
|
5
|
+
export type DealClosureOutcome = 'won' | 'lost'
|
|
6
|
+
|
|
7
|
+
export type PipelineStageSnapshot = {
|
|
8
|
+
id: string
|
|
9
|
+
pipelineId: string
|
|
10
|
+
label: string
|
|
11
|
+
order: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Stage labels that mark a pipeline as terminal for a given closure outcome. Matching is
|
|
15
|
+
// label-based because stages are tenant-configurable rows; see #5107.
|
|
16
|
+
export const TERMINAL_PIPELINE_STAGE_LABELS: Record<DealClosureOutcome, ReadonlySet<string>> = {
|
|
17
|
+
won: new Set(['won', 'win', 'closed won', 'closed win']),
|
|
18
|
+
lost: new Set(['lost', 'loose', 'closed lost', 'closed loose']),
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Map a deal status spelling (UI `win`/`loose` or AI `won`/`lost`) to its closure
|
|
23
|
+
* outcome. Case-insensitive because callers such as the AI tool pass free-form model
|
|
24
|
+
* text through, while every persisted status is lower-case.
|
|
25
|
+
*/
|
|
26
|
+
export function dealClosureOutcomeFromStatus(status: string | null | undefined): DealClosureOutcome | null {
|
|
27
|
+
const normalized = typeof status === 'string' ? status.trim().toLowerCase() : status
|
|
28
|
+
if (normalized === 'win' || normalized === 'won') return 'won'
|
|
29
|
+
if (normalized === 'loose' || normalized === 'lost') return 'lost'
|
|
30
|
+
return null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function normalizePipelineStageLabel(value: string): string {
|
|
34
|
+
return value
|
|
35
|
+
.trim()
|
|
36
|
+
.toLowerCase()
|
|
37
|
+
.replace(/[^a-z0-9]+/g, ' ')
|
|
38
|
+
.trim()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Resolve the terminal stage of the deal's pipeline for a closure outcome, so every
|
|
43
|
+
* writer (command, AI tool preview) agrees on where a closed deal lands (#5107).
|
|
44
|
+
*/
|
|
45
|
+
export async function loadClosurePipelineStageSnapshot(
|
|
46
|
+
em: EntityManager,
|
|
47
|
+
input: {
|
|
48
|
+
pipelineId: string | null
|
|
49
|
+
closureOutcome: DealClosureOutcome
|
|
50
|
+
tenantId: string
|
|
51
|
+
organizationId: string
|
|
52
|
+
},
|
|
53
|
+
): Promise<PipelineStageSnapshot | null> {
|
|
54
|
+
if (!input.pipelineId) return null
|
|
55
|
+
|
|
56
|
+
const stages = await findWithDecryption(
|
|
57
|
+
em,
|
|
58
|
+
CustomerPipelineStage,
|
|
59
|
+
{
|
|
60
|
+
pipelineId: input.pipelineId,
|
|
61
|
+
tenantId: input.tenantId,
|
|
62
|
+
organizationId: input.organizationId,
|
|
63
|
+
},
|
|
64
|
+
{ orderBy: { order: 'ASC' } },
|
|
65
|
+
{ tenantId: input.tenantId, organizationId: input.organizationId },
|
|
66
|
+
)
|
|
67
|
+
const aliases = TERMINAL_PIPELINE_STAGE_LABELS[input.closureOutcome]
|
|
68
|
+
const stage = stages.find((candidate) => aliases.has(normalizePipelineStageLabel(candidate.label)))
|
|
69
|
+
if (!stage) return null
|
|
70
|
+
return {
|
|
71
|
+
id: stage.id,
|
|
72
|
+
pipelineId: stage.pipelineId,
|
|
73
|
+
label: stage.label,
|
|
74
|
+
order: stage.order,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -46,3 +46,45 @@ export function isClosedDealStatus(value: string | null | undefined): boolean {
|
|
|
46
46
|
export function isOpenDealStatus(value: string | null | undefined): boolean {
|
|
47
47
|
return !isClosedDealStatus(value)
|
|
48
48
|
}
|
|
49
|
+
|
|
50
|
+
export function canonicalDealStatus(value: string): string {
|
|
51
|
+
const lower = value.toLowerCase()
|
|
52
|
+
if (lower === 'won') return DEAL_STATUS_WIN
|
|
53
|
+
if (lower === 'lost') return DEAL_STATUS_LOSE
|
|
54
|
+
// Canonical spellings normalize to lower-case too, so an upper-case selection still
|
|
55
|
+
// matches the lower-case persisted values and dictionary options.
|
|
56
|
+
if (lower === 'win' || lower === 'loose' || lower === 'open' || lower === 'closed') return lower
|
|
57
|
+
return value
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Expand operator-selected status filter values into the canonical vocabulary so a
|
|
62
|
+
* single selection matches every spelling the supported writers persist (#5107).
|
|
63
|
+
*
|
|
64
|
+
* Alias groups (`win`/`won`, `loose`/`lost`, `closed`) are matched case-insensitively,
|
|
65
|
+
* expanded to their canonical spellings, and also keep the caller's original token so
|
|
66
|
+
* the result is always a strict superset of a verbatim match. Unknown values emit both
|
|
67
|
+
* the trimmed original and its lower-case form — mixed-case tenant dictionary statuses
|
|
68
|
+
* match exactly while `?status=Open` still hits lower-case stored rows.
|
|
69
|
+
*/
|
|
70
|
+
export function expandDealStatusAliases(values: string[]): string[] {
|
|
71
|
+
const out = new Set<string>()
|
|
72
|
+
for (const value of values) {
|
|
73
|
+
const trimmed = value.trim()
|
|
74
|
+
const lower = trimmed.toLowerCase()
|
|
75
|
+
if (lower === 'win' || lower === 'won') {
|
|
76
|
+
WON_DEAL_STATUS_LIST.forEach((entry) => out.add(entry))
|
|
77
|
+
out.add(trimmed)
|
|
78
|
+
} else if (lower === 'loose' || lower === 'lost') {
|
|
79
|
+
LOST_DEAL_STATUS_LIST.forEach((entry) => out.add(entry))
|
|
80
|
+
out.add(trimmed)
|
|
81
|
+
} else if (lower === 'closed') {
|
|
82
|
+
CLOSED_DEAL_STATUS_LIST.forEach((entry) => out.add(entry))
|
|
83
|
+
out.add(trimmed)
|
|
84
|
+
} else {
|
|
85
|
+
out.add(trimmed)
|
|
86
|
+
out.add(lower)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return Array.from(out)
|
|
90
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import {
|
|
3
|
+
isOrganizationReadAccessAllowed,
|
|
4
|
+
type OrganizationReadAccessInput,
|
|
5
|
+
} from '@open-mercato/core/modules/directory/utils/organizationScopeGuard'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Single-record customers detail routes (person / company / deal) must not leak
|
|
9
|
+
* whether a record exists through the organization-scope check.
|
|
10
|
+
*
|
|
11
|
+
* The API dispatcher already enforces each route's `metadata.requireFeatures`
|
|
12
|
+
* before the handler runs, returning a uniform `403` for callers who lack the
|
|
13
|
+
* grant — so that path never distinguishes an existing id from a missing one.
|
|
14
|
+
* The only remaining existence signal is the *post-load* organization guard: a
|
|
15
|
+
* caller who holds the feature but whose scope excludes the record's
|
|
16
|
+
* organization previously received `403` (record exists in another org) while a
|
|
17
|
+
* non-existent id received `404`. That 403-vs-404 split is an existence oracle
|
|
18
|
+
* (issue #5504).
|
|
19
|
+
*
|
|
20
|
+
* Collapse the organization-scope denial into the route's own not-found
|
|
21
|
+
* response so an out-of-scope caller cannot tell "exists in an organization you
|
|
22
|
+
* cannot see" from "does not exist" — the shape the api_keys hardening
|
|
23
|
+
* (#4033 / PR-4051) established. Sharing this decision keeps the three customers
|
|
24
|
+
* detail routes from drifting apart again.
|
|
25
|
+
*
|
|
26
|
+
* @returns the `404` response to return when read access is denied, or `null`
|
|
27
|
+
* when the caller may read the record.
|
|
28
|
+
*/
|
|
29
|
+
export function denyCustomerDetailReadAsNotFound(
|
|
30
|
+
input: OrganizationReadAccessInput,
|
|
31
|
+
notFoundMessage: string,
|
|
32
|
+
): NextResponse | null {
|
|
33
|
+
if (isOrganizationReadAccessAllowed(input)) return null
|
|
34
|
+
return NextResponse.json({ error: notFoundMessage }, { status: 404 })
|
|
35
|
+
}
|
|
@@ -32,13 +32,15 @@ export interface MatchedPerson {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
* Max
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
35
|
+
* Max rows scanned by in-memory fallback matches over encrypted contact
|
|
36
|
+
* columns (`primary_email` here, `primary_phone` in the check-phone route).
|
|
37
|
+
* These columns are GDPR-encrypted with a random IV (see
|
|
38
|
+
* `customers/encryption.ts`), so they cannot be filtered by value in SQL when
|
|
39
|
+
* tenant data encryption is on — fallbacks decrypt recent rows and compare in
|
|
40
|
+
* memory instead. Bounded to keep interactive lookups cheap; a blind-index
|
|
41
|
+
* (hash) column per field is the follow-up if tenants outgrow it (#5515).
|
|
40
42
|
*/
|
|
41
|
-
const MATCH_CANDIDATE_LIMIT = 500
|
|
43
|
+
export const MATCH_CANDIDATE_LIMIT = 500
|
|
42
44
|
|
|
43
45
|
/**
|
|
44
46
|
* Batch lookup of CustomerEntity rows (kind='person') whose `primaryEmail`
|
|
@@ -56,6 +56,136 @@ async function requireCompany(
|
|
|
56
56
|
return company
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
export type CompanyPersonUnionEntry = {
|
|
60
|
+
entity: CustomerEntity
|
|
61
|
+
profile: CustomerPersonProfile | null
|
|
62
|
+
linkedAt: string | null
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Resolve "people belonging to this company" as the union of active
|
|
67
|
+
* `CustomerPersonCompanyLink` rows and `CustomerPersonProfile.company`
|
|
68
|
+
* profile-only assignments (data that never got a link row, e.g. from
|
|
69
|
+
* migrated CRM imports). This is the single source of truth for both the
|
|
70
|
+
* company People tab list and its badge count — see #5114.
|
|
71
|
+
*/
|
|
72
|
+
export async function loadCompanyPeopleUnion(
|
|
73
|
+
em: EntityManager,
|
|
74
|
+
company: CustomerEntity,
|
|
75
|
+
scope: { tenantId?: string | null; organizationId?: string | null },
|
|
76
|
+
): Promise<CompanyPersonUnionEntry[]> {
|
|
77
|
+
const decryptionScope = {
|
|
78
|
+
tenantId: scope.tenantId ?? company.tenantId ?? null,
|
|
79
|
+
organizationId: scope.organizationId ?? company.organizationId ?? null,
|
|
80
|
+
}
|
|
81
|
+
const relatedPeopleById = new Map<string, CompanyPersonUnionEntry>()
|
|
82
|
+
|
|
83
|
+
const companyLinkWhere = await withActiveCustomerPersonCompanyLinkFilter(
|
|
84
|
+
em,
|
|
85
|
+
{ company: company.id, organizationId: company.organizationId, tenantId: company.tenantId },
|
|
86
|
+
'customers.companies.loadCompanyPeopleUnion',
|
|
87
|
+
)
|
|
88
|
+
const companyLinks = filterActivePersonCompanyLinks(
|
|
89
|
+
await findWithDecryption(
|
|
90
|
+
em,
|
|
91
|
+
CustomerPersonCompanyLink,
|
|
92
|
+
companyLinkWhere,
|
|
93
|
+
{ populate: ['person', 'person.personProfile'], orderBy: { isPrimary: 'desc', createdAt: 'asc' } },
|
|
94
|
+
decryptionScope,
|
|
95
|
+
),
|
|
96
|
+
)
|
|
97
|
+
companyLinks.forEach((link) => {
|
|
98
|
+
const entity = typeof link.person === 'string' ? null : link.person
|
|
99
|
+
if (!entity || entity.kind !== 'person' || entity.deletedAt) return
|
|
100
|
+
const personProfile =
|
|
101
|
+
entity.personProfile && typeof entity.personProfile !== 'string' ? entity.personProfile : null
|
|
102
|
+
relatedPeopleById.set(entity.id, {
|
|
103
|
+
entity,
|
|
104
|
+
profile: personProfile,
|
|
105
|
+
linkedAt: link.createdAt instanceof Date ? link.createdAt.toISOString() : null,
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
const profiles = await findWithDecryption(
|
|
110
|
+
em,
|
|
111
|
+
CustomerPersonProfile,
|
|
112
|
+
{
|
|
113
|
+
company: company.id,
|
|
114
|
+
tenantId: company.tenantId,
|
|
115
|
+
organizationId: company.organizationId,
|
|
116
|
+
entity: { deletedAt: null },
|
|
117
|
+
},
|
|
118
|
+
{ populate: ['entity'] },
|
|
119
|
+
decryptionScope,
|
|
120
|
+
)
|
|
121
|
+
profiles.forEach((entry) => {
|
|
122
|
+
const entity = entry.entity as CustomerEntity | null
|
|
123
|
+
if (!entity || entity.kind !== 'person' || entity.deletedAt) return
|
|
124
|
+
if (!relatedPeopleById.has(entity.id)) {
|
|
125
|
+
relatedPeopleById.set(entity.id, {
|
|
126
|
+
entity,
|
|
127
|
+
profile: entry ?? null,
|
|
128
|
+
linkedAt: entry.createdAt instanceof Date ? entry.createdAt.toISOString() : null,
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
return Array.from(relatedPeopleById.values())
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Count-only sibling of `loadCompanyPeopleUnion` for the company People badge, which
|
|
138
|
+
* needs the size of the union and nothing else. Both queries project just the foreign
|
|
139
|
+
* key column and push the `kind: 'person'` / `deletedAt: null` predicates into the
|
|
140
|
+
* WHERE clause, so no person row is hydrated and no PII is decrypted to produce a
|
|
141
|
+
* number — `findWithDecryption` is deliberately not used here because the projections
|
|
142
|
+
* select no encrypted column.
|
|
143
|
+
*/
|
|
144
|
+
export async function countCompanyPeopleUnion(
|
|
145
|
+
em: EntityManager,
|
|
146
|
+
company: CustomerEntity,
|
|
147
|
+
): Promise<number> {
|
|
148
|
+
const personIds = new Set<string>()
|
|
149
|
+
|
|
150
|
+
const companyLinkWhere = await withActiveCustomerPersonCompanyLinkFilter(
|
|
151
|
+
em,
|
|
152
|
+
{
|
|
153
|
+
company: company.id,
|
|
154
|
+
organizationId: company.organizationId,
|
|
155
|
+
tenantId: company.tenantId,
|
|
156
|
+
person: { kind: 'person', deletedAt: null },
|
|
157
|
+
},
|
|
158
|
+
'customers.companies.countCompanyPeopleUnion',
|
|
159
|
+
)
|
|
160
|
+
const companyLinks = filterActivePersonCompanyLinks(
|
|
161
|
+
await em.find(CustomerPersonCompanyLink, companyLinkWhere as any, {
|
|
162
|
+
fields: ['person', 'deletedAt'],
|
|
163
|
+
} as any),
|
|
164
|
+
)
|
|
165
|
+
companyLinks.forEach((link) => {
|
|
166
|
+
const personId = typeof link.person === 'string' ? link.person : link.person?.id
|
|
167
|
+
if (personId) personIds.add(personId)
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
const profiles = await em.find(
|
|
171
|
+
CustomerPersonProfile,
|
|
172
|
+
{
|
|
173
|
+
company: company.id,
|
|
174
|
+
tenantId: company.tenantId,
|
|
175
|
+
organizationId: company.organizationId,
|
|
176
|
+
entity: { kind: 'person', deletedAt: null },
|
|
177
|
+
} as any,
|
|
178
|
+
{ fields: ['entity'] } as any,
|
|
179
|
+
)
|
|
180
|
+
profiles.forEach((entry) => {
|
|
181
|
+
const entity = entry.entity as CustomerEntity | string | null
|
|
182
|
+
const entityId = typeof entity === 'string' ? entity : entity?.id
|
|
183
|
+
if (entityId) personIds.add(entityId)
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
return personIds.size
|
|
187
|
+
}
|
|
188
|
+
|
|
59
189
|
export async function loadPersonCompanyLinks(
|
|
60
190
|
em: EntityManager,
|
|
61
191
|
person: CustomerEntity,
|
|
@@ -298,7 +428,12 @@ export async function removePersonCompanyLink(
|
|
|
298
428
|
|
|
299
429
|
if (!link) {
|
|
300
430
|
if (profile.company && typeof profile.company !== 'string' && profile.company.id === linkId) {
|
|
301
|
-
|
|
431
|
+
// Profile-only assignment: no link row backs it, so only the legacy field is
|
|
432
|
+
// cleared. It must keep mirroring the primary link the way every other detach
|
|
433
|
+
// path leaves it, so promote a remaining primary link instead of nulling blindly.
|
|
434
|
+
const primary = existingLinks.find((entry) => entry.isPrimary) ?? null
|
|
435
|
+
const primaryCompany = primary ? resolveLinkedCompany(primary) : null
|
|
436
|
+
profile.company = primaryCompany ?? null
|
|
302
437
|
return
|
|
303
438
|
}
|
|
304
439
|
throw notFound('Company link not found')
|
|
@@ -78,6 +78,17 @@ export type CanonicalTodoListResult = {
|
|
|
78
78
|
total: number
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
function emptyCanonicalTodoList(): CanonicalTodoListResult {
|
|
82
|
+
return { items: [], bridgeIds: new Set(), total: 0 }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function isCollapsedRestrictedOrganizationScope(
|
|
86
|
+
organizationIds: string[] | null | undefined,
|
|
87
|
+
isUnrestricted: boolean | undefined,
|
|
88
|
+
): boolean {
|
|
89
|
+
return isUnrestricted !== true && (!organizationIds || organizationIds.length === 0)
|
|
90
|
+
}
|
|
91
|
+
|
|
81
92
|
export type ListTodosPagination = { page: number; pageSize: number }
|
|
82
93
|
|
|
83
94
|
function resolveLegacyTodoSource(source: string | null | undefined): string {
|
|
@@ -377,8 +388,11 @@ export async function listLegacyTodoRows(
|
|
|
377
388
|
tenantId: string,
|
|
378
389
|
organizationIds: string[] | null,
|
|
379
390
|
entityId: string | undefined,
|
|
380
|
-
options?: { limit?: number | null },
|
|
391
|
+
options?: { limit?: number | null; isUnrestricted?: boolean },
|
|
381
392
|
): Promise<CustomerTodoRow[]> {
|
|
393
|
+
if (isCollapsedRestrictedOrganizationScope(organizationIds, options?.isUnrestricted)) {
|
|
394
|
+
return []
|
|
395
|
+
}
|
|
382
396
|
const where: Record<string, unknown> = { tenantId }
|
|
383
397
|
if (organizationIds && organizationIds.length > 0) {
|
|
384
398
|
where.organizationId = { $in: organizationIds }
|
|
@@ -425,8 +439,12 @@ export async function listCanonicalTodoRows(
|
|
|
425
439
|
pagination?: ListTodosPagination | null
|
|
426
440
|
searchText?: string | null
|
|
427
441
|
limit?: number | null
|
|
442
|
+
isUnrestricted?: boolean
|
|
428
443
|
},
|
|
429
444
|
): Promise<CanonicalTodoListResult> {
|
|
445
|
+
if (isCollapsedRestrictedOrganizationScope(organizationIds, options?.isUnrestricted)) {
|
|
446
|
+
return emptyCanonicalTodoList()
|
|
447
|
+
}
|
|
430
448
|
const where: Record<string, unknown> = {
|
|
431
449
|
tenantId: auth.tenantId,
|
|
432
450
|
interactionType: 'task',
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
"dashboards.analytics.comparison.vsLastWeek": "vs semana pasada",
|
|
8
8
|
"dashboards.analytics.comparison.vsLastYear": "vs año pasado",
|
|
9
9
|
"dashboards.analytics.comparison.vsMonthBefore": "vs mes anterior",
|
|
10
|
-
"dashboards.analytics.comparison.vsPrevious30Days": "vs 30
|
|
11
|
-
"dashboards.analytics.comparison.vsPrevious7Days": "vs 7
|
|
12
|
-
"dashboards.analytics.comparison.vsPrevious90Days": "vs 90
|
|
13
|
-
"dashboards.analytics.comparison.vsPreviousPeriod": "vs
|
|
10
|
+
"dashboards.analytics.comparison.vsPrevious30Days": "vs 30 días anteriores",
|
|
11
|
+
"dashboards.analytics.comparison.vsPrevious7Days": "vs 7 días anteriores",
|
|
12
|
+
"dashboards.analytics.comparison.vsPrevious90Days": "vs 90 días anteriores",
|
|
13
|
+
"dashboards.analytics.comparison.vsPreviousPeriod": "vs período anterior",
|
|
14
14
|
"dashboards.analytics.comparison.vsQuarterBefore": "vs trimestre anterior",
|
|
15
15
|
"dashboards.analytics.comparison.vsWeekBefore": "vs semana anterior",
|
|
16
16
|
"dashboards.analytics.comparison.vsYearBefore": "vs año anterior",
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
"dashboards.analytics.chartVariant.donut": "Pierścieniowy",
|
|
3
3
|
"dashboards.analytics.chartVariant.pie": "Kołowy",
|
|
4
4
|
"dashboards.analytics.comparison.vsDayBefore": "vs przedwczoraj",
|
|
5
|
-
"dashboards.analytics.comparison.vsLastMonth": "vs poprzedni
|
|
6
|
-
"dashboards.analytics.comparison.vsLastQuarter": "vs poprzedni
|
|
7
|
-
"dashboards.analytics.comparison.vsLastWeek": "vs poprzedni
|
|
5
|
+
"dashboards.analytics.comparison.vsLastMonth": "vs poprzedni miesiąc",
|
|
6
|
+
"dashboards.analytics.comparison.vsLastQuarter": "vs poprzedni kwartał",
|
|
7
|
+
"dashboards.analytics.comparison.vsLastWeek": "vs poprzedni tydzień",
|
|
8
8
|
"dashboards.analytics.comparison.vsLastYear": "vs poprzedni rok",
|
|
9
|
-
"dashboards.analytics.comparison.vsMonthBefore": "vs
|
|
9
|
+
"dashboards.analytics.comparison.vsMonthBefore": "vs miesiąc wcześniej",
|
|
10
10
|
"dashboards.analytics.comparison.vsPrevious30Days": "vs poprzednie 30 dni",
|
|
11
11
|
"dashboards.analytics.comparison.vsPrevious7Days": "vs poprzednie 7 dni",
|
|
12
12
|
"dashboards.analytics.comparison.vsPrevious90Days": "vs poprzednie 90 dni",
|
|
13
13
|
"dashboards.analytics.comparison.vsPreviousPeriod": "vs poprzedni okres",
|
|
14
|
-
"dashboards.analytics.comparison.vsQuarterBefore": "vs
|
|
15
|
-
"dashboards.analytics.comparison.vsWeekBefore": "vs
|
|
16
|
-
"dashboards.analytics.comparison.vsYearBefore": "vs rok
|
|
14
|
+
"dashboards.analytics.comparison.vsQuarterBefore": "vs kwartał wcześniej",
|
|
15
|
+
"dashboards.analytics.comparison.vsWeekBefore": "vs tydzień wcześniej",
|
|
16
|
+
"dashboards.analytics.comparison.vsYearBefore": "vs rok wcześniej",
|
|
17
17
|
"dashboards.analytics.comparison.vsYesterday": "vs wczoraj",
|
|
18
18
|
"dashboards.analytics.currency.unlabelled": "Kwoty pokazane bez waluty",
|
|
19
19
|
"dashboards.analytics.currency.unlabelledHint": "Nie udało się wiarygodnie ustalić waluty, dlatego kwota jest wyświetlana bez jej oznaczenia.",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
2
2
|
import { createRequestContainer, type AppContainer } from '@open-mercato/shared/lib/di/container'
|
|
3
3
|
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
4
|
+
import { isUnrestrictedOrganizationScope } from '@open-mercato/shared/lib/auth/organizationAccess'
|
|
4
5
|
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
5
6
|
import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
|
|
6
7
|
|
|
@@ -9,6 +10,7 @@ export type WidgetScopeContext = {
|
|
|
9
10
|
em: EntityManager
|
|
10
11
|
tenantId: string
|
|
11
12
|
organizationIds: string[] | null
|
|
13
|
+
isUnrestrictedOrganizationScope?: boolean
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
function normalizeScopeId(value: string | null | undefined): string | null {
|
|
@@ -91,5 +93,9 @@ export async function resolveWidgetScope(
|
|
|
91
93
|
em,
|
|
92
94
|
tenantId,
|
|
93
95
|
organizationIds,
|
|
96
|
+
isUnrestrictedOrganizationScope: isUnrestrictedOrganizationScope({
|
|
97
|
+
isSuperAdmin,
|
|
98
|
+
allowedOrganizationIds: scope?.allowedIds,
|
|
99
|
+
}),
|
|
94
100
|
}
|
|
95
101
|
}
|
|
@@ -206,7 +206,7 @@ If the sync provider needs bootstrap credentials, mappings, locales, channels, o
|
|
|
206
206
|
- **Resetting an opt-out**: A reset flow that deletes the shared `SyncCursor` row MUST also call `syncRunService.resetResumePosition(integrationId, entityType, direction, scope)`. An opted-out entity type has no shared row to delete, so deleting only that leaves the resume position on the last interrupted run and the next incremental run re-imports just the tail of the walk it was reset against. The call is a no-op when nothing is interrupted, so make it unconditionally
|
|
207
207
|
- **Resume**: Retry reads the last successful cursor, resumes from there
|
|
208
208
|
- **Progress**: Linked to `ProgressJob` via `progressJobId` for `ProgressTopBar` display
|
|
209
|
-
- **Cancellation**:
|
|
209
|
+
- **Cancellation**: The engine polls `progressService.isCancellationRequested()` in the batch handler AND on the heartbeat tick while a batch is still in flight, aborting `StreamImportInput.signal` / `StreamExportInput.signal`. Adapters SHOULD honour the signal wherever the work is divisible (per page, per record, around a long flush) and `return` — with the `return` ABOVE the `yield`, never below it, or the engine commits a cursor for a half-applied page. Adapters that ignore the signal keep the old between-batches behavior.
|
|
210
210
|
- **Tracing**: The engine emits one **root** span per batch (`data_sync.import.batch` / `data_sync.export.batch`) linked back to the run, covering the adapter's read *and* the engine's bookkeeping. Adapters MUST NOT hand-roll their own batch span — they cannot root it, so a multi-day run would ride on the single sampling decision taken for the request that triggered it. Inner spans an adapter creates nest under the batch span normally. The final read — the one that finds the stream drained — is traced as `data_sync.import.drain` / `data_sync.export.drain`, so N batches emit exactly N `*.batch` spans plus one `*.drain`.
|
|
211
211
|
- **Stream shape**: The engine drives the adapter's async iterator explicitly (`batch-stream.ts`) so the span wraps `next()`, where a generator does its real work before yielding. Closing follows the language's own `IteratorClose` rules, so `finally` blocks in an adapter generator behave exactly as under `for await`: no `return()` when the stream exhausts or `next()` throws (already closed), `return()` with its failure surfaced on an early stop, and `return()` with its failure swallowed when the engine's own handler threw (that error wins). Keep cleanup in `finally`.
|
|
212
212
|
|
|
@@ -74,6 +74,7 @@ type ResponsePayload = {
|
|
|
74
74
|
total: number
|
|
75
75
|
page: number
|
|
76
76
|
totalPages: number
|
|
77
|
+
totalIsCapped?: boolean
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
type SyncOption = {
|
|
@@ -153,6 +154,7 @@ export default function SyncRunsDashboardPage() {
|
|
|
153
154
|
const [page, setPage] = React.useState(1)
|
|
154
155
|
const [total, setTotal] = React.useState(0)
|
|
155
156
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
157
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
156
158
|
const [search, setSearch] = React.useState('')
|
|
157
159
|
const [filterValues, setFilterValues] = React.useState<FilterValues>({})
|
|
158
160
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
@@ -200,6 +202,7 @@ export default function SyncRunsDashboardPage() {
|
|
|
200
202
|
setRows(Array.isArray(payload.items) ? payload.items : [])
|
|
201
203
|
setTotal(payload.total || 0)
|
|
202
204
|
setTotalPages(payload.totalPages || 1)
|
|
205
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
203
206
|
setIsLoading(false)
|
|
204
207
|
}
|
|
205
208
|
}
|
|
@@ -1065,7 +1068,7 @@ export default function SyncRunsDashboardPage() {
|
|
|
1065
1068
|
}] : []),
|
|
1066
1069
|
]} />
|
|
1067
1070
|
)}
|
|
1068
|
-
pagination={{ page, pageSize: 20, total, totalPages, onPageChange: setPage }}
|
|
1071
|
+
pagination={{ page, pageSize: 20, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
1069
1072
|
isLoading={isLoading}
|
|
1070
1073
|
/>
|
|
1071
1074
|
</PageBody>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { AbandonedJobInfo } from '@open-mercato/queue'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Fail the run behind a job the queue gave up on.
|
|
5
|
+
*
|
|
6
|
+
* A resumable data_sync job is ONE long-lived job for a whole run — `runImport` is entered once and
|
|
7
|
+
* stays there for the duration, which for a full backfill is days. Every worker death (a deploy, an
|
|
8
|
+
* OOM) therefore stalls that job, and BullMQ's stalled counter is cumulative for the job's life:
|
|
9
|
+
* past `DATA_SYNC_MAX_STALLED_COUNT` it writes a deferred failure and the next worker fails the job
|
|
10
|
+
* BEFORE calling the processor.
|
|
11
|
+
*
|
|
12
|
+
* So `runImport` never runs, never throws, and never finalizes — and `sync_runs` is left saying
|
|
13
|
+
* `running` for a run nothing is running, forever. That is the residual state `queue-policy.ts`
|
|
14
|
+
* describes as what remains after a job exhausts its stall budget; this repairs it.
|
|
15
|
+
*
|
|
16
|
+
* It only ever moves a non-terminal run: `markStatus` refuses to overwrite `completed` / `failed` /
|
|
17
|
+
* `cancelled`, so a job abandoned after its run has ended is a no-op. `onJobAbandoned` may deliver
|
|
18
|
+
* the same job more than once, which for the same reason is also a no-op.
|
|
19
|
+
*
|
|
20
|
+
* The run's progress job is failed alongside it, the way the worker's own catch path does in
|
|
21
|
+
* `workers/sync-import.ts`. Without that the two halves disagree — the run reads `failed` while the
|
|
22
|
+
* operation still shows as in flight in the top bar — until the progress staleness sweep eventually
|
|
23
|
+
* fails it with a generic no-heartbeat message instead of the reason the queue recorded.
|
|
24
|
+
*/
|
|
25
|
+
export async function failAbandonedRun(payload: unknown, info: AbandonedJobInfo): Promise<void> {
|
|
26
|
+
const data = payload as { payload?: { runId?: unknown; scope?: { organizationId?: unknown; tenantId?: unknown } } } | undefined
|
|
27
|
+
const runId = data?.payload?.runId
|
|
28
|
+
const scope = data?.payload?.scope
|
|
29
|
+
// Nothing to repair without both: the run row is keyed by id AND tenant scope.
|
|
30
|
+
if (typeof runId !== 'string' || typeof scope?.organizationId !== 'string' || typeof scope?.tenantId !== 'string') return
|
|
31
|
+
|
|
32
|
+
const runScope = { organizationId: scope.organizationId, tenantId: scope.tenantId }
|
|
33
|
+
const errorMessage = `the queue abandoned this run's job without running it: ${info.reason}`
|
|
34
|
+
|
|
35
|
+
const { createRequestContainer } = await import('@open-mercato/shared/lib/di/container')
|
|
36
|
+
const container = await createRequestContainer()
|
|
37
|
+
const runService = container.resolve('dataSyncRunService') as {
|
|
38
|
+
markStatus(
|
|
39
|
+
runId: string,
|
|
40
|
+
status: string,
|
|
41
|
+
scope: { organizationId: string; tenantId: string },
|
|
42
|
+
error?: string,
|
|
43
|
+
): Promise<{ progressJobId?: string | null } | null>
|
|
44
|
+
}
|
|
45
|
+
const run = await runService.markStatus(runId, 'failed', runScope, errorMessage)
|
|
46
|
+
if (!run?.progressJobId) return
|
|
47
|
+
|
|
48
|
+
const progressService = container.resolve('progressService') as {
|
|
49
|
+
failJob(
|
|
50
|
+
jobId: string,
|
|
51
|
+
input: { errorMessage: string },
|
|
52
|
+
ctx: { organizationId: string; tenantId: string },
|
|
53
|
+
): Promise<unknown>
|
|
54
|
+
}
|
|
55
|
+
await progressService.failJob(run.progressJobId, { errorMessage }, runScope)
|
|
56
|
+
}
|
|
@@ -45,6 +45,27 @@ export interface StreamImportInput {
|
|
|
45
45
|
* declares no parameters.
|
|
46
46
|
*/
|
|
47
47
|
parameters?: Record<string, RunParameterValue>
|
|
48
|
+
/**
|
|
49
|
+
* Aborted when the run is cancelled, so an adapter can stop INSIDE a batch.
|
|
50
|
+
*
|
|
51
|
+
* The engine only gets to look at cancellation between batches — its check sits in the batch
|
|
52
|
+
* handler, which runs after the adapter has yielded. An adapter whose batch takes minutes (a
|
|
53
|
+
* whole-table walk over a slow link) therefore keeps working, keeps writing, and keeps its
|
|
54
|
+
* advisory lock for that whole time, however long ago the operator pressed Cancel.
|
|
55
|
+
*
|
|
56
|
+
* Honour it wherever the work is divisible — per page, per record, around a long flush — and just
|
|
57
|
+
* return: the generator's own `finally` runs, which is where a lock or a connection is released.
|
|
58
|
+
* Adapters that ignore it behave exactly as they do today.
|
|
59
|
+
*
|
|
60
|
+
* The `return` MUST sit ABOVE the `yield` for the page you abandoned, never below it. The engine
|
|
61
|
+
* commits `batch.cursor` for every batch it receives, so yielding a half-applied page advances the
|
|
62
|
+
* cursor past records that were never applied and no later run ever walks them again.
|
|
63
|
+
*
|
|
64
|
+
* The signal only reaches work running in THIS process. An adapter that hands part of a batch to
|
|
65
|
+
* other workers must give that work its own cancellation check against the same progress job —
|
|
66
|
+
* aborting here stops the generator, not anything already queued elsewhere.
|
|
67
|
+
*/
|
|
68
|
+
signal?: AbortSignal
|
|
48
69
|
}
|
|
49
70
|
|
|
50
71
|
export interface ImportItem {
|
|
@@ -57,6 +78,18 @@ export interface ImportItem {
|
|
|
57
78
|
export interface ImportBatch {
|
|
58
79
|
items: ImportItem[]
|
|
59
80
|
cursor: string
|
|
81
|
+
/**
|
|
82
|
+
* Whether the source has more to give after this batch. The final batch MUST report `false`.
|
|
83
|
+
*
|
|
84
|
+
* This is not advisory. The engine uses the last batch's value to tell a stream that DRAINED from
|
|
85
|
+
* one the adapter STOPPED EARLY on {@link StreamImportInput.signal}, because both end the same way
|
|
86
|
+
* — the generator simply returns. An adapter that reports `true` on its final batch will have a
|
|
87
|
+
* complete run misreported as `cancelled` whenever a cancel lands during the final read: the
|
|
88
|
+
* operator is told a finished sync was partial, and the run stays resumable with nothing left to
|
|
89
|
+
* resume.
|
|
90
|
+
*
|
|
91
|
+
* Derive it from the source rather than hardcoding it — `Boolean(nextPage)`, `offset < total`.
|
|
92
|
+
*/
|
|
60
93
|
hasMore: boolean
|
|
61
94
|
totalEstimate?: number
|
|
62
95
|
processedCount?: number
|
|
@@ -76,6 +109,8 @@ export interface StreamExportInput {
|
|
|
76
109
|
runId?: string
|
|
77
110
|
/** See {@link StreamImportInput.parameters}. */
|
|
78
111
|
parameters?: Record<string, RunParameterValue>
|
|
112
|
+
/** Aborted when the run is cancelled — see {@link StreamImportInput.signal}. */
|
|
113
|
+
signal?: AbortSignal
|
|
79
114
|
}
|
|
80
115
|
|
|
81
116
|
export interface ExportItemResult {
|
|
@@ -88,6 +123,7 @@ export interface ExportItemResult {
|
|
|
88
123
|
export interface ExportBatch {
|
|
89
124
|
results: ExportItemResult[]
|
|
90
125
|
cursor: string
|
|
126
|
+
/** Whether the source has more to give; the final batch MUST report `false`. See {@link ImportBatch.hasMore}. */
|
|
91
127
|
hasMore: boolean
|
|
92
128
|
batchIndex: number
|
|
93
129
|
}
|