@open-mercato/core 0.6.5-develop.4384.1.ce2ec6eaaa → 0.6.5-develop.4393.1.de282b5dfd
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +2 -2
- package/dist/generated/entities/channel_ingest_dead_letter/index.js +25 -0
- package/dist/generated/entities/channel_ingest_dead_letter/index.js.map +7 -0
- package/dist/generated/entities/channel_thread_mapping/index.js +25 -0
- package/dist/generated/entities/channel_thread_mapping/index.js.map +7 -0
- package/dist/generated/entities/channel_thread_token/index.js +17 -0
- package/dist/generated/entities/channel_thread_token/index.js.map +7 -0
- package/dist/generated/entities/communication_channel/index.js +43 -0
- package/dist/generated/entities/communication_channel/index.js.map +7 -0
- package/dist/generated/entities/customer_interaction/index.js +4 -0
- package/dist/generated/entities/customer_interaction/index.js.map +2 -2
- package/dist/generated/entities/external_conversation/index.js +25 -0
- package/dist/generated/entities/external_conversation/index.js.map +7 -0
- package/dist/generated/entities/external_message/index.js +25 -0
- package/dist/generated/entities/external_message/index.js.map +7 -0
- package/dist/generated/entities/integration_credentials/index.js +3 -1
- package/dist/generated/entities/integration_credentials/index.js.map +2 -2
- package/dist/generated/entities/message/index.js +2 -0
- package/dist/generated/entities/message/index.js.map +2 -2
- package/dist/generated/entities/message_channel_link/index.js +33 -0
- package/dist/generated/entities/message_channel_link/index.js.map +7 -0
- package/dist/generated/entities/message_reaction/index.js +25 -0
- package/dist/generated/entities/message_reaction/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +11 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +117 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/authFixtures.js +2 -1
- package/dist/helpers/integration/authFixtures.js.map +2 -2
- package/dist/helpers/integration/communicationChannelsFixtures.js +58 -0
- package/dist/helpers/integration/communicationChannelsFixtures.js.map +7 -0
- package/dist/modules/communication_channels/acl.js +47 -0
- package/dist/modules/communication_channels/acl.js.map +7 -0
- package/dist/modules/communication_channels/api/delete/channels/[id]/route.js +133 -0
- package/dist/modules/communication_channels/api/delete/channels/[id]/route.js.map +7 -0
- package/dist/modules/communication_channels/api/delete/messages/[messageId]/reactions/[reactionId]/route.js +113 -0
- package/dist/modules/communication_channels/api/delete/messages/[messageId]/reactions/[reactionId]/route.js.map +7 -0
- package/dist/modules/communication_channels/api/get/channels/[id]/health/route.js +138 -0
- package/dist/modules/communication_channels/api/get/channels/[id]/health/route.js.map +7 -0
- package/dist/modules/communication_channels/api/get/channels/[id]/route.js +93 -0
- package/dist/modules/communication_channels/api/get/channels/[id]/route.js.map +7 -0
- package/dist/modules/communication_channels/api/get/channels/route.js +96 -0
- package/dist/modules/communication_channels/api/get/channels/route.js.map +7 -0
- package/dist/modules/communication_channels/api/get/me/channels/route.js +82 -0
- package/dist/modules/communication_channels/api/get/me/channels/route.js.map +7 -0
- package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js +274 -0
- package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js +168 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/poll-now/route.js +143 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/poll-now/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js +127 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/set-primary/route.js +99 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/set-primary/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js +197 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js +124 -0
- package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/messages/[messageId]/reactions/route.js +120 -0
- package/dist/modules/communication_channels/api/post/messages/[messageId]/reactions/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js +157 -0
- package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/send-as-user/route.js +115 -0
- package/dist/modules/communication_channels/api/post/send-as-user/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/test-seed/route.js +217 -0
- package/dist/modules/communication_channels/api/post/test-seed/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +175 -0
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +123 -0
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +7 -0
- package/dist/modules/communication_channels/api/put/threads/[threadId]/assign/route.js +117 -0
- package/dist/modules/communication_channels/api/put/threads/[threadId]/assign/route.js.map +7 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.js +180 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.js.map +7 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.meta.js +36 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.meta.js.map +7 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +107 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +7 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.meta.js +38 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.meta.js.map +7 -0
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +727 -0
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +7 -0
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.meta.js +38 -0
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.meta.js.map +7 -0
- package/dist/modules/communication_channels/commands/connect-credential-channel.js +154 -0
- package/dist/modules/communication_channels/commands/connect-credential-channel.js.map +7 -0
- package/dist/modules/communication_channels/commands/delete-channel.js +137 -0
- package/dist/modules/communication_channels/commands/delete-channel.js.map +7 -0
- package/dist/modules/communication_channels/commands/deliver-outbound-message.js +400 -0
- package/dist/modules/communication_channels/commands/deliver-outbound-message.js.map +7 -0
- package/dist/modules/communication_channels/commands/disconnect-channel.js +163 -0
- package/dist/modules/communication_channels/commands/disconnect-channel.js.map +7 -0
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js +413 -0
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +7 -0
- package/dist/modules/communication_channels/commands/interceptors.js +68 -0
- package/dist/modules/communication_channels/commands/interceptors.js.map +7 -0
- package/dist/modules/communication_channels/commands/process-inbound-reaction.js +198 -0
- package/dist/modules/communication_channels/commands/process-inbound-reaction.js.map +7 -0
- package/dist/modules/communication_channels/commands/push-register.js +146 -0
- package/dist/modules/communication_channels/commands/push-register.js.map +7 -0
- package/dist/modules/communication_channels/commands/push-renew.js +23 -0
- package/dist/modules/communication_channels/commands/push-renew.js.map +7 -0
- package/dist/modules/communication_channels/commands/push-unregister.js +108 -0
- package/dist/modules/communication_channels/commands/push-unregister.js.map +7 -0
- package/dist/modules/communication_channels/commands/queue-import-history.js +113 -0
- package/dist/modules/communication_channels/commands/queue-import-history.js.map +7 -0
- package/dist/modules/communication_channels/commands/reassign-conversation.js +193 -0
- package/dist/modules/communication_channels/commands/reassign-conversation.js.map +7 -0
- package/dist/modules/communication_channels/commands/set-primary-channel.js +114 -0
- package/dist/modules/communication_channels/commands/set-primary-channel.js.map +7 -0
- package/dist/modules/communication_channels/commands/toggle-outbound-reaction.js +260 -0
- package/dist/modules/communication_channels/commands/toggle-outbound-reaction.js.map +7 -0
- package/dist/modules/communication_channels/data/enrichers.js +286 -0
- package/dist/modules/communication_channels/data/enrichers.js.map +7 -0
- package/dist/modules/communication_channels/data/entities.js +447 -0
- package/dist/modules/communication_channels/data/entities.js.map +7 -0
- package/dist/modules/communication_channels/data/extensions.js +67 -0
- package/dist/modules/communication_channels/data/extensions.js.map +7 -0
- package/dist/modules/communication_channels/data/validators.js +123 -0
- package/dist/modules/communication_channels/data/validators.js.map +7 -0
- package/dist/modules/communication_channels/di.js +35 -0
- package/dist/modules/communication_channels/di.js.map +7 -0
- package/dist/modules/communication_channels/encryption.js +12 -0
- package/dist/modules/communication_channels/encryption.js.map +7 -0
- package/dist/modules/communication_channels/events.js +124 -0
- package/dist/modules/communication_channels/events.js.map +7 -0
- package/dist/modules/communication_channels/index.js +20 -0
- package/dist/modules/communication_channels/index.js.map +7 -0
- package/dist/modules/communication_channels/lib/access-control.js +43 -0
- package/dist/modules/communication_channels/lib/access-control.js.map +7 -0
- package/dist/modules/communication_channels/lib/adapter-compat.js +36 -0
- package/dist/modules/communication_channels/lib/adapter-compat.js.map +7 -0
- package/dist/modules/communication_channels/lib/adapter-registry-singleton.js +22 -0
- package/dist/modules/communication_channels/lib/adapter-registry-singleton.js.map +7 -0
- package/dist/modules/communication_channels/lib/adapter.js +1 -0
- package/dist/modules/communication_channels/lib/adapter.js.map +7 -0
- package/dist/modules/communication_channels/lib/connect-channel.js +95 -0
- package/dist/modules/communication_channels/lib/connect-channel.js.map +7 -0
- package/dist/modules/communication_channels/lib/contact-resolver.js +79 -0
- package/dist/modules/communication_channels/lib/contact-resolver.js.map +7 -0
- package/dist/modules/communication_channels/lib/credential-refresh.js +97 -0
- package/dist/modules/communication_channels/lib/credential-refresh.js.map +7 -0
- package/dist/modules/communication_channels/lib/dead-letter.js +62 -0
- package/dist/modules/communication_channels/lib/dead-letter.js.map +7 -0
- package/dist/modules/communication_channels/lib/email-capabilities.js +47 -0
- package/dist/modules/communication_channels/lib/email-capabilities.js.map +7 -0
- package/dist/modules/communication_channels/lib/email-contact.js +14 -0
- package/dist/modules/communication_channels/lib/email-contact.js.map +7 -0
- package/dist/modules/communication_channels/lib/email-mime.js +259 -0
- package/dist/modules/communication_channels/lib/email-mime.js.map +7 -0
- package/dist/modules/communication_channels/lib/error-classification.js +101 -0
- package/dist/modules/communication_channels/lib/error-classification.js.map +7 -0
- package/dist/modules/communication_channels/lib/gmail-pubsub-jwt.js +185 -0
- package/dist/modules/communication_channels/lib/gmail-pubsub-jwt.js.map +7 -0
- package/dist/modules/communication_channels/lib/mutation-guards.js +114 -0
- package/dist/modules/communication_channels/lib/mutation-guards.js.map +7 -0
- package/dist/modules/communication_channels/lib/oauth-client-config.js +32 -0
- package/dist/modules/communication_channels/lib/oauth-client-config.js.map +7 -0
- package/dist/modules/communication_channels/lib/oauth-state.js +128 -0
- package/dist/modules/communication_channels/lib/oauth-state.js.map +7 -0
- package/dist/modules/communication_channels/lib/oauth-token.js +45 -0
- package/dist/modules/communication_channels/lib/oauth-token.js.map +7 -0
- package/dist/modules/communication_channels/lib/pg-errors.js +11 -0
- package/dist/modules/communication_channels/lib/pg-errors.js.map +7 -0
- package/dist/modules/communication_channels/lib/provider-health.js +24 -0
- package/dist/modules/communication_channels/lib/provider-health.js.map +7 -0
- package/dist/modules/communication_channels/lib/push-state.js +19 -0
- package/dist/modules/communication_channels/lib/push-state.js.map +7 -0
- package/dist/modules/communication_channels/lib/queue.js +54 -0
- package/dist/modules/communication_channels/lib/queue.js.map +7 -0
- package/dist/modules/communication_channels/lib/reaction-processor-types.js +5 -0
- package/dist/modules/communication_channels/lib/reaction-processor-types.js.map +7 -0
- package/dist/modules/communication_channels/lib/reaction-semantics.js +11 -0
- package/dist/modules/communication_channels/lib/reaction-semantics.js.map +7 -0
- package/dist/modules/communication_channels/lib/registry.js +67 -0
- package/dist/modules/communication_channels/lib/registry.js.map +7 -0
- package/dist/modules/communication_channels/lib/route-mutation-guard.js +43 -0
- package/dist/modules/communication_channels/lib/route-mutation-guard.js.map +7 -0
- package/dist/modules/communication_channels/lib/sanitize-channel-html.js +96 -0
- package/dist/modules/communication_channels/lib/sanitize-channel-html.js.map +7 -0
- package/dist/modules/communication_channels/lib/send-as-user.js +194 -0
- package/dist/modules/communication_channels/lib/send-as-user.js.map +7 -0
- package/dist/modules/communication_channels/lib/system-user.js +22 -0
- package/dist/modules/communication_channels/lib/system-user.js.map +7 -0
- package/dist/modules/communication_channels/lib/test-seed.js +68 -0
- package/dist/modules/communication_channels/lib/test-seed.js.map +7 -0
- package/dist/modules/communication_channels/lib/thread-matcher.js +263 -0
- package/dist/modules/communication_channels/lib/thread-matcher.js.map +7 -0
- package/dist/modules/communication_channels/lib/thread-token.js +219 -0
- package/dist/modules/communication_channels/lib/thread-token.js.map +7 -0
- package/dist/modules/communication_channels/lib/use-connect-channel.js +61 -0
- package/dist/modules/communication_channels/lib/use-connect-channel.js.map +7 -0
- package/dist/modules/communication_channels/migrations/Migration20260526134719_communication_channels.js +50 -0
- package/dist/modules/communication_channels/migrations/Migration20260526134719_communication_channels.js.map +7 -0
- package/dist/modules/communication_channels/migrations/Migration20260527195446_communication_channels.js +19 -0
- package/dist/modules/communication_channels/migrations/Migration20260527195446_communication_channels.js.map +7 -0
- package/dist/modules/communication_channels/migrations/Migration20260529231848_communication_channels.js +13 -0
- package/dist/modules/communication_channels/migrations/Migration20260529231848_communication_channels.js.map +7 -0
- package/dist/modules/communication_channels/migrations/Migration20260531120000_communication_channels.js +17 -0
- package/dist/modules/communication_channels/migrations/Migration20260531120000_communication_channels.js.map +7 -0
- package/dist/modules/communication_channels/notifications.client.js +51 -0
- package/dist/modules/communication_channels/notifications.client.js.map +7 -0
- package/dist/modules/communication_channels/notifications.handlers.js +53 -0
- package/dist/modules/communication_channels/notifications.handlers.js.map +7 -0
- package/dist/modules/communication_channels/notifications.js +56 -0
- package/dist/modules/communication_channels/notifications.js.map +7 -0
- package/dist/modules/communication_channels/setup.js +105 -0
- package/dist/modules/communication_channels/setup.js.map +7 -0
- package/dist/modules/communication_channels/subscribers/channel-requires-reauth-notification.js +71 -0
- package/dist/modules/communication_channels/subscribers/channel-requires-reauth-notification.js.map +7 -0
- package/dist/modules/communication_channels/subscribers/outbound-bridge.js +103 -0
- package/dist/modules/communication_channels/subscribers/outbound-bridge.js.map +7 -0
- package/dist/modules/communication_channels/subscribers/user-deleted-cascade.js +51 -0
- package/dist/modules/communication_channels/subscribers/user-deleted-cascade.js.map +7 -0
- package/dist/modules/communication_channels/widgets/components.js +7 -0
- package/dist/modules/communication_channels/widgets/components.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.client.js +18 -0
- package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.client.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.js +30 -0
- package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.client.js +185 -0
- package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.client.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.js +17 -0
- package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.js +44 -0
- package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.js +17 -0
- package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/profile-channels-menu/widget.js +23 -0
- package/dist/modules/communication_channels/widgets/injection/profile-channels-menu/widget.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.client.js +141 -0
- package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.client.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.js +17 -0
- package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection-table.js +38 -0
- package/dist/modules/communication_channels/widgets/injection-table.js.map +7 -0
- package/dist/modules/communication_channels/widgets/notifications/ChannelRequiresReauthRenderer.js +25 -0
- package/dist/modules/communication_channels/widgets/notifications/ChannelRequiresReauthRenderer.js.map +7 -0
- package/dist/modules/communication_channels/widgets/notifications/MessageReceivedRenderer.js +19 -0
- package/dist/modules/communication_channels/widgets/notifications/MessageReceivedRenderer.js.map +7 -0
- package/dist/modules/communication_channels/widgets/notifications/index.js +7 -0
- package/dist/modules/communication_channels/widgets/notifications/index.js.map +7 -0
- package/dist/modules/communication_channels/workers/channel-import-history.js +185 -0
- package/dist/modules/communication_channels/workers/channel-import-history.js.map +7 -0
- package/dist/modules/communication_channels/workers/gmail-history-sync.js +154 -0
- package/dist/modules/communication_channels/workers/gmail-history-sync.js.map +7 -0
- package/dist/modules/communication_channels/workers/gmail-renew-watch.js +95 -0
- package/dist/modules/communication_channels/workers/gmail-renew-watch.js.map +7 -0
- package/dist/modules/communication_channels/workers/inbound-processor.js +56 -0
- package/dist/modules/communication_channels/workers/inbound-processor.js.map +7 -0
- package/dist/modules/communication_channels/workers/outbound-delivery.js +85 -0
- package/dist/modules/communication_channels/workers/outbound-delivery.js.map +7 -0
- package/dist/modules/communication_channels/workers/poll-channel.js +240 -0
- package/dist/modules/communication_channels/workers/poll-channel.js.map +7 -0
- package/dist/modules/communication_channels/workers/poll-tick.js +132 -0
- package/dist/modules/communication_channels/workers/poll-tick.js.map +7 -0
- package/dist/modules/communication_channels/workers/reaction-processor.js +192 -0
- package/dist/modules/communication_channels/workers/reaction-processor.js.map +7 -0
- package/dist/modules/customers/acl.js +18 -0
- package/dist/modules/customers/acl.js.map +2 -2
- package/dist/modules/customers/api/activities/route.js +9 -0
- package/dist/modules/customers/api/activities/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/route.js +18 -7
- package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/[id]/visibility/route.js +151 -0
- package/dist/modules/customers/api/interactions/[id]/visibility/route.js.map +7 -0
- package/dist/modules/customers/api/interactions/counts/route.js +6 -0
- package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/route.js +26 -7
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/email-threads/route.js +82 -0
- package/dist/modules/customers/api/people/[id]/email-threads/route.js.map +7 -0
- package/dist/modules/customers/api/people/[id]/emails/route.js +157 -0
- package/dist/modules/customers/api/people/[id]/emails/route.js.map +7 -0
- package/dist/modules/customers/api/people/[id]/route.js +12 -4
- package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +10 -0
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +46 -5
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js +16 -0
- package/dist/modules/customers/commands/interactions.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityCard.js +32 -0
- package/dist/modules/customers/components/detail/ActivityCard.js.map +2 -2
- package/dist/modules/customers/components/detail/ComposeEmailDialog.js +242 -0
- package/dist/modules/customers/components/detail/ComposeEmailDialog.js.map +7 -0
- package/dist/modules/customers/components/detail/DealForm.js +2 -1
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/detail/DealsSection.js +10 -0
- package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
- package/dist/modules/customers/components/detail/EmailCardActions.js +179 -0
- package/dist/modules/customers/components/detail/EmailCardActions.js.map +7 -0
- package/dist/modules/customers/components/detail/EmailReplyForwardActions.js +52 -0
- package/dist/modules/customers/components/detail/EmailReplyForwardActions.js.map +7 -0
- package/dist/modules/customers/components/detail/PersonDetailTabs.js +7 -1
- package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonEmailThreadsTab.js +366 -0
- package/dist/modules/customers/components/detail/PersonEmailThreadsTab.js.map +7 -0
- package/dist/modules/customers/data/enrichers.js +133 -2
- package/dist/modules/customers/data/enrichers.js.map +2 -2
- package/dist/modules/customers/data/entities.js +18 -0
- package/dist/modules/customers/data/entities.js.map +2 -2
- package/dist/modules/customers/data/extensions.js +16 -0
- package/dist/modules/customers/data/extensions.js.map +7 -0
- package/dist/modules/customers/encryption.js +11 -0
- package/dist/modules/customers/encryption.js.map +2 -2
- package/dist/modules/customers/events.js +4 -1
- package/dist/modules/customers/events.js.map +2 -2
- package/dist/modules/customers/lib/findPeopleByAddresses.js +64 -0
- package/dist/modules/customers/lib/findPeopleByAddresses.js.map +7 -0
- package/dist/modules/customers/lib/kysely.js.map +2 -2
- package/dist/modules/customers/lib/link-channel-message-handler.js +303 -0
- package/dist/modules/customers/lib/link-channel-message-handler.js.map +7 -0
- package/dist/modules/customers/lib/personEmailThreads.js +205 -0
- package/dist/modules/customers/lib/personEmailThreads.js.map +7 -0
- package/dist/modules/customers/lib/visibilityFilter.js +51 -0
- package/dist/modules/customers/lib/visibilityFilter.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260527012240_customers.js +20 -0
- package/dist/modules/customers/migrations/Migration20260527012240_customers.js.map +7 -0
- package/dist/modules/customers/setup.js +2 -1
- package/dist/modules/customers/setup.js.map +2 -2
- package/dist/modules/customers/subscribers/link-channel-message-received.js +12 -0
- package/dist/modules/customers/subscribers/link-channel-message-received.js.map +7 -0
- package/dist/modules/customers/subscribers/link-channel-message-sent.js +12 -0
- package/dist/modules/customers/subscribers/link-channel-message-sent.js.map +7 -0
- package/dist/modules/integrations/data/entities.js +8 -1
- package/dist/modules/integrations/data/entities.js.map +2 -2
- package/dist/modules/integrations/lib/credentials-service.js +29 -14
- package/dist/modules/integrations/lib/credentials-service.js.map +2 -2
- package/dist/modules/integrations/migrations/Migration20260526154136_integrations.js +15 -0
- package/dist/modules/integrations/migrations/Migration20260526154136_integrations.js.map +7 -0
- package/dist/modules/messages/commands/messages.js +70 -8
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/messages/components/ComposeMessagePageClient.js +24 -13
- package/dist/modules/messages/components/ComposeMessagePageClient.js.map +2 -2
- package/dist/modules/messages/components/MessageDetailPageClient.js +39 -2
- package/dist/modules/messages/components/MessageDetailPageClient.js.map +2 -2
- package/dist/modules/messages/components/MessagesInboxPageClient.js +1 -0
- package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
- package/dist/modules/messages/data/entities.js +8 -1
- package/dist/modules/messages/data/entities.js.map +2 -2
- package/dist/modules/messages/migrations/Migration20260531130000.js +15 -0
- package/dist/modules/messages/migrations/Migration20260531130000.js.map +7 -0
- package/dist/modules/messages/widgets/injection-table.js +7 -0
- package/dist/modules/messages/widgets/injection-table.js.map +7 -0
- package/generated/entities/channel_ingest_dead_letter/index.ts +11 -0
- package/generated/entities/channel_thread_mapping/index.ts +11 -0
- package/generated/entities/channel_thread_token/index.ts +7 -0
- package/generated/entities/communication_channel/index.ts +20 -0
- package/generated/entities/customer_interaction/index.ts +2 -0
- package/generated/entities/external_conversation/index.ts +11 -0
- package/generated/entities/external_message/index.ts +11 -0
- package/generated/entities/integration_credentials/index.ts +1 -0
- package/generated/entities/message/index.ts +1 -0
- package/generated/entities/message_channel_link/index.ts +15 -0
- package/generated/entities/message_reaction/index.ts +11 -0
- package/generated/entities.ids.generated.ts +11 -0
- package/generated/entity-fields-registry.ts +117 -0
- package/package.json +9 -7
- package/src/helpers/integration/authFixtures.ts +4 -1
- package/src/helpers/integration/communicationChannelsFixtures.ts +124 -0
- package/src/modules/communication_channels/acl.ts +43 -0
- package/src/modules/communication_channels/api/delete/channels/[id]/route.ts +163 -0
- package/src/modules/communication_channels/api/delete/messages/[messageId]/reactions/[reactionId]/route.ts +143 -0
- package/src/modules/communication_channels/api/get/channels/[id]/health/route.ts +173 -0
- package/src/modules/communication_channels/api/get/channels/[id]/route.ts +111 -0
- package/src/modules/communication_channels/api/get/channels/route.ts +109 -0
- package/src/modules/communication_channels/api/get/me/channels/route.ts +100 -0
- package/src/modules/communication_channels/api/get/oauth/[provider]/callback/route.ts +355 -0
- package/src/modules/communication_channels/api/post/channels/[id]/import-history/route.ts +206 -0
- package/src/modules/communication_channels/api/post/channels/[id]/poll-now/route.ts +174 -0
- package/src/modules/communication_channels/api/post/channels/[id]/push/register/route.ts +158 -0
- package/src/modules/communication_channels/api/post/channels/[id]/set-primary/route.ts +114 -0
- package/src/modules/communication_channels/api/post/channels/[id]/test-send/route.ts +241 -0
- package/src/modules/communication_channels/api/post/channels/connect/credentials/route.ts +134 -0
- package/src/modules/communication_channels/api/post/messages/[messageId]/reactions/route.ts +143 -0
- package/src/modules/communication_channels/api/post/oauth/[provider]/initiate/route.ts +192 -0
- package/src/modules/communication_channels/api/post/send-as-user/route.ts +125 -0
- package/src/modules/communication_channels/api/post/test-seed/route.ts +267 -0
- package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +227 -0
- package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +161 -0
- package/src/modules/communication_channels/api/put/threads/[threadId]/assign/route.ts +132 -0
- package/src/modules/communication_channels/backend/communication_channels/channels/[id]/page.meta.ts +34 -0
- package/src/modules/communication_channels/backend/communication_channels/channels/[id]/page.tsx +250 -0
- package/src/modules/communication_channels/backend/communication_channels/channels/page.meta.ts +36 -0
- package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +137 -0
- package/src/modules/communication_channels/backend/profile/communication-channels/page.meta.ts +36 -0
- package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +907 -0
- package/src/modules/communication_channels/commands/connect-credential-channel.ts +243 -0
- package/src/modules/communication_channels/commands/delete-channel.ts +193 -0
- package/src/modules/communication_channels/commands/deliver-outbound-message.ts +579 -0
- package/src/modules/communication_channels/commands/disconnect-channel.ts +241 -0
- package/src/modules/communication_channels/commands/ingest-inbound-message.ts +602 -0
- package/src/modules/communication_channels/commands/interceptors.ts +104 -0
- package/src/modules/communication_channels/commands/process-inbound-reaction.ts +265 -0
- package/src/modules/communication_channels/commands/push-register.ts +203 -0
- package/src/modules/communication_channels/commands/push-renew.ts +49 -0
- package/src/modules/communication_channels/commands/push-unregister.ts +168 -0
- package/src/modules/communication_channels/commands/queue-import-history.ts +180 -0
- package/src/modules/communication_channels/commands/reassign-conversation.ts +273 -0
- package/src/modules/communication_channels/commands/set-primary-channel.ts +154 -0
- package/src/modules/communication_channels/commands/toggle-outbound-reaction.ts +347 -0
- package/src/modules/communication_channels/data/enrichers.ts +413 -0
- package/src/modules/communication_channels/data/entities.ts +546 -0
- package/src/modules/communication_channels/data/extensions.ts +76 -0
- package/src/modules/communication_channels/data/validators.ts +138 -0
- package/src/modules/communication_channels/di.ts +40 -0
- package/src/modules/communication_channels/encryption.ts +44 -0
- package/src/modules/communication_channels/events.ts +122 -0
- package/src/modules/communication_channels/i18n/de.json +138 -0
- package/src/modules/communication_channels/i18n/en.json +138 -0
- package/src/modules/communication_channels/i18n/es.json +138 -0
- package/src/modules/communication_channels/i18n/pl.json +138 -0
- package/src/modules/communication_channels/index.ts +19 -0
- package/src/modules/communication_channels/lib/access-control.ts +110 -0
- package/src/modules/communication_channels/lib/adapter-compat.ts +57 -0
- package/src/modules/communication_channels/lib/adapter-registry-singleton.ts +35 -0
- package/src/modules/communication_channels/lib/adapter.ts +605 -0
- package/src/modules/communication_channels/lib/connect-channel.ts +163 -0
- package/src/modules/communication_channels/lib/contact-resolver.ts +162 -0
- package/src/modules/communication_channels/lib/credential-refresh.ts +197 -0
- package/src/modules/communication_channels/lib/dead-letter.ts +87 -0
- package/src/modules/communication_channels/lib/email-capabilities.ts +60 -0
- package/src/modules/communication_channels/lib/email-contact.ts +17 -0
- package/src/modules/communication_channels/lib/email-mime.ts +425 -0
- package/src/modules/communication_channels/lib/error-classification.ts +144 -0
- package/src/modules/communication_channels/lib/gmail-pubsub-jwt.ts +278 -0
- package/src/modules/communication_channels/lib/mutation-guards.ts +215 -0
- package/src/modules/communication_channels/lib/oauth-client-config.ts +79 -0
- package/src/modules/communication_channels/lib/oauth-state.ts +228 -0
- package/src/modules/communication_channels/lib/oauth-token.ts +81 -0
- package/src/modules/communication_channels/lib/pg-errors.ts +12 -0
- package/src/modules/communication_channels/lib/provider-health.ts +47 -0
- package/src/modules/communication_channels/lib/push-state.ts +38 -0
- package/src/modules/communication_channels/lib/queue.ts +66 -0
- package/src/modules/communication_channels/lib/reaction-processor-types.ts +51 -0
- package/src/modules/communication_channels/lib/reaction-semantics.ts +48 -0
- package/src/modules/communication_channels/lib/registry.ts +99 -0
- package/src/modules/communication_channels/lib/route-mutation-guard.ts +68 -0
- package/src/modules/communication_channels/lib/sanitize-channel-html.ts +129 -0
- package/src/modules/communication_channels/lib/send-as-user.ts +284 -0
- package/src/modules/communication_channels/lib/system-user.ts +74 -0
- package/src/modules/communication_channels/lib/test-seed.ts +140 -0
- package/src/modules/communication_channels/lib/thread-matcher.ts +430 -0
- package/src/modules/communication_channels/lib/thread-token.ts +355 -0
- package/src/modules/communication_channels/lib/use-connect-channel.ts +73 -0
- package/src/modules/communication_channels/migrations/.snapshot-open-mercato.json +2142 -0
- package/src/modules/communication_channels/migrations/Migration20260526134719_communication_channels.ts +55 -0
- package/src/modules/communication_channels/migrations/Migration20260527195446_communication_channels.ts +20 -0
- package/src/modules/communication_channels/migrations/Migration20260529231848_communication_channels.ts +13 -0
- package/src/modules/communication_channels/migrations/Migration20260531120000_communication_channels.ts +24 -0
- package/src/modules/communication_channels/notifications.client.ts +50 -0
- package/src/modules/communication_channels/notifications.handlers.ts +86 -0
- package/src/modules/communication_channels/notifications.ts +52 -0
- package/src/modules/communication_channels/setup.ts +158 -0
- package/src/modules/communication_channels/subscribers/channel-requires-reauth-notification.ts +118 -0
- package/src/modules/communication_channels/subscribers/outbound-bridge.ts +175 -0
- package/src/modules/communication_channels/subscribers/user-deleted-cascade.ts +100 -0
- package/src/modules/communication_channels/widgets/components.ts +36 -0
- package/src/modules/communication_channels/widgets/injection/channel-badge/widget.client.tsx +38 -0
- package/src/modules/communication_channels/widgets/injection/channel-badge/widget.ts +51 -0
- package/src/modules/communication_channels/widgets/injection/channel-info-panel/widget.client.tsx +278 -0
- package/src/modules/communication_channels/widgets/injection/channel-info-panel/widget.ts +24 -0
- package/src/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.tsx +63 -0
- package/src/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.ts +29 -0
- package/src/modules/communication_channels/widgets/injection/profile-channels-menu/widget.ts +34 -0
- package/src/modules/communication_channels/widgets/injection/reaction-bar/widget.client.tsx +177 -0
- package/src/modules/communication_channels/widgets/injection/reaction-bar/widget.ts +26 -0
- package/src/modules/communication_channels/widgets/injection-table.ts +47 -0
- package/src/modules/communication_channels/widgets/notifications/ChannelRequiresReauthRenderer.tsx +48 -0
- package/src/modules/communication_channels/widgets/notifications/MessageReceivedRenderer.tsx +45 -0
- package/src/modules/communication_channels/widgets/notifications/index.ts +2 -0
- package/src/modules/communication_channels/workers/channel-import-history.ts +252 -0
- package/src/modules/communication_channels/workers/gmail-history-sync.ts +223 -0
- package/src/modules/communication_channels/workers/gmail-renew-watch.ts +141 -0
- package/src/modules/communication_channels/workers/inbound-processor.ts +114 -0
- package/src/modules/communication_channels/workers/outbound-delivery.ts +155 -0
- package/src/modules/communication_channels/workers/poll-channel.ts +391 -0
- package/src/modules/communication_channels/workers/poll-tick.ts +210 -0
- package/src/modules/communication_channels/workers/reaction-processor.ts +264 -0
- package/src/modules/customers/acl.ts +18 -0
- package/src/modules/customers/api/activities/route.ts +13 -0
- package/src/modules/customers/api/companies/[id]/route.ts +21 -1
- package/src/modules/customers/api/interactions/[id]/visibility/route.ts +179 -0
- package/src/modules/customers/api/interactions/counts/route.ts +10 -0
- package/src/modules/customers/api/interactions/route.ts +51 -5
- package/src/modules/customers/api/people/[id]/email-threads/route.ts +92 -0
- package/src/modules/customers/api/people/[id]/emails/route.ts +184 -0
- package/src/modules/customers/api/people/[id]/route.ts +17 -2
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +11 -1
- package/src/modules/customers/commands/deals.ts +65 -6
- package/src/modules/customers/commands/interactions.ts +30 -0
- package/src/modules/customers/components/detail/ActivityCard.tsx +48 -0
- package/src/modules/customers/components/detail/ComposeEmailDialog.tsx +329 -0
- package/src/modules/customers/components/detail/DealForm.tsx +2 -1
- package/src/modules/customers/components/detail/DealsSection.tsx +26 -0
- package/src/modules/customers/components/detail/EmailCardActions.tsx +258 -0
- package/src/modules/customers/components/detail/EmailReplyForwardActions.tsx +53 -0
- package/src/modules/customers/components/detail/PersonDetailTabs.tsx +8 -1
- package/src/modules/customers/components/detail/PersonEmailThreadsTab.tsx +448 -0
- package/src/modules/customers/data/enrichers.ts +252 -1
- package/src/modules/customers/data/entities.ts +46 -1
- package/src/modules/customers/data/extensions.ts +26 -0
- package/src/modules/customers/encryption.ts +11 -0
- package/src/modules/customers/events.ts +4 -0
- package/src/modules/customers/i18n/de.json +41 -0
- package/src/modules/customers/i18n/en.json +41 -0
- package/src/modules/customers/i18n/es.json +41 -0
- package/src/modules/customers/i18n/pl.json +41 -0
- package/src/modules/customers/lib/findPeopleByAddresses.ts +107 -0
- package/src/modules/customers/lib/kysely.ts +16 -0
- package/src/modules/customers/lib/link-channel-message-handler.ts +571 -0
- package/src/modules/customers/lib/personEmailThreads.ts +325 -0
- package/src/modules/customers/lib/visibilityFilter.ts +152 -0
- package/src/modules/customers/migrations/.snapshot-open-mercato.json +61 -0
- package/src/modules/customers/migrations/Migration20260527012240_customers.ts +23 -0
- package/src/modules/customers/setup.ts +1 -0
- package/src/modules/customers/subscribers/link-channel-message-received.ts +21 -0
- package/src/modules/customers/subscribers/link-channel-message-sent.ts +21 -0
- package/src/modules/integrations/AGENTS.md +9 -0
- package/src/modules/integrations/data/entities.ts +21 -1
- package/src/modules/integrations/lib/credentials-service.ts +49 -13
- package/src/modules/integrations/migrations/.snapshot-open-mercato.json +26 -1
- package/src/modules/integrations/migrations/Migration20260526154136_integrations.ts +15 -0
- package/src/modules/messages/commands/messages.ts +101 -8
- package/src/modules/messages/components/ComposeMessagePageClient.tsx +17 -0
- package/src/modules/messages/components/MessageDetailPageClient.tsx +43 -0
- package/src/modules/messages/components/MessagesInboxPageClient.tsx +4 -0
- package/src/modules/messages/data/entities.ts +11 -0
- package/src/modules/messages/migrations/.snapshot-open-mercato.json +18 -0
- package/src/modules/messages/migrations/Migration20260531130000.ts +15 -0
- package/src/modules/messages/widgets/injection-table.ts +29 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/customers/api/companies/%5Bid%5D/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerEntity,\n CustomerCompanyProfile,\n CustomerAddress,\n CustomerComment,\n CustomerActivity,\n CustomerTagAssignment,\n CustomerTag,\n CustomerLabelAssignment,\n CustomerLabel,\n CustomerDealCompanyLink,\n CustomerDeal,\n CustomerTodoLink,\n CustomerPersonCompanyLink,\n CustomerPersonProfile,\n CustomerInteraction,\n} from '../../../data/entities'\nimport { User } from '@open-mercato/core/modules/auth/data/entities'\nimport { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n resolveCompanyCustomFieldRouting,\n mergeCompanyCustomFieldValues,\n} from '../../../lib/customFieldRouting'\nimport {\n CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE,\n EXAMPLE_TODO_SOURCE,\n CUSTOMER_INTERACTION_TODO_ADAPTER_SOURCE,\n mapInteractionRecordToActivitySummary,\n mapInteractionRecordToTodoSummary,\n} from '../../../lib/interactionCompatibility'\nimport { resolveCustomerInteractionFeatureFlags } from '../../../lib/interactionFeatureFlags'\nimport { hydrateCanonicalInteractions } from '../../../lib/interactionReadModel'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport type { EntityId } from '@open-mercato/shared/modules/entities'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { parseBooleanFromUnknown } from '@open-mercato/shared/lib/boolean'\nimport {\n filterActivePersonCompanyLinks,\n withActiveCustomerPersonCompanyLinkFilter,\n} from '../../../lib/personCompanyLinkTable'\nimport { normalizeCustomerDetailCustomFields } from '../../detailCustomFields'\nimport { isOrganizationReadAccessAllowed } from '@open-mercato/core/modules/directory/utils/organizationScopeGuard'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['customers.companies.view'] },\n}\n\nconst paramsSchema = z.object({\n id: z.string().uuid(),\n})\n\nfunction parseIncludeParams(request: Request): Set<string> {\n const url = new URL(request.url)\n const raw = url.searchParams.getAll('include')\n const tokens = new Set<string>()\n raw.forEach((entry) => {\n if (!entry) return\n entry\n .split(',')\n .map((part) => part.trim().toLowerCase())\n .filter((part) => part.length > 0)\n .forEach((part) => tokens.add(part))\n })\n return tokens\n}\n\nfunction forbidden(message: string) {\n return NextResponse.json({ error: message }, { status: 403 })\n}\n\nfunction notFound(message: string) {\n return NextResponse.json({ error: message }, { status: 404 })\n}\n\nfunction serializeTags(assignments: CustomerTagAssignment[]): Array<{ id: string; label: string; color: string | null }> {\n return assignments\n .map((assignment) => {\n const tag = assignment.tag as CustomerTag | string | null\n if (!tag || typeof tag === 'string') return null\n return {\n id: tag.id,\n label: tag.label,\n color: tag.color ?? null,\n }\n })\n .filter((tag): tag is { id: string; label: string; color: string | null } => tag !== null)\n}\n\ntype TodoDetail = {\n title: string | null\n isDone: boolean | null\n priority: number | null\n severity: string | null\n description: string | null\n dueAt: string | null\n organizationId: string | null\n customValues: Record<string, unknown> | null\n}\n\nfunction extractTodoTitle(record: Record<string, unknown>): string | null {\n const candidates = ['title', 'subject', 'name', 'summary', 'text', 'description']\n for (const key of candidates) {\n const value = record[key]\n if (typeof value === 'string' && value.trim().length > 0) {\n return value.trim()\n }\n }\n return null\n}\n\nfunction parseNumber(value: unknown): number | null {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return null\n const parsed = Number(trimmed)\n if (!Number.isNaN(parsed)) return parsed\n }\n return null\n}\n\nfunction parseDateValue(value: unknown): string | null {\n if (value instanceof Date) {\n const ts = value.getTime()\n return Number.isNaN(ts) ? null : value.toISOString()\n }\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return null\n const candidate = new Date(trimmed)\n if (!Number.isNaN(candidate.getTime())) return candidate.toISOString()\n }\n return null\n}\n\nfunction readCustomField(record: Record<string, unknown>, key: string): unknown {\n const custom = record.custom ?? record.customFields ?? record.cf\n if (custom && typeof custom === 'object') {\n const bucket = custom as Record<string, unknown>\n if (key in bucket) return bucket[key]\n }\n return undefined\n}\n\ntype CompanyDetailKpiSummary = {\n activeDealsCount: number\n activeDealsValue: number | null\n dealCurrency: string | null\n activityCount: number\n activityTrend: { value: number; direction: 'up' | 'down' | 'unchanged' } | null\n ltvValue: number | null\n completedDealsCount: number\n clientTenureYears: number | null\n}\n\nfunction parseDealAmount(value: string | number | null | undefined): number | null {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed.length) return null\n const parsed = Number(trimmed)\n return Number.isNaN(parsed) ? null : parsed\n }\n return null\n}\n\nfunction computeActivityTrend(\n timestamps: string[],\n): { value: number; direction: 'up' | 'down' | 'unchanged' } | null {\n if (!timestamps.length) return null\n const now = Date.now()\n const weekMs = 7 * 86_400_000\n let thisWeek = 0\n let lastWeek = 0\n timestamps.forEach((value) => {\n const time = new Date(value).getTime()\n if (Number.isNaN(time)) return\n const diff = now - time\n if (diff < 0 || diff >= weekMs * 2) return\n if (diff < weekMs) {\n thisWeek += 1\n return\n }\n lastWeek += 1\n })\n if (lastWeek === 0 && thisWeek === 0) return null\n if (lastWeek === 0) return { value: 100, direction: 'up' }\n const pct = ((thisWeek - lastWeek) / lastWeek) * 100\n if (Math.abs(pct) < 0.5) return { value: 0, direction: 'unchanged' }\n return { value: Math.round(Math.abs(pct) * 100) / 100, direction: pct > 0 ? 'up' : 'down' }\n}\n\nasync function resolveTodoDetails(\n queryEngine: QueryEngine,\n links: CustomerTodoLink[],\n tenantId: string | null,\n organizationIds: Array<string | null>,\n): Promise<Map<string, TodoDetail>> {\n const details = new Map<string, TodoDetail>()\n if (!links.length || !tenantId) return details\n\n const scopedOrgIds = organizationIds\n .filter((value): value is string => typeof value === 'string' && value.trim().length > 0)\n\n const idsBySource = new Map<string, Set<string>>()\n for (const link of links) {\n const source = typeof link.todoSource === 'string' && link.todoSource.trim().length > 0 ? link.todoSource : EXAMPLE_TODO_SOURCE\n const id = typeof link.todoId === 'string' && link.todoId.trim().length > 0 ? link.todoId : String(link.todoId ?? '')\n if (!id) continue\n if (!idsBySource.has(source)) idsBySource.set(source, new Set<string>())\n idsBySource.get(source)!.add(id)\n }\n\n for (const [source, idSet] of idsBySource.entries()) {\n const ids = Array.from(idSet)\n if (!ids.length) continue\n try {\n const result = await queryEngine.query<Record<string, unknown>>(source as EntityId, {\n tenantId,\n organizationIds: scopedOrgIds.length > 0 ? scopedOrgIds : undefined,\n filters: { id: { $in: ids } },\n includeCustomFields: ['priority', 'due_at', 'severity', 'description'],\n page: { page: 1, pageSize: Math.max(ids.length, 1) },\n })\n for (const item of result.items ?? []) {\n if (!item || typeof item !== 'object') continue\n const record = item as Record<string, unknown>\n const rawId = typeof record.id === 'string' && record.id.trim().length > 0 ? record.id : String(record.id ?? '')\n if (!rawId) continue\n const title = extractTodoTitle(record)\n const isDone = (() => {\n const direct = parseBooleanFromUnknown(record.is_done)\n if (direct !== null) return direct\n const custom = parseBooleanFromUnknown(readCustomField(record, 'is_done'))\n if (custom !== null) return custom\n const generic = parseBooleanFromUnknown(record.isDone)\n if (generic !== null) return generic\n return parseBooleanFromUnknown(readCustomField(record, 'isDone'))\n })()\n const priority = (() => {\n const candidates = [\n record['cf:priority'],\n record['cf_priority'],\n record.priority,\n readCustomField(record, 'priority'),\n ]\n for (const candidate of candidates) {\n const parsed = parseNumber(candidate)\n if (parsed !== null) return parsed\n }\n return null\n })()\n const severity = (() => {\n const candidates = [\n record['cf:severity'],\n record['cf_severity'],\n record.severity,\n readCustomField(record, 'severity'),\n ]\n for (const candidate of candidates) {\n if (typeof candidate === 'string' && candidate.trim().length > 0) {\n return candidate.trim()\n }\n }\n return null\n })()\n const dueAt = (() => {\n const candidates = [\n record['cf:due_at'],\n record['cf_due_at'],\n record.due_at,\n readCustomField(record, 'due_at'),\n record.dueAt,\n readCustomField(record, 'dueAt'),\n ]\n for (const candidate of candidates) {\n const parsed = parseDateValue(candidate)\n if (parsed) return parsed\n }\n return null\n })()\n const organizationId = (() => {\n const candidates = [\n record.organization_id,\n record['cf:organization_id'],\n record['cf_organization_id'],\n record.organizationId,\n readCustomField(record, 'organization_id'),\n readCustomField(record, 'organizationId'),\n ]\n for (const candidate of candidates) {\n if (typeof candidate === 'string' && candidate.trim().length > 0) {\n return candidate.trim()\n }\n }\n return null\n })()\n const descriptionValue = (() => {\n const direct = typeof record.description === 'string' ? record.description : null\n if (direct) return direct\n const customDescription = readCustomField(record, 'description')\n if (typeof customDescription === 'string' && customDescription.trim().length > 0) {\n return customDescription.trim()\n }\n return null\n })()\n\n const customValues: Record<string, unknown> = {}\n const assignCustomValue = (key: string, value: unknown) => {\n const trimmedKey = key.trim()\n if (!trimmedKey.length) return\n customValues[trimmedKey] = value === undefined ? null : value\n }\n for (const [rawKey, rawValue] of Object.entries(record)) {\n if (rawKey.startsWith('cf:')) {\n assignCustomValue(rawKey.slice(3), rawValue)\n } else if (rawKey.startsWith('cf_')) {\n assignCustomValue(rawKey.slice(3), rawValue)\n }\n }\n const nestedCustom = record.custom ?? record.customFields ?? record.cf\n if (nestedCustom && typeof nestedCustom === 'object') {\n for (const [nestedKey, nestedValue] of Object.entries(nestedCustom as Record<string, unknown>)) {\n assignCustomValue(nestedKey, nestedValue)\n }\n }\n\n details.set(`${source}:${rawId}`, {\n title,\n isDone,\n priority,\n severity,\n description: descriptionValue,\n dueAt,\n organizationId,\n customValues: Object.keys(customValues).length ? customValues : null,\n })\n }\n } catch (err) {\n console.warn(`customers.companies.detail: failed to resolve todos for source ${source}`, err)\n }\n }\n\n return details\n}\n\nexport async function GET(_req: Request, ctx: { params?: { id?: string } }) {\n const auth = await getAuthFromRequest(_req)\n if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n const parse = paramsSchema.safeParse({ id: ctx.params?.id })\n if (!parse.success) return NextResponse.json({ error: 'Invalid company id' }, { status: 400 })\n\n const includeTokens = parseIncludeParams(_req)\n const includeActivities = includeTokens.has('activities')\n const includeAddresses = includeTokens.has('addresses')\n const includeComments = includeTokens.has('comments') || includeTokens.has('notes')\n const includeDeals = includeTokens.has('deals')\n const includeInteractions = includeTokens.has('interactions')\n const includeTodos = includeTokens.has('todos') || includeTokens.has('tasks')\n const includePeople = includeTokens.has('people')\n const plannedPreviewLimit = 5\n\n const container = await createRequestContainer()\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: _req })\n const em = (container.resolve('em') as EntityManager)\n const interactionFlags = await resolveCustomerInteractionFeatureFlags(container, scope?.tenantId ?? auth.tenantId)\n const interactionMode = interactionFlags.unified ? 'canonical' : 'legacy'\n\n const company = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: parse.data.id, kind: 'company', deletedAt: null },\n { populate: ['companyProfile'] },\n {\n tenantId: auth.tenantId ?? null,\n organizationId: scope?.selectedId ?? auth.orgId ?? null,\n },\n )\n if (!company) return notFound('Company not found')\n\n if (auth.tenantId && company.tenantId !== auth.tenantId) return notFound('Company not found')\n if (!isOrganizationReadAccessAllowed({ scope, auth, organizationId: company.organizationId })) {\n return forbidden('Access denied')\n }\n\n const companyScope = {\n tenantId: company.tenantId ?? auth.tenantId ?? null,\n organizationId: company.organizationId ?? scope?.selectedId ?? auth.orgId ?? null,\n }\n\n const profile = company.companyProfile\n ? await findOneWithDecryption(\n em,\n CustomerCompanyProfile,\n {\n id: company.companyProfile.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n {},\n companyScope,\n )\n : await findOneWithDecryption(\n em,\n CustomerCompanyProfile,\n {\n entity: company,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n {},\n companyScope,\n )\n\n const addresses = includeAddresses\n ? await findWithDecryption(\n em,\n CustomerAddress,\n {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n { orderBy: { isPrimary: 'desc', createdAt: 'desc' } },\n companyScope,\n )\n : []\n const tagAssignments = await findWithDecryption(\n em,\n CustomerTagAssignment,\n {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n { populate: ['tag'] },\n companyScope,\n )\n const labelAssignments = await findWithDecryption(\n em,\n CustomerLabelAssignment,\n {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n { populate: ['label'] },\n companyScope,\n )\n\n const comments = includeComments\n ? await findWithDecryption(\n em,\n CustomerComment,\n {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n { orderBy: { createdAt: 'desc' }, limit: 50 },\n companyScope,\n )\n : []\n const shouldLoadCanonicalInteractions = includeInteractions || includeActivities || includeTodos\n const canonicalInteractionRows = shouldLoadCanonicalInteractions\n ? await findWithDecryption(\n em,\n CustomerInteraction,\n interactionFlags.unified\n ? {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n deletedAt: null,\n }\n : {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n { orderBy: { scheduledAt: 'asc', createdAt: 'desc' }, limit: 100 },\n companyScope,\n )\n : []\n const canonicalActiveInteractions = canonicalInteractionRows.filter((interaction) => !interaction.deletedAt)\n const canonicalInteractions = shouldLoadCanonicalInteractions\n ? await hydrateCanonicalInteractions({\n em,\n container,\n auth,\n selectedOrganizationId: scope?.selectedId ?? auth.orgId ?? null,\n interactions: canonicalActiveInteractions,\n enrich: includeInteractions,\n })\n : []\n\n const plannedPreviewRows =\n canonicalActiveInteractions.length > 0\n ? canonicalActiveInteractions\n .filter((interaction) => interaction.status === 'planned' && interaction.interactionType !== 'task')\n .sort((left, right) => {\n const leftTime = new Date(left.scheduledAt ?? left.createdAt).getTime()\n const rightTime = new Date(right.scheduledAt ?? right.createdAt).getTime()\n if (leftTime === rightTime) return left.id.localeCompare(right.id)\n return leftTime - rightTime\n })\n .slice(0, plannedPreviewLimit)\n : await findWithDecryption(\n em,\n CustomerInteraction,\n {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n deletedAt: null,\n status: 'planned',\n interactionType: { $ne: 'task' },\n },\n { orderBy: { scheduledAt: 'ASC', createdAt: 'ASC' }, limit: plannedPreviewLimit },\n companyScope,\n )\n const plannedActivitiesPreview = plannedPreviewRows.length\n ? await hydrateCanonicalInteractions({\n em,\n container,\n auth,\n selectedOrganizationId: scope?.selectedId ?? auth.orgId ?? null,\n interactions: plannedPreviewRows,\n enrich: true,\n })\n : []\n\n const activities = includeActivities && !interactionFlags.unified\n ? await findWithDecryption(\n em,\n CustomerActivity,\n {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n { orderBy: { occurredAt: 'desc', createdAt: 'desc' }, limit: 50 },\n companyScope,\n )\n : []\n const todoLinks = includeTodos && !interactionFlags.unified\n ? await findWithDecryption(\n em,\n CustomerTodoLink,\n {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n { orderBy: { createdAt: 'desc' }, limit: 50 },\n companyScope,\n )\n : []\n\n let todoDetails = new Map<string, TodoDetail>()\n if (includeTodos && !interactionFlags.unified && todoLinks.length) {\n const queryEngine = (container.resolve('queryEngine') as QueryEngine)\n try {\n todoDetails = await resolveTodoDetails(\n queryEngine,\n todoLinks,\n company.tenantId ?? auth.tenantId ?? null,\n [company.organizationId ?? null, ...(scope?.filterIds ?? [])],\n )\n } catch (err) {\n console.warn('customers.companies.detail: failed to enrich todo links', err)\n }\n }\n\n const canonicalActivityBridgeIds = new Set(\n canonicalInteractionRows\n .filter((interaction) => interaction.source === CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE)\n .map((interaction) => interaction.id),\n )\n const canonicalTodoBridgeIds = new Set(\n canonicalInteractionRows\n .filter((interaction) => interaction.source === CUSTOMER_INTERACTION_TODO_ADAPTER_SOURCE)\n .map((interaction) => interaction.id),\n )\n\n const canonicalActivityItems = canonicalInteractions\n .filter((interaction) => interaction.interactionType !== 'task')\n .map((interaction) => mapInteractionRecordToActivitySummary(interaction))\n const canonicalTodoItems = canonicalInteractions\n .filter((interaction) => interaction.interactionType === 'task')\n .map((interaction) => mapInteractionRecordToTodoSummary(interaction))\n\n const authorIds = new Set<string>()\n if (includeActivities) {\n for (const activity of activities) {\n if (activity.authorUserId) authorIds.add(activity.authorUserId)\n }\n }\n if (includeComments) {\n for (const comment of comments) {\n if (comment.authorUserId) authorIds.add(comment.authorUserId)\n }\n }\n const viewerUserId = auth.isApiKey ? null : auth.sub ?? null\n if (viewerUserId) authorIds.add(viewerUserId)\n\n let userMap = new Map<string, { name: string | null; email: string | null }>()\n if (authorIds.size) {\n const authorIdList = Array.from(authorIds)\n const users = await findWithDecryption(\n em,\n User,\n {\n id: { $in: authorIdList },\n tenantId: company.tenantId,\n },\n {},\n companyScope,\n )\n userMap = new Map(\n users.map((user) => [\n user.id,\n {\n name: user.name ?? null,\n email: user.email ?? null,\n },\n ])\n )\n }\n\n let deals: CustomerDeal[] = []\n if (includeDeals) {\n const dealLinks = await findWithDecryption(\n em,\n CustomerDealCompanyLink,\n {\n company: company.id,\n },\n { populate: ['deal'] },\n companyScope,\n )\n deals = dealLinks\n .map((link) => (link.deal as CustomerDeal | string | null) ?? null)\n .filter(\n (deal): deal is CustomerDeal =>\n !!deal &&\n typeof deal !== 'string' &&\n deal.tenantId === company.tenantId &&\n deal.organizationId === company.organizationId,\n )\n }\n\n const dealLinksForMetrics = includeDeals\n ? deals\n : (\n await findWithDecryption(\n em,\n CustomerDealCompanyLink,\n {\n company: company.id,\n },\n { populate: ['deal'] },\n companyScope,\n )\n )\n .map((link) => (link.deal as CustomerDeal | string | null) ?? null)\n .filter(\n (deal): deal is CustomerDeal =>\n !!deal &&\n typeof deal !== 'string' &&\n deal.tenantId === company.tenantId &&\n deal.organizationId === company.organizationId,\n )\n\n let relatedPeople: Array<{\n entity: CustomerEntity\n profile: CustomerPersonProfile | null\n linkedAt: string | null\n }> = []\n if (includePeople) {\n const peopleDecryptionScope = {\n tenantId: company.tenantId ?? auth.tenantId ?? null,\n organizationId: company.organizationId ?? scope?.selectedId ?? auth.orgId ?? null,\n }\n const relatedPeopleById = new Map<\n string,\n { entity: CustomerEntity; profile: CustomerPersonProfile | null; linkedAt: string | null }\n >()\n const companyLinkWhere = await withActiveCustomerPersonCompanyLinkFilter(\n em,\n {\n company: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n },\n 'customers.companies.GET',\n )\n const companyLinks = filterActivePersonCompanyLinks(\n await findWithDecryption(\n em,\n CustomerPersonCompanyLink,\n companyLinkWhere,\n {\n populate: ['person', 'person.personProfile'],\n orderBy: { isPrimary: 'desc', createdAt: 'asc' },\n },\n peopleDecryptionScope,\n ),\n )\n companyLinks.forEach((link) => {\n const entity = typeof link.person === 'string' ? null : link.person\n if (!entity || entity.kind !== 'person' || entity.deletedAt) return\n const personProfile =\n entity.personProfile && typeof entity.personProfile !== 'string'\n ? entity.personProfile\n : null\n relatedPeopleById.set(entity.id, {\n entity,\n profile: personProfile,\n linkedAt: link.createdAt instanceof Date ? link.createdAt.toISOString() : null,\n })\n })\n\n const profiles = await findWithDecryption(\n em,\n CustomerPersonProfile,\n {\n company: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n entity: { deletedAt: null },\n },\n { populate: ['entity'] },\n peopleDecryptionScope,\n )\n profiles.forEach((entry) => {\n const entity = entry.entity as CustomerEntity | null\n if (!entity || entity.kind !== 'person' || entity.deletedAt) return\n if (!relatedPeopleById.has(entity.id)) {\n relatedPeopleById.set(entity.id, {\n entity,\n profile: entry ?? null,\n linkedAt: entry.createdAt instanceof Date ? entry.createdAt.toISOString() : null,\n })\n }\n })\n relatedPeople = Array.from(relatedPeopleById.values())\n }\n\n const entityCustomFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.customers.customer_entity,\n recordIds: [company.id],\n tenantIdByRecord: { [company.id]: company.tenantId ?? null },\n organizationIdByRecord: { [company.id]: company.organizationId ?? null },\n tenantFallbacks: [\n company.tenantId ?? auth.tenantId ?? null,\n ].filter((v): v is string => !!v),\n })\n let profileCustomFieldValues: Record<string, Record<string, unknown>> = {}\n const profileId = profile?.id ?? null\n if (profileId) {\n profileCustomFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.customers.customer_company_profile,\n recordIds: [profileId],\n tenantIdByRecord: { [profileId]: profile?.tenantId ?? null },\n organizationIdByRecord: { [profileId]: profile?.organizationId ?? null },\n tenantFallbacks: [\n profile?.tenantId ?? company.tenantId ?? auth.tenantId ?? null,\n ].filter((v): v is string => !!v),\n })\n }\n\n const routing = await resolveCompanyCustomFieldRouting(em, company.tenantId ?? null, company.organizationId ?? null)\n const customFields = normalizeCustomerDetailCustomFields(\n mergeCompanyCustomFieldValues(\n routing,\n entityCustomFieldValues?.[company.id] ?? {},\n profileId ? profileCustomFieldValues?.[profileId] ?? {} : {},\n ),\n )\n\n const activityCount = await em.count(CustomerInteraction, {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n deletedAt: null,\n interactionType: { $ne: 'task' },\n })\n const interactionCount = await em.count(CustomerInteraction, {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n deletedAt: null,\n })\n const todoCount = interactionFlags.unified\n ? await em.count(CustomerInteraction, {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n deletedAt: null,\n interactionType: 'task',\n })\n : await em.count(CustomerTodoLink, {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n })\n const commentsCount = includeComments\n ? comments.length\n : await em.count(CustomerComment, {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n })\n const addressesCount = includeAddresses\n ? addresses.length\n : await em.count(CustomerAddress, {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n })\n const peopleCount = includePeople\n ? relatedPeople.length\n : filterActivePersonCompanyLinks(\n await findWithDecryption(\n em,\n CustomerPersonCompanyLink,\n await withActiveCustomerPersonCompanyLinkFilter(\n em,\n {\n company: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n },\n 'customers.companies.GET',\n ),\n {},\n { tenantId: company.tenantId, organizationId: company.organizationId },\n ),\n ).length\n const kpiInteractionRows = canonicalActiveInteractions.length\n ? canonicalActiveInteractions\n : await findWithDecryption(\n em,\n CustomerInteraction,\n {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n deletedAt: null,\n },\n {\n fields: ['id', 'occurredAt', 'scheduledAt', 'createdAt'],\n orderBy: { createdAt: 'DESC' },\n },\n { tenantId: company.tenantId, organizationId: company.organizationId },\n )\n const activityTrend = computeActivityTrend(\n kpiInteractionRows\n .map((interaction) => interaction.occurredAt ?? interaction.scheduledAt ?? interaction.createdAt)\n .map((value) => (value instanceof Date ? value.toISOString() : typeof value === 'string' ? value : ''))\n .filter((value) => value.length > 0),\n )\n const activeDeals = dealLinksForMetrics.filter(\n (deal) => deal.status !== 'won' && deal.status !== 'lost' && deal.status !== 'closed',\n )\n const wonDeals = dealLinksForMetrics.filter((deal) => deal.status === 'won')\n const activeDealsValue = activeDeals.reduce((sum, deal) => sum + (parseDealAmount(deal.valueAmount) ?? 0), 0)\n const ltvValue = wonDeals.length\n ? wonDeals.reduce((sum, deal) => sum + (parseDealAmount(deal.valueAmount) ?? 0), 0)\n : null\n const earliestInteractionTime = kpiInteractionRows.reduce<number | null>((earliest, interaction) => {\n const candidate = interaction.occurredAt ?? interaction.scheduledAt ?? interaction.createdAt\n const time = candidate instanceof Date ? candidate.getTime() : new Date(candidate).getTime()\n if (Number.isNaN(time)) return earliest\n if (earliest === null) return time\n return Math.min(earliest, time)\n }, null)\n const companyKpis: CompanyDetailKpiSummary = {\n activeDealsCount: activeDeals.length,\n activeDealsValue: activeDeals.length ? activeDealsValue : null,\n dealCurrency:\n activeDeals[0]?.valueCurrency ??\n dealLinksForMetrics[0]?.valueCurrency ??\n null,\n activityCount,\n activityTrend,\n ltvValue,\n completedDealsCount: wonDeals.length,\n clientTenureYears:\n earliestInteractionTime === null\n ? null\n : Math.floor((Date.now() - earliestInteractionTime) / (365.25 * 86_400_000)),\n }\n const counts = {\n tags: tagAssignments.length + labelAssignments.length,\n comments: commentsCount,\n activities: activityCount,\n interactions: interactionCount,\n todos: todoCount,\n deals: includeDeals ? deals.length : dealLinksForMetrics.length,\n people: peopleCount,\n addresses: addressesCount,\n }\n\n return NextResponse.json({\n interactionMode,\n company: {\n id: company.id,\n displayName: company.displayName,\n description: company.description,\n ownerUserId: company.ownerUserId,\n primaryEmail: company.primaryEmail,\n primaryPhone: company.primaryPhone,\n status: company.status,\n lifecycleStage: company.lifecycleStage,\n source: company.source,\n nextInteractionAt: company.nextInteractionAt ? company.nextInteractionAt.toISOString() : null,\n nextInteractionName: company.nextInteractionName,\n nextInteractionRefId: company.nextInteractionRefId,\n nextInteractionIcon: company.nextInteractionIcon,\n nextInteractionColor: company.nextInteractionColor,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n isActive: company.isActive,\n temperature: company.temperature ?? null,\n renewalQuarter: company.renewalQuarter ?? null,\n createdAt: company.createdAt.toISOString(),\n updatedAt: company.updatedAt.toISOString(),\n },\n profile: profile\n ? {\n id: profile.id,\n legalName: profile.legalName,\n brandName: profile.brandName,\n domain: profile.domain,\n websiteUrl: profile.websiteUrl,\n industry: profile.industry,\n sizeBucket: profile.sizeBucket,\n annualRevenue: profile.annualRevenue,\n }\n : null,\n customFields,\n tags: [\n ...serializeTags(tagAssignments),\n ...labelAssignments\n .map((assignment) => {\n const label = assignment.label as CustomerLabel | string | null\n if (!label || typeof label === 'string') return null\n return { id: label.id, label: label.label, color: null }\n })\n .filter((tag): tag is { id: string; label: string; color: null } => tag !== null),\n ],\n addresses: includeAddresses\n ? addresses.map((address) => ({\n id: address.id,\n name: address.name,\n purpose: address.purpose,\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2,\n buildingNumber: address.buildingNumber,\n flatNumber: address.flatNumber,\n city: address.city,\n region: address.region,\n postalCode: address.postalCode,\n country: address.country,\n latitude: address.latitude,\n longitude: address.longitude,\n isPrimary: address.isPrimary,\n createdAt: address.createdAt.toISOString(),\n }))\n : [],\n comments: includeComments\n ? comments.map((comment) => {\n const authorInfo = comment.authorUserId ? userMap.get(comment.authorUserId) : null\n return {\n id: comment.id,\n body: comment.body,\n authorUserId: comment.authorUserId,\n authorName: comment.authorUserId ? authorInfo?.name ?? null : null,\n authorEmail: comment.authorUserId ? authorInfo?.email ?? null : null,\n dealId: comment.deal ? (typeof comment.deal === 'string' ? comment.deal : comment.deal.id) : null,\n createdAt: comment.createdAt.toISOString(),\n appearanceIcon: comment.appearanceIcon ?? null,\n appearanceColor: comment.appearanceColor ?? null,\n }\n })\n : [],\n activities: includeActivities\n ? (\n interactionFlags.unified\n ? canonicalActivityItems\n : [\n ...activities\n .filter((activity) => !canonicalActivityBridgeIds.has(activity.id))\n .map((activity) => ({\n id: activity.id,\n activityType: activity.activityType,\n subject: activity.subject,\n body: activity.body,\n occurredAt: activity.occurredAt ? activity.occurredAt.toISOString() : null,\n dealId: activity.deal ? (typeof activity.deal === 'string' ? activity.deal : activity.deal.id) : null,\n authorUserId: activity.authorUserId,\n authorName: activity.authorUserId ? userMap.get(activity.authorUserId)?.name ?? null : null,\n authorEmail: activity.authorUserId ? userMap.get(activity.authorUserId)?.email ?? null : null,\n createdAt: activity.createdAt.toISOString(),\n appearanceIcon: activity.appearanceIcon ?? null,\n appearanceColor: activity.appearanceColor ?? null,\n })),\n ...canonicalActivityItems.filter(\n (activity) =>\n canonicalInteractions.some(\n (interaction) =>\n interaction.id === activity.id &&\n interaction.source === CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE,\n ),\n ),\n ].sort((left, right) => {\n const leftTime = new Date(left.occurredAt ?? left.createdAt).getTime()\n const rightTime = new Date(right.occurredAt ?? right.createdAt).getTime()\n if (leftTime === rightTime) return right.id.localeCompare(left.id)\n return rightTime - leftTime\n }).slice(0, 50)\n )\n : [],\n interactions: includeInteractions\n ? canonicalInteractions\n : [],\n deals: includeDeals\n ? deals.map((deal) => ({\n id: deal.id,\n title: deal.title,\n status: deal.status,\n pipelineStage: deal.pipelineStage,\n pipelineId: deal.pipelineId ?? null,\n pipelineStageId: deal.pipelineStageId ?? null,\n valueAmount: deal.valueAmount,\n valueCurrency: deal.valueCurrency,\n probability: deal.probability,\n expectedCloseAt: deal.expectedCloseAt ? deal.expectedCloseAt.toISOString() : null,\n ownerUserId: deal.ownerUserId,\n source: deal.source,\n createdAt: deal.createdAt.toISOString(),\n updatedAt: deal.updatedAt.toISOString(),\n }))\n : [],\n todos: includeTodos\n ? (\n interactionFlags.unified\n ? canonicalTodoItems\n : [\n ...todoLinks\n .filter((link) => !canonicalTodoBridgeIds.has(link.todoId))\n .map((link) => {\n const source = typeof link.todoSource === 'string' && link.todoSource.trim().length > 0 ? link.todoSource : EXAMPLE_TODO_SOURCE\n const key = `${source}:${link.todoId}`\n const detail = todoDetails.get(key)\n return {\n id: link.id,\n todoId: link.todoId,\n todoSource: source,\n createdAt: link.createdAt.toISOString(),\n createdByUserId: link.createdByUserId,\n title: detail?.title ?? null,\n isDone: detail?.isDone ?? null,\n priority: detail?.priority ?? null,\n severity: detail?.severity ?? null,\n description: detail?.description ?? null,\n dueAt: detail?.dueAt ?? null,\n todoOrganizationId: detail?.organizationId ?? null,\n customValues: detail?.customValues ?? null,\n }\n }),\n ...canonicalTodoItems.filter(\n (todo) =>\n canonicalInteractions.some(\n (interaction) =>\n interaction.id === todo.todoId &&\n interaction.source === CUSTOMER_INTERACTION_TODO_ADAPTER_SOURCE,\n ),\n ),\n ].sort((left, right) => {\n const leftTime = new Date(left.createdAt).getTime()\n const rightTime = new Date(right.createdAt).getTime()\n if (leftTime === rightTime) return right.id.localeCompare(left.id)\n return rightTime - leftTime\n }).slice(0, 50)\n )\n : [],\n people: includePeople\n ? relatedPeople.map(({ entity, profile: personProfile, linkedAt }) => ({\n id: entity.id,\n displayName: entity.displayName,\n primaryEmail: entity.primaryEmail ?? null,\n primaryPhone: entity.primaryPhone ?? null,\n status: entity.status ?? null,\n lifecycleStage: entity.lifecycleStage ?? null,\n jobTitle: personProfile?.jobTitle ?? null,\n department: personProfile?.department ?? null,\n createdAt: entity.createdAt.toISOString(),\n organizationId: entity.organizationId,\n source: entity.source ?? null,\n temperature: entity.temperature ?? null,\n linkedAt,\n }))\n : [],\n plannedActivitiesPreview,\n counts,\n kpis: companyKpis,\n viewer: {\n userId: viewerUserId,\n name: viewerUserId ? userMap.get(viewerUserId)?.name ?? null : null,\n email: viewerUserId ? userMap.get(viewerUserId)?.email ?? auth.email ?? null : auth.email ?? null,\n },\n })\n}\n\nconst companyDetailQuerySchema = z.object({\n include: z\n .string()\n .optional()\n .describe('Comma-separated list of relations to include (addresses, comments, activities, interactions, deals, todos, people).'),\n}).passthrough()\n\nconst companyDetailResponseSchema = z.object({\n interactionMode: z.enum(['canonical', 'legacy']),\n company: z.object({\n id: z.string().uuid(),\n displayName: z.string().nullable().optional(),\n description: z.string().nullable().optional(),\n ownerUserId: z.string().uuid().nullable().optional(),\n primaryEmail: z.string().nullable().optional(),\n primaryPhone: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n lifecycleStage: z.string().nullable().optional(),\n source: z.string().nullable().optional(),\n nextInteractionAt: z.string().nullable().optional(),\n nextInteractionName: z.string().nullable().optional(),\n nextInteractionRefId: z.string().nullable().optional(),\n nextInteractionIcon: z.string().nullable().optional(),\n nextInteractionColor: z.string().nullable().optional(),\n organizationId: z.string().uuid().nullable().optional(),\n tenantId: z.string().uuid().nullable().optional(),\n isActive: z.boolean().optional(),\n temperature: z.string().nullable().optional(),\n renewalQuarter: z.string().nullable().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n }),\n profile: z\n .object({\n id: z.string().uuid(),\n legalName: z.string().nullable().optional(),\n brandName: z.string().nullable().optional(),\n domain: z.string().nullable().optional(),\n websiteUrl: z.string().nullable().optional(),\n industry: z.string().nullable().optional(),\n sizeBucket: z.string().nullable().optional(),\n annualRevenue: z.number().nullable().optional(),\n })\n .nullable(),\n customFields: z.record(z.string(), z.unknown()),\n tags: z.array(\n z.object({\n id: z.string().uuid(),\n label: z.string(),\n color: z.string().nullable().optional(),\n }),\n ),\n addresses: z.array(\n z.object({\n id: z.string().uuid(),\n name: z.string().nullable().optional(),\n purpose: z.string().nullable().optional(),\n addressLine1: z.string().nullable().optional(),\n addressLine2: z.string().nullable().optional(),\n buildingNumber: z.string().nullable().optional(),\n flatNumber: z.string().nullable().optional(),\n city: z.string().nullable().optional(),\n region: z.string().nullable().optional(),\n postalCode: z.string().nullable().optional(),\n country: z.string().nullable().optional(),\n latitude: z.number().nullable().optional(),\n longitude: z.number().nullable().optional(),\n isPrimary: z.boolean().nullable().optional(),\n createdAt: z.string(),\n }),\n ),\n comments: z.array(\n z.object({\n id: z.string().uuid(),\n body: z.string().nullable().optional(),\n authorUserId: z.string().uuid().nullable().optional(),\n authorName: z.string().nullable().optional(),\n authorEmail: z.string().nullable().optional(),\n dealId: z.string().uuid().nullable().optional(),\n createdAt: z.string(),\n appearanceIcon: z.string().nullable().optional(),\n appearanceColor: z.string().nullable().optional(),\n }),\n ),\n activities: z.array(\n z.object({\n id: z.string().uuid(),\n activityType: z.string(),\n subject: z.string().nullable().optional(),\n body: z.string().nullable().optional(),\n occurredAt: z.string().nullable().optional(),\n dealId: z.string().uuid().nullable().optional(),\n authorUserId: z.string().uuid().nullable().optional(),\n authorName: z.string().nullable().optional(),\n authorEmail: z.string().nullable().optional(),\n createdAt: z.string(),\n appearanceIcon: z.string().nullable().optional(),\n appearanceColor: z.string().nullable().optional(),\n }),\n ),\n interactions: z.array(\n z.object({\n id: z.string().uuid(),\n entityId: z.string().uuid().nullable().optional(),\n interactionType: z.string(),\n title: z.string().nullable().optional(),\n body: z.string().nullable().optional(),\n status: z.string(),\n scheduledAt: z.string().nullable().optional(),\n occurredAt: z.string().nullable().optional(),\n priority: z.number().nullable().optional(),\n authorUserId: z.string().uuid().nullable().optional(),\n ownerUserId: z.string().uuid().nullable().optional(),\n dealId: z.string().uuid().nullable().optional(),\n organizationId: z.string().uuid().nullable().optional(),\n tenantId: z.string().uuid().nullable().optional(),\n authorName: z.string().nullable().optional(),\n authorEmail: z.string().nullable().optional(),\n dealTitle: z.string().nullable().optional(),\n customValues: z.record(z.string(), z.unknown()).nullable().optional(),\n appearanceIcon: z.string().nullable().optional(),\n appearanceColor: z.string().nullable().optional(),\n source: z.string().nullable().optional(),\n _integrations: z.record(z.string(), z.unknown()).optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n }),\n ),\n deals: z.array(\n z.object({\n id: z.string().uuid(),\n title: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n pipelineStage: z.string().nullable().optional(),\n valueAmount: z.number().nullable().optional(),\n valueCurrency: z.string().nullable().optional(),\n probability: z.number().nullable().optional(),\n expectedCloseAt: z.string().nullable().optional(),\n ownerUserId: z.string().uuid().nullable().optional(),\n source: z.string().nullable().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n }),\n ),\n todos: z.array(\n z.object({\n id: z.string().uuid(),\n todoId: z.string().uuid(),\n todoSource: z.string(),\n createdAt: z.string(),\n createdByUserId: z.string().uuid().nullable().optional(),\n title: z.string().nullable().optional(),\n isDone: z.boolean().nullable().optional(),\n priority: z.number().nullable().optional(),\n severity: z.string().nullable().optional(),\n description: z.string().nullable().optional(),\n dueAt: z.string().nullable().optional(),\n todoOrganizationId: z.string().uuid().nullable().optional(),\n customValues: z.record(z.string(), z.unknown()).nullable().optional(),\n }),\n ),\n people: z.array(\n z.object({\n id: z.string().uuid(),\n displayName: z.string().nullable().optional(),\n primaryEmail: z.string().nullable().optional(),\n primaryPhone: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n lifecycleStage: z.string().nullable().optional(),\n jobTitle: z.string().nullable().optional(),\n department: z.string().nullable().optional(),\n createdAt: z.string(),\n organizationId: z.string().uuid().nullable().optional(),\n source: z.string().nullable().optional(),\n temperature: z.string().nullable().optional(),\n linkedAt: z.string().nullable().optional(),\n }),\n ),\n viewer: z.object({\n userId: z.string().uuid().nullable(),\n name: z.string().nullable(),\n email: z.string().nullable(),\n }),\n})\n\nconst companyDetailErrorSchema = z.object({\n error: z.string(),\n})\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Customers',\n summary: 'Fetch company detail',\n methods: {\n GET: {\n summary: 'Fetch company with related data',\n description: 'Returns a company customer record with optional related resources such as addresses, comments, activities, interactions, deals, todos, and linked people.',\n query: companyDetailQuerySchema,\n responses: [\n { status: 200, description: 'Company detail payload', schema: companyDetailResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid identifier', schema: companyDetailErrorSchema },\n { status: 401, description: 'Unauthorized', schema: companyDetailErrorSchema },\n { status: 403, description: 'Forbidden for tenant/organization scope', schema: companyDetailErrorSchema },\n { status: 404, description: 'Company not found', schema: companyDetailErrorSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerEntity,\n CustomerCompanyProfile,\n CustomerAddress,\n CustomerComment,\n CustomerActivity,\n CustomerTagAssignment,\n CustomerTag,\n CustomerLabelAssignment,\n CustomerLabel,\n CustomerDealCompanyLink,\n CustomerDeal,\n CustomerTodoLink,\n CustomerPersonCompanyLink,\n CustomerPersonProfile,\n CustomerInteraction,\n} from '../../../data/entities'\nimport { User } from '@open-mercato/core/modules/auth/data/entities'\nimport { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n resolveCompanyCustomFieldRouting,\n mergeCompanyCustomFieldValues,\n} from '../../../lib/customFieldRouting'\nimport {\n CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE,\n EXAMPLE_TODO_SOURCE,\n CUSTOMER_INTERACTION_TODO_ADAPTER_SOURCE,\n mapInteractionRecordToActivitySummary,\n mapInteractionRecordToTodoSummary,\n} from '../../../lib/interactionCompatibility'\nimport { resolveCustomerInteractionFeatureFlags } from '../../../lib/interactionFeatureFlags'\nimport { hydrateCanonicalInteractions } from '../../../lib/interactionReadModel'\nimport { buildEmailVisibilityMikroFilter } from '../../../lib/visibilityFilter'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport type { EntityId } from '@open-mercato/shared/modules/entities'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { parseBooleanFromUnknown } from '@open-mercato/shared/lib/boolean'\nimport {\n filterActivePersonCompanyLinks,\n withActiveCustomerPersonCompanyLinkFilter,\n} from '../../../lib/personCompanyLinkTable'\nimport { normalizeCustomerDetailCustomFields } from '../../detailCustomFields'\nimport { isOrganizationReadAccessAllowed } from '@open-mercato/core/modules/directory/utils/organizationScopeGuard'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['customers.companies.view'] },\n}\n\nconst paramsSchema = z.object({\n id: z.string().uuid(),\n})\n\nfunction parseIncludeParams(request: Request): Set<string> {\n const url = new URL(request.url)\n const raw = url.searchParams.getAll('include')\n const tokens = new Set<string>()\n raw.forEach((entry) => {\n if (!entry) return\n entry\n .split(',')\n .map((part) => part.trim().toLowerCase())\n .filter((part) => part.length > 0)\n .forEach((part) => tokens.add(part))\n })\n return tokens\n}\n\nfunction forbidden(message: string) {\n return NextResponse.json({ error: message }, { status: 403 })\n}\n\nfunction notFound(message: string) {\n return NextResponse.json({ error: message }, { status: 404 })\n}\n\nfunction serializeTags(assignments: CustomerTagAssignment[]): Array<{ id: string; label: string; color: string | null }> {\n return assignments\n .map((assignment) => {\n const tag = assignment.tag as CustomerTag | string | null\n if (!tag || typeof tag === 'string') return null\n return {\n id: tag.id,\n label: tag.label,\n color: tag.color ?? null,\n }\n })\n .filter((tag): tag is { id: string; label: string; color: string | null } => tag !== null)\n}\n\ntype TodoDetail = {\n title: string | null\n isDone: boolean | null\n priority: number | null\n severity: string | null\n description: string | null\n dueAt: string | null\n organizationId: string | null\n customValues: Record<string, unknown> | null\n}\n\nfunction extractTodoTitle(record: Record<string, unknown>): string | null {\n const candidates = ['title', 'subject', 'name', 'summary', 'text', 'description']\n for (const key of candidates) {\n const value = record[key]\n if (typeof value === 'string' && value.trim().length > 0) {\n return value.trim()\n }\n }\n return null\n}\n\nfunction parseNumber(value: unknown): number | null {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return null\n const parsed = Number(trimmed)\n if (!Number.isNaN(parsed)) return parsed\n }\n return null\n}\n\nfunction parseDateValue(value: unknown): string | null {\n if (value instanceof Date) {\n const ts = value.getTime()\n return Number.isNaN(ts) ? null : value.toISOString()\n }\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return null\n const candidate = new Date(trimmed)\n if (!Number.isNaN(candidate.getTime())) return candidate.toISOString()\n }\n return null\n}\n\nfunction readCustomField(record: Record<string, unknown>, key: string): unknown {\n const custom = record.custom ?? record.customFields ?? record.cf\n if (custom && typeof custom === 'object') {\n const bucket = custom as Record<string, unknown>\n if (key in bucket) return bucket[key]\n }\n return undefined\n}\n\ntype CompanyDetailKpiSummary = {\n activeDealsCount: number\n activeDealsValue: number | null\n dealCurrency: string | null\n activityCount: number\n activityTrend: { value: number; direction: 'up' | 'down' | 'unchanged' } | null\n ltvValue: number | null\n completedDealsCount: number\n clientTenureYears: number | null\n}\n\nfunction parseDealAmount(value: string | number | null | undefined): number | null {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed.length) return null\n const parsed = Number(trimmed)\n return Number.isNaN(parsed) ? null : parsed\n }\n return null\n}\n\nfunction computeActivityTrend(\n timestamps: string[],\n): { value: number; direction: 'up' | 'down' | 'unchanged' } | null {\n if (!timestamps.length) return null\n const now = Date.now()\n const weekMs = 7 * 86_400_000\n let thisWeek = 0\n let lastWeek = 0\n timestamps.forEach((value) => {\n const time = new Date(value).getTime()\n if (Number.isNaN(time)) return\n const diff = now - time\n if (diff < 0 || diff >= weekMs * 2) return\n if (diff < weekMs) {\n thisWeek += 1\n return\n }\n lastWeek += 1\n })\n if (lastWeek === 0 && thisWeek === 0) return null\n if (lastWeek === 0) return { value: 100, direction: 'up' }\n const pct = ((thisWeek - lastWeek) / lastWeek) * 100\n if (Math.abs(pct) < 0.5) return { value: 0, direction: 'unchanged' }\n return { value: Math.round(Math.abs(pct) * 100) / 100, direction: pct > 0 ? 'up' : 'down' }\n}\n\nasync function resolveTodoDetails(\n queryEngine: QueryEngine,\n links: CustomerTodoLink[],\n tenantId: string | null,\n organizationIds: Array<string | null>,\n): Promise<Map<string, TodoDetail>> {\n const details = new Map<string, TodoDetail>()\n if (!links.length || !tenantId) return details\n\n const scopedOrgIds = organizationIds\n .filter((value): value is string => typeof value === 'string' && value.trim().length > 0)\n\n const idsBySource = new Map<string, Set<string>>()\n for (const link of links) {\n const source = typeof link.todoSource === 'string' && link.todoSource.trim().length > 0 ? link.todoSource : EXAMPLE_TODO_SOURCE\n const id = typeof link.todoId === 'string' && link.todoId.trim().length > 0 ? link.todoId : String(link.todoId ?? '')\n if (!id) continue\n if (!idsBySource.has(source)) idsBySource.set(source, new Set<string>())\n idsBySource.get(source)!.add(id)\n }\n\n for (const [source, idSet] of idsBySource.entries()) {\n const ids = Array.from(idSet)\n if (!ids.length) continue\n try {\n const result = await queryEngine.query<Record<string, unknown>>(source as EntityId, {\n tenantId,\n organizationIds: scopedOrgIds.length > 0 ? scopedOrgIds : undefined,\n filters: { id: { $in: ids } },\n includeCustomFields: ['priority', 'due_at', 'severity', 'description'],\n page: { page: 1, pageSize: Math.max(ids.length, 1) },\n })\n for (const item of result.items ?? []) {\n if (!item || typeof item !== 'object') continue\n const record = item as Record<string, unknown>\n const rawId = typeof record.id === 'string' && record.id.trim().length > 0 ? record.id : String(record.id ?? '')\n if (!rawId) continue\n const title = extractTodoTitle(record)\n const isDone = (() => {\n const direct = parseBooleanFromUnknown(record.is_done)\n if (direct !== null) return direct\n const custom = parseBooleanFromUnknown(readCustomField(record, 'is_done'))\n if (custom !== null) return custom\n const generic = parseBooleanFromUnknown(record.isDone)\n if (generic !== null) return generic\n return parseBooleanFromUnknown(readCustomField(record, 'isDone'))\n })()\n const priority = (() => {\n const candidates = [\n record['cf:priority'],\n record['cf_priority'],\n record.priority,\n readCustomField(record, 'priority'),\n ]\n for (const candidate of candidates) {\n const parsed = parseNumber(candidate)\n if (parsed !== null) return parsed\n }\n return null\n })()\n const severity = (() => {\n const candidates = [\n record['cf:severity'],\n record['cf_severity'],\n record.severity,\n readCustomField(record, 'severity'),\n ]\n for (const candidate of candidates) {\n if (typeof candidate === 'string' && candidate.trim().length > 0) {\n return candidate.trim()\n }\n }\n return null\n })()\n const dueAt = (() => {\n const candidates = [\n record['cf:due_at'],\n record['cf_due_at'],\n record.due_at,\n readCustomField(record, 'due_at'),\n record.dueAt,\n readCustomField(record, 'dueAt'),\n ]\n for (const candidate of candidates) {\n const parsed = parseDateValue(candidate)\n if (parsed) return parsed\n }\n return null\n })()\n const organizationId = (() => {\n const candidates = [\n record.organization_id,\n record['cf:organization_id'],\n record['cf_organization_id'],\n record.organizationId,\n readCustomField(record, 'organization_id'),\n readCustomField(record, 'organizationId'),\n ]\n for (const candidate of candidates) {\n if (typeof candidate === 'string' && candidate.trim().length > 0) {\n return candidate.trim()\n }\n }\n return null\n })()\n const descriptionValue = (() => {\n const direct = typeof record.description === 'string' ? record.description : null\n if (direct) return direct\n const customDescription = readCustomField(record, 'description')\n if (typeof customDescription === 'string' && customDescription.trim().length > 0) {\n return customDescription.trim()\n }\n return null\n })()\n\n const customValues: Record<string, unknown> = {}\n const assignCustomValue = (key: string, value: unknown) => {\n const trimmedKey = key.trim()\n if (!trimmedKey.length) return\n customValues[trimmedKey] = value === undefined ? null : value\n }\n for (const [rawKey, rawValue] of Object.entries(record)) {\n if (rawKey.startsWith('cf:')) {\n assignCustomValue(rawKey.slice(3), rawValue)\n } else if (rawKey.startsWith('cf_')) {\n assignCustomValue(rawKey.slice(3), rawValue)\n }\n }\n const nestedCustom = record.custom ?? record.customFields ?? record.cf\n if (nestedCustom && typeof nestedCustom === 'object') {\n for (const [nestedKey, nestedValue] of Object.entries(nestedCustom as Record<string, unknown>)) {\n assignCustomValue(nestedKey, nestedValue)\n }\n }\n\n details.set(`${source}:${rawId}`, {\n title,\n isDone,\n priority,\n severity,\n description: descriptionValue,\n dueAt,\n organizationId,\n customValues: Object.keys(customValues).length ? customValues : null,\n })\n }\n } catch (err) {\n console.warn(`customers.companies.detail: failed to resolve todos for source ${source}`, err)\n }\n }\n\n return details\n}\n\nexport async function GET(_req: Request, ctx: { params?: { id?: string } }) {\n const auth = await getAuthFromRequest(_req)\n if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n const parse = paramsSchema.safeParse({ id: ctx.params?.id })\n if (!parse.success) return NextResponse.json({ error: 'Invalid company id' }, { status: 400 })\n\n const includeTokens = parseIncludeParams(_req)\n const includeActivities = includeTokens.has('activities')\n const includeAddresses = includeTokens.has('addresses')\n const includeComments = includeTokens.has('comments') || includeTokens.has('notes')\n const includeDeals = includeTokens.has('deals')\n const includeInteractions = includeTokens.has('interactions')\n const includeTodos = includeTokens.has('todos') || includeTokens.has('tasks')\n const includePeople = includeTokens.has('people')\n const plannedPreviewLimit = 5\n\n const container = await createRequestContainer()\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: _req })\n const em = (container.resolve('em') as EntityManager)\n const interactionFlags = await resolveCustomerInteractionFeatureFlags(container, scope?.tenantId ?? auth.tenantId)\n const interactionMode = interactionFlags.unified ? 'canonical' : 'legacy'\n\n const company = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: parse.data.id, kind: 'company', deletedAt: null },\n { populate: ['companyProfile'] },\n {\n tenantId: auth.tenantId ?? null,\n organizationId: scope?.selectedId ?? auth.orgId ?? null,\n },\n )\n if (!company) return notFound('Company not found')\n\n if (auth.tenantId && company.tenantId !== auth.tenantId) return notFound('Company not found')\n if (!isOrganizationReadAccessAllowed({ scope, auth, organizationId: company.organizationId })) {\n return forbidden('Access denied')\n }\n\n const companyScope = {\n tenantId: company.tenantId ?? auth.tenantId ?? null,\n organizationId: company.organizationId ?? scope?.selectedId ?? auth.orgId ?? null,\n }\n\n // Per-user email privacy (CRM email integration): exclude private email\n // interactions owned by other users from every read path that returns\n // customer_interactions. Non-email rows, shared emails, and legacy\n // null-visibility rows pass through. v1 is strict owner-only: there is NO\n // admin bypass \u2014 the filter ignores caller features, and\n // `customers.email.view_private` is reserved (inert) for v2 oversight.\n // Mirrors the people detail route. API-key callers resolve to null\n // (no author match \u2014 shared/non-email rows only).\n const viewerUserId = auth.isApiKey ? null : (auth.sub ?? null)\n const emailVisibilityFilter = buildEmailVisibilityMikroFilter({\n currentUserId: viewerUserId,\n userFeatures: undefined,\n })\n\n const profile = company.companyProfile\n ? await findOneWithDecryption(\n em,\n CustomerCompanyProfile,\n {\n id: company.companyProfile.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n {},\n companyScope,\n )\n : await findOneWithDecryption(\n em,\n CustomerCompanyProfile,\n {\n entity: company,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n {},\n companyScope,\n )\n\n const addresses = includeAddresses\n ? await findWithDecryption(\n em,\n CustomerAddress,\n {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n { orderBy: { isPrimary: 'desc', createdAt: 'desc' } },\n companyScope,\n )\n : []\n const tagAssignments = await findWithDecryption(\n em,\n CustomerTagAssignment,\n {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n { populate: ['tag'] },\n companyScope,\n )\n const labelAssignments = await findWithDecryption(\n em,\n CustomerLabelAssignment,\n {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n { populate: ['label'] },\n companyScope,\n )\n\n const comments = includeComments\n ? await findWithDecryption(\n em,\n CustomerComment,\n {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n { orderBy: { createdAt: 'desc' }, limit: 50 },\n companyScope,\n )\n : []\n const shouldLoadCanonicalInteractions = includeInteractions || includeActivities || includeTodos\n const canonicalInteractionRows = shouldLoadCanonicalInteractions\n ? await findWithDecryption(\n em,\n CustomerInteraction,\n interactionFlags.unified\n ? {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n deletedAt: null,\n ...emailVisibilityFilter,\n }\n : {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n ...emailVisibilityFilter,\n },\n { orderBy: { scheduledAt: 'asc', createdAt: 'desc' }, limit: 100 },\n companyScope,\n )\n : []\n const canonicalActiveInteractions = canonicalInteractionRows.filter((interaction) => !interaction.deletedAt)\n const canonicalInteractions = shouldLoadCanonicalInteractions\n ? await hydrateCanonicalInteractions({\n em,\n container,\n auth,\n selectedOrganizationId: scope?.selectedId ?? auth.orgId ?? null,\n interactions: canonicalActiveInteractions,\n enrich: includeInteractions,\n })\n : []\n\n const plannedPreviewRows =\n canonicalActiveInteractions.length > 0\n ? canonicalActiveInteractions\n .filter((interaction) => interaction.status === 'planned' && interaction.interactionType !== 'task')\n .sort((left, right) => {\n const leftTime = new Date(left.scheduledAt ?? left.createdAt).getTime()\n const rightTime = new Date(right.scheduledAt ?? right.createdAt).getTime()\n if (leftTime === rightTime) return left.id.localeCompare(right.id)\n return leftTime - rightTime\n })\n .slice(0, plannedPreviewLimit)\n : await findWithDecryption(\n em,\n CustomerInteraction,\n {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n deletedAt: null,\n status: 'planned',\n interactionType: { $ne: 'task' },\n ...emailVisibilityFilter,\n },\n { orderBy: { scheduledAt: 'ASC', createdAt: 'ASC' }, limit: plannedPreviewLimit },\n companyScope,\n )\n const plannedActivitiesPreview = plannedPreviewRows.length\n ? await hydrateCanonicalInteractions({\n em,\n container,\n auth,\n selectedOrganizationId: scope?.selectedId ?? auth.orgId ?? null,\n interactions: plannedPreviewRows,\n enrich: true,\n })\n : []\n\n const activities = includeActivities && !interactionFlags.unified\n ? await findWithDecryption(\n em,\n CustomerActivity,\n {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n { orderBy: { occurredAt: 'desc', createdAt: 'desc' }, limit: 50 },\n companyScope,\n )\n : []\n const todoLinks = includeTodos && !interactionFlags.unified\n ? await findWithDecryption(\n em,\n CustomerTodoLink,\n {\n entity: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n },\n { orderBy: { createdAt: 'desc' }, limit: 50 },\n companyScope,\n )\n : []\n\n let todoDetails = new Map<string, TodoDetail>()\n if (includeTodos && !interactionFlags.unified && todoLinks.length) {\n const queryEngine = (container.resolve('queryEngine') as QueryEngine)\n try {\n todoDetails = await resolveTodoDetails(\n queryEngine,\n todoLinks,\n company.tenantId ?? auth.tenantId ?? null,\n [company.organizationId ?? null, ...(scope?.filterIds ?? [])],\n )\n } catch (err) {\n console.warn('customers.companies.detail: failed to enrich todo links', err)\n }\n }\n\n const canonicalActivityBridgeIds = new Set(\n canonicalInteractionRows\n .filter((interaction) => interaction.source === CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE)\n .map((interaction) => interaction.id),\n )\n const canonicalTodoBridgeIds = new Set(\n canonicalInteractionRows\n .filter((interaction) => interaction.source === CUSTOMER_INTERACTION_TODO_ADAPTER_SOURCE)\n .map((interaction) => interaction.id),\n )\n\n const canonicalActivityItems = canonicalInteractions\n .filter((interaction) => interaction.interactionType !== 'task')\n .map((interaction) => mapInteractionRecordToActivitySummary(interaction))\n const canonicalTodoItems = canonicalInteractions\n .filter((interaction) => interaction.interactionType === 'task')\n .map((interaction) => mapInteractionRecordToTodoSummary(interaction))\n\n const authorIds = new Set<string>()\n if (includeActivities) {\n for (const activity of activities) {\n if (activity.authorUserId) authorIds.add(activity.authorUserId)\n }\n }\n if (includeComments) {\n for (const comment of comments) {\n if (comment.authorUserId) authorIds.add(comment.authorUserId)\n }\n }\n if (viewerUserId) authorIds.add(viewerUserId)\n\n let userMap = new Map<string, { name: string | null; email: string | null }>()\n if (authorIds.size) {\n const authorIdList = Array.from(authorIds)\n const users = await findWithDecryption(\n em,\n User,\n {\n id: { $in: authorIdList },\n tenantId: company.tenantId,\n },\n {},\n companyScope,\n )\n userMap = new Map(\n users.map((user) => [\n user.id,\n {\n name: user.name ?? null,\n email: user.email ?? null,\n },\n ])\n )\n }\n\n let deals: CustomerDeal[] = []\n if (includeDeals) {\n const dealLinks = await findWithDecryption(\n em,\n CustomerDealCompanyLink,\n {\n company: company.id,\n },\n { populate: ['deal'] },\n companyScope,\n )\n deals = dealLinks\n .map((link) => (link.deal as CustomerDeal | string | null) ?? null)\n .filter(\n (deal): deal is CustomerDeal =>\n !!deal &&\n typeof deal !== 'string' &&\n deal.tenantId === company.tenantId &&\n deal.organizationId === company.organizationId,\n )\n }\n\n const dealLinksForMetrics = includeDeals\n ? deals\n : (\n await findWithDecryption(\n em,\n CustomerDealCompanyLink,\n {\n company: company.id,\n },\n { populate: ['deal'] },\n companyScope,\n )\n )\n .map((link) => (link.deal as CustomerDeal | string | null) ?? null)\n .filter(\n (deal): deal is CustomerDeal =>\n !!deal &&\n typeof deal !== 'string' &&\n deal.tenantId === company.tenantId &&\n deal.organizationId === company.organizationId,\n )\n\n let relatedPeople: Array<{\n entity: CustomerEntity\n profile: CustomerPersonProfile | null\n linkedAt: string | null\n }> = []\n if (includePeople) {\n const peopleDecryptionScope = {\n tenantId: company.tenantId ?? auth.tenantId ?? null,\n organizationId: company.organizationId ?? scope?.selectedId ?? auth.orgId ?? null,\n }\n const relatedPeopleById = new Map<\n string,\n { entity: CustomerEntity; profile: CustomerPersonProfile | null; linkedAt: string | null }\n >()\n const companyLinkWhere = await withActiveCustomerPersonCompanyLinkFilter(\n em,\n {\n company: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n },\n 'customers.companies.GET',\n )\n const companyLinks = filterActivePersonCompanyLinks(\n await findWithDecryption(\n em,\n CustomerPersonCompanyLink,\n companyLinkWhere,\n {\n populate: ['person', 'person.personProfile'],\n orderBy: { isPrimary: 'desc', createdAt: 'asc' },\n },\n peopleDecryptionScope,\n ),\n )\n companyLinks.forEach((link) => {\n const entity = typeof link.person === 'string' ? null : link.person\n if (!entity || entity.kind !== 'person' || entity.deletedAt) return\n const personProfile =\n entity.personProfile && typeof entity.personProfile !== 'string'\n ? entity.personProfile\n : null\n relatedPeopleById.set(entity.id, {\n entity,\n profile: personProfile,\n linkedAt: link.createdAt instanceof Date ? link.createdAt.toISOString() : null,\n })\n })\n\n const profiles = await findWithDecryption(\n em,\n CustomerPersonProfile,\n {\n company: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n entity: { deletedAt: null },\n },\n { populate: ['entity'] },\n peopleDecryptionScope,\n )\n profiles.forEach((entry) => {\n const entity = entry.entity as CustomerEntity | null\n if (!entity || entity.kind !== 'person' || entity.deletedAt) return\n if (!relatedPeopleById.has(entity.id)) {\n relatedPeopleById.set(entity.id, {\n entity,\n profile: entry ?? null,\n linkedAt: entry.createdAt instanceof Date ? entry.createdAt.toISOString() : null,\n })\n }\n })\n relatedPeople = Array.from(relatedPeopleById.values())\n }\n\n const entityCustomFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.customers.customer_entity,\n recordIds: [company.id],\n tenantIdByRecord: { [company.id]: company.tenantId ?? null },\n organizationIdByRecord: { [company.id]: company.organizationId ?? null },\n tenantFallbacks: [\n company.tenantId ?? auth.tenantId ?? null,\n ].filter((v): v is string => !!v),\n })\n let profileCustomFieldValues: Record<string, Record<string, unknown>> = {}\n const profileId = profile?.id ?? null\n if (profileId) {\n profileCustomFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.customers.customer_company_profile,\n recordIds: [profileId],\n tenantIdByRecord: { [profileId]: profile?.tenantId ?? null },\n organizationIdByRecord: { [profileId]: profile?.organizationId ?? null },\n tenantFallbacks: [\n profile?.tenantId ?? company.tenantId ?? auth.tenantId ?? null,\n ].filter((v): v is string => !!v),\n })\n }\n\n const routing = await resolveCompanyCustomFieldRouting(em, company.tenantId ?? null, company.organizationId ?? null)\n const customFields = normalizeCustomerDetailCustomFields(\n mergeCompanyCustomFieldValues(\n routing,\n entityCustomFieldValues?.[company.id] ?? {},\n profileId ? profileCustomFieldValues?.[profileId] ?? {} : {},\n ),\n )\n\n const activityCount = await em.count(CustomerInteraction, {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n deletedAt: null,\n interactionType: { $ne: 'task' },\n ...emailVisibilityFilter,\n })\n const interactionCount = await em.count(CustomerInteraction, {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n deletedAt: null,\n ...emailVisibilityFilter,\n })\n const todoCount = interactionFlags.unified\n ? await em.count(CustomerInteraction, {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n deletedAt: null,\n interactionType: 'task',\n })\n : await em.count(CustomerTodoLink, {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n })\n const commentsCount = includeComments\n ? comments.length\n : await em.count(CustomerComment, {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n })\n const addressesCount = includeAddresses\n ? addresses.length\n : await em.count(CustomerAddress, {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n })\n const peopleCount = includePeople\n ? relatedPeople.length\n : filterActivePersonCompanyLinks(\n await findWithDecryption(\n em,\n CustomerPersonCompanyLink,\n await withActiveCustomerPersonCompanyLinkFilter(\n em,\n {\n company: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n },\n 'customers.companies.GET',\n ),\n {},\n { tenantId: company.tenantId, organizationId: company.organizationId },\n ),\n ).length\n const kpiInteractionRows = canonicalActiveInteractions.length\n ? canonicalActiveInteractions\n : await findWithDecryption(\n em,\n CustomerInteraction,\n {\n entity: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n deletedAt: null,\n ...emailVisibilityFilter,\n },\n {\n fields: ['id', 'occurredAt', 'scheduledAt', 'createdAt'],\n orderBy: { createdAt: 'DESC' },\n },\n { tenantId: company.tenantId, organizationId: company.organizationId },\n )\n const activityTrend = computeActivityTrend(\n kpiInteractionRows\n .map((interaction) => interaction.occurredAt ?? interaction.scheduledAt ?? interaction.createdAt)\n .map((value) => (value instanceof Date ? value.toISOString() : typeof value === 'string' ? value : ''))\n .filter((value) => value.length > 0),\n )\n const activeDeals = dealLinksForMetrics.filter(\n (deal) => deal.status !== 'won' && deal.status !== 'lost' && deal.status !== 'closed',\n )\n const wonDeals = dealLinksForMetrics.filter((deal) => deal.status === 'won')\n const activeDealsValue = activeDeals.reduce((sum, deal) => sum + (parseDealAmount(deal.valueAmount) ?? 0), 0)\n const ltvValue = wonDeals.length\n ? wonDeals.reduce((sum, deal) => sum + (parseDealAmount(deal.valueAmount) ?? 0), 0)\n : null\n const earliestInteractionTime = kpiInteractionRows.reduce<number | null>((earliest, interaction) => {\n const candidate = interaction.occurredAt ?? interaction.scheduledAt ?? interaction.createdAt\n const time = candidate instanceof Date ? candidate.getTime() : new Date(candidate).getTime()\n if (Number.isNaN(time)) return earliest\n if (earliest === null) return time\n return Math.min(earliest, time)\n }, null)\n const companyKpis: CompanyDetailKpiSummary = {\n activeDealsCount: activeDeals.length,\n activeDealsValue: activeDeals.length ? activeDealsValue : null,\n dealCurrency:\n activeDeals[0]?.valueCurrency ??\n dealLinksForMetrics[0]?.valueCurrency ??\n null,\n activityCount,\n activityTrend,\n ltvValue,\n completedDealsCount: wonDeals.length,\n clientTenureYears:\n earliestInteractionTime === null\n ? null\n : Math.floor((Date.now() - earliestInteractionTime) / (365.25 * 86_400_000)),\n }\n const counts = {\n tags: tagAssignments.length + labelAssignments.length,\n comments: commentsCount,\n activities: activityCount,\n interactions: interactionCount,\n todos: todoCount,\n deals: includeDeals ? deals.length : dealLinksForMetrics.length,\n people: peopleCount,\n addresses: addressesCount,\n }\n\n return NextResponse.json({\n interactionMode,\n company: {\n id: company.id,\n displayName: company.displayName,\n description: company.description,\n ownerUserId: company.ownerUserId,\n primaryEmail: company.primaryEmail,\n primaryPhone: company.primaryPhone,\n status: company.status,\n lifecycleStage: company.lifecycleStage,\n source: company.source,\n nextInteractionAt: company.nextInteractionAt ? company.nextInteractionAt.toISOString() : null,\n nextInteractionName: company.nextInteractionName,\n nextInteractionRefId: company.nextInteractionRefId,\n nextInteractionIcon: company.nextInteractionIcon,\n nextInteractionColor: company.nextInteractionColor,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n isActive: company.isActive,\n temperature: company.temperature ?? null,\n renewalQuarter: company.renewalQuarter ?? null,\n createdAt: company.createdAt.toISOString(),\n updatedAt: company.updatedAt.toISOString(),\n },\n profile: profile\n ? {\n id: profile.id,\n legalName: profile.legalName,\n brandName: profile.brandName,\n domain: profile.domain,\n websiteUrl: profile.websiteUrl,\n industry: profile.industry,\n sizeBucket: profile.sizeBucket,\n annualRevenue: profile.annualRevenue,\n }\n : null,\n customFields,\n tags: [\n ...serializeTags(tagAssignments),\n ...labelAssignments\n .map((assignment) => {\n const label = assignment.label as CustomerLabel | string | null\n if (!label || typeof label === 'string') return null\n return { id: label.id, label: label.label, color: null }\n })\n .filter((tag): tag is { id: string; label: string; color: null } => tag !== null),\n ],\n addresses: includeAddresses\n ? addresses.map((address) => ({\n id: address.id,\n name: address.name,\n purpose: address.purpose,\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2,\n buildingNumber: address.buildingNumber,\n flatNumber: address.flatNumber,\n city: address.city,\n region: address.region,\n postalCode: address.postalCode,\n country: address.country,\n latitude: address.latitude,\n longitude: address.longitude,\n isPrimary: address.isPrimary,\n createdAt: address.createdAt.toISOString(),\n }))\n : [],\n comments: includeComments\n ? comments.map((comment) => {\n const authorInfo = comment.authorUserId ? userMap.get(comment.authorUserId) : null\n return {\n id: comment.id,\n body: comment.body,\n authorUserId: comment.authorUserId,\n authorName: comment.authorUserId ? authorInfo?.name ?? null : null,\n authorEmail: comment.authorUserId ? authorInfo?.email ?? null : null,\n dealId: comment.deal ? (typeof comment.deal === 'string' ? comment.deal : comment.deal.id) : null,\n createdAt: comment.createdAt.toISOString(),\n appearanceIcon: comment.appearanceIcon ?? null,\n appearanceColor: comment.appearanceColor ?? null,\n }\n })\n : [],\n activities: includeActivities\n ? (\n interactionFlags.unified\n ? canonicalActivityItems\n : [\n ...activities\n .filter((activity) => !canonicalActivityBridgeIds.has(activity.id))\n .map((activity) => ({\n id: activity.id,\n activityType: activity.activityType,\n subject: activity.subject,\n body: activity.body,\n occurredAt: activity.occurredAt ? activity.occurredAt.toISOString() : null,\n dealId: activity.deal ? (typeof activity.deal === 'string' ? activity.deal : activity.deal.id) : null,\n authorUserId: activity.authorUserId,\n authorName: activity.authorUserId ? userMap.get(activity.authorUserId)?.name ?? null : null,\n authorEmail: activity.authorUserId ? userMap.get(activity.authorUserId)?.email ?? null : null,\n createdAt: activity.createdAt.toISOString(),\n appearanceIcon: activity.appearanceIcon ?? null,\n appearanceColor: activity.appearanceColor ?? null,\n })),\n ...canonicalActivityItems.filter(\n (activity) =>\n canonicalInteractions.some(\n (interaction) =>\n interaction.id === activity.id &&\n interaction.source === CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE,\n ),\n ),\n ].sort((left, right) => {\n const leftTime = new Date(left.occurredAt ?? left.createdAt).getTime()\n const rightTime = new Date(right.occurredAt ?? right.createdAt).getTime()\n if (leftTime === rightTime) return right.id.localeCompare(left.id)\n return rightTime - leftTime\n }).slice(0, 50)\n )\n : [],\n interactions: includeInteractions\n ? canonicalInteractions\n : [],\n deals: includeDeals\n ? deals.map((deal) => ({\n id: deal.id,\n title: deal.title,\n status: deal.status,\n pipelineStage: deal.pipelineStage,\n pipelineId: deal.pipelineId ?? null,\n pipelineStageId: deal.pipelineStageId ?? null,\n valueAmount: deal.valueAmount,\n valueCurrency: deal.valueCurrency,\n probability: deal.probability,\n expectedCloseAt: deal.expectedCloseAt ? deal.expectedCloseAt.toISOString() : null,\n ownerUserId: deal.ownerUserId,\n source: deal.source,\n createdAt: deal.createdAt.toISOString(),\n updatedAt: deal.updatedAt.toISOString(),\n }))\n : [],\n todos: includeTodos\n ? (\n interactionFlags.unified\n ? canonicalTodoItems\n : [\n ...todoLinks\n .filter((link) => !canonicalTodoBridgeIds.has(link.todoId))\n .map((link) => {\n const source = typeof link.todoSource === 'string' && link.todoSource.trim().length > 0 ? link.todoSource : EXAMPLE_TODO_SOURCE\n const key = `${source}:${link.todoId}`\n const detail = todoDetails.get(key)\n return {\n id: link.id,\n todoId: link.todoId,\n todoSource: source,\n createdAt: link.createdAt.toISOString(),\n createdByUserId: link.createdByUserId,\n title: detail?.title ?? null,\n isDone: detail?.isDone ?? null,\n priority: detail?.priority ?? null,\n severity: detail?.severity ?? null,\n description: detail?.description ?? null,\n dueAt: detail?.dueAt ?? null,\n todoOrganizationId: detail?.organizationId ?? null,\n customValues: detail?.customValues ?? null,\n }\n }),\n ...canonicalTodoItems.filter(\n (todo) =>\n canonicalInteractions.some(\n (interaction) =>\n interaction.id === todo.todoId &&\n interaction.source === CUSTOMER_INTERACTION_TODO_ADAPTER_SOURCE,\n ),\n ),\n ].sort((left, right) => {\n const leftTime = new Date(left.createdAt).getTime()\n const rightTime = new Date(right.createdAt).getTime()\n if (leftTime === rightTime) return right.id.localeCompare(left.id)\n return rightTime - leftTime\n }).slice(0, 50)\n )\n : [],\n people: includePeople\n ? relatedPeople.map(({ entity, profile: personProfile, linkedAt }) => ({\n id: entity.id,\n displayName: entity.displayName,\n primaryEmail: entity.primaryEmail ?? null,\n primaryPhone: entity.primaryPhone ?? null,\n status: entity.status ?? null,\n lifecycleStage: entity.lifecycleStage ?? null,\n jobTitle: personProfile?.jobTitle ?? null,\n department: personProfile?.department ?? null,\n createdAt: entity.createdAt.toISOString(),\n organizationId: entity.organizationId,\n source: entity.source ?? null,\n temperature: entity.temperature ?? null,\n linkedAt,\n }))\n : [],\n plannedActivitiesPreview,\n counts,\n kpis: companyKpis,\n viewer: {\n userId: viewerUserId,\n name: viewerUserId ? userMap.get(viewerUserId)?.name ?? null : null,\n email: viewerUserId ? userMap.get(viewerUserId)?.email ?? auth.email ?? null : auth.email ?? null,\n },\n })\n}\n\nconst companyDetailQuerySchema = z.object({\n include: z\n .string()\n .optional()\n .describe('Comma-separated list of relations to include (addresses, comments, activities, interactions, deals, todos, people).'),\n}).passthrough()\n\nconst companyDetailResponseSchema = z.object({\n interactionMode: z.enum(['canonical', 'legacy']),\n company: z.object({\n id: z.string().uuid(),\n displayName: z.string().nullable().optional(),\n description: z.string().nullable().optional(),\n ownerUserId: z.string().uuid().nullable().optional(),\n primaryEmail: z.string().nullable().optional(),\n primaryPhone: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n lifecycleStage: z.string().nullable().optional(),\n source: z.string().nullable().optional(),\n nextInteractionAt: z.string().nullable().optional(),\n nextInteractionName: z.string().nullable().optional(),\n nextInteractionRefId: z.string().nullable().optional(),\n nextInteractionIcon: z.string().nullable().optional(),\n nextInteractionColor: z.string().nullable().optional(),\n organizationId: z.string().uuid().nullable().optional(),\n tenantId: z.string().uuid().nullable().optional(),\n isActive: z.boolean().optional(),\n temperature: z.string().nullable().optional(),\n renewalQuarter: z.string().nullable().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n }),\n profile: z\n .object({\n id: z.string().uuid(),\n legalName: z.string().nullable().optional(),\n brandName: z.string().nullable().optional(),\n domain: z.string().nullable().optional(),\n websiteUrl: z.string().nullable().optional(),\n industry: z.string().nullable().optional(),\n sizeBucket: z.string().nullable().optional(),\n annualRevenue: z.number().nullable().optional(),\n })\n .nullable(),\n customFields: z.record(z.string(), z.unknown()),\n tags: z.array(\n z.object({\n id: z.string().uuid(),\n label: z.string(),\n color: z.string().nullable().optional(),\n }),\n ),\n addresses: z.array(\n z.object({\n id: z.string().uuid(),\n name: z.string().nullable().optional(),\n purpose: z.string().nullable().optional(),\n addressLine1: z.string().nullable().optional(),\n addressLine2: z.string().nullable().optional(),\n buildingNumber: z.string().nullable().optional(),\n flatNumber: z.string().nullable().optional(),\n city: z.string().nullable().optional(),\n region: z.string().nullable().optional(),\n postalCode: z.string().nullable().optional(),\n country: z.string().nullable().optional(),\n latitude: z.number().nullable().optional(),\n longitude: z.number().nullable().optional(),\n isPrimary: z.boolean().nullable().optional(),\n createdAt: z.string(),\n }),\n ),\n comments: z.array(\n z.object({\n id: z.string().uuid(),\n body: z.string().nullable().optional(),\n authorUserId: z.string().uuid().nullable().optional(),\n authorName: z.string().nullable().optional(),\n authorEmail: z.string().nullable().optional(),\n dealId: z.string().uuid().nullable().optional(),\n createdAt: z.string(),\n appearanceIcon: z.string().nullable().optional(),\n appearanceColor: z.string().nullable().optional(),\n }),\n ),\n activities: z.array(\n z.object({\n id: z.string().uuid(),\n activityType: z.string(),\n subject: z.string().nullable().optional(),\n body: z.string().nullable().optional(),\n occurredAt: z.string().nullable().optional(),\n dealId: z.string().uuid().nullable().optional(),\n authorUserId: z.string().uuid().nullable().optional(),\n authorName: z.string().nullable().optional(),\n authorEmail: z.string().nullable().optional(),\n createdAt: z.string(),\n appearanceIcon: z.string().nullable().optional(),\n appearanceColor: z.string().nullable().optional(),\n }),\n ),\n interactions: z.array(\n z.object({\n id: z.string().uuid(),\n entityId: z.string().uuid().nullable().optional(),\n interactionType: z.string(),\n title: z.string().nullable().optional(),\n body: z.string().nullable().optional(),\n status: z.string(),\n scheduledAt: z.string().nullable().optional(),\n occurredAt: z.string().nullable().optional(),\n priority: z.number().nullable().optional(),\n authorUserId: z.string().uuid().nullable().optional(),\n ownerUserId: z.string().uuid().nullable().optional(),\n dealId: z.string().uuid().nullable().optional(),\n organizationId: z.string().uuid().nullable().optional(),\n tenantId: z.string().uuid().nullable().optional(),\n authorName: z.string().nullable().optional(),\n authorEmail: z.string().nullable().optional(),\n dealTitle: z.string().nullable().optional(),\n customValues: z.record(z.string(), z.unknown()).nullable().optional(),\n appearanceIcon: z.string().nullable().optional(),\n appearanceColor: z.string().nullable().optional(),\n source: z.string().nullable().optional(),\n _integrations: z.record(z.string(), z.unknown()).optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n }),\n ),\n deals: z.array(\n z.object({\n id: z.string().uuid(),\n title: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n pipelineStage: z.string().nullable().optional(),\n valueAmount: z.number().nullable().optional(),\n valueCurrency: z.string().nullable().optional(),\n probability: z.number().nullable().optional(),\n expectedCloseAt: z.string().nullable().optional(),\n ownerUserId: z.string().uuid().nullable().optional(),\n source: z.string().nullable().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n }),\n ),\n todos: z.array(\n z.object({\n id: z.string().uuid(),\n todoId: z.string().uuid(),\n todoSource: z.string(),\n createdAt: z.string(),\n createdByUserId: z.string().uuid().nullable().optional(),\n title: z.string().nullable().optional(),\n isDone: z.boolean().nullable().optional(),\n priority: z.number().nullable().optional(),\n severity: z.string().nullable().optional(),\n description: z.string().nullable().optional(),\n dueAt: z.string().nullable().optional(),\n todoOrganizationId: z.string().uuid().nullable().optional(),\n customValues: z.record(z.string(), z.unknown()).nullable().optional(),\n }),\n ),\n people: z.array(\n z.object({\n id: z.string().uuid(),\n displayName: z.string().nullable().optional(),\n primaryEmail: z.string().nullable().optional(),\n primaryPhone: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n lifecycleStage: z.string().nullable().optional(),\n jobTitle: z.string().nullable().optional(),\n department: z.string().nullable().optional(),\n createdAt: z.string(),\n organizationId: z.string().uuid().nullable().optional(),\n source: z.string().nullable().optional(),\n temperature: z.string().nullable().optional(),\n linkedAt: z.string().nullable().optional(),\n }),\n ),\n viewer: z.object({\n userId: z.string().uuid().nullable(),\n name: z.string().nullable(),\n email: z.string().nullable(),\n }),\n})\n\nconst companyDetailErrorSchema = z.object({\n error: z.string(),\n})\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Customers',\n summary: 'Fetch company detail',\n methods: {\n GET: {\n summary: 'Fetch company with related data',\n description: 'Returns a company customer record with optional related resources such as addresses, comments, activities, interactions, deals, todos, and linked people.',\n query: companyDetailQuerySchema,\n responses: [\n { status: 200, description: 'Company detail payload', schema: companyDetailResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid identifier', schema: companyDetailErrorSchema },\n { status: 401, description: 'Unauthorized', schema: companyDetailErrorSchema },\n { status: 403, description: 'Forbidden for tenant/organization scope', schema: companyDetailErrorSchema },\n { status: 404, description: 'Company not found', schema: companyDetailErrorSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
|
|
4
|
+
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
5
|
+
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
6
|
+
import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
|
|
7
|
+
import {
|
|
8
|
+
validateCrudMutationGuard,
|
|
9
|
+
runCrudMutationGuardAfterSuccess
|
|
10
|
+
} from "@open-mercato/shared/lib/crud/mutation-guard";
|
|
11
|
+
import { resolveOrganizationScopeForRequest } from "@open-mercato/core/modules/directory/utils/organizationScope";
|
|
12
|
+
import { CustomerInteraction } from "../../../../data/entities.js";
|
|
13
|
+
import { resolveAuthActorId } from "../../../../lib/interactionRequestContext.js";
|
|
14
|
+
import { emitCustomersEvent } from "../../../../events.js";
|
|
15
|
+
const metadata = {
|
|
16
|
+
path: "/customers/interactions/[id]/visibility",
|
|
17
|
+
PATCH: {
|
|
18
|
+
requireAuth: true,
|
|
19
|
+
requireFeatures: ["customers.email.compose"]
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
const bodySchema = z.object({ visibility: z.enum(["private", "shared"]) }).strict();
|
|
23
|
+
async function PATCH(req, context) {
|
|
24
|
+
const { id } = await context.params;
|
|
25
|
+
if (!z.string().uuid().safeParse(id).success) {
|
|
26
|
+
return NextResponse.json({ error: "Invalid interaction id" }, { status: 400 });
|
|
27
|
+
}
|
|
28
|
+
const auth = await getAuthFromRequest(req);
|
|
29
|
+
if (!auth?.sub || !auth?.tenantId) {
|
|
30
|
+
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
31
|
+
}
|
|
32
|
+
let body;
|
|
33
|
+
try {
|
|
34
|
+
body = bodySchema.parse(await readJsonSafe(req, null));
|
|
35
|
+
} catch (err) {
|
|
36
|
+
return NextResponse.json(
|
|
37
|
+
{ error: err instanceof Error ? err.message : "Invalid request body" },
|
|
38
|
+
{ status: 422 }
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
const container = await createRequestContainer();
|
|
42
|
+
const em = container.resolve("em").fork();
|
|
43
|
+
const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req });
|
|
44
|
+
const organizationId = scope?.selectedId ?? auth.orgId ?? null;
|
|
45
|
+
const dscope = { tenantId: auth.tenantId, organizationId };
|
|
46
|
+
const userId = resolveAuthActorId(auth);
|
|
47
|
+
const guardResult = await validateCrudMutationGuard(container, {
|
|
48
|
+
tenantId: auth.tenantId,
|
|
49
|
+
organizationId,
|
|
50
|
+
userId,
|
|
51
|
+
resourceKind: "customers.interaction",
|
|
52
|
+
resourceId: id,
|
|
53
|
+
operation: "custom",
|
|
54
|
+
requestMethod: req.method,
|
|
55
|
+
requestHeaders: req.headers
|
|
56
|
+
});
|
|
57
|
+
if (guardResult && !guardResult.ok) {
|
|
58
|
+
return NextResponse.json(guardResult.body, { status: guardResult.status });
|
|
59
|
+
}
|
|
60
|
+
const interaction = await findOneWithDecryption(
|
|
61
|
+
em,
|
|
62
|
+
CustomerInteraction,
|
|
63
|
+
{
|
|
64
|
+
id,
|
|
65
|
+
tenantId: auth.tenantId,
|
|
66
|
+
organizationId,
|
|
67
|
+
deletedAt: null,
|
|
68
|
+
interactionType: "email"
|
|
69
|
+
},
|
|
70
|
+
void 0,
|
|
71
|
+
dscope
|
|
72
|
+
);
|
|
73
|
+
if (!interaction) {
|
|
74
|
+
return NextResponse.json({ error: "Email not found" }, { status: 404 });
|
|
75
|
+
}
|
|
76
|
+
const isAuthor = !!interaction.authorUserId && interaction.authorUserId === auth.sub;
|
|
77
|
+
if (!isAuthor) {
|
|
78
|
+
return NextResponse.json({ error: "Email not found" }, { status: 404 });
|
|
79
|
+
}
|
|
80
|
+
if (interaction.visibility === body.visibility) {
|
|
81
|
+
return NextResponse.json({ ok: true, changed: false });
|
|
82
|
+
}
|
|
83
|
+
const previousVisibility = interaction.visibility ?? "private";
|
|
84
|
+
const commandBus = container.resolve("commandBus");
|
|
85
|
+
await commandBus.execute(
|
|
86
|
+
"customers.interactions.update",
|
|
87
|
+
{
|
|
88
|
+
input: { id, visibility: body.visibility },
|
|
89
|
+
ctx: {
|
|
90
|
+
container,
|
|
91
|
+
auth,
|
|
92
|
+
organizationScope: null,
|
|
93
|
+
selectedOrganizationId: organizationId,
|
|
94
|
+
organizationIds: organizationId ? [organizationId] : null
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {
|
|
99
|
+
await runCrudMutationGuardAfterSuccess(container, {
|
|
100
|
+
tenantId: auth.tenantId,
|
|
101
|
+
organizationId,
|
|
102
|
+
userId,
|
|
103
|
+
resourceKind: "customers.interaction",
|
|
104
|
+
resourceId: id,
|
|
105
|
+
operation: "custom",
|
|
106
|
+
requestMethod: req.method,
|
|
107
|
+
requestHeaders: req.headers,
|
|
108
|
+
metadata: guardResult.metadata ?? null
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
await emitCustomersEvent("customers.email.visibility_changed", {
|
|
113
|
+
interactionId: interaction.id,
|
|
114
|
+
previousVisibility,
|
|
115
|
+
nextVisibility: body.visibility,
|
|
116
|
+
authorUserId: interaction.authorUserId ?? null,
|
|
117
|
+
actorUserId: auth.sub,
|
|
118
|
+
// v1: strict owner-only — only the author reaches this point, so a
|
|
119
|
+
// visibility change is never an admin bypass.
|
|
120
|
+
adminBypass: false,
|
|
121
|
+
tenantId: auth.tenantId,
|
|
122
|
+
organizationId
|
|
123
|
+
});
|
|
124
|
+
} catch {
|
|
125
|
+
}
|
|
126
|
+
return NextResponse.json({ ok: true, changed: true });
|
|
127
|
+
}
|
|
128
|
+
const openApi = {
|
|
129
|
+
tags: ["Customers", "Email"],
|
|
130
|
+
methods: {
|
|
131
|
+
PATCH: {
|
|
132
|
+
summary: "Flip an email interaction visibility (private \u2194 shared)",
|
|
133
|
+
tags: ["Customers", "Email"],
|
|
134
|
+
responses: [
|
|
135
|
+
{ status: 200, description: "Updated" },
|
|
136
|
+
{ status: 400, description: "Invalid id" },
|
|
137
|
+
{ status: 401, description: "Unauthorized" },
|
|
138
|
+
{ status: 404, description: "Email not found or not visible to caller" },
|
|
139
|
+
{ status: 422, description: "Invalid body" }
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
var route_default = PATCH;
|
|
145
|
+
export {
|
|
146
|
+
PATCH,
|
|
147
|
+
route_default as default,
|
|
148
|
+
metadata,
|
|
149
|
+
openApi
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/customers/api/interactions/%5Bid%5D/visibility/route.ts"],
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands'\nimport {\n validateCrudMutationGuard,\n runCrudMutationGuardAfterSuccess,\n} from '@open-mercato/shared/lib/crud/mutation-guard'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport { CustomerInteraction } from '../../../../data/entities'\nimport type { InteractionUpdateInput } from '../../../../data/validators'\nimport { resolveAuthActorId } from '../../../../lib/interactionRequestContext'\nimport { emitCustomersEvent } from '../../../../events'\n\nexport const metadata = {\n path: '/customers/interactions/[id]/visibility',\n PATCH: {\n requireAuth: true,\n requireFeatures: ['customers.email.compose'],\n },\n}\n\nconst bodySchema = z.object({ visibility: z.enum(['private', 'shared']) }).strict()\n\ntype RouteContext = { params: Promise<{ id: string }> | { id: string } }\n\nexport async function PATCH(req: Request, context: RouteContext): Promise<Response> {\n const { id } = await context.params\n if (!z.string().uuid().safeParse(id).success) {\n return NextResponse.json({ error: 'Invalid interaction id' }, { status: 400 })\n }\n\n const auth = await getAuthFromRequest(req)\n if (!auth?.sub || !auth?.tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n let body: z.infer<typeof bodySchema>\n try {\n body = bodySchema.parse(await readJsonSafe(req, null))\n } catch (err) {\n return NextResponse.json(\n { error: err instanceof Error ? err.message : 'Invalid request body' },\n { status: 422 },\n )\n }\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager).fork()\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n const organizationId = scope?.selectedId ?? (auth as { orgId?: string | null }).orgId ?? null\n const dscope = { tenantId: auth.tenantId as string, organizationId }\n const userId = resolveAuthActorId(auth)\n\n const guardResult = await validateCrudMutationGuard(container, {\n tenantId: auth.tenantId,\n organizationId,\n userId,\n resourceKind: 'customers.interaction',\n resourceId: id,\n operation: 'custom',\n requestMethod: req.method,\n requestHeaders: req.headers,\n })\n if (guardResult && !guardResult.ok) {\n return NextResponse.json(guardResult.body, { status: guardResult.status })\n }\n\n const interaction = (await findOneWithDecryption(\n em,\n CustomerInteraction,\n {\n id,\n tenantId: auth.tenantId,\n organizationId,\n deletedAt: null,\n interactionType: 'email',\n } as any,\n undefined,\n dscope,\n )) as { id: string; authorUserId?: string | null; visibility?: string | null } | null\n\n if (!interaction) {\n return NextResponse.json({ error: 'Email not found' }, { status: 404 })\n }\n\n // Personal mailbox privacy (v1: strict owner-only): ONLY the author may flip\n // their own email's visibility \u2014 no admin bypass. Return 404 (not 403) for\n // everyone else so we don't leak the row's existence \u2014 this also covers\n // non-authors who cannot see a private email in the first place.\n const isAuthor = !!interaction.authorUserId && interaction.authorUserId === auth.sub\n if (!isAuthor) {\n return NextResponse.json({ error: 'Email not found' }, { status: 404 })\n }\n\n // No-op: visibility is already at the requested value.\n if (interaction.visibility === body.visibility) {\n return NextResponse.json({ ok: true, changed: false })\n }\n\n const previousVisibility = (interaction.visibility ?? 'private') as 'private' | 'shared'\n\n // Route the write through the interactions update command so the change runs\n // the full mutation pipeline \u2014 query-index refresh, audit log and undo \u2014\n // instead of a raw em.flush() that would leave the indexed `entity_indexes`\n // doc stale. Authorization (author-only, v1) was already enforced above; the\n // command only owns persistence and side effects.\n const commandBus = container.resolve('commandBus') as CommandBus\n await commandBus.execute<InteractionUpdateInput, { interactionId: string }>(\n 'customers.interactions.update',\n {\n input: { id, visibility: body.visibility },\n ctx: {\n container,\n auth: auth as never,\n organizationScope: null,\n selectedOrganizationId: organizationId,\n organizationIds: organizationId ? [organizationId] : null,\n },\n },\n )\n\n if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {\n await runCrudMutationGuardAfterSuccess(container, {\n tenantId: auth.tenantId,\n organizationId,\n userId,\n resourceKind: 'customers.interaction',\n resourceId: id,\n operation: 'custom',\n requestMethod: req.method,\n requestHeaders: req.headers,\n metadata: guardResult.metadata ?? null,\n })\n }\n\n // Emit audit event best-effort \u2014 failure must NOT roll back the DB flush.\n try {\n await emitCustomersEvent('customers.email.visibility_changed', {\n interactionId: interaction.id,\n previousVisibility,\n nextVisibility: body.visibility,\n authorUserId: interaction.authorUserId ?? null,\n actorUserId: auth.sub,\n // v1: strict owner-only \u2014 only the author reaches this point, so a\n // visibility change is never an admin bypass.\n adminBypass: false,\n tenantId: auth.tenantId,\n organizationId,\n })\n } catch {\n /* swallow \u2014 audit emission must not block the response */\n }\n\n return NextResponse.json({ ok: true, changed: true })\n}\n\nexport const openApi = {\n tags: ['Customers', 'Email'],\n methods: {\n PATCH: {\n summary: 'Flip an email interaction visibility (private \u2194 shared)',\n tags: ['Customers', 'Email'],\n responses: [\n { status: 200, description: 'Updated' },\n { status: 400, description: 'Invalid id' },\n { status: 401, description: 'Unauthorized' },\n { status: 404, description: 'Email not found or not visible to caller' },\n { status: 422, description: 'Invalid body' },\n ],\n },\n },\n}\n\nexport default PATCH\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -6,6 +6,7 @@ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
|
6
6
|
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
|
|
7
7
|
import { resolveOrganizationScopeForRequest } from "@open-mercato/core/modules/directory/utils/organizationScope";
|
|
8
8
|
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
|
|
9
|
+
import { applyEmailVisibilityFilter } from "../../../lib/visibilityFilter.js";
|
|
9
10
|
const querySchema = z.object({
|
|
10
11
|
entityId: z.string().uuid(),
|
|
11
12
|
status: z.enum(["done", "planned"]).optional()
|
|
@@ -66,6 +67,11 @@ async function GET(req) {
|
|
|
66
67
|
if (query.status) {
|
|
67
68
|
baseQuery = baseQuery.where("status", "=", query.status);
|
|
68
69
|
}
|
|
70
|
+
const viewerUserId = auth.isApiKey ? null : auth.sub ?? null;
|
|
71
|
+
baseQuery = applyEmailVisibilityFilter(baseQuery, {
|
|
72
|
+
currentUserId: viewerUserId,
|
|
73
|
+
userFeatures: void 0
|
|
74
|
+
});
|
|
69
75
|
const rows = await baseQuery.select(["interaction_type", sql`count(*)`.as("count")]).groupBy("interaction_type").execute();
|
|
70
76
|
const counts = { call: 0, email: 0, meeting: 0, note: 0, task: 0 };
|
|
71
77
|
let total = 0;
|