@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/backend/customers/people-v2/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { User, Hash, Users, Building2 } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { CollapsibleZoneLayout, type ZoneSectionDescriptor } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, RecordNotFoundState, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\nimport { ActivitiesCard } from '../../../../components/detail/ActivitiesCard'\nimport type { ActivityKind } from '../../../../components/detail/ActivitiesAddNewMenu'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { TasksSection } from '../../../../components/detail/TasksSection'\nimport type { TagSummary } from '../../../../components/detail/types'\nimport { ScheduleActivityDialog, type ScheduleActivityEditData } from '../../../../components/detail/ScheduleActivityDialog'\nimport { PersonDetailHeader } from '../../../../components/detail/PersonDetailHeader'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { PersonDetailTabs, resolveLegacyTab, type PersonTabId } from '../../../../components/detail/PersonDetailTabs'\nimport { PersonCompaniesSection } from '../../../../components/detail/PersonCompaniesSection'\nimport { MobilePersonDetail } from '../../../../components/detail/MobilePersonDetail'\nimport type { TagsSectionController } from '@open-mercato/ui/backend/detail'\nimport {\n buildPersonEditPayload,\n createPersonEditFields,\n createPersonPersonalDataGroups,\n createPersonEditSchema,\n mapPersonOverviewToFormValues,\n type PersonEditFormValues,\n type PersonOverview,\n} from '../../../../components/formConfig'\nimport { coerceDisplayName, coerceDisplayNameOrNull } from '../../../../lib/displayName'\n\nexport default function PersonDetailV2Page({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { organizationId } = useOrganizationScopeDetail()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n\n\n const formSchema = React.useMemo(() => createPersonEditSchema(), [])\n const fields = React.useMemo(() => createPersonEditFields(t), [t])\n\n const [data, setData] = React.useState<PersonOverview | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n\n // Form state lifted for header Save button\n const [isDirty, setIsDirty] = React.useState(false)\n const [isSaving, setIsSaving] = React.useState(false)\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n\n const initialTab = React.useMemo(() => {\n return resolveLegacyTab(searchParams?.get('tab'))\n }, [searchParams])\n const [activeTab, setActiveTab] = React.useState<PersonTabId>(initialTab)\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n const [scheduleDialogOpen, setScheduleDialogOpen] = React.useState(false)\n const [scheduleEditData, setScheduleEditData] = React.useState<ScheduleActivityEditData | null>(null)\n const [activityRefreshKey, setActivityRefreshKey] = React.useState(0)\n const [dealCount, setDealCount] = React.useState(0)\n\n const currentPersonId = data?.person?.id ?? null\n const mutationContextId = React.useMemo(\n () => (currentPersonId ? `customer-person:${currentPersonId}` : `customer-person:${id ?? 'pending'}`),\n [currentPersonId, id],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n personId?: string | null\n resourceKind: string\n resourceId?: string\n data: PersonOverview | null\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const personDisplayName = coerceDisplayName(data?.person?.displayName)\n const personName = personDisplayName.trim().length\n ? personDisplayName\n : t('customers.people.list.deleteFallbackName', 'this person')\n\n const personDisplayNameForGroups = personDisplayName.trim().length\n ? personDisplayName.trim()\n : null\n\n const scheduleDialogCompanyName = coerceDisplayNameOrNull(\n data?.company?.displayName ?? data?.companies?.[0]?.displayName ?? null,\n )\n\n const groups = React.useMemo(\n () => createPersonPersonalDataGroups(t, { entityName: personDisplayNameForGroups }),\n [t, personDisplayNameForGroups],\n )\n\n const zoneSections = React.useMemo<ZoneSectionDescriptor[]>(() => [\n { id: 'personalData', icon: User, label: t('customers.people.form.groups.personalData', 'Personal data') },\n { id: 'companyRole', icon: Building2, label: t('customers.people.form.groups.companyRole', 'Company & role') },\n { id: 'customFields', icon: Hash, label: t('customers.people.form.groups.customAttributes', 'Custom attributes') },\n { id: 'roles', icon: Users, label: t('customers.people.form.groups.roles', 'My roles') },\n ], [t])\n\n // Data loading\n const initialLoadDoneRef = React.useRef(false)\n const loadData = React.useCallback(async () => {\n if (!id) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n setIsNotFound(false)\n try {\n const payload = await readApiResultOrThrow<PersonOverview>(\n `/api/customers/people/${encodeURIComponent(id)}`,\n undefined,\n { errorMessage: t('customers.people.detail.error.load', 'Failed to load person.') },\n )\n setData(payload as PersonOverview)\n } catch (err) {\n if ((err as { status?: number }).status === 404) {\n setIsNotFound(true)\n } else {\n const message = err instanceof Error ? err.message : t('customers.people.detail.error.load', 'Failed to load person.')\n setError(message)\n }\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch((err) => console.warn('[people-v2] loadData failed', err))\n }, [loadData])\n\n React.useEffect(() => {\n setDealCount(data?.counts?.deals ?? 0)\n }, [data?.counts?.deals])\n\n const handleActivityCreated = React.useCallback(() => {\n setActivityRefreshKey((k) => k + 1)\n loadData().catch((err) => console.warn('[people-v2] reload after activity failed', err))\n }, [loadData])\n\n const plannedActivities = React.useMemo(() => {\n return data?.plannedActivitiesPreview ?? []\n }, [data?.plannedActivitiesPreview])\n\n // Injection context for UMES\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n personId: currentPersonId,\n resourceKind: 'customers.person',\n resourceId: currentPersonId ?? (id ?? undefined),\n data,\n retryLastMutation,\n }),\n [currentPersonId, data, id, mutationContextId, retryLastMutation],\n )\n const runMutationWithContext = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: injectionContext,\n })\n },\n [injectionContext, runMutation],\n )\n\n const handleAddActivity = React.useCallback((kind: ActivityKind) => {\n setScheduleEditData({\n id: '',\n interactionType: kind,\n title: null,\n body: null,\n scheduledAt: null,\n durationMinutes: null,\n location: null,\n allDay: null,\n recurrenceRule: null,\n recurrenceEnd: null,\n participants: null,\n reminderMinutes: null,\n visibility: null,\n linkedEntities: null,\n guestPermissions: null,\n })\n setScheduleDialogOpen(true)\n }, [])\n\n const handleEditActivity = React.useCallback((activity: { id: string; interactionType?: string; title?: string | null; body?: string | null; scheduledAt?: string | null; occurredAt?: string | null; [key: string]: unknown }) => {\n const raw = activity as Record<string, unknown>\n const durationValue = typeof raw.duration === 'number'\n ? raw.duration\n : typeof raw.durationMinutes === 'number'\n ? raw.durationMinutes as number\n : null\n // Forward `customValues` so per-type chip state (callPhoneNumber, callDirection,\n // taskPriority, \u2026) round-trips on edit (#1808 phone persistence).\n // Forward `occurredAt` so historical activity edits prefill from the original\n // moment instead of \"today\" (#1807 prefill).\n const editPayload = {\n id: activity.id,\n interactionType: typeof activity.interactionType === 'string' ? activity.interactionType : undefined,\n title: typeof activity.title === 'string' ? activity.title : null,\n body: typeof activity.body === 'string' ? activity.body : null,\n scheduledAt: typeof activity.scheduledAt === 'string' ? activity.scheduledAt : null,\n occurredAt: typeof activity.occurredAt === 'string' ? activity.occurredAt : null,\n durationMinutes: durationValue,\n location: typeof raw.location === 'string' ? raw.location as string : null,\n allDay: typeof raw.allDay === 'boolean' ? raw.allDay as boolean : null,\n recurrenceRule: typeof raw.recurrenceRule === 'string' ? raw.recurrenceRule as string : null,\n recurrenceEnd: typeof raw.recurrenceEnd === 'string' ? raw.recurrenceEnd as string : null,\n participants: Array.isArray(raw.participants) ? raw.participants as ScheduleActivityEditData['participants'] : null,\n reminderMinutes: typeof raw.reminderMinutes === 'number' ? raw.reminderMinutes as number : null,\n visibility: typeof raw.visibility === 'string' ? raw.visibility as string : null,\n linkedEntities: Array.isArray(raw.linkedEntities) ? raw.linkedEntities as ScheduleActivityEditData['linkedEntities'] : null,\n guestPermissions: raw.guestPermissions && typeof raw.guestPermissions === 'object'\n ? raw.guestPermissions as ScheduleActivityEditData['guestPermissions']\n : null,\n customValues: raw.customValues && typeof raw.customValues === 'object'\n ? raw.customValues as Record<string, unknown>\n : null,\n phoneNumber: typeof raw.phoneNumber === 'string' ? raw.phoneNumber as string : null,\n } as ScheduleActivityEditData & { customValues?: Record<string, unknown> | null; phoneNumber?: string | null }\n setScheduleEditData(editPayload)\n setScheduleDialogOpen(true)\n }, [])\n\n // Injected tabs from UMES\n const { widgets: injectedTabWidgets } = useInjectionWidgets('detail:customers.person:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const tabId = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel ?? widget.module.metadata.title ?? tabId\n const priority = typeof widget.placement?.priority === 'number' ? widget.placement.priority : 0\n const render = () => (\n <widget.module.Widget\n context={injectionContext}\n data={data}\n onDataChange={(next: unknown) => setData(next as PersonOverview)}\n />\n )\n return { id: tabId, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext],\n )\n\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n // Tags\n const handleTagsChange = React.useCallback((nextTags: TagSummary[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n const tagsSectionControllerRef = React.useRef<TagsSectionController | null>(null)\n\n // Section action (for tabs that expose add/create buttons)\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction((prev) => (action !== null ? action : prev))\n }, [])\n\n React.useEffect(() => {\n setSectionAction(null)\n }, [activeTab])\n\n // Deals scope\n const dealsScope = React.useMemo(\n () => (currentPersonId ? ({ kind: 'person', entityId: currentPersonId } as const) : null),\n [currentPersonId],\n )\n\n const initialValues = React.useMemo(\n () => (data ? mapPersonOverviewToFormValues(data) : undefined),\n [data],\n )\n\n // Form submit/delete\n const handleFormSubmit = React.useCallback(\n async (values: PersonEditFormValues) => {\n setIsSaving(true)\n try {\n await tagsSectionControllerRef.current?.flush()\n\n let payload: Record<string, unknown>\n try {\n payload = buildPersonEditPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error && err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.people.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n throw err\n }\n\n await updateCrud('customers/people', payload)\n flash(t('customers.people.form.updateSuccess', 'Person updated.'), 'success')\n await loadData()\n } finally {\n setIsSaving(false)\n }\n },\n [loadData, organizationId, t],\n )\n\n const handleFormDelete = React.useCallback(\n async () => {\n const personId = data?.person?.id ?? ''\n if (!personId) return\n const approved = await confirm({\n title: t('customers.people.detail.deleteConfirmTitle', 'Delete person?'),\n description: t('customers.people.detail.deleteConfirmDescription', 'This action cannot be undone.'),\n confirmText: t('customers.people.detail.actions.delete', 'Delete'),\n cancelText: t('customers.people.detail.actions.cancel', 'Cancel'),\n variant: 'destructive',\n })\n if (!approved) return\n await runMutationWithContext(\n () => deleteCrud('customers/people', { id: personId }),\n { id: personId, operation: 'deletePerson' },\n )\n flash(t('customers.people.list.deleteSuccess', 'Person deleted.'), 'success')\n router.push('/backend/customers/people')\n },\n [confirm, data?.person?.id, router, runMutationWithContext, t],\n )\n\n const handleHeaderSave = React.useCallback(() => {\n const form = formWrapperRef.current?.querySelector('form')\n if (form) form.requestSubmit()\n }, [])\n\n // Counts for tab badges\n const interactionCount = data?.counts?.activities ?? 0\n const todoCount = data?.counts?.todos ?? 0\n const companyCount = data?.counts?.companies ?? (data?.companies?.length ?? (data?.company ? 1 : 0))\n\n // Loading / error states\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.people.detail.loading', 'Loading person\u2026')} />\n </PageBody>\n </Page>\n )\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('customers.people.detail.error.notFound', 'Person not found.')}\n backHref=\"/backend/customers/people\"\n backLabel={t('customers.people.detail.actions.backToList', 'Back to people')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data?.person?.id || !initialValues) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error ?? t('customers.people.detail.error.load', 'Failed to load person.')}\n action={(\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/customers/people\">\n {t('customers.people.detail.actions.backToList', 'Back to people')}\n </Link>\n </Button>\n )}\n />\n </PageBody>\n </Page>\n )\n }\n\n const personId = data.person.id\n const useCanonicalInteractions = data.interactionMode === 'canonical'\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n {/* UMES header injection */}\n <InjectionSpot spotId=\"detail:customers.person:header\" context={injectionContext} data={data} />\n <InjectionSpot spotId=\"detail:customers.person:status-badges\" context={injectionContext} data={data} />\n\n {/* Persistent person header */}\n <PersonDetailHeader\n data={data}\n onTagsChange={handleTagsChange}\n tagsSectionControllerRef={tagsSectionControllerRef}\n onSave={handleHeaderSave}\n onDelete={handleFormDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n onOpenCompaniesTab={() => setActiveTab('companies')}\n onDataReload={() => { loadData().catch((err) => console.warn('[people-v2] onDataReload failed', err)) }}\n onFocusField={(fieldName) => {\n const selectorMap: Record<string, string> = {\n primaryEmail: 'input[type=\"email\"]',\n primaryPhone: 'input[type=\"tel\"]',\n }\n const selector = selectorMap[fieldName]\n const input = selector ? formWrapperRef.current?.querySelector<HTMLInputElement>(selector) : null\n if (input) {\n input.scrollIntoView({ behavior: 'smooth', block: 'center' })\n requestAnimationFrame(() => input.focus())\n }\n }}\n />\n\n {/* Zone content shared between desktop (CollapsibleZoneLayout) and mobile (MobilePersonDetail). */}\n {(() => {\n const zone1Content = (\n <div ref={formWrapperRef}>\n <CrudForm<PersonEditFormValues>\n embedded\n trackDirtyWhenEmbedded\n injectionSpotId=\"customers.person\"\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n schema={formSchema}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n onSubmit={handleFormSubmit}\n onDelete={handleFormDelete}\n hideFooterActions\n collapsibleGroups={{ pageType: 'person-v2', chevronPosition: 'right' }}\n sortableGroups={{ pageType: 'person-v2' }}\n onDirtyChange={setIsDirty}\n />\n </div>\n )\n const zone2Content = (\n <PersonDetailTabs\n activeTab={activeTab}\n onTabChange={setActiveTab}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n activitiesCount={interactionCount}\n dealsCount={dealCount}\n companiesCount={companyCount}\n tasksCount={todoCount}\n sectionAction={sectionAction}\n >\n <div className=\"min-w-0\">\n {(() => {\n // Injected tab content\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\n\n if (activeTab === 'activities') {\n return (\n <div className=\"space-y-4\">\n <ActivitiesCard\n entityId={personId}\n plannedActivities={plannedActivities}\n refreshKey={activityRefreshKey}\n onAddNew={handleAddActivity}\n onEditActivity={handleEditActivity}\n entityCompanyName={data.company?.displayName ?? data.companies?.[0]?.displayName ?? null}\n />\n <ActivitiesSection\n entityId={personId}\n entityName={personName}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={handleActivityCreated}\n refreshKey={activityRefreshKey}\n addActionLabel={t('customers.people.detail.activities.add', 'Log activity')}\n emptyState={{\n title: t('customers.people.detail.emptyState.activities.title', 'No activities logged yet'),\n actionLabel: t('customers.people.detail.emptyState.activities.action', 'Log activity'),\n }}\n onActionChange={handleSectionActionChange}\n onEditActivity={handleEditActivity}\n />\n </div>\n )\n }\n\n if (activeTab === 'deals') {\n return (\n <DealsSection\n scope={dealsScope}\n emptyLabel={t('customers.people.detail.empty.deals', 'No deals linked to this person.')}\n addActionLabel={t('customers.people.detail.actions.addDeal', 'Add deal')}\n emptyState={{\n title: t('customers.people.detail.emptyState.deals.title', 'No deals yet'),\n actionLabel: t('customers.people.detail.emptyState.deals.action', 'Create a deal'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n onCountDelta={(delta) => setDealCount((current) => Math.max(0, current + delta))}\n />\n )\n }\n\n if (activeTab === 'companies') {\n return (\n <PersonCompaniesSection\n personId={personId}\n personName={personName}\n initialLinkedCompanies={data?.companies ?? []}\n onChanged={loadData}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n\n if (activeTab === 'tasks') {\n return (\n <TasksSection\n entityId={personId}\n initialTasks={[]}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={loadData}\n emptyLabel={t('customers.people.detail.empty.todos', 'No tasks linked to this person.')}\n addActionLabel={t('customers.people.detail.tasks.add', 'Add task')}\n emptyState={{\n title: t('customers.people.detail.emptyState.tasks.title', 'Plan what happens next'),\n actionLabel: t('customers.people.detail.emptyState.tasks.action', 'Create task'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n entityName={personName}\n dialogContextKey=\"customers.people.detail.tasks.dialog.context\"\n dialogContextFallback=\"This task will be linked to {{name}}\"\n />\n )\n }\n\n if (activeTab === 'files') {\n return (\n <AttachmentsSection\n entityId={E.customers.customer_entity}\n recordId={personId}\n title={t('customers.people.detail.tabs.files', 'Files')}\n description={t('customers.people.detail.files.subtitle', 'Upload and manage files linked to this person.')}\n />\n )\n }\n\n if (activeTab === 'changelog') {\n return <ChangelogTab entityId={personId} entityType=\"person\" />\n }\n\n return null\n })()}\n </div>\n </PersonDetailTabs>\n )\n return (\n <>\n <div className=\"md:hidden\">\n <MobilePersonDetail zone1={zone1Content} zone2={zone2Content} />\n </div>\n <div className=\"hidden md:block\">\n <CollapsibleZoneLayout\n pageType=\"person-v2\"\n entityName={personName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1={zone1Content}\n zone2={zone2Content}\n />\n </div>\n </>\n )\n })()}\n\n {/* UMES footer injection */}\n <InjectionSpot spotId=\"detail:customers.person:footer\" context={injectionContext} data={data} />\n\n {/* Schedule Activity Dialog \u2014 opened from PlannedActivities \"+ Schedule\" or other triggers */}\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={() => { setScheduleDialogOpen(false); setScheduleEditData(null) }}\n entityId={personId}\n entityName={personName}\n companyName={scheduleDialogCompanyName}\n entityType=\"person\"\n onActivityCreated={handleActivityCreated}\n editData={scheduleEditData}\n />\n {ConfirmDialogElement}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { User, Hash, Users, Building2 } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { CollapsibleZoneLayout, type ZoneSectionDescriptor } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, RecordNotFoundState, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\nimport { PersonEmailThreadsTab } from '../../../../components/detail/PersonEmailThreadsTab'\nimport { ActivitiesCard } from '../../../../components/detail/ActivitiesCard'\nimport type { ActivityKind } from '../../../../components/detail/ActivitiesAddNewMenu'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { TasksSection } from '../../../../components/detail/TasksSection'\nimport type { TagSummary } from '../../../../components/detail/types'\nimport { ScheduleActivityDialog, type ScheduleActivityEditData } from '../../../../components/detail/ScheduleActivityDialog'\nimport { PersonDetailHeader } from '../../../../components/detail/PersonDetailHeader'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { PersonDetailTabs, resolveLegacyTab, type PersonTabId } from '../../../../components/detail/PersonDetailTabs'\nimport { PersonCompaniesSection } from '../../../../components/detail/PersonCompaniesSection'\nimport { MobilePersonDetail } from '../../../../components/detail/MobilePersonDetail'\nimport type { TagsSectionController } from '@open-mercato/ui/backend/detail'\nimport {\n buildPersonEditPayload,\n createPersonEditFields,\n createPersonPersonalDataGroups,\n createPersonEditSchema,\n mapPersonOverviewToFormValues,\n type PersonEditFormValues,\n type PersonOverview,\n} from '../../../../components/formConfig'\nimport { coerceDisplayName, coerceDisplayNameOrNull } from '../../../../lib/displayName'\n\nexport default function PersonDetailV2Page({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const { organizationId } = useOrganizationScopeDetail()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n\n\n const formSchema = React.useMemo(() => createPersonEditSchema(), [])\n const fields = React.useMemo(() => createPersonEditFields(t), [t])\n\n const [data, setData] = React.useState<PersonOverview | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n\n // Form state lifted for header Save button\n const [isDirty, setIsDirty] = React.useState(false)\n const [isSaving, setIsSaving] = React.useState(false)\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n\n const initialTab = React.useMemo(() => {\n return resolveLegacyTab(searchParams?.get('tab'))\n }, [searchParams])\n const [activeTab, setActiveTab] = React.useState<PersonTabId>(initialTab)\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n const [scheduleDialogOpen, setScheduleDialogOpen] = React.useState(false)\n const [scheduleEditData, setScheduleEditData] = React.useState<ScheduleActivityEditData | null>(null)\n const [activityRefreshKey, setActivityRefreshKey] = React.useState(0)\n const [dealCount, setDealCount] = React.useState(0)\n\n const currentPersonId = data?.person?.id ?? null\n const mutationContextId = React.useMemo(\n () => (currentPersonId ? `customer-person:${currentPersonId}` : `customer-person:${id ?? 'pending'}`),\n [currentPersonId, id],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n personId?: string | null\n resourceKind: string\n resourceId?: string\n data: PersonOverview | null\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const personDisplayName = coerceDisplayName(data?.person?.displayName)\n const personName = personDisplayName.trim().length\n ? personDisplayName\n : t('customers.people.list.deleteFallbackName', 'this person')\n\n const personDisplayNameForGroups = personDisplayName.trim().length\n ? personDisplayName.trim()\n : null\n\n const scheduleDialogCompanyName = coerceDisplayNameOrNull(\n data?.company?.displayName ?? data?.companies?.[0]?.displayName ?? null,\n )\n\n const groups = React.useMemo(\n () => createPersonPersonalDataGroups(t, { entityName: personDisplayNameForGroups }),\n [t, personDisplayNameForGroups],\n )\n\n const zoneSections = React.useMemo<ZoneSectionDescriptor[]>(() => [\n { id: 'personalData', icon: User, label: t('customers.people.form.groups.personalData', 'Personal data') },\n { id: 'companyRole', icon: Building2, label: t('customers.people.form.groups.companyRole', 'Company & role') },\n { id: 'customFields', icon: Hash, label: t('customers.people.form.groups.customAttributes', 'Custom attributes') },\n { id: 'roles', icon: Users, label: t('customers.people.form.groups.roles', 'My roles') },\n ], [t])\n\n // Data loading\n const initialLoadDoneRef = React.useRef(false)\n const loadData = React.useCallback(async () => {\n if (!id) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n setIsNotFound(false)\n try {\n const payload = await readApiResultOrThrow<PersonOverview>(\n `/api/customers/people/${encodeURIComponent(id)}`,\n undefined,\n { errorMessage: t('customers.people.detail.error.load', 'Failed to load person.') },\n )\n setData(payload as PersonOverview)\n } catch (err) {\n if ((err as { status?: number }).status === 404) {\n setIsNotFound(true)\n } else {\n const message = err instanceof Error ? err.message : t('customers.people.detail.error.load', 'Failed to load person.')\n setError(message)\n }\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch((err) => console.warn('[people-v2] loadData failed', err))\n }, [loadData])\n\n React.useEffect(() => {\n setDealCount(data?.counts?.deals ?? 0)\n }, [data?.counts?.deals])\n\n const handleActivityCreated = React.useCallback(() => {\n setActivityRefreshKey((k) => k + 1)\n loadData().catch((err) => console.warn('[people-v2] reload after activity failed', err))\n }, [loadData])\n\n const plannedActivities = React.useMemo(() => {\n return data?.plannedActivitiesPreview ?? []\n }, [data?.plannedActivitiesPreview])\n\n // Injection context for UMES\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n personId: currentPersonId,\n resourceKind: 'customers.person',\n resourceId: currentPersonId ?? (id ?? undefined),\n data,\n retryLastMutation,\n }),\n [currentPersonId, data, id, mutationContextId, retryLastMutation],\n )\n const runMutationWithContext = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: injectionContext,\n })\n },\n [injectionContext, runMutation],\n )\n\n const handleAddActivity = React.useCallback((kind: ActivityKind) => {\n setScheduleEditData({\n id: '',\n interactionType: kind,\n title: null,\n body: null,\n scheduledAt: null,\n durationMinutes: null,\n location: null,\n allDay: null,\n recurrenceRule: null,\n recurrenceEnd: null,\n participants: null,\n reminderMinutes: null,\n visibility: null,\n linkedEntities: null,\n guestPermissions: null,\n })\n setScheduleDialogOpen(true)\n }, [])\n\n const handleEditActivity = React.useCallback((activity: { id: string; interactionType?: string; title?: string | null; body?: string | null; scheduledAt?: string | null; occurredAt?: string | null; [key: string]: unknown }) => {\n const raw = activity as Record<string, unknown>\n const durationValue = typeof raw.duration === 'number'\n ? raw.duration\n : typeof raw.durationMinutes === 'number'\n ? raw.durationMinutes as number\n : null\n // Forward `customValues` so per-type chip state (callPhoneNumber, callDirection,\n // taskPriority, \u2026) round-trips on edit (#1808 phone persistence).\n // Forward `occurredAt` so historical activity edits prefill from the original\n // moment instead of \"today\" (#1807 prefill).\n const editPayload = {\n id: activity.id,\n interactionType: typeof activity.interactionType === 'string' ? activity.interactionType : undefined,\n title: typeof activity.title === 'string' ? activity.title : null,\n body: typeof activity.body === 'string' ? activity.body : null,\n scheduledAt: typeof activity.scheduledAt === 'string' ? activity.scheduledAt : null,\n occurredAt: typeof activity.occurredAt === 'string' ? activity.occurredAt : null,\n durationMinutes: durationValue,\n location: typeof raw.location === 'string' ? raw.location as string : null,\n allDay: typeof raw.allDay === 'boolean' ? raw.allDay as boolean : null,\n recurrenceRule: typeof raw.recurrenceRule === 'string' ? raw.recurrenceRule as string : null,\n recurrenceEnd: typeof raw.recurrenceEnd === 'string' ? raw.recurrenceEnd as string : null,\n participants: Array.isArray(raw.participants) ? raw.participants as ScheduleActivityEditData['participants'] : null,\n reminderMinutes: typeof raw.reminderMinutes === 'number' ? raw.reminderMinutes as number : null,\n visibility: typeof raw.visibility === 'string' ? raw.visibility as string : null,\n linkedEntities: Array.isArray(raw.linkedEntities) ? raw.linkedEntities as ScheduleActivityEditData['linkedEntities'] : null,\n guestPermissions: raw.guestPermissions && typeof raw.guestPermissions === 'object'\n ? raw.guestPermissions as ScheduleActivityEditData['guestPermissions']\n : null,\n customValues: raw.customValues && typeof raw.customValues === 'object'\n ? raw.customValues as Record<string, unknown>\n : null,\n phoneNumber: typeof raw.phoneNumber === 'string' ? raw.phoneNumber as string : null,\n } as ScheduleActivityEditData & { customValues?: Record<string, unknown> | null; phoneNumber?: string | null }\n setScheduleEditData(editPayload)\n setScheduleDialogOpen(true)\n }, [])\n\n // Injected tabs from UMES\n const { widgets: injectedTabWidgets } = useInjectionWidgets('detail:customers.person:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const tabId = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel ?? widget.module.metadata.title ?? tabId\n const priority = typeof widget.placement?.priority === 'number' ? widget.placement.priority : 0\n const render = () => (\n <widget.module.Widget\n context={injectionContext}\n data={data}\n onDataChange={(next: unknown) => setData(next as PersonOverview)}\n />\n )\n return { id: tabId, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext],\n )\n\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n // Tags\n const handleTagsChange = React.useCallback((nextTags: TagSummary[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n const tagsSectionControllerRef = React.useRef<TagsSectionController | null>(null)\n\n // Section action (for tabs that expose add/create buttons)\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction((prev) => (action !== null ? action : prev))\n }, [])\n\n React.useEffect(() => {\n setSectionAction(null)\n }, [activeTab])\n\n // Deals scope\n const dealsScope = React.useMemo(\n () => (currentPersonId ? ({ kind: 'person', entityId: currentPersonId } as const) : null),\n [currentPersonId],\n )\n\n const initialValues = React.useMemo(\n () => (data ? mapPersonOverviewToFormValues(data) : undefined),\n [data],\n )\n\n // Form submit/delete\n const handleFormSubmit = React.useCallback(\n async (values: PersonEditFormValues) => {\n setIsSaving(true)\n try {\n await tagsSectionControllerRef.current?.flush()\n\n let payload: Record<string, unknown>\n try {\n payload = buildPersonEditPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error && err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.people.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n throw err\n }\n\n await updateCrud('customers/people', payload)\n flash(t('customers.people.form.updateSuccess', 'Person updated.'), 'success')\n await loadData()\n } finally {\n setIsSaving(false)\n }\n },\n [loadData, organizationId, t],\n )\n\n const handleFormDelete = React.useCallback(\n async () => {\n const personId = data?.person?.id ?? ''\n if (!personId) return\n const approved = await confirm({\n title: t('customers.people.detail.deleteConfirmTitle', 'Delete person?'),\n description: t('customers.people.detail.deleteConfirmDescription', 'This action cannot be undone.'),\n confirmText: t('customers.people.detail.actions.delete', 'Delete'),\n cancelText: t('customers.people.detail.actions.cancel', 'Cancel'),\n variant: 'destructive',\n })\n if (!approved) return\n await runMutationWithContext(\n () => deleteCrud('customers/people', { id: personId }),\n { id: personId, operation: 'deletePerson' },\n )\n flash(t('customers.people.list.deleteSuccess', 'Person deleted.'), 'success')\n router.push('/backend/customers/people')\n },\n [confirm, data?.person?.id, router, runMutationWithContext, t],\n )\n\n const handleHeaderSave = React.useCallback(() => {\n const form = formWrapperRef.current?.querySelector('form')\n if (form) form.requestSubmit()\n }, [])\n\n // Counts for tab badges\n const interactionCount = data?.counts?.activities ?? 0\n const todoCount = data?.counts?.todos ?? 0\n const companyCount = data?.counts?.companies ?? (data?.companies?.length ?? (data?.company ? 1 : 0))\n\n // Loading / error states\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.people.detail.loading', 'Loading person\u2026')} />\n </PageBody>\n </Page>\n )\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('customers.people.detail.error.notFound', 'Person not found.')}\n backHref=\"/backend/customers/people\"\n backLabel={t('customers.people.detail.actions.backToList', 'Back to people')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data?.person?.id || !initialValues) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error ?? t('customers.people.detail.error.load', 'Failed to load person.')}\n action={(\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/customers/people\">\n {t('customers.people.detail.actions.backToList', 'Back to people')}\n </Link>\n </Button>\n )}\n />\n </PageBody>\n </Page>\n )\n }\n\n const personId = data.person.id\n const useCanonicalInteractions = data.interactionMode === 'canonical'\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n {/* UMES header injection (third-party extensions) */}\n <InjectionSpot spotId=\"detail:customers.person:header\" context={injectionContext} data={data} />\n <InjectionSpot spotId=\"detail:customers.person:status-badges\" context={injectionContext} data={data} />\n\n {/* Persistent person header */}\n <PersonDetailHeader\n data={data}\n onTagsChange={handleTagsChange}\n tagsSectionControllerRef={tagsSectionControllerRef}\n onSave={handleHeaderSave}\n onDelete={handleFormDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n onOpenCompaniesTab={() => setActiveTab('companies')}\n onDataReload={() => { loadData().catch((err) => console.warn('[people-v2] onDataReload failed', err)) }}\n onFocusField={(fieldName) => {\n const selectorMap: Record<string, string> = {\n primaryEmail: 'input[type=\"email\"]',\n primaryPhone: 'input[type=\"tel\"]',\n }\n const selector = selectorMap[fieldName]\n const input = selector ? formWrapperRef.current?.querySelector<HTMLInputElement>(selector) : null\n if (input) {\n input.scrollIntoView({ behavior: 'smooth', block: 'center' })\n requestAnimationFrame(() => input.focus())\n }\n }}\n />\n\n {/* Zone content shared between desktop (CollapsibleZoneLayout) and mobile (MobilePersonDetail). */}\n {(() => {\n const zone1Content = (\n <div ref={formWrapperRef}>\n <CrudForm<PersonEditFormValues>\n embedded\n trackDirtyWhenEmbedded\n injectionSpotId=\"customers.person\"\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n schema={formSchema}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n onSubmit={handleFormSubmit}\n onDelete={handleFormDelete}\n hideFooterActions\n collapsibleGroups={{ pageType: 'person-v2', chevronPosition: 'right' }}\n sortableGroups={{ pageType: 'person-v2' }}\n onDirtyChange={setIsDirty}\n />\n </div>\n )\n const zone2Content = (\n <PersonDetailTabs\n activeTab={activeTab}\n onTabChange={setActiveTab}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n activitiesCount={interactionCount}\n dealsCount={dealCount}\n companiesCount={companyCount}\n tasksCount={todoCount}\n sectionAction={sectionAction}\n >\n <div className=\"min-w-0\">\n {(() => {\n // Injected tab content\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\n\n if (activeTab === 'activities') {\n return (\n <div className=\"space-y-4\">\n <ActivitiesCard\n entityId={personId}\n plannedActivities={plannedActivities}\n refreshKey={activityRefreshKey}\n onAddNew={handleAddActivity}\n onEditActivity={handleEditActivity}\n entityCompanyName={data.company?.displayName ?? data.companies?.[0]?.displayName ?? null}\n />\n <ActivitiesSection\n entityId={personId}\n entityName={personName}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={handleActivityCreated}\n refreshKey={activityRefreshKey}\n addActionLabel={t('customers.people.detail.activities.add', 'Log activity')}\n emptyState={{\n title: t('customers.people.detail.emptyState.activities.title', 'No activities logged yet'),\n actionLabel: t('customers.people.detail.emptyState.activities.action', 'Log activity'),\n }}\n onActionChange={handleSectionActionChange}\n onEditActivity={handleEditActivity}\n />\n </div>\n )\n }\n\n if (activeTab === 'emails') {\n return (\n <PersonEmailThreadsTab\n personId={personId}\n defaultRecipient={data.person?.primaryEmail ?? null}\n />\n )\n }\n\n if (activeTab === 'deals') {\n return (\n <DealsSection\n scope={dealsScope}\n emptyLabel={t('customers.people.detail.empty.deals', 'No deals linked to this person.')}\n addActionLabel={t('customers.people.detail.actions.addDeal', 'Add deal')}\n emptyState={{\n title: t('customers.people.detail.emptyState.deals.title', 'No deals yet'),\n actionLabel: t('customers.people.detail.emptyState.deals.action', 'Create a deal'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n onCountDelta={(delta) => setDealCount((current) => Math.max(0, current + delta))}\n />\n )\n }\n\n if (activeTab === 'companies') {\n return (\n <PersonCompaniesSection\n personId={personId}\n personName={personName}\n initialLinkedCompanies={data?.companies ?? []}\n onChanged={loadData}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n\n if (activeTab === 'tasks') {\n return (\n <TasksSection\n entityId={personId}\n initialTasks={[]}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={loadData}\n emptyLabel={t('customers.people.detail.empty.todos', 'No tasks linked to this person.')}\n addActionLabel={t('customers.people.detail.tasks.add', 'Add task')}\n emptyState={{\n title: t('customers.people.detail.emptyState.tasks.title', 'Plan what happens next'),\n actionLabel: t('customers.people.detail.emptyState.tasks.action', 'Create task'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n entityName={personName}\n dialogContextKey=\"customers.people.detail.tasks.dialog.context\"\n dialogContextFallback=\"This task will be linked to {{name}}\"\n />\n )\n }\n\n if (activeTab === 'files') {\n return (\n <AttachmentsSection\n entityId={E.customers.customer_entity}\n recordId={personId}\n title={t('customers.people.detail.tabs.files', 'Files')}\n description={t('customers.people.detail.files.subtitle', 'Upload and manage files linked to this person.')}\n />\n )\n }\n\n if (activeTab === 'changelog') {\n return <ChangelogTab entityId={personId} entityType=\"person\" />\n }\n\n return null\n })()}\n </div>\n </PersonDetailTabs>\n )\n return (\n <>\n <div className=\"md:hidden\">\n <MobilePersonDetail zone1={zone1Content} zone2={zone2Content} />\n </div>\n <div className=\"hidden md:block\">\n <CollapsibleZoneLayout\n pageType=\"person-v2\"\n entityName={personName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1={zone1Content}\n zone2={zone2Content}\n />\n </div>\n </>\n )\n })()}\n\n {/* UMES footer injection */}\n <InjectionSpot spotId=\"detail:customers.person:footer\" context={injectionContext} data={data} />\n\n {/* Schedule Activity Dialog \u2014 opened from PlannedActivities \"+ Schedule\" or other triggers */}\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={() => { setScheduleDialogOpen(false); setScheduleEditData(null) }}\n entityId={personId}\n entityName={personName}\n companyName={scheduleDialogCompanyName}\n entityType=\"person\"\n onActivityCreated={handleActivityCreated}\n editData={scheduleEditData}\n />\n {ConfirmDialogElement}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["personId"]
|
|
7
7
|
}
|
|
@@ -71,6 +71,22 @@ async function resolvePipelineStageValue(em, pipelineStageId, tenantId, organiza
|
|
|
71
71
|
});
|
|
72
72
|
return entry?.value ?? stage.label;
|
|
73
73
|
}
|
|
74
|
+
function resolvePipelineAssignment(input) {
|
|
75
|
+
const requestedPipelineId = input.pipelineId ?? null;
|
|
76
|
+
const requestedPipelineStageId = input.pipelineStageId ?? null;
|
|
77
|
+
if (requestedPipelineStageId && !input.stageSnapshot) {
|
|
78
|
+
throw new CrudHttpError(400, { error: "Pipeline stage not found" });
|
|
79
|
+
}
|
|
80
|
+
if (requestedPipelineId && input.stageSnapshot && input.stageSnapshot.pipelineId !== requestedPipelineId) {
|
|
81
|
+
throw new CrudHttpError(400, {
|
|
82
|
+
error: "Pipeline stage does not belong to the selected pipeline"
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
pipelineId: requestedPipelineId ?? input.stageSnapshot?.pipelineId ?? null,
|
|
87
|
+
pipelineStageId: requestedPipelineStageId
|
|
88
|
+
};
|
|
89
|
+
}
|
|
74
90
|
async function upsertDealStageTransition(em, input) {
|
|
75
91
|
let existing = null;
|
|
76
92
|
try {
|
|
@@ -262,10 +278,19 @@ const createDealCommand = {
|
|
|
262
278
|
const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth);
|
|
263
279
|
let deal;
|
|
264
280
|
let stageSnapshot = null;
|
|
281
|
+
let pipelineAssignment = {
|
|
282
|
+
pipelineId: null,
|
|
283
|
+
pipelineStageId: null
|
|
284
|
+
};
|
|
265
285
|
let resolvedPipelineStageLabel = null;
|
|
266
286
|
await withAtomicFlush(em, [
|
|
267
287
|
async () => {
|
|
268
288
|
stageSnapshot = parsed.pipelineStageId ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, parsed.tenantId, parsed.organizationId) : null;
|
|
289
|
+
pipelineAssignment = resolvePipelineAssignment({
|
|
290
|
+
pipelineId: parsed.pipelineId,
|
|
291
|
+
pipelineStageId: parsed.pipelineStageId,
|
|
292
|
+
stageSnapshot
|
|
293
|
+
});
|
|
269
294
|
resolvedPipelineStageLabel = stageSnapshot ? (await ensureDictionaryEntry(em, {
|
|
270
295
|
tenantId: parsed.tenantId,
|
|
271
296
|
organizationId: parsed.organizationId,
|
|
@@ -281,8 +306,8 @@ const createDealCommand = {
|
|
|
281
306
|
description: parsed.description ?? null,
|
|
282
307
|
status: parsed.status ?? "open",
|
|
283
308
|
pipelineStage: resolvedPipelineStageLabel,
|
|
284
|
-
pipelineId:
|
|
285
|
-
pipelineStageId:
|
|
309
|
+
pipelineId: pipelineAssignment.pipelineId,
|
|
310
|
+
pipelineStageId: pipelineAssignment.pipelineStageId,
|
|
286
311
|
valueAmount: toNumericString(parsed.valueAmount),
|
|
287
312
|
valueCurrency: parsed.valueCurrency ?? null,
|
|
288
313
|
probability: parsed.probability ?? null,
|
|
@@ -390,11 +415,25 @@ const updateDealCommand = {
|
|
|
390
415
|
const previousPipelineStageId = record.pipelineStageId ?? null;
|
|
391
416
|
const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth);
|
|
392
417
|
let nextStageSnapshot = null;
|
|
418
|
+
let nextPipelineAssignment = {
|
|
419
|
+
pipelineId: record.pipelineId ?? null,
|
|
420
|
+
pipelineStageId: record.pipelineStageId ?? null
|
|
421
|
+
};
|
|
393
422
|
let nextPipelineStageLabel = null;
|
|
394
423
|
let resolvedCurrentPipelineStageLabel = null;
|
|
395
424
|
await withAtomicFlush(em, [
|
|
396
425
|
async () => {
|
|
397
|
-
|
|
426
|
+
const pipelineAssignmentChanged = parsed.pipelineId !== void 0 || parsed.pipelineStageId !== void 0;
|
|
427
|
+
const requestedPipelineStageId = parsed.pipelineStageId !== void 0 ? parsed.pipelineStageId ?? null : record.pipelineStageId ?? null;
|
|
428
|
+
const requestedPipelineId = parsed.pipelineId !== void 0 ? parsed.pipelineId ?? null : record.pipelineId ?? null;
|
|
429
|
+
nextStageSnapshot = requestedPipelineStageId && (pipelineAssignmentChanged || !record.pipelineStage) ? await loadPipelineStageSnapshot(em, requestedPipelineStageId, record.tenantId, record.organizationId) : null;
|
|
430
|
+
if (pipelineAssignmentChanged) {
|
|
431
|
+
nextPipelineAssignment = resolvePipelineAssignment({
|
|
432
|
+
pipelineId: requestedPipelineId,
|
|
433
|
+
pipelineStageId: requestedPipelineStageId,
|
|
434
|
+
stageSnapshot: nextStageSnapshot
|
|
435
|
+
});
|
|
436
|
+
}
|
|
398
437
|
nextPipelineStageLabel = nextStageSnapshot ? (await ensureDictionaryEntry(em, {
|
|
399
438
|
tenantId: record.tenantId,
|
|
400
439
|
organizationId: record.organizationId,
|
|
@@ -408,8 +447,10 @@ const updateDealCommand = {
|
|
|
408
447
|
if (parsed.description !== void 0) record.description = parsed.description ?? null;
|
|
409
448
|
if (parsed.status !== void 0) record.status = parsed.status ?? record.status;
|
|
410
449
|
if (parsed.pipelineStage !== void 0) record.pipelineStage = parsed.pipelineStage ?? null;
|
|
411
|
-
if (parsed.pipelineId !== void 0
|
|
412
|
-
|
|
450
|
+
if (parsed.pipelineId !== void 0 || parsed.pipelineStageId !== void 0 && nextStageSnapshot) {
|
|
451
|
+
record.pipelineId = nextPipelineAssignment.pipelineId;
|
|
452
|
+
}
|
|
453
|
+
if (parsed.pipelineStageId !== void 0) record.pipelineStageId = nextPipelineAssignment.pipelineStageId;
|
|
413
454
|
if (nextPipelineStageLabel && (parsed.pipelineStageId !== void 0 || !record.pipelineStage)) {
|
|
414
455
|
record.pipelineStage = nextPipelineStageLabel;
|
|
415
456
|
} else if (resolvedCurrentPipelineStageLabel && (parsed.pipelineStageId !== void 0 || !record.pipelineStage)) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/customers/commands/deals.ts"],
|
|
4
|
-
"sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport {\n parseWithCustomFields,\n setCustomFieldsIfAny,\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n requireId,\n normalizeAuthorUserId,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerDeal,\n CustomerDealPersonLink,\n CustomerDealCompanyLink,\n CustomerDealStageTransition,\n CustomerPipelineStage,\n} from '../data/entities'\nimport {\n dealCreateSchema,\n dealUpdateSchema,\n type DealCreateInput,\n type DealUpdateInput,\n} from '../data/validators'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n requireCustomerEntity,\n ensureSameScope,\n extractUndoPayload,\n ensureDictionaryEntry,\n} from './shared'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport {\n loadCustomFieldSnapshot,\n buildCustomFieldResetMap,\n type CustomFieldChangeSet,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { E } from '#generated/entities.ids.generated'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isMissingDealStageTransitionTable, warnMissingDealStageTransitionTable } from '../lib/dealStageTransitionTable'\n\nconst DEAL_ENTITY_ID = 'customers:customer_deal'\nconst dealCrudIndexer: CrudIndexerConfig<CustomerDeal> = {\n entityType: E.customers.customer_deal,\n}\n\nconst dealCrudEvents: CrudEventsConfig = {\n module: 'customers',\n entity: 'deal',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\ntype PipelineStageSnapshot = {\n id: string\n pipelineId: string\n label: string\n order: number\n}\n\ntype DealStageTransitionSnapshot = {\n id: string\n pipelineId: string\n stageId: string\n stageLabel: string\n stageOrder: number\n transitionedAt: Date\n transitionedByUserId: string | null\n}\n\nasync function loadPipelineStageSnapshot(\n em: EntityManager,\n pipelineStageId: string,\n tenantId: string,\n organizationId: string,\n): Promise<PipelineStageSnapshot | null> {\n const stage = await findOneWithDecryption(em, CustomerPipelineStage, { id: pipelineStageId }, {}, { tenantId, organizationId })\n if (!stage) return null\n return {\n id: stage.id,\n pipelineId: stage.pipelineId,\n label: stage.label,\n order: stage.order,\n }\n}\n\nasync function resolvePipelineStageValue(\n em: EntityManager,\n pipelineStageId: string,\n tenantId: string,\n organizationId: string,\n): Promise<string | null> {\n const stage = await loadPipelineStageSnapshot(em, pipelineStageId, tenantId, organizationId)\n if (!stage) return null\n const entry = await ensureDictionaryEntry(em, {\n tenantId,\n organizationId,\n kind: 'pipeline_stage',\n value: stage.label,\n })\n return entry?.value ?? stage.label\n}\n\nasync function upsertDealStageTransition(\n em: EntityManager,\n input: {\n deal: CustomerDeal\n pipelineId: string\n stageId: string\n stageLabel: string\n stageOrder: number\n transitionedByUserId: string | null\n transitionedAt?: Date\n },\n): Promise<void> {\n let existing: CustomerDealStageTransition | null = null\n try {\n existing = await findOneWithDecryption(\n em,\n CustomerDealStageTransition,\n { deal: input.deal.id, stageId: input.stageId, deletedAt: null },\n {},\n { tenantId: input.deal.tenantId, organizationId: input.deal.organizationId },\n )\n } catch (error) {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.upsertTransition')\n return\n }\n const transitionedAt = input.transitionedAt ?? new Date()\n if (existing) {\n existing.pipelineId = input.pipelineId\n existing.stageLabel = input.stageLabel\n existing.stageOrder = input.stageOrder\n existing.transitionedAt = transitionedAt\n existing.transitionedByUserId = input.transitionedByUserId\n existing.deletedAt = null\n existing.isActive = true\n return\n }\n\n const transition = em.create(CustomerDealStageTransition, {\n organizationId: input.deal.organizationId,\n tenantId: input.deal.tenantId,\n deal: input.deal,\n pipelineId: input.pipelineId,\n stageId: input.stageId,\n stageLabel: input.stageLabel,\n stageOrder: input.stageOrder,\n transitionedAt,\n transitionedByUserId: input.transitionedByUserId,\n isActive: true,\n })\n em.persist(transition)\n}\n\nasync function deleteDealStageTransitions(em: EntityManager, deal: CustomerDeal): Promise<void> {\n try {\n await em.nativeDelete(CustomerDealStageTransition, { deal: deal.id })\n } catch (error) {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.deleteTransitions')\n }\n}\n\nasync function restoreDealStageTransitions(\n em: EntityManager,\n deal: CustomerDeal,\n transitions: DealStageTransitionSnapshot[],\n): Promise<void> {\n if (!transitions.length) return\n for (const transitionSnapshot of transitions) {\n const transition = em.create(CustomerDealStageTransition, {\n id: transitionSnapshot.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n deal,\n pipelineId: transitionSnapshot.pipelineId,\n stageId: transitionSnapshot.stageId,\n stageLabel: transitionSnapshot.stageLabel,\n stageOrder: transitionSnapshot.stageOrder,\n transitionedAt: transitionSnapshot.transitionedAt,\n transitionedByUserId: transitionSnapshot.transitionedByUserId,\n isActive: true,\n })\n em.persist(transition)\n }\n}\n\ntype DealSnapshot = {\n deal: {\n id: string\n organizationId: string\n tenantId: string\n title: string\n description: string | null\n status: string\n pipelineStage: string | null\n pipelineId: string | null\n pipelineStageId: string | null\n valueAmount: string | null\n valueCurrency: string | null\n probability: number | null\n expectedCloseAt: Date | null\n ownerUserId: string | null\n source: string | null\n closureOutcome: string | null\n lossReasonId: string | null\n lossNotes: string | null\n }\n people: string[]\n companies: string[]\n transitions: DealStageTransitionSnapshot[]\n custom?: Record<string, unknown>\n}\n\ntype DealUndoPayload = {\n before?: DealSnapshot | null\n after?: DealSnapshot | null\n}\n\ntype DealChangeMap = Record<string, { from: unknown; to: unknown }> & {\n custom?: CustomFieldChangeSet\n}\n\nasync function loadDealSnapshot(em: EntityManager, id: string): Promise<DealSnapshot | null> {\n const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })\n if (!deal) return null\n const decryptionScope = { tenantId: deal.tenantId ?? null, organizationId: deal.organizationId ?? null }\n const peopleLinks = await findWithDecryption(\n em,\n CustomerDealPersonLink,\n { deal: deal },\n { populate: ['person'] },\n decryptionScope,\n )\n const companyLinks = await findWithDecryption(\n em,\n CustomerDealCompanyLink,\n { deal: deal },\n { populate: ['company'] },\n decryptionScope,\n )\n const transitions = await findWithDecryption(\n em,\n CustomerDealStageTransition,\n { deal: deal.id, deletedAt: null },\n { orderBy: { stageOrder: 'ASC', transitionedAt: 'ASC' } },\n decryptionScope,\n ).catch((error: unknown) => {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.loadSnapshot')\n return [] as CustomerDealStageTransition[]\n })\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n tenantId: deal.tenantId,\n organizationId: deal.organizationId,\n })\n return {\n deal: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n title: deal.title,\n description: deal.description ?? null,\n status: deal.status,\n pipelineStage: deal.pipelineStage ?? null,\n pipelineId: deal.pipelineId ?? null,\n pipelineStageId: deal.pipelineStageId ?? null,\n valueAmount: deal.valueAmount ?? null,\n valueCurrency: deal.valueCurrency ?? null,\n probability: deal.probability ?? null,\n expectedCloseAt: deal.expectedCloseAt ?? null,\n ownerUserId: deal.ownerUserId ?? null,\n source: deal.source ?? null,\n closureOutcome: deal.closureOutcome ?? null,\n lossReasonId: deal.lossReasonId ?? null,\n lossNotes: deal.lossNotes ?? null,\n },\n people: peopleLinks.map((link) =>\n typeof link.person === 'string' ? link.person : link.person.id\n ),\n companies: companyLinks.map((link) =>\n typeof link.company === 'string' ? link.company : link.company.id\n ),\n transitions: transitions.map((transition) => ({\n id: transition.id,\n pipelineId: transition.pipelineId,\n stageId: transition.stageId,\n stageLabel: transition.stageLabel,\n stageOrder: transition.stageOrder,\n transitionedAt: transition.transitionedAt,\n transitionedByUserId: transition.transitionedByUserId ?? null,\n })),\n custom,\n }\n}\n\nfunction toNumericString(value: number | null | undefined): string | null {\n if (value === undefined || value === null) return null\n return value.toString()\n}\n\nasync function syncDealPeople(\n em: EntityManager,\n deal: CustomerDeal,\n personIds: string[] | undefined | null\n): Promise<void> {\n if (personIds === undefined) return\n await em.nativeDelete(CustomerDealPersonLink, { deal })\n if (!personIds || !personIds.length) return\n const unique = Array.from(new Set(personIds))\n for (const personId of unique) {\n const person = await requireCustomerEntity(em, personId, 'person', 'Person not found')\n ensureSameScope(person, deal.organizationId, deal.tenantId)\n const link = em.create(CustomerDealPersonLink, {\n deal,\n person,\n })\n em.persist(link)\n }\n}\n\nasync function syncDealCompanies(\n em: EntityManager,\n deal: CustomerDeal,\n companyIds: string[] | undefined | null\n): Promise<void> {\n if (companyIds === undefined) return\n await em.nativeDelete(CustomerDealCompanyLink, { deal })\n if (!companyIds || !companyIds.length) return\n const unique = Array.from(new Set(companyIds))\n for (const companyId of unique) {\n const company = await requireCustomerEntity(em, companyId, 'company', 'Company not found')\n ensureSameScope(company, deal.organizationId, deal.tenantId)\n const link = em.create(CustomerDealCompanyLink, {\n deal,\n company,\n })\n em.persist(link)\n }\n}\n\nconst createDealCommand: CommandHandler<DealCreateInput, { dealId: string }> = {\n id: 'customers.deals.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(dealCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n let deal!: CustomerDeal\n let stageSnapshot: PipelineStageSnapshot | null = null\n let resolvedPipelineStageLabel: string | null = null\n await withAtomicFlush(em, [\n async () => {\n stageSnapshot = parsed.pipelineStageId\n ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, parsed.tenantId, parsed.organizationId)\n : null\n resolvedPipelineStageLabel = stageSnapshot\n ? (await ensureDictionaryEntry(em, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: 'pipeline_stage',\n value: stageSnapshot.label,\n }))?.value ?? stageSnapshot.label\n : parsed.pipelineStage ?? null\n },\n async () => {\n deal = em.create(CustomerDeal, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n title: parsed.title,\n description: parsed.description ?? null,\n status: parsed.status ?? 'open',\n pipelineStage: resolvedPipelineStageLabel,\n pipelineId: parsed.pipelineId ?? null,\n pipelineStageId: parsed.pipelineStageId ?? null,\n valueAmount: toNumericString(parsed.valueAmount),\n valueCurrency: parsed.valueCurrency ?? null,\n probability: parsed.probability ?? null,\n expectedCloseAt: parsed.expectedCloseAt ?? null,\n ownerUserId: parsed.ownerUserId ?? null,\n source: parsed.source ?? null,\n closureOutcome: parsed.closureOutcome ?? null,\n lossReasonId: parsed.lossReasonId ?? null,\n lossNotes: parsed.lossNotes ?? null,\n })\n em.persist(deal)\n await em.flush()\n },\n async () => {\n const snapshot = stageSnapshot\n if (!snapshot) return\n await upsertDealStageTransition(em, {\n deal,\n pipelineId: snapshot.pipelineId,\n stageId: snapshot.id,\n stageLabel: snapshot.label,\n stageOrder: snapshot.order,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, deal, parsed.personIds ?? []),\n () => syncDealCompanies(em, deal, parsed.companyIds ?? []),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: custom,\n notify: false,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n return { dealId: deal.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadDealSnapshot(em, result.dealId)\n },\n buildLog: async ({ result, ctx }) => {\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, result.dealId)\n return {\n actionLabel: translate('customers.audit.deals.create', 'Create deal'),\n resourceKind: 'customers.deal',\n resourceId: result.dealId,\n tenantId: snapshot?.deal.tenantId ?? null,\n organizationId: snapshot?.deal.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const dealId = logEntry?.resourceId\n if (!dealId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id: dealId })\n if (!deal) return\n await deleteDealStageTransitions(em, deal)\n await em.nativeDelete(CustomerDealPersonLink, { deal })\n await em.nativeDelete(CustomerDealCompanyLink, { deal })\n em.remove(deal)\n await em.flush()\n },\n}\n\nconst updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {\n id: 'customers.deals.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(dealUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(dealUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id: parsed.id, deletedAt: null })\n const record = deal ?? null\n if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n\n const previousStatus = record.status\n const previousPipelineStageId = record.pipelineStageId ?? null\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n\n let nextStageSnapshot: PipelineStageSnapshot | null = null\n let nextPipelineStageLabel: string | null = null\n let resolvedCurrentPipelineStageLabel: string | null = null\n\n await withAtomicFlush(em, [\n async () => {\n nextStageSnapshot = parsed.pipelineStageId\n ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, record.tenantId, record.organizationId)\n : null\n nextPipelineStageLabel = nextStageSnapshot\n ? (await ensureDictionaryEntry(em, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n kind: 'pipeline_stage',\n value: nextStageSnapshot.label,\n }))?.value ?? nextStageSnapshot.label\n : null\n resolvedCurrentPipelineStageLabel =\n !nextStageSnapshot && record.pipelineStageId && (parsed.pipelineStageId !== undefined || !record.pipelineStage)\n ? await resolvePipelineStageValue(em, record.pipelineStageId, record.tenantId, record.organizationId)\n : null\n },\n () => {\n if (parsed.title !== undefined) record.title = parsed.title\n if (parsed.description !== undefined) record.description = parsed.description ?? null\n if (parsed.status !== undefined) record.status = parsed.status ?? record.status\n if (parsed.pipelineStage !== undefined) record.pipelineStage = parsed.pipelineStage ?? null\n if (parsed.pipelineId !== undefined) record.pipelineId = parsed.pipelineId ?? null\n if (parsed.pipelineStageId !== undefined) record.pipelineStageId = parsed.pipelineStageId ?? null\n\n if (nextPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {\n record.pipelineStage = nextPipelineStageLabel\n } else if (resolvedCurrentPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {\n record.pipelineStage = resolvedCurrentPipelineStageLabel\n }\n\n if (parsed.valueAmount !== undefined) record.valueAmount = toNumericString(parsed.valueAmount)\n if (parsed.valueCurrency !== undefined) record.valueCurrency = parsed.valueCurrency ?? null\n if (parsed.probability !== undefined) record.probability = parsed.probability ?? null\n if (parsed.expectedCloseAt !== undefined) record.expectedCloseAt = parsed.expectedCloseAt ?? null\n if (parsed.ownerUserId !== undefined) record.ownerUserId = parsed.ownerUserId ?? null\n if (parsed.source !== undefined) record.source = parsed.source ?? null\n if (parsed.closureOutcome !== undefined) record.closureOutcome = parsed.closureOutcome ?? null\n if (parsed.lossReasonId !== undefined) record.lossReasonId = parsed.lossReasonId ?? null\n if (parsed.lossNotes !== undefined) record.lossNotes = parsed.lossNotes ?? null\n },\n async () => {\n // CRITICAL: persist the scalar mutations above before any further `em.findOne` / sync\n // helpers run inside this transaction. MikroORM v7's identity-map silently discards\n // pending scalar changes on `record` if a query (such as the stage-transition lookup\n // inside `upsertDealStageTransition`, or the linked-entity finds inside\n // `syncDealPeople` / `syncDealCompanies`) executes on the same `EntityManager`\n // before we explicitly flush. Without this flush, the entire kanban drag-and-drop\n // returns 200 OK but never actually updates `customer_deals` rows \u2014 the card\n // snaps back to its source lane on the next refetch (see SPEC-018).\n await em.flush()\n },\n async () => {\n const snapshot = nextStageSnapshot\n if (!snapshot) return\n const shouldRecord =\n parsed.pipelineStageId !== undefined &&\n parsed.pipelineStageId !== null &&\n parsed.pipelineStageId !== previousPipelineStageId\n if (!shouldRecord) return\n await upsertDealStageTransition(em, {\n deal: record,\n pipelineId: snapshot.pipelineId,\n stageId: snapshot.id,\n stageLabel: nextPipelineStageLabel ?? snapshot.label,\n stageOrder: snapshot.order,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, record, parsed.personIds),\n () => syncDealCompanies(em, record, parsed.companyIds),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n notify: false,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n // Emit a lifecycle event for deal won/lost status changes; the notifications\n // subscriber translates these into recipient notifications.\n const newStatus = record.status\n const normalizedStatus = newStatus === 'win' ? 'won' : newStatus === 'loose' ? 'lost' : newStatus\n if (previousStatus !== newStatus && (normalizedStatus === 'won' || normalizedStatus === 'lost')) {\n const closureEvent = normalizedStatus === 'won' ? 'customers.deal.won' : 'customers.deal.lost'\n try {\n const eventBus = ctx.container.resolve('eventBus') as { emitEvent(event: string, payload: unknown, options?: unknown): Promise<void> } | undefined\n if (eventBus) {\n await eventBus.emitEvent(\n closureEvent,\n {\n id: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n ownerUserId: record.ownerUserId ?? null,\n title: record.title,\n valueAmount: record.valueAmount ?? null,\n valueCurrency: record.valueCurrency ?? null,\n },\n { persistent: true },\n )\n }\n } catch (err) {\n console.warn('[customers.deals.update] deal closure event emit failed', closureEvent, err)\n }\n }\n\n return { dealId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadDealSnapshot(em, result.dealId)\n },\n buildLog: async ({ result, snapshots, ctx }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as DealSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const afterSnapshot = await loadDealSnapshot(em, result.dealId)\n return {\n actionLabel: translate('customers.audit.deals.update', 'Update deal'),\n resourceKind: 'customers.deal',\n resourceId: before.deal.id,\n tenantId: before.deal.tenantId,\n organizationId: before.deal.organizationId,\n snapshotBefore: before,\n snapshotAfter: afterSnapshot ?? null,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DealUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: before.deal.id,\n organizationId: before.deal.organizationId,\n tenantId: before.deal.tenantId,\n title: before.deal.title,\n description: before.deal.description,\n status: before.deal.status,\n pipelineStage: before.deal.pipelineStage,\n pipelineId: before.deal.pipelineId,\n pipelineStageId: before.deal.pipelineStageId,\n valueAmount: before.deal.valueAmount,\n valueCurrency: before.deal.valueCurrency,\n probability: before.deal.probability,\n expectedCloseAt: before.deal.expectedCloseAt,\n ownerUserId: before.deal.ownerUserId,\n source: before.deal.source,\n closureOutcome: before.deal.closureOutcome,\n lossReasonId: before.deal.lossReasonId,\n lossNotes: before.deal.lossNotes,\n })\n em.persist(deal)\n }\n const revertedStageSnapshot = before.deal.pipelineStageId\n ? await loadPipelineStageSnapshot(em, before.deal.pipelineStageId, before.deal.tenantId, before.deal.organizationId)\n : null\n const existingTransition = before.deal.pipelineStageId\n ? before.transitions.find((transition) => transition.stageId === before.deal.pipelineStageId) ?? null\n : null\n const shouldRecordRevertTransition =\n before.deal.pipelineStageId !== (payload?.after?.deal.pipelineStageId ?? null) &&\n !!before.deal.pipelineStageId &&\n !!(revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId) &&\n !!(revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel)\n\n await withAtomicFlush(em, [\n () => {\n deal.title = before.deal.title\n deal.description = before.deal.description\n deal.status = before.deal.status\n deal.pipelineStage = before.deal.pipelineStage\n deal.pipelineId = before.deal.pipelineId\n deal.pipelineStageId = before.deal.pipelineStageId\n deal.valueAmount = before.deal.valueAmount\n deal.valueCurrency = before.deal.valueCurrency\n deal.probability = before.deal.probability\n deal.expectedCloseAt = before.deal.expectedCloseAt\n deal.ownerUserId = before.deal.ownerUserId\n deal.source = before.deal.source\n deal.closureOutcome = before.deal.closureOutcome\n deal.lossReasonId = before.deal.lossReasonId\n deal.lossNotes = before.deal.lossNotes\n },\n async () => {\n // Mirror of the fix applied to the forward `execute` path: persist the scalar\n // mutations on `deal` before any further `em.findOne` (the transition lookup\n // inside `upsertDealStageTransition`) or sync-helper queries run on the same EM.\n // MikroORM v7 silently discards the pending scalar changes if we don't flush here\n // (see SPEC-018), which would make an undo of a kanban stage move silently no-op.\n await em.flush()\n },\n async () => {\n if (!shouldRecordRevertTransition || !before.deal.pipelineStageId) return\n const pipelineId = revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId\n const stageLabel = revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel\n if (!pipelineId || !stageLabel) return\n await upsertDealStageTransition(em, {\n deal,\n pipelineId,\n stageId: before.deal.pipelineStageId,\n stageLabel,\n stageOrder: revertedStageSnapshot?.order ?? existingTransition?.stageOrder ?? 0,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, deal, before.people),\n () => syncDealCompanies(em, deal, before.companies),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, payload?.after?.custom)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n}\n\nconst deleteDealCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { dealId: string }> =\n {\n id: 'customers.deals.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Deal id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Deal id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })\n const record = deal ?? null\n if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n await deleteDealStageTransitions(em, record)\n await em.nativeDelete(CustomerDealPersonLink, { deal: record })\n await em.nativeDelete(CustomerDealCompanyLink, { deal: record })\n em.remove(record)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n return { dealId: record.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DealSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('customers.audit.deals.delete', 'Delete deal'),\n resourceKind: 'customers.deal',\n resourceId: before.deal.id,\n tenantId: before.deal.tenantId,\n organizationId: before.deal.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DealUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: before.deal.id,\n organizationId: before.deal.organizationId,\n tenantId: before.deal.tenantId,\n title: before.deal.title,\n description: before.deal.description,\n status: before.deal.status,\n pipelineStage: before.deal.pipelineStage,\n pipelineId: before.deal.pipelineId,\n pipelineStageId: before.deal.pipelineStageId,\n valueAmount: before.deal.valueAmount,\n valueCurrency: before.deal.valueCurrency,\n probability: before.deal.probability,\n expectedCloseAt: before.deal.expectedCloseAt,\n ownerUserId: before.deal.ownerUserId,\n source: before.deal.source,\n closureOutcome: before.deal.closureOutcome,\n lossReasonId: before.deal.lossReasonId,\n lossNotes: before.deal.lossNotes,\n })\n em.persist(deal)\n }\n await withAtomicFlush(em, [\n () => syncDealPeople(em, deal, before.people),\n () => syncDealCompanies(em, deal, before.companies),\n () => deleteDealStageTransitions(em, deal),\n () => restoreDealStageTransitions(em, deal, before.transitions),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n }\n\nregisterCommand(createDealCommand)\nregisterCommand(updateDealCommand)\nregisterCommand(deleteDealCommand)\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport {\n parseWithCustomFields,\n setCustomFieldsIfAny,\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n requireId,\n normalizeAuthorUserId,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerDeal,\n CustomerDealPersonLink,\n CustomerDealCompanyLink,\n CustomerDealStageTransition,\n CustomerPipelineStage,\n} from '../data/entities'\nimport {\n dealCreateSchema,\n dealUpdateSchema,\n type DealCreateInput,\n type DealUpdateInput,\n} from '../data/validators'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n requireCustomerEntity,\n ensureSameScope,\n extractUndoPayload,\n ensureDictionaryEntry,\n} from './shared'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport {\n loadCustomFieldSnapshot,\n buildCustomFieldResetMap,\n type CustomFieldChangeSet,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { E } from '#generated/entities.ids.generated'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isMissingDealStageTransitionTable, warnMissingDealStageTransitionTable } from '../lib/dealStageTransitionTable'\n\nconst DEAL_ENTITY_ID = 'customers:customer_deal'\nconst dealCrudIndexer: CrudIndexerConfig<CustomerDeal> = {\n entityType: E.customers.customer_deal,\n}\n\nconst dealCrudEvents: CrudEventsConfig = {\n module: 'customers',\n entity: 'deal',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\ntype PipelineStageSnapshot = {\n id: string\n pipelineId: string\n label: string\n order: number\n}\n\ntype DealStageTransitionSnapshot = {\n id: string\n pipelineId: string\n stageId: string\n stageLabel: string\n stageOrder: number\n transitionedAt: Date\n transitionedByUserId: string | null\n}\n\nasync function loadPipelineStageSnapshot(\n em: EntityManager,\n pipelineStageId: string,\n tenantId: string,\n organizationId: string,\n): Promise<PipelineStageSnapshot | null> {\n const stage = await findOneWithDecryption(em, CustomerPipelineStage, { id: pipelineStageId }, {}, { tenantId, organizationId })\n if (!stage) return null\n return {\n id: stage.id,\n pipelineId: stage.pipelineId,\n label: stage.label,\n order: stage.order,\n }\n}\n\nasync function resolvePipelineStageValue(\n em: EntityManager,\n pipelineStageId: string,\n tenantId: string,\n organizationId: string,\n): Promise<string | null> {\n const stage = await loadPipelineStageSnapshot(em, pipelineStageId, tenantId, organizationId)\n if (!stage) return null\n const entry = await ensureDictionaryEntry(em, {\n tenantId,\n organizationId,\n kind: 'pipeline_stage',\n value: stage.label,\n })\n return entry?.value ?? stage.label\n}\n\nfunction resolvePipelineAssignment(input: {\n pipelineId?: string | null\n pipelineStageId?: string | null\n stageSnapshot: PipelineStageSnapshot | null\n}): { pipelineId: string | null; pipelineStageId: string | null } {\n const requestedPipelineId = input.pipelineId ?? null\n const requestedPipelineStageId = input.pipelineStageId ?? null\n\n if (requestedPipelineStageId && !input.stageSnapshot) {\n throw new CrudHttpError(400, { error: 'Pipeline stage not found' })\n }\n\n if (\n requestedPipelineId &&\n input.stageSnapshot &&\n input.stageSnapshot.pipelineId !== requestedPipelineId\n ) {\n throw new CrudHttpError(400, {\n error: 'Pipeline stage does not belong to the selected pipeline',\n })\n }\n\n return {\n pipelineId: requestedPipelineId ?? input.stageSnapshot?.pipelineId ?? null,\n pipelineStageId: requestedPipelineStageId,\n }\n}\n\nasync function upsertDealStageTransition(\n em: EntityManager,\n input: {\n deal: CustomerDeal\n pipelineId: string\n stageId: string\n stageLabel: string\n stageOrder: number\n transitionedByUserId: string | null\n transitionedAt?: Date\n },\n): Promise<void> {\n let existing: CustomerDealStageTransition | null = null\n try {\n existing = await findOneWithDecryption(\n em,\n CustomerDealStageTransition,\n { deal: input.deal.id, stageId: input.stageId, deletedAt: null },\n {},\n { tenantId: input.deal.tenantId, organizationId: input.deal.organizationId },\n )\n } catch (error) {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.upsertTransition')\n return\n }\n const transitionedAt = input.transitionedAt ?? new Date()\n if (existing) {\n existing.pipelineId = input.pipelineId\n existing.stageLabel = input.stageLabel\n existing.stageOrder = input.stageOrder\n existing.transitionedAt = transitionedAt\n existing.transitionedByUserId = input.transitionedByUserId\n existing.deletedAt = null\n existing.isActive = true\n return\n }\n\n const transition = em.create(CustomerDealStageTransition, {\n organizationId: input.deal.organizationId,\n tenantId: input.deal.tenantId,\n deal: input.deal,\n pipelineId: input.pipelineId,\n stageId: input.stageId,\n stageLabel: input.stageLabel,\n stageOrder: input.stageOrder,\n transitionedAt,\n transitionedByUserId: input.transitionedByUserId,\n isActive: true,\n })\n em.persist(transition)\n}\n\nasync function deleteDealStageTransitions(em: EntityManager, deal: CustomerDeal): Promise<void> {\n try {\n await em.nativeDelete(CustomerDealStageTransition, { deal: deal.id })\n } catch (error) {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.deleteTransitions')\n }\n}\n\nasync function restoreDealStageTransitions(\n em: EntityManager,\n deal: CustomerDeal,\n transitions: DealStageTransitionSnapshot[],\n): Promise<void> {\n if (!transitions.length) return\n for (const transitionSnapshot of transitions) {\n const transition = em.create(CustomerDealStageTransition, {\n id: transitionSnapshot.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n deal,\n pipelineId: transitionSnapshot.pipelineId,\n stageId: transitionSnapshot.stageId,\n stageLabel: transitionSnapshot.stageLabel,\n stageOrder: transitionSnapshot.stageOrder,\n transitionedAt: transitionSnapshot.transitionedAt,\n transitionedByUserId: transitionSnapshot.transitionedByUserId,\n isActive: true,\n })\n em.persist(transition)\n }\n}\n\ntype DealSnapshot = {\n deal: {\n id: string\n organizationId: string\n tenantId: string\n title: string\n description: string | null\n status: string\n pipelineStage: string | null\n pipelineId: string | null\n pipelineStageId: string | null\n valueAmount: string | null\n valueCurrency: string | null\n probability: number | null\n expectedCloseAt: Date | null\n ownerUserId: string | null\n source: string | null\n closureOutcome: string | null\n lossReasonId: string | null\n lossNotes: string | null\n }\n people: string[]\n companies: string[]\n transitions: DealStageTransitionSnapshot[]\n custom?: Record<string, unknown>\n}\n\ntype DealUndoPayload = {\n before?: DealSnapshot | null\n after?: DealSnapshot | null\n}\n\ntype DealChangeMap = Record<string, { from: unknown; to: unknown }> & {\n custom?: CustomFieldChangeSet\n}\n\nasync function loadDealSnapshot(em: EntityManager, id: string): Promise<DealSnapshot | null> {\n const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })\n if (!deal) return null\n const decryptionScope = { tenantId: deal.tenantId ?? null, organizationId: deal.organizationId ?? null }\n const peopleLinks = await findWithDecryption(\n em,\n CustomerDealPersonLink,\n { deal: deal },\n { populate: ['person'] },\n decryptionScope,\n )\n const companyLinks = await findWithDecryption(\n em,\n CustomerDealCompanyLink,\n { deal: deal },\n { populate: ['company'] },\n decryptionScope,\n )\n const transitions = await findWithDecryption(\n em,\n CustomerDealStageTransition,\n { deal: deal.id, deletedAt: null },\n { orderBy: { stageOrder: 'ASC', transitionedAt: 'ASC' } },\n decryptionScope,\n ).catch((error: unknown) => {\n if (!isMissingDealStageTransitionTable(error)) {\n throw error\n }\n warnMissingDealStageTransitionTable('customers.commands.deals.loadSnapshot')\n return [] as CustomerDealStageTransition[]\n })\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n tenantId: deal.tenantId,\n organizationId: deal.organizationId,\n })\n return {\n deal: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n title: deal.title,\n description: deal.description ?? null,\n status: deal.status,\n pipelineStage: deal.pipelineStage ?? null,\n pipelineId: deal.pipelineId ?? null,\n pipelineStageId: deal.pipelineStageId ?? null,\n valueAmount: deal.valueAmount ?? null,\n valueCurrency: deal.valueCurrency ?? null,\n probability: deal.probability ?? null,\n expectedCloseAt: deal.expectedCloseAt ?? null,\n ownerUserId: deal.ownerUserId ?? null,\n source: deal.source ?? null,\n closureOutcome: deal.closureOutcome ?? null,\n lossReasonId: deal.lossReasonId ?? null,\n lossNotes: deal.lossNotes ?? null,\n },\n people: peopleLinks.map((link) =>\n typeof link.person === 'string' ? link.person : link.person.id\n ),\n companies: companyLinks.map((link) =>\n typeof link.company === 'string' ? link.company : link.company.id\n ),\n transitions: transitions.map((transition) => ({\n id: transition.id,\n pipelineId: transition.pipelineId,\n stageId: transition.stageId,\n stageLabel: transition.stageLabel,\n stageOrder: transition.stageOrder,\n transitionedAt: transition.transitionedAt,\n transitionedByUserId: transition.transitionedByUserId ?? null,\n })),\n custom,\n }\n}\n\nfunction toNumericString(value: number | null | undefined): string | null {\n if (value === undefined || value === null) return null\n return value.toString()\n}\n\nasync function syncDealPeople(\n em: EntityManager,\n deal: CustomerDeal,\n personIds: string[] | undefined | null\n): Promise<void> {\n if (personIds === undefined) return\n await em.nativeDelete(CustomerDealPersonLink, { deal })\n if (!personIds || !personIds.length) return\n const unique = Array.from(new Set(personIds))\n for (const personId of unique) {\n const person = await requireCustomerEntity(em, personId, 'person', 'Person not found')\n ensureSameScope(person, deal.organizationId, deal.tenantId)\n const link = em.create(CustomerDealPersonLink, {\n deal,\n person,\n })\n em.persist(link)\n }\n}\n\nasync function syncDealCompanies(\n em: EntityManager,\n deal: CustomerDeal,\n companyIds: string[] | undefined | null\n): Promise<void> {\n if (companyIds === undefined) return\n await em.nativeDelete(CustomerDealCompanyLink, { deal })\n if (!companyIds || !companyIds.length) return\n const unique = Array.from(new Set(companyIds))\n for (const companyId of unique) {\n const company = await requireCustomerEntity(em, companyId, 'company', 'Company not found')\n ensureSameScope(company, deal.organizationId, deal.tenantId)\n const link = em.create(CustomerDealCompanyLink, {\n deal,\n company,\n })\n em.persist(link)\n }\n}\n\nconst createDealCommand: CommandHandler<DealCreateInput, { dealId: string }> = {\n id: 'customers.deals.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(dealCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n let deal!: CustomerDeal\n let stageSnapshot: PipelineStageSnapshot | null = null\n let pipelineAssignment: { pipelineId: string | null; pipelineStageId: string | null } = {\n pipelineId: null,\n pipelineStageId: null,\n }\n let resolvedPipelineStageLabel: string | null = null\n await withAtomicFlush(em, [\n async () => {\n stageSnapshot = parsed.pipelineStageId\n ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, parsed.tenantId, parsed.organizationId)\n : null\n pipelineAssignment = resolvePipelineAssignment({\n pipelineId: parsed.pipelineId,\n pipelineStageId: parsed.pipelineStageId,\n stageSnapshot,\n })\n resolvedPipelineStageLabel = stageSnapshot\n ? (await ensureDictionaryEntry(em, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: 'pipeline_stage',\n value: stageSnapshot.label,\n }))?.value ?? stageSnapshot.label\n : parsed.pipelineStage ?? null\n },\n async () => {\n deal = em.create(CustomerDeal, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n title: parsed.title,\n description: parsed.description ?? null,\n status: parsed.status ?? 'open',\n pipelineStage: resolvedPipelineStageLabel,\n pipelineId: pipelineAssignment.pipelineId,\n pipelineStageId: pipelineAssignment.pipelineStageId,\n valueAmount: toNumericString(parsed.valueAmount),\n valueCurrency: parsed.valueCurrency ?? null,\n probability: parsed.probability ?? null,\n expectedCloseAt: parsed.expectedCloseAt ?? null,\n ownerUserId: parsed.ownerUserId ?? null,\n source: parsed.source ?? null,\n closureOutcome: parsed.closureOutcome ?? null,\n lossReasonId: parsed.lossReasonId ?? null,\n lossNotes: parsed.lossNotes ?? null,\n })\n em.persist(deal)\n await em.flush()\n },\n async () => {\n const snapshot = stageSnapshot\n if (!snapshot) return\n await upsertDealStageTransition(em, {\n deal,\n pipelineId: snapshot.pipelineId,\n stageId: snapshot.id,\n stageLabel: snapshot.label,\n stageOrder: snapshot.order,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, deal, parsed.personIds ?? []),\n () => syncDealCompanies(em, deal, parsed.companyIds ?? []),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: custom,\n notify: false,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n return { dealId: deal.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadDealSnapshot(em, result.dealId)\n },\n buildLog: async ({ result, ctx }) => {\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, result.dealId)\n return {\n actionLabel: translate('customers.audit.deals.create', 'Create deal'),\n resourceKind: 'customers.deal',\n resourceId: result.dealId,\n tenantId: snapshot?.deal.tenantId ?? null,\n organizationId: snapshot?.deal.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const dealId = logEntry?.resourceId\n if (!dealId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id: dealId })\n if (!deal) return\n await deleteDealStageTransitions(em, deal)\n await em.nativeDelete(CustomerDealPersonLink, { deal })\n await em.nativeDelete(CustomerDealCompanyLink, { deal })\n em.remove(deal)\n await em.flush()\n },\n}\n\nconst updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {\n id: 'customers.deals.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(dealUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(dealUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id: parsed.id, deletedAt: null })\n const record = deal ?? null\n if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n\n const previousStatus = record.status\n const previousPipelineStageId = record.pipelineStageId ?? null\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n\n let nextStageSnapshot: PipelineStageSnapshot | null = null\n let nextPipelineAssignment: { pipelineId: string | null; pipelineStageId: string | null } = {\n pipelineId: record.pipelineId ?? null,\n pipelineStageId: record.pipelineStageId ?? null,\n }\n let nextPipelineStageLabel: string | null = null\n let resolvedCurrentPipelineStageLabel: string | null = null\n\n await withAtomicFlush(em, [\n async () => {\n const pipelineAssignmentChanged =\n parsed.pipelineId !== undefined || parsed.pipelineStageId !== undefined\n const requestedPipelineStageId =\n parsed.pipelineStageId !== undefined\n ? parsed.pipelineStageId ?? null\n : record.pipelineStageId ?? null\n const requestedPipelineId =\n parsed.pipelineId !== undefined ? parsed.pipelineId ?? null : record.pipelineId ?? null\n\n nextStageSnapshot = requestedPipelineStageId && (pipelineAssignmentChanged || !record.pipelineStage)\n ? await loadPipelineStageSnapshot(em, requestedPipelineStageId, record.tenantId, record.organizationId)\n : null\n if (pipelineAssignmentChanged) {\n nextPipelineAssignment = resolvePipelineAssignment({\n pipelineId: requestedPipelineId,\n pipelineStageId: requestedPipelineStageId,\n stageSnapshot: nextStageSnapshot,\n })\n }\n nextPipelineStageLabel = nextStageSnapshot\n ? (await ensureDictionaryEntry(em, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n kind: 'pipeline_stage',\n value: nextStageSnapshot.label,\n }))?.value ?? nextStageSnapshot.label\n : null\n resolvedCurrentPipelineStageLabel =\n !nextStageSnapshot && record.pipelineStageId && (parsed.pipelineStageId !== undefined || !record.pipelineStage)\n ? await resolvePipelineStageValue(em, record.pipelineStageId, record.tenantId, record.organizationId)\n : null\n },\n () => {\n if (parsed.title !== undefined) record.title = parsed.title\n if (parsed.description !== undefined) record.description = parsed.description ?? null\n if (parsed.status !== undefined) record.status = parsed.status ?? record.status\n if (parsed.pipelineStage !== undefined) record.pipelineStage = parsed.pipelineStage ?? null\n if (parsed.pipelineId !== undefined || (parsed.pipelineStageId !== undefined && nextStageSnapshot)) {\n record.pipelineId = nextPipelineAssignment.pipelineId\n }\n if (parsed.pipelineStageId !== undefined) record.pipelineStageId = nextPipelineAssignment.pipelineStageId\n\n if (nextPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {\n record.pipelineStage = nextPipelineStageLabel\n } else if (resolvedCurrentPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {\n record.pipelineStage = resolvedCurrentPipelineStageLabel\n }\n\n if (parsed.valueAmount !== undefined) record.valueAmount = toNumericString(parsed.valueAmount)\n if (parsed.valueCurrency !== undefined) record.valueCurrency = parsed.valueCurrency ?? null\n if (parsed.probability !== undefined) record.probability = parsed.probability ?? null\n if (parsed.expectedCloseAt !== undefined) record.expectedCloseAt = parsed.expectedCloseAt ?? null\n if (parsed.ownerUserId !== undefined) record.ownerUserId = parsed.ownerUserId ?? null\n if (parsed.source !== undefined) record.source = parsed.source ?? null\n if (parsed.closureOutcome !== undefined) record.closureOutcome = parsed.closureOutcome ?? null\n if (parsed.lossReasonId !== undefined) record.lossReasonId = parsed.lossReasonId ?? null\n if (parsed.lossNotes !== undefined) record.lossNotes = parsed.lossNotes ?? null\n },\n async () => {\n // CRITICAL: persist the scalar mutations above before any further `em.findOne` / sync\n // helpers run inside this transaction. MikroORM v7's identity-map silently discards\n // pending scalar changes on `record` if a query (such as the stage-transition lookup\n // inside `upsertDealStageTransition`, or the linked-entity finds inside\n // `syncDealPeople` / `syncDealCompanies`) executes on the same `EntityManager`\n // before we explicitly flush. Without this flush, the entire kanban drag-and-drop\n // returns 200 OK but never actually updates `customer_deals` rows \u2014 the card\n // snaps back to its source lane on the next refetch (see SPEC-018).\n await em.flush()\n },\n async () => {\n const snapshot = nextStageSnapshot\n if (!snapshot) return\n const shouldRecord =\n parsed.pipelineStageId !== undefined &&\n parsed.pipelineStageId !== null &&\n parsed.pipelineStageId !== previousPipelineStageId\n if (!shouldRecord) return\n await upsertDealStageTransition(em, {\n deal: record,\n pipelineId: snapshot.pipelineId,\n stageId: snapshot.id,\n stageLabel: nextPipelineStageLabel ?? snapshot.label,\n stageOrder: snapshot.order,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, record, parsed.personIds),\n () => syncDealCompanies(em, record, parsed.companyIds),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n notify: false,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n // Emit a lifecycle event for deal won/lost status changes; the notifications\n // subscriber translates these into recipient notifications.\n const newStatus = record.status\n const normalizedStatus = newStatus === 'win' ? 'won' : newStatus === 'loose' ? 'lost' : newStatus\n if (previousStatus !== newStatus && (normalizedStatus === 'won' || normalizedStatus === 'lost')) {\n const closureEvent = normalizedStatus === 'won' ? 'customers.deal.won' : 'customers.deal.lost'\n try {\n const eventBus = ctx.container.resolve('eventBus') as { emitEvent(event: string, payload: unknown, options?: unknown): Promise<void> } | undefined\n if (eventBus) {\n await eventBus.emitEvent(\n closureEvent,\n {\n id: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n ownerUserId: record.ownerUserId ?? null,\n title: record.title,\n valueAmount: record.valueAmount ?? null,\n valueCurrency: record.valueCurrency ?? null,\n },\n { persistent: true },\n )\n }\n } catch (err) {\n console.warn('[customers.deals.update] deal closure event emit failed', closureEvent, err)\n }\n }\n\n return { dealId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadDealSnapshot(em, result.dealId)\n },\n buildLog: async ({ result, snapshots, ctx }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as DealSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const afterSnapshot = await loadDealSnapshot(em, result.dealId)\n return {\n actionLabel: translate('customers.audit.deals.update', 'Update deal'),\n resourceKind: 'customers.deal',\n resourceId: before.deal.id,\n tenantId: before.deal.tenantId,\n organizationId: before.deal.organizationId,\n snapshotBefore: before,\n snapshotAfter: afterSnapshot ?? null,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DealUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: before.deal.id,\n organizationId: before.deal.organizationId,\n tenantId: before.deal.tenantId,\n title: before.deal.title,\n description: before.deal.description,\n status: before.deal.status,\n pipelineStage: before.deal.pipelineStage,\n pipelineId: before.deal.pipelineId,\n pipelineStageId: before.deal.pipelineStageId,\n valueAmount: before.deal.valueAmount,\n valueCurrency: before.deal.valueCurrency,\n probability: before.deal.probability,\n expectedCloseAt: before.deal.expectedCloseAt,\n ownerUserId: before.deal.ownerUserId,\n source: before.deal.source,\n closureOutcome: before.deal.closureOutcome,\n lossReasonId: before.deal.lossReasonId,\n lossNotes: before.deal.lossNotes,\n })\n em.persist(deal)\n }\n const revertedStageSnapshot = before.deal.pipelineStageId\n ? await loadPipelineStageSnapshot(em, before.deal.pipelineStageId, before.deal.tenantId, before.deal.organizationId)\n : null\n const existingTransition = before.deal.pipelineStageId\n ? before.transitions.find((transition) => transition.stageId === before.deal.pipelineStageId) ?? null\n : null\n const shouldRecordRevertTransition =\n before.deal.pipelineStageId !== (payload?.after?.deal.pipelineStageId ?? null) &&\n !!before.deal.pipelineStageId &&\n !!(revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId) &&\n !!(revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel)\n\n await withAtomicFlush(em, [\n () => {\n deal.title = before.deal.title\n deal.description = before.deal.description\n deal.status = before.deal.status\n deal.pipelineStage = before.deal.pipelineStage\n deal.pipelineId = before.deal.pipelineId\n deal.pipelineStageId = before.deal.pipelineStageId\n deal.valueAmount = before.deal.valueAmount\n deal.valueCurrency = before.deal.valueCurrency\n deal.probability = before.deal.probability\n deal.expectedCloseAt = before.deal.expectedCloseAt\n deal.ownerUserId = before.deal.ownerUserId\n deal.source = before.deal.source\n deal.closureOutcome = before.deal.closureOutcome\n deal.lossReasonId = before.deal.lossReasonId\n deal.lossNotes = before.deal.lossNotes\n },\n async () => {\n // Mirror of the fix applied to the forward `execute` path: persist the scalar\n // mutations on `deal` before any further `em.findOne` (the transition lookup\n // inside `upsertDealStageTransition`) or sync-helper queries run on the same EM.\n // MikroORM v7 silently discards the pending scalar changes if we don't flush here\n // (see SPEC-018), which would make an undo of a kanban stage move silently no-op.\n await em.flush()\n },\n async () => {\n if (!shouldRecordRevertTransition || !before.deal.pipelineStageId) return\n const pipelineId = revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId\n const stageLabel = revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel\n if (!pipelineId || !stageLabel) return\n await upsertDealStageTransition(em, {\n deal,\n pipelineId,\n stageId: before.deal.pipelineStageId,\n stageLabel,\n stageOrder: revertedStageSnapshot?.order ?? existingTransition?.stageOrder ?? 0,\n transitionedByUserId: normalizedTransitionAuthorUserId,\n })\n },\n () => syncDealPeople(em, deal, before.people),\n () => syncDealCompanies(em, deal, before.companies),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, payload?.after?.custom)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n}\n\nconst deleteDealCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { dealId: string }> =\n {\n id: 'customers.deals.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Deal id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadDealSnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Deal id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })\n const record = deal ?? null\n if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n await deleteDealStageTransitions(em, record)\n await em.nativeDelete(CustomerDealPersonLink, { deal: record })\n await em.nativeDelete(CustomerDealCompanyLink, { deal: record })\n em.remove(record)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n return { dealId: record.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DealSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('customers.audit.deals.delete', 'Delete deal'),\n resourceKind: 'customers.deal',\n resourceId: before.deal.id,\n tenantId: before.deal.tenantId,\n organizationId: before.deal.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies DealUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DealUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })\n if (!deal) {\n deal = em.create(CustomerDeal, {\n id: before.deal.id,\n organizationId: before.deal.organizationId,\n tenantId: before.deal.tenantId,\n title: before.deal.title,\n description: before.deal.description,\n status: before.deal.status,\n pipelineStage: before.deal.pipelineStage,\n pipelineId: before.deal.pipelineId,\n pipelineStageId: before.deal.pipelineStageId,\n valueAmount: before.deal.valueAmount,\n valueCurrency: before.deal.valueCurrency,\n probability: before.deal.probability,\n expectedCloseAt: before.deal.expectedCloseAt,\n ownerUserId: before.deal.ownerUserId,\n source: before.deal.source,\n closureOutcome: before.deal.closureOutcome,\n lossReasonId: before.deal.lossReasonId,\n lossNotes: before.deal.lossNotes,\n })\n em.persist(deal)\n }\n await withAtomicFlush(em, [\n () => syncDealPeople(em, deal, before.people),\n () => syncDealCompanies(em, deal, before.companies),\n () => deleteDealStageTransitions(em, deal),\n () => restoreDealStageTransitions(em, deal, before.transitions),\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: deal,\n identifiers: {\n id: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n },\n indexer: dealCrudIndexer,\n events: dealCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: DEAL_ENTITY_ID,\n recordId: deal.id,\n organizationId: deal.organizationId,\n tenantId: deal.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n }\n\nregisterCommand(createDealCommand)\nregisterCommand(updateDealCommand)\nregisterCommand(deleteDealCommand)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
|
|
34
34
|
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
35
35
|
import { recomputeNextInteraction } from "../lib/interactionProjection.js";
|
|
36
|
+
import { canChangeEmailVisibility } from "../lib/visibilityFilter.js";
|
|
36
37
|
const INTERACTION_ENTITY_ID = "customers:customer_interaction";
|
|
37
38
|
const interactionCrudIndexer = {
|
|
38
39
|
entityType: "customers:customer_interaction"
|
|
@@ -327,6 +328,21 @@ const updateInteractionCommand = {
|
|
|
327
328
|
if (!interaction2) throw new CrudHttpError(404, { error: "Interaction not found" });
|
|
328
329
|
ensureTenantScope(ctx, interaction2.tenantId);
|
|
329
330
|
ensureOrganizationScope(ctx, interaction2.organizationId);
|
|
331
|
+
if (parsed.visibility !== void 0 && interaction2.interactionType === "email" && (parsed.visibility ?? null) !== (interaction2.visibility ?? null)) {
|
|
332
|
+
const actorUserId = ctx.auth?.sub ?? null;
|
|
333
|
+
if (!canChangeEmailVisibility({
|
|
334
|
+
interactionType: interaction2.interactionType,
|
|
335
|
+
currentVisibility: interaction2.visibility,
|
|
336
|
+
nextVisibility: parsed.visibility,
|
|
337
|
+
authorUserId: interaction2.authorUserId,
|
|
338
|
+
actorUserId,
|
|
339
|
+
// v1 strict owner-only: only the author may flip visibility; no admin
|
|
340
|
+
// bypass (canChangeEmailVisibility ignores caller features in v1).
|
|
341
|
+
userFeatures: void 0
|
|
342
|
+
})) {
|
|
343
|
+
throw new CrudHttpError(404, { error: "Email not found" });
|
|
344
|
+
}
|
|
345
|
+
}
|
|
330
346
|
if (parsed.dealId !== void 0) {
|
|
331
347
|
if (parsed.dealId) {
|
|
332
348
|
await requireDealInScope(trx, parsed.dealId, interaction2.tenantId, interaction2.organizationId);
|