@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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/messages/data/validators.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from 'zod'\nimport { parseBooleanFlag } from '@open-mercato/shared/lib/boolean'\nimport { sanitizeRichTextHref } from '@open-mercato/shared/lib/html/sanitizeRichText'\n\nfunction collectDuplicateRecipientIds(\n recipients: Array<{ userId: string }>,\n): string[] {\n const seen = new Set<string>()\n const duplicates = new Set<string>()\n for (const recipient of recipients) {\n if (seen.has(recipient.userId)) {\n duplicates.add(recipient.userId)\n continue\n }\n seen.add(recipient.userId)\n }\n return Array.from(duplicates)\n}\n\nfunction validateDefaultWithObjectsPayload(\n value: {\n type?: string\n objects?: Array<{ actionRequired?: boolean; actionType?: string; actionLabel?: string }>\n },\n ctx: z.RefinementCtx,\n): void {\n if (value.type !== 'messages.defaultWithObjects') return\n\n if (!Array.isArray(value.objects) || value.objects.length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects'],\n message: 'at least one object is required for messages.defaultWithObjects',\n })\n return\n }\n\n value.objects.forEach((object, index) => {\n if (object.actionRequired === true) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects', index, 'actionRequired'],\n message: 'actionRequired must be false for messages.defaultWithObjects',\n })\n }\n if (typeof object.actionType === 'string' && object.actionType.trim().length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects', index, 'actionType'],\n message: 'actionType is not allowed for messages.defaultWithObjects',\n })\n }\n if (typeof object.actionLabel === 'string' && object.actionLabel.trim().length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects', index, 'actionLabel'],\n message: 'actionLabel is not allowed for messages.defaultWithObjects',\n })\n }\n })\n}\n\nexport const messageRecipientSchema = z.object({\n userId: z.string().uuid(),\n type: z.enum(['to', 'cc', 'bcc']).optional().default('to'),\n})\n\nexport const messageObjectSchema = z.object({\n entityModule: z.string().min(1),\n entityType: z.string().min(1),\n entityId: z.string().uuid(),\n actionRequired: z.boolean().optional().default(false),\n actionType: z.string().optional(),\n actionLabel: z.string().optional(),\n})\n\nexport const messageActionSchema = z.object({\n id: z.string().min(1),\n label: z.string().min(1),\n labelKey: z.string().optional(),\n variant: z.enum(['default', 'secondary', 'destructive', 'outline', 'ghost']).optional(),\n icon: z.string().optional(),\n commandId: z.string().optional(),\n href: z\n .string()\n .optional()\n .refine(\n (value) => value == null || sanitizeRichTextHref(value) != null,\n { message: '[internal] message action href must be http(s), mailto, tel, or a relative path' },\n ),\n isTerminal: z.boolean().optional(),\n confirmRequired: z.boolean().optional(),\n confirmMessage: z.string().optional(),\n})\n\nexport const messageActionDataSchema = z.object({\n actions: z.array(messageActionSchema),\n primaryActionId: z.string().optional(),\n expiresAt: z.string().datetime().optional(),\n})\n\nexport const composeMessageSchema = z.object({\n type: z.string().optional().default('default'),\n visibility: z.enum(['public', 'internal']).nullable().optional(),\n sourceEntityType: z.string().min(1).optional(),\n sourceEntityId: z.string().uuid().optional(),\n externalEmail: z.string().email().optional(),\n externalName: z.string().min(1).max(255).optional(),\n recipients: z.array(messageRecipientSchema).max(100).optional().default([]),\n subject: z.string().max(500).optional().default(''),\n body: z.string().max(50000).optional().default(''),\n bodyFormat: z.enum(['text', 'markdown']).optional().default('text'),\n priority: z.enum(['low', 'normal', 'high', 'urgent']).optional().default('normal'),\n objects: z.array(messageObjectSchema).optional(),\n attachmentIds: z.array(z.string().uuid()).optional(),\n attachmentRecordId: z.string().min(1).max(255).optional(),\n actionData: messageActionDataSchema.optional(),\n sendViaEmail: z.boolean().optional().default(false),\n parentMessageId: z.string().uuid().optional(),\n isDraft: z.boolean().optional().default(false),\n}).superRefine((value, ctx) => {\n const isDraft = value.isDraft ?? false\n const visibility = value.visibility ?? 'internal'\n const recipientCount = value.recipients.length\n const hasExternalEmail = Boolean(value.externalEmail?.trim())\n const hasSubject = value.subject.trim().length > 0\n const hasBody = value.body.trim().length > 0\n\n if (!isDraft) {\n if (visibility === 'public') {\n if (!hasExternalEmail) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['externalEmail'],\n message: 'externalEmail is required when visibility is public',\n })\n }\n if (recipientCount > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipients must be empty when visibility is public',\n })\n }\n } else if (recipientCount === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'at least one recipient is required when visibility is internal',\n })\n }\n\n if (!hasSubject) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['subject'],\n message: 'subject is required',\n })\n }\n if (!hasBody) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['body'],\n message: 'body is required',\n })\n }\n }\n\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n\n validateDefaultWithObjectsPayload(value, ctx)\n})\n\nexport const updateDraftSchema = z.object({\n type: z.string().optional(),\n visibility: z.enum(['public', 'internal']).nullable().optional(),\n sourceEntityType: z.string().min(1).optional(),\n sourceEntityId: z.string().uuid().optional(),\n externalEmail: z.string().email().optional(),\n externalName: z.string().min(1).max(255).optional(),\n recipients: z.array(messageRecipientSchema).optional(),\n subject: z.string().max(500).optional(),\n body: z.string().max(50000).optional(),\n bodyFormat: z.enum(['text', 'markdown']).optional(),\n priority: z.enum(['low', 'normal', 'high', 'urgent']).optional(),\n objects: z.array(messageObjectSchema).optional(),\n attachmentIds: z.array(z.string().uuid()).optional(),\n actionData: messageActionDataSchema.optional(),\n sendViaEmail: z.boolean().optional(),\n isDraft: z.literal(false).optional(),\n}).superRefine((value, ctx) => {\n if (value.recipients) {\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n }\n\n validateDefaultWithObjectsPayload(value, ctx)\n})\n\nexport const listMessagesSchema = z.object({\n folder: z.enum(['inbox', 'sent', 'drafts', 'archived', 'all']).optional().default('inbox'),\n status: z.enum(['unread', 'read', 'archived']).optional(),\n type: z.string().optional(),\n visibility: z.enum(['public', 'internal']).optional(),\n sourceEntityType: z.string().optional(),\n sourceEntityId: z.string().uuid().optional(),\n externalEmail: z.string().email().optional(),\n hasObjects: z.string().transform(parseBooleanFlag).optional(),\n hasAttachments: z.string().transform(parseBooleanFlag).optional(),\n hasActions: z.string().transform(parseBooleanFlag).optional(),\n senderId: z.string().uuid().optional(),\n search: z.string().max(200).optional(),\n since: z.string().datetime().optional(),\n page: z.coerce.number().int().min(1).optional().default(1),\n pageSize: z.coerce.number().int().min(1).max(100).optional().default(20),\n})\n\nexport const forwardMessageSchema = z.object({\n recipients: z.array(messageRecipientSchema).min(1).max(100),\n body: z.string().max(50000).optional(),\n additionalBody: z.string().max(10000).optional(),\n includeAttachments: z.boolean().optional().default(true),\n sendViaEmail: z.boolean().optional().default(false),\n}).superRefine((value, ctx) => {\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n})\n\nexport const replyMessageSchema = z.object({\n body: z.string().min(1).max(50000),\n bodyFormat: z.enum(['text', 'markdown']).optional().default('text'),\n recipients: z.array(messageRecipientSchema).max(100).optional(),\n attachmentIds: z.array(z.string().uuid()).optional(),\n attachmentRecordId: z.string().min(1).max(255).optional(),\n replyAll: z.boolean().optional().default(false),\n sendViaEmail: z.boolean().optional().default(false),\n}).superRefine((value, ctx) => {\n if (!value.recipients) return\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n})\n\nexport const executeActionSchema = z.object({\n messageId: z.string().uuid(),\n actionId: z.string().min(1),\n payload: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const confirmMessageSchema = z.object({\n messageId: z.string().uuid(),\n tenantId: z.string().uuid().optional(),\n organizationId: z.string().uuid().nullable().optional(),\n confirmed: z.boolean().optional().default(true),\n})\n\nexport const messageObjectTypesQuerySchema = z.object({\n messageType: z.string().min(1),\n})\n\nexport const attachmentIdsPayloadSchema = z.object({\n attachmentIds: z.array(z.string().uuid()).min(1).max(100),\n})\n\nexport const unlinkAttachmentPayloadSchema = z.object({\n attachmentId: z.string().uuid().optional(),\n attachmentIds: z.array(z.string().uuid()).min(1).max(100).optional(),\n}).refine(\n (value) => Boolean(value.attachmentId || value.attachmentIds?.length),\n { message: 'attachmentId or attachmentIds is required' }\n)\n\nexport type ComposeMessageInput = z.infer<typeof composeMessageSchema>\nexport type UpdateDraftInput = z.infer<typeof updateDraftSchema>\nexport type ListMessagesInput = z.infer<typeof listMessagesSchema>\nexport type ForwardMessageInput = z.infer<typeof forwardMessageSchema>\nexport type ReplyMessageInput = z.infer<typeof replyMessageSchema>\nexport type ExecuteActionInput = z.infer<typeof executeActionSchema>\nexport type ConfirmMessageInput = z.infer<typeof confirmMessageSchema>\nexport type MessageObjectTypesQueryInput = z.infer<typeof messageObjectTypesQuerySchema>\nexport type AttachmentIdsPayload = z.infer<typeof attachmentIdsPayloadSchema>\nexport type UnlinkAttachmentPayload = z.infer<typeof unlinkAttachmentPayloadSchema>\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,SAAS;AAClB,SAAS,wBAAwB;AACjC,SAAS,4BAA4B;
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport { parseBooleanFlag } from '@open-mercato/shared/lib/boolean'\nimport { sanitizeRichTextHref } from '@open-mercato/shared/lib/html/sanitizeRichText'\nimport { channelTypeRequiresExternalEmail } from '../lib/channel-sender-identity'\n\nfunction collectDuplicateRecipientIds(\n recipients: Array<{ userId: string }>,\n): string[] {\n const seen = new Set<string>()\n const duplicates = new Set<string>()\n for (const recipient of recipients) {\n if (seen.has(recipient.userId)) {\n duplicates.add(recipient.userId)\n continue\n }\n seen.add(recipient.userId)\n }\n return Array.from(duplicates)\n}\n\nfunction validateDefaultWithObjectsPayload(\n value: {\n type?: string\n objects?: Array<{ actionRequired?: boolean; actionType?: string; actionLabel?: string }>\n },\n ctx: z.RefinementCtx,\n): void {\n if (value.type !== 'messages.defaultWithObjects') return\n\n if (!Array.isArray(value.objects) || value.objects.length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects'],\n message: 'at least one object is required for messages.defaultWithObjects',\n })\n return\n }\n\n value.objects.forEach((object, index) => {\n if (object.actionRequired === true) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects', index, 'actionRequired'],\n message: 'actionRequired must be false for messages.defaultWithObjects',\n })\n }\n if (typeof object.actionType === 'string' && object.actionType.trim().length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects', index, 'actionType'],\n message: 'actionType is not allowed for messages.defaultWithObjects',\n })\n }\n if (typeof object.actionLabel === 'string' && object.actionLabel.trim().length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects', index, 'actionLabel'],\n message: 'actionLabel is not allowed for messages.defaultWithObjects',\n })\n }\n })\n}\n\nexport const messageRecipientSchema = z.object({\n userId: z.string().uuid(),\n type: z.enum(['to', 'cc', 'bcc']).optional().default('to'),\n})\n\nexport const messageObjectSchema = z.object({\n entityModule: z.string().min(1),\n entityType: z.string().min(1),\n entityId: z.string().uuid(),\n actionRequired: z.boolean().optional().default(false),\n actionType: z.string().optional(),\n actionLabel: z.string().optional(),\n})\n\nexport const messageActionSchema = z.object({\n id: z.string().min(1),\n label: z.string().min(1),\n labelKey: z.string().optional(),\n variant: z.enum(['default', 'secondary', 'destructive', 'outline', 'ghost']).optional(),\n icon: z.string().optional(),\n commandId: z.string().optional(),\n href: z\n .string()\n .optional()\n .refine(\n (value) => value == null || sanitizeRichTextHref(value) != null,\n { message: '[internal] message action href must be http(s), mailto, tel, or a relative path' },\n ),\n isTerminal: z.boolean().optional(),\n confirmRequired: z.boolean().optional(),\n confirmMessage: z.string().optional(),\n})\n\nexport const messageActionDataSchema = z.object({\n actions: z.array(messageActionSchema),\n primaryActionId: z.string().optional(),\n expiresAt: z.string().datetime().optional(),\n})\n\nconst composeMessageBaseSchema = z.object({\n type: z.string().optional().default('default'),\n visibility: z.enum(['public', 'internal']).nullable().optional(),\n sourceEntityType: z.string().min(1).optional(),\n sourceEntityId: z.string().uuid().optional(),\n externalEmail: z.string().email().optional(),\n externalName: z.string().min(1).max(255).optional(),\n /**\n * Channel type the message originates from, when the caller knows it (#4975).\n * Non-email channels (Discord, Slack, SMS\u2026) have senders with no address, so\n * `externalEmail` is not required for them. Resolved server-side \u2014 the HTTP\n * route strips any client-sent value and derives it from the referenced\n * conversation or parent message, so a caller cannot waive the requirement by\n * asserting its own channel type.\n */\n sourceChannelType: z.string().min(1).max(64).optional(),\n recipients: z.array(messageRecipientSchema).max(100).optional().default([]),\n subject: z.string().max(500).optional().default(''),\n body: z.string().max(50000).optional().default(''),\n bodyFormat: z.enum(['text', 'markdown']).optional().default('text'),\n priority: z.enum(['low', 'normal', 'high', 'urgent']).optional().default('normal'),\n objects: z.array(messageObjectSchema).optional(),\n attachmentIds: z.array(z.string().uuid()).optional(),\n attachmentRecordId: z.string().min(1).max(255).optional(),\n actionData: messageActionDataSchema.optional(),\n sendViaEmail: z.boolean().optional().default(false),\n parentMessageId: z.string().uuid().optional(),\n isDraft: z.boolean().optional().default(false),\n})\n\ntype ComposeMessageRefinementValue = Omit<\n z.infer<typeof composeMessageBaseSchema>,\n 'sourceChannelType'\n> & { sourceChannelType?: string }\n\nfunction refineComposeMessage(value: ComposeMessageRefinementValue, ctx: z.RefinementCtx): void {\n const isDraft = value.isDraft ?? false\n const visibility = value.visibility ?? 'internal'\n const recipientCount = value.recipients.length\n const hasExternalEmail = Boolean(value.externalEmail?.trim())\n const hasSubject = value.subject.trim().length > 0\n const hasBody = value.body.trim().length > 0\n\n if (!isDraft) {\n if (visibility === 'public') {\n // #4975: an external correspondent is only guaranteed to have an address\n // on an email-typed channel. `channelTypeRequiresExternalEmail` fails\n // closed, so an unknown or absent channel type keeps the original rule.\n if (!hasExternalEmail && channelTypeRequiresExternalEmail(value.sourceChannelType)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['externalEmail'],\n message: 'externalEmail is required when visibility is public',\n })\n }\n if (recipientCount > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipients must be empty when visibility is public',\n })\n }\n } else if (recipientCount === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'at least one recipient is required when visibility is internal',\n })\n }\n\n if (!hasSubject) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['subject'],\n message: 'subject is required',\n })\n }\n if (!hasBody) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['body'],\n message: 'body is required',\n })\n }\n }\n\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n\n validateDefaultWithObjectsPayload(value, ctx)\n}\n\n/**\n * Full compose contract, including the server-resolved `sourceChannelType`.\n * Used by the `messages.messages.compose` command and by the HTTP route AFTER\n * it has resolved the channel type itself.\n */\nexport const composeMessageSchema = composeMessageBaseSchema.superRefine(refineComposeMessage)\n\n/**\n * Client-facing compose contract \u2014 the same rules minus `sourceChannelType`,\n * which is never accepted from a request body (#4975). Published in OpenAPI so\n * the documented request shape matches what `POST /api/messages` actually reads:\n * the route discards any client-sent channel type, resolves the real one from\n * the referenced conversation or parent message, and only then validates against\n * {@link composeMessageSchema}.\n */\nexport const composeMessageRequestSchema = composeMessageBaseSchema\n .omit({ sourceChannelType: true })\n .superRefine(refineComposeMessage)\n\nexport const updateDraftSchema = z.object({\n type: z.string().optional(),\n visibility: z.enum(['public', 'internal']).nullable().optional(),\n sourceEntityType: z.string().min(1).optional(),\n sourceEntityId: z.string().uuid().optional(),\n externalEmail: z.string().email().optional(),\n externalName: z.string().min(1).max(255).optional(),\n recipients: z.array(messageRecipientSchema).optional(),\n subject: z.string().max(500).optional(),\n body: z.string().max(50000).optional(),\n bodyFormat: z.enum(['text', 'markdown']).optional(),\n priority: z.enum(['low', 'normal', 'high', 'urgent']).optional(),\n objects: z.array(messageObjectSchema).optional(),\n attachmentIds: z.array(z.string().uuid()).optional(),\n actionData: messageActionDataSchema.optional(),\n sendViaEmail: z.boolean().optional(),\n isDraft: z.literal(false).optional(),\n}).superRefine((value, ctx) => {\n if (value.recipients) {\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n }\n\n validateDefaultWithObjectsPayload(value, ctx)\n})\n\nexport const listMessagesSchema = z.object({\n folder: z.enum(['inbox', 'sent', 'drafts', 'archived', 'all']).optional().default('inbox'),\n status: z.enum(['unread', 'read', 'archived']).optional(),\n type: z.string().optional(),\n visibility: z.enum(['public', 'internal']).optional(),\n sourceEntityType: z.string().optional(),\n sourceEntityId: z.string().uuid().optional(),\n externalEmail: z.string().email().optional(),\n hasObjects: z.string().transform(parseBooleanFlag).optional(),\n hasAttachments: z.string().transform(parseBooleanFlag).optional(),\n hasActions: z.string().transform(parseBooleanFlag).optional(),\n senderId: z.string().uuid().optional(),\n search: z.string().max(200).optional(),\n since: z.string().datetime().optional(),\n page: z.coerce.number().int().min(1).optional().default(1),\n pageSize: z.coerce.number().int().min(1).max(100).optional().default(20),\n})\n\nexport const forwardMessageSchema = z.object({\n recipients: z.array(messageRecipientSchema).min(1).max(100),\n body: z.string().max(50000).optional(),\n additionalBody: z.string().max(10000).optional(),\n includeAttachments: z.boolean().optional().default(true),\n sendViaEmail: z.boolean().optional().default(false),\n}).superRefine((value, ctx) => {\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n})\n\nexport const replyMessageSchema = z.object({\n body: z.string().min(1).max(50000),\n bodyFormat: z.enum(['text', 'markdown']).optional().default('text'),\n recipients: z.array(messageRecipientSchema).max(100).optional(),\n attachmentIds: z.array(z.string().uuid()).optional(),\n attachmentRecordId: z.string().min(1).max(255).optional(),\n replyAll: z.boolean().optional().default(false),\n sendViaEmail: z.boolean().optional().default(false),\n}).superRefine((value, ctx) => {\n if (!value.recipients) return\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n})\n\nexport const executeActionSchema = z.object({\n messageId: z.string().uuid(),\n actionId: z.string().min(1),\n payload: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const confirmMessageSchema = z.object({\n messageId: z.string().uuid(),\n tenantId: z.string().uuid().optional(),\n organizationId: z.string().uuid().nullable().optional(),\n confirmed: z.boolean().optional().default(true),\n})\n\nexport const messageObjectTypesQuerySchema = z.object({\n messageType: z.string().min(1),\n})\n\nexport const attachmentIdsPayloadSchema = z.object({\n attachmentIds: z.array(z.string().uuid()).min(1).max(100),\n})\n\nexport const unlinkAttachmentPayloadSchema = z.object({\n attachmentId: z.string().uuid().optional(),\n attachmentIds: z.array(z.string().uuid()).min(1).max(100).optional(),\n}).refine(\n (value) => Boolean(value.attachmentId || value.attachmentIds?.length),\n { message: 'attachmentId or attachmentIds is required' }\n)\n\nexport type ComposeMessageInput = z.infer<typeof composeMessageSchema>\nexport type UpdateDraftInput = z.infer<typeof updateDraftSchema>\nexport type ListMessagesInput = z.infer<typeof listMessagesSchema>\nexport type ForwardMessageInput = z.infer<typeof forwardMessageSchema>\nexport type ReplyMessageInput = z.infer<typeof replyMessageSchema>\nexport type ExecuteActionInput = z.infer<typeof executeActionSchema>\nexport type ConfirmMessageInput = z.infer<typeof confirmMessageSchema>\nexport type MessageObjectTypesQueryInput = z.infer<typeof messageObjectTypesQuerySchema>\nexport type AttachmentIdsPayload = z.infer<typeof attachmentIdsPayloadSchema>\nexport type UnlinkAttachmentPayload = z.infer<typeof unlinkAttachmentPayloadSchema>\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const NON_EMAIL_SENDER_CHANNEL_TYPES = /* @__PURE__ */ new Set([
|
|
2
|
+
"discord",
|
|
3
|
+
"slack",
|
|
4
|
+
"teams",
|
|
5
|
+
"telegram",
|
|
6
|
+
"signal",
|
|
7
|
+
"whatsapp",
|
|
8
|
+
"messenger",
|
|
9
|
+
"instagram",
|
|
10
|
+
"sms",
|
|
11
|
+
"push"
|
|
12
|
+
]);
|
|
13
|
+
function channelTypeRequiresExternalEmail(channelType) {
|
|
14
|
+
if (typeof channelType !== "string") return true;
|
|
15
|
+
const normalized = channelType.trim().toLowerCase();
|
|
16
|
+
if (!normalized) return true;
|
|
17
|
+
return !NON_EMAIL_SENDER_CHANNEL_TYPES.has(normalized);
|
|
18
|
+
}
|
|
19
|
+
function listNonEmailSenderChannelTypes() {
|
|
20
|
+
return Array.from(NON_EMAIL_SENDER_CHANNEL_TYPES).sort((left, right) => left.localeCompare(right));
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
channelTypeRequiresExternalEmail,
|
|
24
|
+
listNonEmailSenderChannelTypes
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=channel-sender-identity.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/messages/lib/channel-sender-identity.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * How the hub decides whether an external correspondent must be identified by an\n * email address.\n *\n * Background (#4975): `composeMessageSchema` used to require `externalEmail` for\n * every non-draft message with `visibility: 'public'` \u2014 which is every message\n * from an external sender. That assumption holds only for email-typed channels.\n * A Discord sender is a snowflake and has no address at all, so inbound Discord\n * failed validation deterministically and the ingest job died in the queue while\n * the channel still reported `Connected`.\n *\n * Variant A of the spec's \u00A7 Open decision \u2014 hub sender-identity contract makes\n * the requirement conditional on the originating channel type, and **fails\n * closed**: only a channel type this list positively recognizes as non-email\n * waives the requirement. An unrecognized, empty or absent channel type keeps\n * the pre-existing behaviour, so no current caller changes and a typo'd or\n * caller-asserted type cannot quietly switch a validation rule off.\n *\n * For these channels the sender identity is not lost \u2014 it is carried by\n * `ExternalMessage.sender_identifier` and joined 1:1 to the platform message\n * through `MessageChannelLink`.\n *\n * Adding a channel type here is additive and non-breaking: it only widens the\n * set of inputs the hub accepts.\n */\nconst NON_EMAIL_SENDER_CHANNEL_TYPES = new Set([\n 'discord',\n 'slack',\n 'teams',\n 'telegram',\n 'signal',\n 'whatsapp',\n 'messenger',\n 'instagram',\n 'sms',\n 'push',\n])\n\n/**\n * True when a message originating from `channelType` must carry an\n * `externalEmail` to be composed with `visibility: 'public'`.\n *\n * Fail-closed by design \u2014 see the note above.\n */\nexport function channelTypeRequiresExternalEmail(channelType?: string | null): boolean {\n if (typeof channelType !== 'string') return true\n const normalized = channelType.trim().toLowerCase()\n if (!normalized) return true\n return !NON_EMAIL_SENDER_CHANNEL_TYPES.has(normalized)\n}\n\n/** The recognized non-email channel types, for tests and diagnostics. */\nexport function listNonEmailSenderChannelTypes(): string[] {\n return Array.from(NON_EMAIL_SENDER_CHANNEL_TYPES).sort((left, right) => left.localeCompare(right))\n}\n"],
|
|
5
|
+
"mappings": "AAyBA,MAAM,iCAAiC,oBAAI,IAAI;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAQM,SAAS,iCAAiC,aAAsC;AACrF,MAAI,OAAO,gBAAgB,SAAU,QAAO;AAC5C,QAAM,aAAa,YAAY,KAAK,EAAE,YAAY;AAClD,MAAI,CAAC,WAAY,QAAO;AACxB,SAAO,CAAC,+BAA+B,IAAI,UAAU;AACvD;AAGO,SAAS,iCAA2C;AACzD,SAAO,MAAM,KAAK,8BAA8B,EAAE,KAAK,CAAC,MAAM,UAAU,KAAK,cAAc,KAAK,CAAC;AACnG;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const EXTERNAL_CONVERSATION_SOURCE_ENTITY_TYPE = "communication_channels.external_conversation";
|
|
3
|
+
const composeSourceHintSchema = z.object({
|
|
4
|
+
sourceEntityType: z.string().optional(),
|
|
5
|
+
sourceEntityId: z.string().uuid().optional(),
|
|
6
|
+
parentMessageId: z.string().uuid().optional()
|
|
7
|
+
});
|
|
8
|
+
function composeRequiresChannelTypeResolution(body) {
|
|
9
|
+
if (!body || typeof body !== "object") return false;
|
|
10
|
+
const raw = body;
|
|
11
|
+
if (raw.visibility !== "public") return false;
|
|
12
|
+
if (raw.isDraft === true) return false;
|
|
13
|
+
const externalEmail = raw.externalEmail;
|
|
14
|
+
return !(typeof externalEmail === "string" && externalEmail.trim().length > 0);
|
|
15
|
+
}
|
|
16
|
+
function tryResolveChannelTypeService(container) {
|
|
17
|
+
try {
|
|
18
|
+
return container.resolve("communicationChannelsResolveChannelType");
|
|
19
|
+
} catch {
|
|
20
|
+
return void 0;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function resolveComposeSourceChannelType(container, scope, hint) {
|
|
24
|
+
const externalConversationId = hint.sourceEntityType === EXTERNAL_CONVERSATION_SOURCE_ENTITY_TYPE ? hint.sourceEntityId ?? null : null;
|
|
25
|
+
const messageId = hint.parentMessageId ?? null;
|
|
26
|
+
if (!externalConversationId && !messageId) return void 0;
|
|
27
|
+
const resolveChannelType = tryResolveChannelTypeService(container);
|
|
28
|
+
if (!resolveChannelType) return void 0;
|
|
29
|
+
const channelType = await resolveChannelType(container, scope, {
|
|
30
|
+
externalConversationId,
|
|
31
|
+
messageId
|
|
32
|
+
});
|
|
33
|
+
return channelType ?? void 0;
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
EXTERNAL_CONVERSATION_SOURCE_ENTITY_TYPE,
|
|
37
|
+
composeRequiresChannelTypeResolution,
|
|
38
|
+
composeSourceHintSchema,
|
|
39
|
+
resolveComposeSourceChannelType
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=composeSourceChannelType.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/messages/lib/composeSourceChannelType.ts"],
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\n\n/**\n * Entity type a channel-backed conversation is exposed under on a message's\n * `sourceEntityType`. Written by `communication_channels`' inbound ingest.\n */\nconst EXTERNAL_CONVERSATION_SOURCE_ENTITY_TYPE = 'communication_channels.external_conversation'\n\n/**\n * The only parts of a compose body this resolution needs. Read defensively from\n * the raw request body, before the body is validated, because the validation\n * outcome itself depends on the answer (#4975).\n */\nexport const composeSourceHintSchema = z.object({\n sourceEntityType: z.string().optional(),\n sourceEntityId: z.string().uuid().optional(),\n parentMessageId: z.string().uuid().optional(),\n})\n\nexport type ComposeSourceHint = z.infer<typeof composeSourceHintSchema>\n\n/**\n * Whether the compose validator can consult a resolved channel type at all.\n *\n * `sourceChannelType` is read in exactly one branch \u2014 a non-draft, public\n * message that carries no address. Every internal reply, every draft and every\n * public message that already supplies an address ignores it, so resolving it\n * for them is a DI resolve plus a database round-trip whose answer is\n * discarded. Mirrors `refineComposeMessage` and reads the raw body defensively,\n * because this runs before validation. Skipping resolution yields `undefined`,\n * which is already the fail-closed value.\n */\nexport function composeRequiresChannelTypeResolution(body: unknown): boolean {\n if (!body || typeof body !== 'object') return false\n const raw = body as Record<string, unknown>\n if (raw.visibility !== 'public') return false\n if (raw.isDraft === true) return false\n const externalEmail = raw.externalEmail\n return !(typeof externalEmail === 'string' && externalEmail.trim().length > 0)\n}\n\ntype ResolveChannelTypeService = (\n container: ContainerLike,\n scope: { tenantId: string; organizationId: string | null },\n reference: { externalConversationId?: string | null; messageId?: string | null },\n) => Promise<string | null>\n\ntype ContainerLike = { resolve: <T = unknown>(name: string) => T }\n\nfunction tryResolveChannelTypeService(\n container: ContainerLike,\n): ResolveChannelTypeService | undefined {\n try {\n return container.resolve<ResolveChannelTypeService>('communicationChannelsResolveChannelType')\n } catch {\n // `communication_channels` is optional: without it no message can originate\n // from a channel, so \"unknown\" is both correct and fail-closed.\n return undefined\n }\n}\n\n/**\n * Resolve the channel type a compose request originates from, server-side.\n *\n * Never derived from the request body's own `sourceChannelType` \u2014 that would let\n * any caller waive the `externalEmail` requirement by asserting a channel type.\n * It is looked up from the conversation the message is being composed on, or\n * from the parent message it replies to.\n *\n * Returns `undefined` when nothing can be established, which the compose\n * validator treats as \"unknown\" and therefore keeps the pre-#4975 rule.\n */\nexport async function resolveComposeSourceChannelType(\n container: ContainerLike,\n scope: { tenantId: string; organizationId: string | null },\n hint: ComposeSourceHint,\n): Promise<string | undefined> {\n const externalConversationId =\n hint.sourceEntityType === EXTERNAL_CONVERSATION_SOURCE_ENTITY_TYPE\n ? hint.sourceEntityId ?? null\n : null\n const messageId = hint.parentMessageId ?? null\n if (!externalConversationId && !messageId) return undefined\n\n const resolveChannelType = tryResolveChannelTypeService(container)\n if (!resolveChannelType) return undefined\n\n const channelType = await resolveChannelType(container, scope, {\n externalConversationId,\n messageId,\n })\n return channelType ?? undefined\n}\n\nexport { EXTERNAL_CONVERSATION_SOURCE_ENTITY_TYPE }\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS;AAMlB,MAAM,2CAA2C;AAO1C,MAAM,0BAA0B,EAAE,OAAO;AAAA,EAC9C,kBAAkB,EAAE,OAAO,EAAE,SAAS;AAAA,EACtC,gBAAgB,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EAC3C,iBAAiB,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAC9C,CAAC;AAeM,SAAS,qCAAqC,MAAwB;AAC3E,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,QAAM,MAAM;AACZ,MAAI,IAAI,eAAe,SAAU,QAAO;AACxC,MAAI,IAAI,YAAY,KAAM,QAAO;AACjC,QAAM,gBAAgB,IAAI;AAC1B,SAAO,EAAE,OAAO,kBAAkB,YAAY,cAAc,KAAK,EAAE,SAAS;AAC9E;AAUA,SAAS,6BACP,WACuC;AACvC,MAAI;AACF,WAAO,UAAU,QAAmC,yCAAyC;AAAA,EAC/F,QAAQ;AAGN,WAAO;AAAA,EACT;AACF;AAaA,eAAsB,gCACpB,WACA,OACA,MAC6B;AAC7B,QAAM,yBACJ,KAAK,qBAAqB,2CACtB,KAAK,kBAAkB,OACvB;AACN,QAAM,YAAY,KAAK,mBAAmB;AAC1C,MAAI,CAAC,0BAA0B,CAAC,UAAW,QAAO;AAElD,QAAM,qBAAqB,6BAA6B,SAAS;AACjE,MAAI,CAAC,mBAAoB,QAAO;AAEhC,QAAM,cAAc,MAAM,mBAAmB,WAAW,OAAO;AAAA,IAC7D;AAAA,IACA;AAAA,EACF,CAAC;AACD,SAAO,eAAe;AACxB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -4,6 +4,7 @@ import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
|
4
4
|
import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
|
|
5
5
|
import { checkRateLimit, getClientIp, RATE_LIMIT_ERROR_FALLBACK } from "@open-mercato/shared/lib/ratelimit/helpers";
|
|
6
6
|
import { getWebhookHandler } from "@open-mercato/shared/modules/payment_gateways/types";
|
|
7
|
+
import { markQueueJobOrigin } from "@open-mercato/shared/lib/queue/dispatchOrigin";
|
|
7
8
|
import { GatewayTransaction } from "../../../data/entities.js";
|
|
8
9
|
import { getPaymentGatewayQueue } from "../../../lib/queue.js";
|
|
9
10
|
import { processPaymentGatewayWebhookJob } from "../../../lib/webhook-processor.js";
|
|
@@ -81,17 +82,14 @@ async function POST(req, { params }) {
|
|
|
81
82
|
throw lastVerificationError ?? new Error("Webhook verification failed: no matching transaction");
|
|
82
83
|
}
|
|
83
84
|
const scope = matchedScope;
|
|
84
|
-
const jobPayload = {
|
|
85
|
+
const jobPayload = markQueueJobOrigin({
|
|
85
86
|
providerKey,
|
|
86
87
|
event,
|
|
87
88
|
transactionId: transaction.id,
|
|
88
89
|
scope
|
|
89
|
-
};
|
|
90
|
+
}, "inbound-webhook");
|
|
90
91
|
if (process.env.QUEUE_STRATEGY === "async") {
|
|
91
|
-
await queue.enqueue(
|
|
92
|
-
name: "payment-gateway-webhook",
|
|
93
|
-
payload: jobPayload
|
|
94
|
-
});
|
|
92
|
+
await queue.enqueue(jobPayload);
|
|
95
93
|
} else {
|
|
96
94
|
await processPaymentGatewayWebhookJob(
|
|
97
95
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/payment_gateways/api/webhook/%5Bprovider%5D/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { checkRateLimit, getClientIp, RATE_LIMIT_ERROR_FALLBACK } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport type { RateLimiterService } from '@open-mercato/shared/lib/ratelimit/service'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { getWebhookHandler } from '@open-mercato/shared/modules/payment_gateways/types'\nimport type { IntegrationLogService } from '../../../../integrations/lib/log-service'\nimport type { PaymentGatewayService } from '../../../lib/gateway-service'\nimport type { CredentialsService } from '../../../../integrations/lib/credentials-service'\nimport { GatewayTransaction } from '../../../data/entities'\nimport { getPaymentGatewayQueue } from '../../../lib/queue'\nimport { processPaymentGatewayWebhookJob } from '../../../lib/webhook-processor'\nimport { paymentGatewaysTag } from '../../openapi'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { readBoundedRequestBody, WebhookBodyTooLargeError } from '@open-mercato/shared/lib/webhooks'\n\nconst logger = createLogger('payment_gateways').child({ component: 'webhook' })\n\nexport const metadata = {\n path: '/payment_gateways/webhook/[provider]',\n POST: { requireAuth: false },\n}\n\nconst WEBHOOK_VERIFICATION_FAILED = 'Webhook verification failed'\n\nconst paymentGatewayWebhookRateLimitConfig = {\n points: 60,\n duration: 60,\n keyPrefix: 'payment_gateways:webhook',\n}\n\nexport async function POST(req: Request, { params }: { params: Promise<{ provider: string }> | { provider: string } }) {\n const resolvedParams = await params\n const providerKey = resolvedParams.provider\n const container = await createRequestContainer()\n const registration = getWebhookHandler(providerKey)\n if (!registration) {\n return NextResponse.json({ error: `No webhook handler for provider: ${providerKey}` }, { status: 404 })\n }\n\n const rateLimitResponse = await checkProviderWebhookRateLimit(container, req, providerKey)\n if (rateLimitResponse) return rateLimitResponse\n\n let rawBody: string\n try {\n rawBody = registration.maxBodyBytes === undefined\n ? await req.text()\n : await readBoundedRequestBody(req, { maxBytes: registration.maxBodyBytes })\n } catch (error) {\n if (error instanceof WebhookBodyTooLargeError) {\n return NextResponse.json({ error: 'Webhook payload too large' }, { status: 413 })\n }\n throw error\n }\n const headers: Record<string, string> = {}\n req.headers.forEach((value, key) => {\n headers[key] = value\n })\n\n const service = container.resolve('paymentGatewayService') as PaymentGatewayService\n const em = container.resolve('em') as EntityManager\n const integrationCredentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const queue = getPaymentGatewayQueue(registration.queue ?? 'payment-gateways-webhook')\n const payload = await readJsonSafe<Record<string, unknown>>(rawBody)\n const sessionIdHint = registration.readSessionIdHint?.(payload) ?? null\n\n try {\n // The webhook endpoint is unauthenticated. Tenant/organization scope MUST come from a\n // GatewayTransaction whose per-tenant credentials successfully verify the inbound\n // signature \u2014 NEVER from attacker-controlled payload metadata. If no candidate\n // transaction can be located by the provider-reported session id, or no candidate's\n // credentials can verify the signature, we fail closed with 401. This prevents\n // forged webhooks (e.g. mock gateway PoC) from mutating another tenant's payment\n // state via `event.data.metadata.{organizationId,tenantId}`.\n const candidates = sessionIdHint\n ? await findWithDecryption(\n em,\n GatewayTransaction,\n {\n providerKey,\n providerSessionId: sessionIdHint,\n deletedAt: null,\n },\n { limit: 10, orderBy: { createdAt: 'desc' } },\n )\n : []\n\n let transaction: GatewayTransaction | null = null\n let matchedScope: { organizationId: string; tenantId: string } | null = null\n let event: Awaited<ReturnType<typeof registration.handler>> | null = null\n let lastVerificationError: unknown = null\n\n for (const candidate of candidates) {\n const candidateScope = { organizationId: candidate.organizationId, tenantId: candidate.tenantId }\n const credentials = await integrationCredentialsService.resolve(`gateway_${providerKey}`, candidateScope) ?? {}\n try {\n event = await registration.handler({ rawBody, headers, credentials })\n transaction = candidate\n matchedScope = candidateScope\n break\n } catch (error: unknown) {\n lastVerificationError = error\n }\n }\n\n if (!event || !transaction || !matchedScope) {\n throw lastVerificationError ?? new Error('Webhook verification failed: no matching transaction')\n }\n\n const scope = matchedScope\n\n const jobPayload = {\n providerKey,\n event,\n transactionId: transaction.id,\n scope,\n }\n\n if (process.env.QUEUE_STRATEGY === 'async') {\n await queue.enqueue(
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AACvC,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB,aAAa,iCAAiC;AAGvE,SAAS,yBAAyB;
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { checkRateLimit, getClientIp, RATE_LIMIT_ERROR_FALLBACK } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport type { RateLimiterService } from '@open-mercato/shared/lib/ratelimit/service'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { getWebhookHandler } from '@open-mercato/shared/modules/payment_gateways/types'\nimport { markQueueJobOrigin } from '@open-mercato/shared/lib/queue/dispatchOrigin'\nimport type { IntegrationLogService } from '../../../../integrations/lib/log-service'\nimport type { PaymentGatewayService } from '../../../lib/gateway-service'\nimport type { CredentialsService } from '../../../../integrations/lib/credentials-service'\nimport { GatewayTransaction } from '../../../data/entities'\nimport { getPaymentGatewayQueue } from '../../../lib/queue'\nimport { processPaymentGatewayWebhookJob } from '../../../lib/webhook-processor'\nimport { paymentGatewaysTag } from '../../openapi'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { readBoundedRequestBody, WebhookBodyTooLargeError } from '@open-mercato/shared/lib/webhooks'\n\nconst logger = createLogger('payment_gateways').child({ component: 'webhook' })\n\nexport const metadata = {\n path: '/payment_gateways/webhook/[provider]',\n POST: { requireAuth: false },\n}\n\nconst WEBHOOK_VERIFICATION_FAILED = 'Webhook verification failed'\n\nconst paymentGatewayWebhookRateLimitConfig = {\n points: 60,\n duration: 60,\n keyPrefix: 'payment_gateways:webhook',\n}\n\nexport async function POST(req: Request, { params }: { params: Promise<{ provider: string }> | { provider: string } }) {\n const resolvedParams = await params\n const providerKey = resolvedParams.provider\n const container = await createRequestContainer()\n const registration = getWebhookHandler(providerKey)\n if (!registration) {\n return NextResponse.json({ error: `No webhook handler for provider: ${providerKey}` }, { status: 404 })\n }\n\n const rateLimitResponse = await checkProviderWebhookRateLimit(container, req, providerKey)\n if (rateLimitResponse) return rateLimitResponse\n\n let rawBody: string\n try {\n rawBody = registration.maxBodyBytes === undefined\n ? await req.text()\n : await readBoundedRequestBody(req, { maxBytes: registration.maxBodyBytes })\n } catch (error) {\n if (error instanceof WebhookBodyTooLargeError) {\n return NextResponse.json({ error: 'Webhook payload too large' }, { status: 413 })\n }\n throw error\n }\n const headers: Record<string, string> = {}\n req.headers.forEach((value, key) => {\n headers[key] = value\n })\n\n const service = container.resolve('paymentGatewayService') as PaymentGatewayService\n const em = container.resolve('em') as EntityManager\n const integrationCredentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const queue = getPaymentGatewayQueue(registration.queue ?? 'payment-gateways-webhook')\n const payload = await readJsonSafe<Record<string, unknown>>(rawBody)\n const sessionIdHint = registration.readSessionIdHint?.(payload) ?? null\n\n try {\n // The webhook endpoint is unauthenticated. Tenant/organization scope MUST come from a\n // GatewayTransaction whose per-tenant credentials successfully verify the inbound\n // signature \u2014 NEVER from attacker-controlled payload metadata. If no candidate\n // transaction can be located by the provider-reported session id, or no candidate's\n // credentials can verify the signature, we fail closed with 401. This prevents\n // forged webhooks (e.g. mock gateway PoC) from mutating another tenant's payment\n // state via `event.data.metadata.{organizationId,tenantId}`.\n const candidates = sessionIdHint\n ? await findWithDecryption(\n em,\n GatewayTransaction,\n {\n providerKey,\n providerSessionId: sessionIdHint,\n deletedAt: null,\n },\n { limit: 10, orderBy: { createdAt: 'desc' } },\n )\n : []\n\n let transaction: GatewayTransaction | null = null\n let matchedScope: { organizationId: string; tenantId: string } | null = null\n let event: Awaited<ReturnType<typeof registration.handler>> | null = null\n let lastVerificationError: unknown = null\n\n for (const candidate of candidates) {\n const candidateScope = { organizationId: candidate.organizationId, tenantId: candidate.tenantId }\n const credentials = await integrationCredentialsService.resolve(`gateway_${providerKey}`, candidateScope) ?? {}\n try {\n event = await registration.handler({ rawBody, headers, credentials })\n transaction = candidate\n matchedScope = candidateScope\n break\n } catch (error: unknown) {\n lastVerificationError = error\n }\n }\n\n if (!event || !transaction || !matchedScope) {\n throw lastVerificationError ?? new Error('Webhook verification failed: no matching transaction')\n }\n\n const scope = matchedScope\n\n const jobPayload = markQueueJobOrigin({\n providerKey,\n event,\n transactionId: transaction.id,\n scope,\n }, 'inbound-webhook')\n\n if (process.env.QUEUE_STRATEGY === 'async') {\n await queue.enqueue(jobPayload)\n } else {\n await processPaymentGatewayWebhookJob(\n {\n em: container.resolve('em') as EntityManager,\n paymentGatewayService: service,\n integrationLogService: container.resolve('integrationLogService') as IntegrationLogService,\n },\n jobPayload,\n )\n }\n\n return NextResponse.json({ received: true, queued: true }, { status: 202 })\n } catch (err: unknown) {\n logger.warn('Webhook verification failed', { providerKey, err })\n return NextResponse.json({ error: WEBHOOK_VERIFICATION_FAILED }, { status: 401 })\n }\n}\n\nasync function checkProviderWebhookRateLimit(\n container: { resolve: (name: string) => unknown },\n req: Request,\n providerKey: string,\n): Promise<NextResponse | null> {\n const rateLimiterService = tryResolve<RateLimiterService>(container, 'rateLimiterService')\n if (!rateLimiterService) return null\n\n return checkRateLimit(\n rateLimiterService,\n paymentGatewayWebhookRateLimitConfig,\n `${providerKey}:${getClientIp(req, rateLimiterService.trustProxyDepth) ?? 'unknown'}`,\n RATE_LIMIT_ERROR_FALLBACK,\n )\n}\n\nfunction tryResolve<T>(container: { resolve: (name: string) => unknown }, name: string): T | null {\n try {\n return container.resolve(name) as T\n } catch {\n return null\n }\n}\n\nexport const openApi = {\n tags: [paymentGatewaysTag],\n summary: 'Receive payment gateway webhook',\n methods: {\n POST: {\n summary: 'Process inbound webhook from payment provider',\n tags: [paymentGatewaysTag],\n responses: [\n { status: 202, description: 'Webhook accepted for async processing' },\n { status: 401, description: 'Signature verification failed' },\n { status: 413, description: 'Webhook payload too large' },\n { status: 404, description: 'Unknown provider' },\n ],\n },\n },\n}\n\nexport default POST\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -91,6 +91,7 @@ function PaymentTransactionsPage() {
|
|
|
91
91
|
const [page, setPage] = React.useState(1);
|
|
92
92
|
const [total, setTotal] = React.useState(0);
|
|
93
93
|
const [totalPages, setTotalPages] = React.useState(1);
|
|
94
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false);
|
|
94
95
|
const [search, setSearch] = React.useState("");
|
|
95
96
|
const [filterValues, setFilterValues] = React.useState({});
|
|
96
97
|
const [isLoading, setIsLoading] = React.useState(true);
|
|
@@ -132,6 +133,7 @@ function PaymentTransactionsPage() {
|
|
|
132
133
|
setRows(Array.isArray(call.result.items) ? call.result.items : []);
|
|
133
134
|
setTotal(call.result.total ?? 0);
|
|
134
135
|
setTotalPages(call.result.totalPages ?? 1);
|
|
136
|
+
setTotalIsCapped(call.result?.totalIsCapped === true);
|
|
135
137
|
} else {
|
|
136
138
|
flash(t("payment_gateways.transactions.error.load", "Failed to load payment transactions"), "error");
|
|
137
139
|
setRows([]);
|
|
@@ -354,7 +356,7 @@ function PaymentTransactionsPage() {
|
|
|
354
356
|
},
|
|
355
357
|
searchPlaceholder: t("payment_gateways.transactions.searchPlaceholder", "Search by payment, transaction, session, or gateway id"),
|
|
356
358
|
perspective: { tableId: extensionPoints.hosts.transactionsTable.tableId },
|
|
357
|
-
pagination: { page, pageSize: 20, total, totalPages, onPageChange: setPage },
|
|
359
|
+
pagination: { page, pageSize: 20, total, totalPages, totalIsCapped, onPageChange: setPage },
|
|
358
360
|
isLoading,
|
|
359
361
|
onRowClick: (row) => setSelectedId((current) => current === row.id ? null : row.id),
|
|
360
362
|
rowActions: (row) => /* @__PURE__ */ jsx(RowActions, { items: [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/payment_gateways/backend/payment-gateways/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/core/modules/payment_gateways/extension-points'\nimport { useSearchParams } from 'next/navigation'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { Page, PageHeader, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Card, CardContent, CardHeader, CardTitle } from '@open-mercato/ui/primitives/card'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { LogList, type LogListEntry } from '@open-mercato/ui/backend/LogList'\nimport { CreditCard, HandCoins, RefreshCw, Webhook } from 'lucide-react'\n\ntype TransactionRow = {\n id: string\n paymentId: string\n providerKey: string\n providerSessionId?: string | null\n gatewayPaymentId?: string | null\n gatewayRefundId?: string | null\n unifiedStatus: string\n gatewayStatus?: string | null\n amount: string\n currencyCode: string\n redirectUrl?: string | null\n lastWebhookAt?: string | null\n lastPolledAt?: string | null\n createdAt: string | null\n updatedAt: string | null\n}\n\ntype TransactionLogEntry = {\n id: string\n integrationId: string\n runId?: string | null\n scopeEntityType?: string | null\n scopeEntityId?: string | null\n level: 'info' | 'warn' | 'error'\n message: string\n code?: string | null\n payload?: Record<string, unknown> | null\n createdAt: string | null\n}\n\ntype TransactionDetail = {\n transaction: {\n id: string\n paymentId: string\n providerKey: string\n providerSessionId?: string | null\n gatewayPaymentId?: string | null\n gatewayRefundId?: string | null\n unifiedStatus: string\n gatewayStatus?: string | null\n redirectUrl?: string | null\n amount: string\n currencyCode: string\n gatewayMetadata?: Record<string, unknown> | null\n webhookLog?: Array<{\n eventType: string\n receivedAt: string\n idempotencyKey: string\n unifiedStatus: string\n processed: boolean\n }> | null\n lastWebhookAt?: string | null\n lastPolledAt?: string | null\n expiresAt?: string | null\n createdAt: string | null\n updatedAt: string | null\n }\n logs: TransactionLogEntry[]\n}\n\ntype TransactionsResponse = {\n items: TransactionRow[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n}\n\nconst STATUS_STYLES: Record<string, string> = {\n pending: 'bg-slate-100 text-slate-800',\n authorized: 'bg-blue-100 text-blue-800',\n captured: 'bg-green-100 text-green-800',\n partially_captured: 'bg-emerald-100 text-emerald-800',\n refunded: 'bg-amber-100 text-amber-800',\n partially_refunded: 'bg-orange-100 text-orange-800',\n cancelled: 'bg-zinc-200 text-zinc-900',\n failed: 'bg-red-100 text-red-800',\n expired: 'bg-neutral-200 text-neutral-900',\n unknown: 'bg-purple-100 text-purple-800',\n}\n\nfunction formatDateTime(value: string | null | undefined): string {\n if (!value) return '\u2014'\n const parsed = new Date(value)\n if (Number.isNaN(parsed.getTime())) return value\n return parsed.toLocaleString()\n}\n\nfunction formatAmount(value: string, currencyCode: string): string {\n const amount = Number(value)\n if (Number.isNaN(amount)) return `${value} ${currencyCode}`\n try {\n return new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency: currencyCode,\n }).format(amount)\n } catch {\n return `${amount.toFixed(2)} ${currencyCode}`\n }\n}\n\nfunction formatTypeLabel(value: string): string {\n return value\n .split('_')\n .filter(Boolean)\n .map((part) => part[0]?.toUpperCase() + part.slice(1))\n .join(' ')\n}\n\nfunction formatLogDetailLabel(key: string): string {\n return key\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .split(' ')\n .filter(Boolean)\n .map((part) => part[0]?.toUpperCase() + part.slice(1))\n .join(' ')\n}\n\nfunction isPrimitiveLogValue(value: unknown): value is string | number | boolean | null {\n return value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'\n}\n\nfunction splitLogPayload(payload: Record<string, unknown> | null | undefined) {\n if (!payload) {\n return {\n inlineEntries: [] as Array<[string, string | number | boolean | null]>,\n nestedEntries: [] as Array<[string, unknown]>,\n }\n }\n\n const inlineEntries: Array<[string, string | number | boolean | null]> = []\n const nestedEntries: Array<[string, unknown]> = []\n Object.entries(payload).forEach(([key, value]) => {\n if (isPrimitiveLogValue(value)) {\n inlineEntries.push([key, value])\n return\n }\n nestedEntries.push([key, value])\n })\n return { inlineEntries, nestedEntries }\n}\n\nfunction DetailStat({ label, value }: { label: string; value: React.ReactNode }) {\n return (\n <div className=\"rounded-lg border bg-muted/30 px-4 py-3\">\n <div className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">{label}</div>\n <div className=\"mt-1 text-sm font-medium\">{value}</div>\n </div>\n )\n}\n\nexport default function PaymentTransactionsPage() {\n const t = useT()\n const searchParams = useSearchParams()\n const scopeVersion = useOrganizationScopeVersion()\n const [rows, setRows] = React.useState<TransactionRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [isLoading, setIsLoading] = React.useState(true)\n const [selectedId, setSelectedId] = React.useState<string | null>(null)\n const [detail, setDetail] = React.useState<TransactionDetail | null>(null)\n const [isLoadingDetail, setIsLoadingDetail] = React.useState(false)\n const [detailError, setDetailError] = React.useState<string | null>(null)\n const [isRefreshingStatus, setIsRefreshingStatus] = React.useState(false)\n const [isCapturing, setIsCapturing] = React.useState(false)\n const { runMutation } = useGuardedMutation<{\n entityType: string\n entityId?: string\n }>({\n contextId: 'payment_gateways:transactions-detail',\n })\n const noneLabel = t('common.none', 'None')\n const requestedTransactionId = React.useMemo(() => {\n const raw = searchParams.get('transactionId')\n return raw && raw.trim().length > 0 ? raw.trim() : null\n }, [searchParams])\n\n const formatLogPrimitiveValue = React.useCallback((value: string | number | boolean | null): string => {\n if (value === null) return noneLabel\n if (typeof value === 'boolean') return value ? t('common.yes', 'Yes') : t('common.no', 'No')\n return String(value)\n }, [noneLabel, t])\n\n const loadRows = React.useCallback(async () => {\n setIsLoading(true)\n const params = new URLSearchParams({\n page: String(page),\n pageSize: '20',\n })\n if (search.trim()) params.set('search', search.trim())\n if (typeof filterValues.providerKey === 'string' && filterValues.providerKey) {\n params.set('providerKey', filterValues.providerKey)\n }\n if (typeof filterValues.status === 'string' && filterValues.status) {\n params.set('status', filterValues.status)\n }\n const fallback: TransactionsResponse = { items: [], total: 0, page, pageSize: 20, totalPages: 1 }\n const call = await apiCall<TransactionsResponse>(`/api/payment_gateways/transactions?${params.toString()}`, undefined, { fallback })\n if (call.ok && call.result) {\n setRows(Array.isArray(call.result.items) ? call.result.items : [])\n setTotal(call.result.total ?? 0)\n setTotalPages(call.result.totalPages ?? 1)\n } else {\n flash(t('payment_gateways.transactions.error.load', 'Failed to load payment transactions'), 'error')\n setRows([])\n setTotal(0)\n setTotalPages(1)\n }\n setIsLoading(false)\n }, [filterValues.providerKey, filterValues.status, page, search, t])\n\n const loadDetail = React.useCallback(async (transactionId: string) => {\n setIsLoadingDetail(true)\n setDetailError(null)\n const call = await apiCall<TransactionDetail>(`/api/payment_gateways/transactions/${encodeURIComponent(transactionId)}`, undefined, { fallback: null })\n if (call.ok && call.result) {\n setDetail(call.result)\n } else {\n setDetail(null)\n setDetailError(t('payment_gateways.transactions.error.loadDetail', 'Failed to load transaction details'))\n }\n setIsLoadingDetail(false)\n }, [t])\n\n React.useEffect(() => {\n void loadRows()\n }, [loadRows, scopeVersion])\n\n React.useEffect(() => {\n if (!selectedId) {\n setDetail(null)\n setDetailError(null)\n return\n }\n void loadDetail(selectedId)\n }, [loadDetail, selectedId])\n\n React.useEffect(() => {\n setSelectedId((current) => (current && rows.some((row) => row.id === current) ? current : null))\n }, [rows])\n\n React.useEffect(() => {\n if (!requestedTransactionId) return\n if (!rows.some((row) => row.id === requestedTransactionId)) return\n setSelectedId(requestedTransactionId)\n }, [requestedTransactionId, rows])\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n const next: FilterValues = {}\n Object.entries(values).forEach(([key, value]) => {\n if (typeof value === 'string' && value.trim()) next[key] = value\n })\n setFilterValues(next)\n setPage(1)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n setPage(1)\n }, [])\n\n const handleRefreshStatus = React.useCallback(async () => {\n if (!selectedId) return\n setIsRefreshingStatus(true)\n try {\n await runMutation({\n operation: async () => {\n await apiCallOrThrow('/api/payment_gateways/status', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ transactionId: selectedId }),\n })\n },\n context: {\n entityType: 'payment_gateways:gateway_transaction',\n entityId: selectedId,\n },\n mutationPayload: { transactionId: selectedId },\n })\n await Promise.all([\n loadRows(),\n loadDetail(selectedId),\n ])\n flash(t('payment_gateways.transactions.success.refreshStatus', 'Transaction status refreshed'), 'success')\n } catch (error) {\n const message = error instanceof Error && error.message\n ? error.message\n : t('payment_gateways.transactions.error.refreshStatus', 'Failed to refresh transaction status')\n flash(message, 'error')\n } finally {\n setIsRefreshingStatus(false)\n }\n }, [loadDetail, loadRows, runMutation, selectedId, t])\n\n const handleCapturePayment = React.useCallback(async () => {\n if (!selectedId) return\n setIsCapturing(true)\n try {\n await runMutation({\n operation: async () => {\n await apiCallOrThrow('/api/payment_gateways/capture', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ transactionId: selectedId }),\n })\n },\n context: {\n entityType: 'payment_gateways:gateway_transaction',\n entityId: selectedId,\n },\n mutationPayload: { transactionId: selectedId },\n })\n await Promise.all([\n loadRows(),\n loadDetail(selectedId),\n ])\n flash(t('payment_gateways.transactions.success.capture', 'Payment captured'), 'success')\n } catch (error) {\n const message = error instanceof Error && error.message\n ? error.message\n : t('payment_gateways.transactions.error.capture', 'Failed to capture payment')\n flash(message, 'error')\n } finally {\n setIsCapturing(false)\n }\n }, [loadDetail, loadRows, runMutation, selectedId, t])\n\n const providerOptions = React.useMemo(() => {\n const values = Array.from(new Set(rows.map((row) => row.providerKey).filter(Boolean))).sort((a, b) => a.localeCompare(b))\n return values.map((value) => ({\n label: formatTypeLabel(value),\n value,\n }))\n }, [rows])\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'providerKey',\n type: 'select',\n label: t('payment_gateways.transactions.filters.provider', 'Provider'),\n options: [\n { label: t('payment_gateways.transactions.filters.allProviders', 'All providers'), value: '' },\n ...providerOptions,\n ],\n },\n {\n id: 'status',\n type: 'select',\n label: t('payment_gateways.transactions.filters.status', 'Status'),\n options: [\n { label: t('payment_gateways.transactions.filters.allStatuses', 'All statuses'), value: '' },\n { label: t('payment_gateways.status.pending', 'Pending'), value: 'pending' },\n { label: t('payment_gateways.status.authorized', 'Authorized'), value: 'authorized' },\n { label: t('payment_gateways.status.captured', 'Captured'), value: 'captured' },\n { label: t('payment_gateways.status.partially_captured', 'Partially Captured'), value: 'partially_captured' },\n { label: t('payment_gateways.status.refunded', 'Refunded'), value: 'refunded' },\n { label: t('payment_gateways.status.partially_refunded', 'Partially Refunded'), value: 'partially_refunded' },\n { label: t('payment_gateways.status.cancelled', 'Cancelled'), value: 'cancelled' },\n { label: t('payment_gateways.status.failed', 'Failed'), value: 'failed' },\n { label: t('payment_gateways.status.expired', 'Expired'), value: 'expired' },\n { label: t('payment_gateways.status.unknown', 'Unknown'), value: 'unknown' },\n ],\n },\n ], [providerOptions, t])\n\n const columns = React.useMemo<ColumnDef<TransactionRow>[]>(() => [\n {\n accessorKey: 'paymentId',\n header: t('payment_gateways.transactions.columns.paymentId', 'Payment'),\n cell: ({ row }) => (\n <div className=\"space-y-1\">\n <div className=\"font-medium\">{row.original.paymentId}</div>\n <div className=\"text-xs text-muted-foreground\">{row.original.id}</div>\n </div>\n ),\n meta: { maxWidth: '20rem' },\n },\n {\n accessorKey: 'providerKey',\n header: t('payment_gateways.transactions.columns.provider', 'Provider'),\n cell: ({ row }) => (\n <div className=\"flex items-center gap-2\">\n <CreditCard className=\"h-4 w-4 text-muted-foreground\" />\n <span>{formatTypeLabel(row.original.providerKey)}</span>\n </div>\n ),\n },\n {\n accessorKey: 'unifiedStatus',\n header: t('payment_gateways.transactions.columns.status', 'Status'),\n cell: ({ row }) => (\n <Badge variant=\"secondary\" className={STATUS_STYLES[row.original.unifiedStatus] ?? ''}>\n {t(`payment_gateways.status.${row.original.unifiedStatus}`, formatTypeLabel(row.original.unifiedStatus))}\n </Badge>\n ),\n },\n {\n accessorKey: 'amount',\n header: t('payment_gateways.transactions.columns.amount', 'Amount'),\n cell: ({ row }) => formatAmount(row.original.amount, row.original.currencyCode),\n },\n {\n accessorKey: 'providerSessionId',\n header: t('payment_gateways.transactions.columns.session', 'Session'),\n cell: ({ row }) => (\n <span className=\"font-mono text-xs text-muted-foreground\">\n {row.original.providerSessionId ?? '\u2014'}\n </span>\n ),\n meta: { maxWidth: '18rem', truncate: true },\n },\n {\n accessorKey: 'updatedAt',\n header: t('payment_gateways.transactions.columns.updatedAt', 'Updated'),\n cell: ({ row }) => formatDateTime(row.original.updatedAt),\n },\n ], [t])\n\n const selectedSummary = React.useMemo(\n () => rows.find((row) => row.id === selectedId) ?? null,\n [rows, selectedId],\n )\n const canCaptureSelected = React.useMemo(() => {\n const status = detail?.transaction.unifiedStatus ?? selectedSummary?.unifiedStatus ?? null\n return status === 'authorized'\n }, [detail?.transaction.unifiedStatus, selectedSummary?.unifiedStatus])\n\n return (\n <Page>\n <PageHeader\n title={t('payment_gateways.transactions.title', 'Payment Transactions')}\n description={t('payment_gateways.transactions.description', 'Track all payment-gateway transactions, inspect webhook activity, and review provider logs from one place.')}\n />\n <PageBody className=\"space-y-6\">\n <DataTable\n stickyActionsColumn\n title={t('payment_gateways.transactions.tableTitle', 'Transactions')}\n columns={columns}\n data={rows}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n searchValue={search}\n onSearchChange={(value) => { setSearch(value); setPage(1) }}\n searchPlaceholder={t('payment_gateways.transactions.searchPlaceholder', 'Search by payment, transaction, session, or gateway id')}\n perspective={{ tableId: extensionPoints.hosts.transactionsTable.tableId }}\n pagination={{ page, pageSize: 20, total, totalPages, onPageChange: setPage }}\n isLoading={isLoading}\n onRowClick={(row) => setSelectedId((current) => current === row.id ? null : row.id)}\n rowActions={(row) => (\n <RowActions items={[\n {\n id: 'details',\n label: selectedId === row.id\n ? t('payment_gateways.transactions.actions.hideDetails', 'Hide details')\n : t('payment_gateways.transactions.actions.showDetails', 'Show details'),\n onSelect: () => setSelectedId((current) => current === row.id ? null : row.id),\n },\n ]} />\n )}\n />\n\n {selectedId ? (\n <Card>\n <CardHeader className=\"gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-1\">\n <CardTitle>{t('payment_gateways.transactions.detail.title', 'Transaction details')}</CardTitle>\n {selectedSummary ? (\n <div className=\"flex flex-wrap items-center gap-2 text-sm text-muted-foreground\">\n <span>{selectedSummary.paymentId}</span>\n <span>\u2022</span>\n <span>{formatTypeLabel(selectedSummary.providerKey)}</span>\n <Badge variant=\"secondary\" className={STATUS_STYLES[selectedSummary.unifiedStatus] ?? ''}>\n {t(`payment_gateways.status.${selectedSummary.unifiedStatus}`, formatTypeLabel(selectedSummary.unifiedStatus))}\n </Badge>\n </div>\n ) : null}\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void handleRefreshStatus()}\n disabled={isRefreshingStatus || isLoadingDetail || isCapturing}\n >\n {isRefreshingStatus ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('payment_gateways.transactions.actions.refreshStatus', 'Refresh status')}\n </Button>\n {canCaptureSelected ? (\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void handleCapturePayment()}\n disabled={isRefreshingStatus || isLoadingDetail || isCapturing}\n >\n {isCapturing ? <Spinner className=\"mr-2 h-4 w-4\" /> : <HandCoins className=\"mr-2 h-4 w-4\" />}\n {t('payment_gateways.transactions.actions.capture', 'Capture payment')}\n </Button>\n ) : null}\n </CardHeader>\n <CardContent className=\"space-y-6\">\n {isLoadingDetail ? <LoadingMessage label={t('payment_gateways.transactions.detail.loading', 'Loading transaction details')} /> : null}\n {!isLoadingDetail && detailError ? <ErrorMessage label={detailError} /> : null}\n {!isLoadingDetail && !detailError && detail ? (\n <>\n <div className=\"grid gap-4 lg:grid-cols-4\">\n <DetailStat\n label={t('payment_gateways.transactions.detail.summary.status', 'Status')}\n value={(\n <Badge variant=\"secondary\" className={STATUS_STYLES[detail.transaction.unifiedStatus] ?? ''}>\n {t(`payment_gateways.status.${detail.transaction.unifiedStatus}`, formatTypeLabel(detail.transaction.unifiedStatus))}\n </Badge>\n )}\n />\n <DetailStat\n label={t('payment_gateways.transactions.detail.summary.gatewayStatus', 'Gateway status')}\n value={detail.transaction.gatewayStatus ?? noneLabel}\n />\n <DetailStat\n label={t('payment_gateways.transactions.detail.summary.amount', 'Amount')}\n value={formatAmount(detail.transaction.amount, detail.transaction.currencyCode)}\n />\n <DetailStat\n label={t('payment_gateways.transactions.detail.summary.provider', 'Provider')}\n value={formatTypeLabel(detail.transaction.providerKey)}\n />\n </div>\n\n <div className=\"grid gap-6 xl:grid-cols-[minmax(0,1.2fr)_minmax(0,0.8fr)]\">\n <div className=\"space-y-6\">\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">{t('payment_gateways.transactions.detail.identifiers', 'Identifiers')}</h3>\n <dl className=\"grid gap-3 md:grid-cols-2\">\n {[\n [t('payment_gateways.transactions.columns.transactionId', 'Transaction ID'), detail.transaction.id],\n [t('payment_gateways.transactions.columns.paymentId', 'Payment ID'), detail.transaction.paymentId],\n [t('payment_gateways.transactions.columns.session', 'Session ID'), detail.transaction.providerSessionId ?? '\u2014'],\n [t('payment_gateways.transactions.columns.gatewayPaymentId', 'Gateway payment ID'), detail.transaction.gatewayPaymentId ?? '\u2014'],\n [t('payment_gateways.transactions.columns.gatewayRefundId', 'Gateway refund ID'), detail.transaction.gatewayRefundId ?? '\u2014'],\n [t('payment_gateways.transactions.columns.redirectUrl', 'Redirect URL'), detail.transaction.redirectUrl ?? '\u2014'],\n [t('payment_gateways.transactions.columns.createdAt', 'Created at'), formatDateTime(detail.transaction.createdAt)],\n [t('payment_gateways.transactions.columns.updatedAt', 'Updated at'), formatDateTime(detail.transaction.updatedAt)],\n [t('payment_gateways.transactions.columns.lastWebhookAt', 'Last webhook'), formatDateTime(detail.transaction.lastWebhookAt)],\n [t('payment_gateways.transactions.columns.lastPolledAt', 'Last poll'), formatDateTime(detail.transaction.lastPolledAt)],\n ].map(([label, value]) => (\n <div key={label} className=\"rounded-lg border bg-muted/30 px-4 py-3\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">{label}</dt>\n <dd className=\"mt-1 break-all text-sm\">{value}</dd>\n </div>\n ))}\n </dl>\n </section>\n\n <section className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <Webhook className=\"h-4 w-4 text-muted-foreground\" />\n <h3 className=\"text-sm font-semibold\">{t('payment_gateways.transactions.detail.webhooks', 'Webhook activity')}</h3>\n </div>\n {detail.transaction.webhookLog && detail.transaction.webhookLog.length > 0 ? (\n <div className=\"overflow-hidden rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-2 text-left font-medium\">{t('payment_gateways.transactions.columns.eventType', 'Event')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('payment_gateways.transactions.columns.status', 'Status')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('payment_gateways.transactions.columns.processed', 'Processed')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('payment_gateways.transactions.columns.receivedAt', 'Received')}</th>\n </tr>\n </thead>\n <tbody>\n {detail.transaction.webhookLog.map((entry) => (\n <tr key={`${entry.idempotencyKey}:${entry.receivedAt}`} className=\"border-b last:border-0\">\n <td className=\"px-4 py-2 font-medium\">{entry.eventType}</td>\n <td className=\"px-4 py-2\">\n <Badge variant=\"secondary\" className={STATUS_STYLES[entry.unifiedStatus] ?? ''}>\n {t(`payment_gateways.status.${entry.unifiedStatus}`, formatTypeLabel(entry.unifiedStatus))}\n </Badge>\n </td>\n <td className=\"px-4 py-2\">{entry.processed ? t('common.yes', 'Yes') : t('common.no', 'No')}</td>\n <td className=\"px-4 py-2 text-muted-foreground\">{formatDateTime(entry.receivedAt)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('payment_gateways.transactions.detail.webhooksEmpty', 'No webhook events have been recorded for this transaction yet.')}</p>\n )}\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">{t('payment_gateways.transactions.detail.logs', 'Gateway logs')}</h3>\n <LogList\n entries={detail.logs.map<LogListEntry>((log) => {\n const metadataEntries = [\n [t('payment_gateways.transactions.log.time', 'Time'), formatDateTime(log.createdAt)],\n [t('payment_gateways.transactions.log.level', 'Level'), t(`payment_gateways.transactions.level.${log.level}`, log.level)],\n [t('payment_gateways.transactions.log.code', 'Code'), log.code ?? null],\n [t('payment_gateways.transactions.log.runId', 'Run ID'), log.runId ?? null],\n [t('payment_gateways.transactions.log.entityType', 'Entity Type'), log.scopeEntityType ?? null],\n [t('payment_gateways.transactions.log.entityId', 'Entity ID'), log.scopeEntityId ?? null],\n ].filter((entry): entry is [string, string] => typeof entry[1] === 'string' && entry[1].trim().length > 0)\n const { inlineEntries, nestedEntries } = splitLogPayload(log.payload)\n\n return {\n id: log.id,\n time: formatDateTime(log.createdAt),\n level: log.level,\n levelLabel: t(`payment_gateways.transactions.level.${log.level}`, log.level),\n message: log.message,\n body: (\n <div className=\"space-y-4\">\n {metadataEntries.length > 0 ? (\n <dl className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n {metadataEntries.map(([label, value]) => (\n <div key={label} className=\"rounded-md border bg-muted/30 px-3 py-2\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">{label}</dt>\n <dd className=\"mt-1 break-all text-sm\">{value}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n {inlineEntries.length > 0 ? (\n <dl className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n {inlineEntries.map(([key, value]) => (\n <div key={key} className=\"rounded-md border bg-muted/30 px-3 py-2\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">{formatLogDetailLabel(key)}</dt>\n <dd className=\"mt-1 break-words text-sm\">{formatLogPrimitiveValue(value)}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n {nestedEntries.map(([key, value]) => (\n <JsonDisplay\n key={key}\n data={value}\n title={formatLogDetailLabel(key)}\n defaultExpanded\n maxInitialDepth={1}\n theme=\"dark\"\n maxHeight=\"16rem\"\n className=\"p-4\"\n />\n ))}\n </div>\n ),\n }\n })}\n emptyMessage={t('payment_gateways.transactions.detail.logsEmpty', 'No transaction-scoped logs are available yet.')}\n />\n </section>\n </div>\n\n <div className=\"space-y-4\">\n <JsonDisplay\n data={detail.transaction.gatewayMetadata ?? {}}\n title={t('payment_gateways.transactions.detail.gatewayMetadata', 'Gateway metadata')}\n defaultExpanded\n maxInitialDepth={1}\n theme=\"dark\"\n maxHeight=\"24rem\"\n className=\"p-4\"\n />\n <InjectionSpot\n spotId={extensionPoints.hosts.transactionsAfter.spotId}\n context={{ selectedPaymentId: detail.transaction.paymentId }}\n />\n </div>\n </div>\n </>\n ) : null}\n </CardContent>\n </Card>\n ) : null}\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/core/modules/payment_gateways/extension-points'\nimport { useSearchParams } from 'next/navigation'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { Page, PageHeader, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Card, CardContent, CardHeader, CardTitle } from '@open-mercato/ui/primitives/card'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { LogList, type LogListEntry } from '@open-mercato/ui/backend/LogList'\nimport { CreditCard, HandCoins, RefreshCw, Webhook } from 'lucide-react'\n\ntype TransactionRow = {\n id: string\n paymentId: string\n providerKey: string\n providerSessionId?: string | null\n gatewayPaymentId?: string | null\n gatewayRefundId?: string | null\n unifiedStatus: string\n gatewayStatus?: string | null\n amount: string\n currencyCode: string\n redirectUrl?: string | null\n lastWebhookAt?: string | null\n lastPolledAt?: string | null\n createdAt: string | null\n updatedAt: string | null\n}\n\ntype TransactionLogEntry = {\n id: string\n integrationId: string\n runId?: string | null\n scopeEntityType?: string | null\n scopeEntityId?: string | null\n level: 'info' | 'warn' | 'error'\n message: string\n code?: string | null\n payload?: Record<string, unknown> | null\n createdAt: string | null\n}\n\ntype TransactionDetail = {\n transaction: {\n id: string\n paymentId: string\n providerKey: string\n providerSessionId?: string | null\n gatewayPaymentId?: string | null\n gatewayRefundId?: string | null\n unifiedStatus: string\n gatewayStatus?: string | null\n redirectUrl?: string | null\n amount: string\n currencyCode: string\n gatewayMetadata?: Record<string, unknown> | null\n webhookLog?: Array<{\n eventType: string\n receivedAt: string\n idempotencyKey: string\n unifiedStatus: string\n processed: boolean\n }> | null\n lastWebhookAt?: string | null\n lastPolledAt?: string | null\n expiresAt?: string | null\n createdAt: string | null\n updatedAt: string | null\n }\n logs: TransactionLogEntry[]\n}\n\ntype TransactionsResponse = {\n items: TransactionRow[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n totalIsCapped?: boolean\n}\n\nconst STATUS_STYLES: Record<string, string> = {\n pending: 'bg-slate-100 text-slate-800',\n authorized: 'bg-blue-100 text-blue-800',\n captured: 'bg-green-100 text-green-800',\n partially_captured: 'bg-emerald-100 text-emerald-800',\n refunded: 'bg-amber-100 text-amber-800',\n partially_refunded: 'bg-orange-100 text-orange-800',\n cancelled: 'bg-zinc-200 text-zinc-900',\n failed: 'bg-red-100 text-red-800',\n expired: 'bg-neutral-200 text-neutral-900',\n unknown: 'bg-purple-100 text-purple-800',\n}\n\nfunction formatDateTime(value: string | null | undefined): string {\n if (!value) return '\u2014'\n const parsed = new Date(value)\n if (Number.isNaN(parsed.getTime())) return value\n return parsed.toLocaleString()\n}\n\nfunction formatAmount(value: string, currencyCode: string): string {\n const amount = Number(value)\n if (Number.isNaN(amount)) return `${value} ${currencyCode}`\n try {\n return new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency: currencyCode,\n }).format(amount)\n } catch {\n return `${amount.toFixed(2)} ${currencyCode}`\n }\n}\n\nfunction formatTypeLabel(value: string): string {\n return value\n .split('_')\n .filter(Boolean)\n .map((part) => part[0]?.toUpperCase() + part.slice(1))\n .join(' ')\n}\n\nfunction formatLogDetailLabel(key: string): string {\n return key\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .split(' ')\n .filter(Boolean)\n .map((part) => part[0]?.toUpperCase() + part.slice(1))\n .join(' ')\n}\n\nfunction isPrimitiveLogValue(value: unknown): value is string | number | boolean | null {\n return value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'\n}\n\nfunction splitLogPayload(payload: Record<string, unknown> | null | undefined) {\n if (!payload) {\n return {\n inlineEntries: [] as Array<[string, string | number | boolean | null]>,\n nestedEntries: [] as Array<[string, unknown]>,\n }\n }\n\n const inlineEntries: Array<[string, string | number | boolean | null]> = []\n const nestedEntries: Array<[string, unknown]> = []\n Object.entries(payload).forEach(([key, value]) => {\n if (isPrimitiveLogValue(value)) {\n inlineEntries.push([key, value])\n return\n }\n nestedEntries.push([key, value])\n })\n return { inlineEntries, nestedEntries }\n}\n\nfunction DetailStat({ label, value }: { label: string; value: React.ReactNode }) {\n return (\n <div className=\"rounded-lg border bg-muted/30 px-4 py-3\">\n <div className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">{label}</div>\n <div className=\"mt-1 text-sm font-medium\">{value}</div>\n </div>\n )\n}\n\nexport default function PaymentTransactionsPage() {\n const t = useT()\n const searchParams = useSearchParams()\n const scopeVersion = useOrganizationScopeVersion()\n const [rows, setRows] = React.useState<TransactionRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [totalIsCapped, setTotalIsCapped] = React.useState(false)\n const [search, setSearch] = React.useState('')\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [isLoading, setIsLoading] = React.useState(true)\n const [selectedId, setSelectedId] = React.useState<string | null>(null)\n const [detail, setDetail] = React.useState<TransactionDetail | null>(null)\n const [isLoadingDetail, setIsLoadingDetail] = React.useState(false)\n const [detailError, setDetailError] = React.useState<string | null>(null)\n const [isRefreshingStatus, setIsRefreshingStatus] = React.useState(false)\n const [isCapturing, setIsCapturing] = React.useState(false)\n const { runMutation } = useGuardedMutation<{\n entityType: string\n entityId?: string\n }>({\n contextId: 'payment_gateways:transactions-detail',\n })\n const noneLabel = t('common.none', 'None')\n const requestedTransactionId = React.useMemo(() => {\n const raw = searchParams.get('transactionId')\n return raw && raw.trim().length > 0 ? raw.trim() : null\n }, [searchParams])\n\n const formatLogPrimitiveValue = React.useCallback((value: string | number | boolean | null): string => {\n if (value === null) return noneLabel\n if (typeof value === 'boolean') return value ? t('common.yes', 'Yes') : t('common.no', 'No')\n return String(value)\n }, [noneLabel, t])\n\n const loadRows = React.useCallback(async () => {\n setIsLoading(true)\n const params = new URLSearchParams({\n page: String(page),\n pageSize: '20',\n })\n if (search.trim()) params.set('search', search.trim())\n if (typeof filterValues.providerKey === 'string' && filterValues.providerKey) {\n params.set('providerKey', filterValues.providerKey)\n }\n if (typeof filterValues.status === 'string' && filterValues.status) {\n params.set('status', filterValues.status)\n }\n const fallback: TransactionsResponse = { items: [], total: 0, page, pageSize: 20, totalPages: 1 }\n const call = await apiCall<TransactionsResponse>(`/api/payment_gateways/transactions?${params.toString()}`, undefined, { fallback })\n if (call.ok && call.result) {\n setRows(Array.isArray(call.result.items) ? call.result.items : [])\n setTotal(call.result.total ?? 0)\n setTotalPages(call.result.totalPages ?? 1)\n setTotalIsCapped(call.result?.totalIsCapped === true)\n } else {\n flash(t('payment_gateways.transactions.error.load', 'Failed to load payment transactions'), 'error')\n setRows([])\n setTotal(0)\n setTotalPages(1)\n }\n setIsLoading(false)\n }, [filterValues.providerKey, filterValues.status, page, search, t])\n\n const loadDetail = React.useCallback(async (transactionId: string) => {\n setIsLoadingDetail(true)\n setDetailError(null)\n const call = await apiCall<TransactionDetail>(`/api/payment_gateways/transactions/${encodeURIComponent(transactionId)}`, undefined, { fallback: null })\n if (call.ok && call.result) {\n setDetail(call.result)\n } else {\n setDetail(null)\n setDetailError(t('payment_gateways.transactions.error.loadDetail', 'Failed to load transaction details'))\n }\n setIsLoadingDetail(false)\n }, [t])\n\n React.useEffect(() => {\n void loadRows()\n }, [loadRows, scopeVersion])\n\n React.useEffect(() => {\n if (!selectedId) {\n setDetail(null)\n setDetailError(null)\n return\n }\n void loadDetail(selectedId)\n }, [loadDetail, selectedId])\n\n React.useEffect(() => {\n setSelectedId((current) => (current && rows.some((row) => row.id === current) ? current : null))\n }, [rows])\n\n React.useEffect(() => {\n if (!requestedTransactionId) return\n if (!rows.some((row) => row.id === requestedTransactionId)) return\n setSelectedId(requestedTransactionId)\n }, [requestedTransactionId, rows])\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n const next: FilterValues = {}\n Object.entries(values).forEach(([key, value]) => {\n if (typeof value === 'string' && value.trim()) next[key] = value\n })\n setFilterValues(next)\n setPage(1)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n setPage(1)\n }, [])\n\n const handleRefreshStatus = React.useCallback(async () => {\n if (!selectedId) return\n setIsRefreshingStatus(true)\n try {\n await runMutation({\n operation: async () => {\n await apiCallOrThrow('/api/payment_gateways/status', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ transactionId: selectedId }),\n })\n },\n context: {\n entityType: 'payment_gateways:gateway_transaction',\n entityId: selectedId,\n },\n mutationPayload: { transactionId: selectedId },\n })\n await Promise.all([\n loadRows(),\n loadDetail(selectedId),\n ])\n flash(t('payment_gateways.transactions.success.refreshStatus', 'Transaction status refreshed'), 'success')\n } catch (error) {\n const message = error instanceof Error && error.message\n ? error.message\n : t('payment_gateways.transactions.error.refreshStatus', 'Failed to refresh transaction status')\n flash(message, 'error')\n } finally {\n setIsRefreshingStatus(false)\n }\n }, [loadDetail, loadRows, runMutation, selectedId, t])\n\n const handleCapturePayment = React.useCallback(async () => {\n if (!selectedId) return\n setIsCapturing(true)\n try {\n await runMutation({\n operation: async () => {\n await apiCallOrThrow('/api/payment_gateways/capture', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ transactionId: selectedId }),\n })\n },\n context: {\n entityType: 'payment_gateways:gateway_transaction',\n entityId: selectedId,\n },\n mutationPayload: { transactionId: selectedId },\n })\n await Promise.all([\n loadRows(),\n loadDetail(selectedId),\n ])\n flash(t('payment_gateways.transactions.success.capture', 'Payment captured'), 'success')\n } catch (error) {\n const message = error instanceof Error && error.message\n ? error.message\n : t('payment_gateways.transactions.error.capture', 'Failed to capture payment')\n flash(message, 'error')\n } finally {\n setIsCapturing(false)\n }\n }, [loadDetail, loadRows, runMutation, selectedId, t])\n\n const providerOptions = React.useMemo(() => {\n const values = Array.from(new Set(rows.map((row) => row.providerKey).filter(Boolean))).sort((a, b) => a.localeCompare(b))\n return values.map((value) => ({\n label: formatTypeLabel(value),\n value,\n }))\n }, [rows])\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'providerKey',\n type: 'select',\n label: t('payment_gateways.transactions.filters.provider', 'Provider'),\n options: [\n { label: t('payment_gateways.transactions.filters.allProviders', 'All providers'), value: '' },\n ...providerOptions,\n ],\n },\n {\n id: 'status',\n type: 'select',\n label: t('payment_gateways.transactions.filters.status', 'Status'),\n options: [\n { label: t('payment_gateways.transactions.filters.allStatuses', 'All statuses'), value: '' },\n { label: t('payment_gateways.status.pending', 'Pending'), value: 'pending' },\n { label: t('payment_gateways.status.authorized', 'Authorized'), value: 'authorized' },\n { label: t('payment_gateways.status.captured', 'Captured'), value: 'captured' },\n { label: t('payment_gateways.status.partially_captured', 'Partially Captured'), value: 'partially_captured' },\n { label: t('payment_gateways.status.refunded', 'Refunded'), value: 'refunded' },\n { label: t('payment_gateways.status.partially_refunded', 'Partially Refunded'), value: 'partially_refunded' },\n { label: t('payment_gateways.status.cancelled', 'Cancelled'), value: 'cancelled' },\n { label: t('payment_gateways.status.failed', 'Failed'), value: 'failed' },\n { label: t('payment_gateways.status.expired', 'Expired'), value: 'expired' },\n { label: t('payment_gateways.status.unknown', 'Unknown'), value: 'unknown' },\n ],\n },\n ], [providerOptions, t])\n\n const columns = React.useMemo<ColumnDef<TransactionRow>[]>(() => [\n {\n accessorKey: 'paymentId',\n header: t('payment_gateways.transactions.columns.paymentId', 'Payment'),\n cell: ({ row }) => (\n <div className=\"space-y-1\">\n <div className=\"font-medium\">{row.original.paymentId}</div>\n <div className=\"text-xs text-muted-foreground\">{row.original.id}</div>\n </div>\n ),\n meta: { maxWidth: '20rem' },\n },\n {\n accessorKey: 'providerKey',\n header: t('payment_gateways.transactions.columns.provider', 'Provider'),\n cell: ({ row }) => (\n <div className=\"flex items-center gap-2\">\n <CreditCard className=\"h-4 w-4 text-muted-foreground\" />\n <span>{formatTypeLabel(row.original.providerKey)}</span>\n </div>\n ),\n },\n {\n accessorKey: 'unifiedStatus',\n header: t('payment_gateways.transactions.columns.status', 'Status'),\n cell: ({ row }) => (\n <Badge variant=\"secondary\" className={STATUS_STYLES[row.original.unifiedStatus] ?? ''}>\n {t(`payment_gateways.status.${row.original.unifiedStatus}`, formatTypeLabel(row.original.unifiedStatus))}\n </Badge>\n ),\n },\n {\n accessorKey: 'amount',\n header: t('payment_gateways.transactions.columns.amount', 'Amount'),\n cell: ({ row }) => formatAmount(row.original.amount, row.original.currencyCode),\n },\n {\n accessorKey: 'providerSessionId',\n header: t('payment_gateways.transactions.columns.session', 'Session'),\n cell: ({ row }) => (\n <span className=\"font-mono text-xs text-muted-foreground\">\n {row.original.providerSessionId ?? '\u2014'}\n </span>\n ),\n meta: { maxWidth: '18rem', truncate: true },\n },\n {\n accessorKey: 'updatedAt',\n header: t('payment_gateways.transactions.columns.updatedAt', 'Updated'),\n cell: ({ row }) => formatDateTime(row.original.updatedAt),\n },\n ], [t])\n\n const selectedSummary = React.useMemo(\n () => rows.find((row) => row.id === selectedId) ?? null,\n [rows, selectedId],\n )\n const canCaptureSelected = React.useMemo(() => {\n const status = detail?.transaction.unifiedStatus ?? selectedSummary?.unifiedStatus ?? null\n return status === 'authorized'\n }, [detail?.transaction.unifiedStatus, selectedSummary?.unifiedStatus])\n\n return (\n <Page>\n <PageHeader\n title={t('payment_gateways.transactions.title', 'Payment Transactions')}\n description={t('payment_gateways.transactions.description', 'Track all payment-gateway transactions, inspect webhook activity, and review provider logs from one place.')}\n />\n <PageBody className=\"space-y-6\">\n <DataTable\n stickyActionsColumn\n title={t('payment_gateways.transactions.tableTitle', 'Transactions')}\n columns={columns}\n data={rows}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n searchValue={search}\n onSearchChange={(value) => { setSearch(value); setPage(1) }}\n searchPlaceholder={t('payment_gateways.transactions.searchPlaceholder', 'Search by payment, transaction, session, or gateway id')}\n perspective={{ tableId: extensionPoints.hosts.transactionsTable.tableId }}\n pagination={{ page, pageSize: 20, total, totalPages, totalIsCapped, onPageChange: setPage }}\n isLoading={isLoading}\n onRowClick={(row) => setSelectedId((current) => current === row.id ? null : row.id)}\n rowActions={(row) => (\n <RowActions items={[\n {\n id: 'details',\n label: selectedId === row.id\n ? t('payment_gateways.transactions.actions.hideDetails', 'Hide details')\n : t('payment_gateways.transactions.actions.showDetails', 'Show details'),\n onSelect: () => setSelectedId((current) => current === row.id ? null : row.id),\n },\n ]} />\n )}\n />\n\n {selectedId ? (\n <Card>\n <CardHeader className=\"gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-1\">\n <CardTitle>{t('payment_gateways.transactions.detail.title', 'Transaction details')}</CardTitle>\n {selectedSummary ? (\n <div className=\"flex flex-wrap items-center gap-2 text-sm text-muted-foreground\">\n <span>{selectedSummary.paymentId}</span>\n <span>\u2022</span>\n <span>{formatTypeLabel(selectedSummary.providerKey)}</span>\n <Badge variant=\"secondary\" className={STATUS_STYLES[selectedSummary.unifiedStatus] ?? ''}>\n {t(`payment_gateways.status.${selectedSummary.unifiedStatus}`, formatTypeLabel(selectedSummary.unifiedStatus))}\n </Badge>\n </div>\n ) : null}\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void handleRefreshStatus()}\n disabled={isRefreshingStatus || isLoadingDetail || isCapturing}\n >\n {isRefreshingStatus ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('payment_gateways.transactions.actions.refreshStatus', 'Refresh status')}\n </Button>\n {canCaptureSelected ? (\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void handleCapturePayment()}\n disabled={isRefreshingStatus || isLoadingDetail || isCapturing}\n >\n {isCapturing ? <Spinner className=\"mr-2 h-4 w-4\" /> : <HandCoins className=\"mr-2 h-4 w-4\" />}\n {t('payment_gateways.transactions.actions.capture', 'Capture payment')}\n </Button>\n ) : null}\n </CardHeader>\n <CardContent className=\"space-y-6\">\n {isLoadingDetail ? <LoadingMessage label={t('payment_gateways.transactions.detail.loading', 'Loading transaction details')} /> : null}\n {!isLoadingDetail && detailError ? <ErrorMessage label={detailError} /> : null}\n {!isLoadingDetail && !detailError && detail ? (\n <>\n <div className=\"grid gap-4 lg:grid-cols-4\">\n <DetailStat\n label={t('payment_gateways.transactions.detail.summary.status', 'Status')}\n value={(\n <Badge variant=\"secondary\" className={STATUS_STYLES[detail.transaction.unifiedStatus] ?? ''}>\n {t(`payment_gateways.status.${detail.transaction.unifiedStatus}`, formatTypeLabel(detail.transaction.unifiedStatus))}\n </Badge>\n )}\n />\n <DetailStat\n label={t('payment_gateways.transactions.detail.summary.gatewayStatus', 'Gateway status')}\n value={detail.transaction.gatewayStatus ?? noneLabel}\n />\n <DetailStat\n label={t('payment_gateways.transactions.detail.summary.amount', 'Amount')}\n value={formatAmount(detail.transaction.amount, detail.transaction.currencyCode)}\n />\n <DetailStat\n label={t('payment_gateways.transactions.detail.summary.provider', 'Provider')}\n value={formatTypeLabel(detail.transaction.providerKey)}\n />\n </div>\n\n <div className=\"grid gap-6 xl:grid-cols-[minmax(0,1.2fr)_minmax(0,0.8fr)]\">\n <div className=\"space-y-6\">\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">{t('payment_gateways.transactions.detail.identifiers', 'Identifiers')}</h3>\n <dl className=\"grid gap-3 md:grid-cols-2\">\n {[\n [t('payment_gateways.transactions.columns.transactionId', 'Transaction ID'), detail.transaction.id],\n [t('payment_gateways.transactions.columns.paymentId', 'Payment ID'), detail.transaction.paymentId],\n [t('payment_gateways.transactions.columns.session', 'Session ID'), detail.transaction.providerSessionId ?? '\u2014'],\n [t('payment_gateways.transactions.columns.gatewayPaymentId', 'Gateway payment ID'), detail.transaction.gatewayPaymentId ?? '\u2014'],\n [t('payment_gateways.transactions.columns.gatewayRefundId', 'Gateway refund ID'), detail.transaction.gatewayRefundId ?? '\u2014'],\n [t('payment_gateways.transactions.columns.redirectUrl', 'Redirect URL'), detail.transaction.redirectUrl ?? '\u2014'],\n [t('payment_gateways.transactions.columns.createdAt', 'Created at'), formatDateTime(detail.transaction.createdAt)],\n [t('payment_gateways.transactions.columns.updatedAt', 'Updated at'), formatDateTime(detail.transaction.updatedAt)],\n [t('payment_gateways.transactions.columns.lastWebhookAt', 'Last webhook'), formatDateTime(detail.transaction.lastWebhookAt)],\n [t('payment_gateways.transactions.columns.lastPolledAt', 'Last poll'), formatDateTime(detail.transaction.lastPolledAt)],\n ].map(([label, value]) => (\n <div key={label} className=\"rounded-lg border bg-muted/30 px-4 py-3\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">{label}</dt>\n <dd className=\"mt-1 break-all text-sm\">{value}</dd>\n </div>\n ))}\n </dl>\n </section>\n\n <section className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <Webhook className=\"h-4 w-4 text-muted-foreground\" />\n <h3 className=\"text-sm font-semibold\">{t('payment_gateways.transactions.detail.webhooks', 'Webhook activity')}</h3>\n </div>\n {detail.transaction.webhookLog && detail.transaction.webhookLog.length > 0 ? (\n <div className=\"overflow-hidden rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-2 text-left font-medium\">{t('payment_gateways.transactions.columns.eventType', 'Event')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('payment_gateways.transactions.columns.status', 'Status')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('payment_gateways.transactions.columns.processed', 'Processed')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('payment_gateways.transactions.columns.receivedAt', 'Received')}</th>\n </tr>\n </thead>\n <tbody>\n {detail.transaction.webhookLog.map((entry) => (\n <tr key={`${entry.idempotencyKey}:${entry.receivedAt}`} className=\"border-b last:border-0\">\n <td className=\"px-4 py-2 font-medium\">{entry.eventType}</td>\n <td className=\"px-4 py-2\">\n <Badge variant=\"secondary\" className={STATUS_STYLES[entry.unifiedStatus] ?? ''}>\n {t(`payment_gateways.status.${entry.unifiedStatus}`, formatTypeLabel(entry.unifiedStatus))}\n </Badge>\n </td>\n <td className=\"px-4 py-2\">{entry.processed ? t('common.yes', 'Yes') : t('common.no', 'No')}</td>\n <td className=\"px-4 py-2 text-muted-foreground\">{formatDateTime(entry.receivedAt)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('payment_gateways.transactions.detail.webhooksEmpty', 'No webhook events have been recorded for this transaction yet.')}</p>\n )}\n </section>\n\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">{t('payment_gateways.transactions.detail.logs', 'Gateway logs')}</h3>\n <LogList\n entries={detail.logs.map<LogListEntry>((log) => {\n const metadataEntries = [\n [t('payment_gateways.transactions.log.time', 'Time'), formatDateTime(log.createdAt)],\n [t('payment_gateways.transactions.log.level', 'Level'), t(`payment_gateways.transactions.level.${log.level}`, log.level)],\n [t('payment_gateways.transactions.log.code', 'Code'), log.code ?? null],\n [t('payment_gateways.transactions.log.runId', 'Run ID'), log.runId ?? null],\n [t('payment_gateways.transactions.log.entityType', 'Entity Type'), log.scopeEntityType ?? null],\n [t('payment_gateways.transactions.log.entityId', 'Entity ID'), log.scopeEntityId ?? null],\n ].filter((entry): entry is [string, string] => typeof entry[1] === 'string' && entry[1].trim().length > 0)\n const { inlineEntries, nestedEntries } = splitLogPayload(log.payload)\n\n return {\n id: log.id,\n time: formatDateTime(log.createdAt),\n level: log.level,\n levelLabel: t(`payment_gateways.transactions.level.${log.level}`, log.level),\n message: log.message,\n body: (\n <div className=\"space-y-4\">\n {metadataEntries.length > 0 ? (\n <dl className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n {metadataEntries.map(([label, value]) => (\n <div key={label} className=\"rounded-md border bg-muted/30 px-3 py-2\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">{label}</dt>\n <dd className=\"mt-1 break-all text-sm\">{value}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n {inlineEntries.length > 0 ? (\n <dl className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n {inlineEntries.map(([key, value]) => (\n <div key={key} className=\"rounded-md border bg-muted/30 px-3 py-2\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">{formatLogDetailLabel(key)}</dt>\n <dd className=\"mt-1 break-words text-sm\">{formatLogPrimitiveValue(value)}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n {nestedEntries.map(([key, value]) => (\n <JsonDisplay\n key={key}\n data={value}\n title={formatLogDetailLabel(key)}\n defaultExpanded\n maxInitialDepth={1}\n theme=\"dark\"\n maxHeight=\"16rem\"\n className=\"p-4\"\n />\n ))}\n </div>\n ),\n }\n })}\n emptyMessage={t('payment_gateways.transactions.detail.logsEmpty', 'No transaction-scoped logs are available yet.')}\n />\n </section>\n </div>\n\n <div className=\"space-y-4\">\n <JsonDisplay\n data={detail.transaction.gatewayMetadata ?? {}}\n title={t('payment_gateways.transactions.detail.gatewayMetadata', 'Gateway metadata')}\n defaultExpanded\n maxInitialDepth={1}\n theme=\"dark\"\n maxHeight=\"24rem\"\n className=\"p-4\"\n />\n <InjectionSpot\n spotId={extensionPoints.hosts.transactionsAfter.spotId}\n context={{ selectedPaymentId: detail.transaction.paymentId }}\n />\n </div>\n </div>\n </>\n ) : null}\n </CardContent>\n </Card>\n ) : null}\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|