import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { EntityManager, Repository } from 'typeorm'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { CreateCompanyAndContactJobData, CreateCompanyAndContactJob, } from 'src/modules/connected-account/auto-companies-and-contacts-creation/jobs/create-company-and-contact.job'; import { FeatureFlagEntity, FeatureFlagKeys, } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { GmailMessage, Participant, ParticipantWithMessageId, } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; import { MessagingMessageService } from 'src/modules/messaging/common/services/messaging-message.service'; import { MessagingMessageParticipantService } from 'src/modules/messaging/common/services/messaging-message-participant.service'; import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; @Injectable() export class MessagingSaveMessagesAndEnqueueContactCreationService { constructor( private readonly workspaceDataSourceService: WorkspaceDataSourceService, @InjectMessageQueue(MessageQueue.contactCreationQueue) private readonly messageQueueService: MessageQueueService, private readonly messageService: MessagingMessageService, private readonly messageParticipantService: MessagingMessageParticipantService, @InjectRepository(FeatureFlagEntity, 'core') private readonly featureFlagRepository: Repository, private readonly eventEmitter: EventEmitter2, ) {} async saveMessagesAndEnqueueContactCreationJob( messagesToSave: GmailMessage[], messageChannel: MessageChannelWorkspaceEntity, connectedAccount: ConnectedAccountWorkspaceEntity, workspaceId: string, ) { const workspaceDataSource = await this.workspaceDataSourceService.connectToWorkspaceDataSource( workspaceId, ); const isContactCreationForSentAndReceivedEmailsEnabledFeatureFlag = await this.featureFlagRepository.findOneBy({ workspaceId: workspaceId, key: FeatureFlagKeys.IsContactCreationForSentAndReceivedEmailsEnabled, value: true, }); const emailAliases = connectedAccount.emailAliases?.split(',') || []; const isContactCreationForSentAndReceivedEmailsEnabled = isContactCreationForSentAndReceivedEmailsEnabledFeatureFlag?.value; let savedMessageParticipants: MessageParticipantWorkspaceEntity[] = []; const participantsWithMessageId = await workspaceDataSource?.transaction( async (transactionManager: EntityManager) => { const messageExternalIdsAndIdsMap = await this.messageService.saveMessagesWithinTransaction( messagesToSave, connectedAccount, messageChannel.id, workspaceId, transactionManager, ); const participantsWithMessageId: (ParticipantWithMessageId & { shouldCreateContact: boolean; })[] = messagesToSave.flatMap((message) => { const messageId = messageExternalIdsAndIdsMap.get(message.externalId); return messageId ? message.participants.map((participant: Participant) => { const fromHandle = message.participants.find((p) => p.role === 'from')?.handle || ''; return { ...participant, messageId, shouldCreateContact: messageChannel.isContactAutoCreationEnabled && (isContactCreationForSentAndReceivedEmailsEnabled || emailAliases.includes(fromHandle)) && !emailAliases.includes(participant.handle), }; }) : []; }); savedMessageParticipants = await this.messageParticipantService.saveMessageParticipants( participantsWithMessageId, workspaceId, transactionManager, ); return participantsWithMessageId; }, ); this.eventEmitter.emit(`messageParticipant.matched`, { workspaceId, workspaceMemberId: connectedAccount.accountOwnerId, messageParticipants: savedMessageParticipants, }); if (messageChannel.isContactAutoCreationEnabled) { const contactsToCreate = participantsWithMessageId.filter( (participant) => participant.shouldCreateContact, ); await this.messageQueueService.add( CreateCompanyAndContactJob.name, { workspaceId, connectedAccount, contactsToCreate, }, ); } } }