Introduce a new feature flag for contact creation (#5570)
Introduce new feature flag `IS_CONTACT_CREATION_FOR_SENT_AND_RECEIVED_EMAILS_ENABLED` to allow contacts to be created for sent and received emails.
This commit is contained in:
@ -50,6 +50,11 @@ export const seedFeatureFlags = async (
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKeys.IsContactCreationForSentAndReceivedEmailsEnabled,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
|
||||
@ -23,6 +23,7 @@ export enum FeatureFlagKeys {
|
||||
IsStripeIntegrationEnabled = 'IS_STRIPE_INTEGRATION_ENABLED',
|
||||
IsGmailSyncV2Enabled = 'IS_GMAIL_SYNC_V2_ENABLED',
|
||||
IsLinksFieldEnabled = 'IS_LINKS_FIELD_ENABLED',
|
||||
IsContactCreationForSentAndReceivedEmailsEnabled = 'IS_CONTACT_CREATION_FOR_SENT_AND_RECEIVED_EMAILS_ENABLED',
|
||||
}
|
||||
|
||||
@Entity({ name: 'featureFlag', schema: 'core' })
|
||||
|
||||
@ -60,6 +60,7 @@ export class AddStandardIdCommand extends CommandRunner {
|
||||
IS_STRIPE_INTEGRATION_ENABLED: false,
|
||||
IS_GMAIL_SYNC_V2_ENABLED: true,
|
||||
IS_LINKS_FIELD_ENABLED: true,
|
||||
IS_CONTACT_CREATION_FOR_SENT_AND_RECEIVED_EMAILS_ENABLED: true,
|
||||
},
|
||||
);
|
||||
const standardFieldMetadataCollection = this.standardFieldFactory.create(
|
||||
@ -76,6 +77,7 @@ export class AddStandardIdCommand extends CommandRunner {
|
||||
IS_STRIPE_INTEGRATION_ENABLED: false,
|
||||
IS_GMAIL_SYNC_V2_ENABLED: true,
|
||||
IS_LINKS_FIELD_ENABLED: true,
|
||||
IS_CONTACT_CREATION_FOR_SENT_AND_RECEIVED_EMAILS_ENABLED: true,
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
||||
|
||||
import {
|
||||
FeatureFlagEntity,
|
||||
FeatureFlagKeys,
|
||||
} from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||
import { CreateCompanyAndContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service';
|
||||
import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository';
|
||||
@ -27,6 +34,8 @@ export class MessagingCreateCompanyAndContactAfterSyncJob
|
||||
private readonly messageChannelService: MessageChannelRepository,
|
||||
@InjectObjectMetadataRepository(MessageParticipantWorkspaceEntity)
|
||||
private readonly messageParticipantRepository: MessageParticipantRepository,
|
||||
@InjectRepository(FeatureFlagEntity, 'core')
|
||||
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
||||
) {}
|
||||
|
||||
async handle(
|
||||
@ -48,11 +57,25 @@ export class MessagingCreateCompanyAndContactAfterSyncJob
|
||||
return;
|
||||
}
|
||||
|
||||
const contactsToCreate =
|
||||
await this.messageParticipantRepository.getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberIdAndMessageOutgoing(
|
||||
messageChannelId,
|
||||
workspaceId,
|
||||
);
|
||||
const isContactCreationForSentAndReceivedEmailsEnabledFeatureFlag =
|
||||
await this.featureFlagRepository.findOneBy({
|
||||
workspaceId: workspaceId,
|
||||
key: FeatureFlagKeys.IsContactCreationForSentAndReceivedEmailsEnabled,
|
||||
value: true,
|
||||
});
|
||||
|
||||
const isContactCreationForSentAndReceivedEmailsEnabled =
|
||||
isContactCreationForSentAndReceivedEmailsEnabledFeatureFlag?.value;
|
||||
|
||||
const contactsToCreate = isContactCreationForSentAndReceivedEmailsEnabled
|
||||
? await this.messageParticipantRepository.getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberId(
|
||||
messageChannelId,
|
||||
workspaceId,
|
||||
)
|
||||
: await this.messageParticipantRepository.getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberIdAndMessageOutgoing(
|
||||
messageChannelId,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.createCompanyAndContactService.createCompaniesAndContactsAndUpdateParticipants(
|
||||
handle,
|
||||
|
||||
@ -131,6 +131,41 @@ export class MessageParticipantRepository {
|
||||
return messageParticipants;
|
||||
}
|
||||
|
||||
public async getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberId(
|
||||
messageChannelId: string,
|
||||
workspaceId: string,
|
||||
transactionManager?: EntityManager,
|
||||
): Promise<ParticipantWithId[]> {
|
||||
if (!messageChannelId || !workspaceId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const dataSourceSchema =
|
||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||
|
||||
const messageParticipants: ParticipantWithId[] =
|
||||
await this.workspaceDataSourceService.executeRawQuery(
|
||||
`SELECT "messageParticipant".id,
|
||||
"messageParticipant"."role",
|
||||
"messageParticipant"."handle",
|
||||
"messageParticipant"."displayName",
|
||||
"messageParticipant"."personId",
|
||||
"messageParticipant"."workspaceMemberId",
|
||||
"messageParticipant"."messageId"
|
||||
FROM ${dataSourceSchema}."messageParticipant" "messageParticipant"
|
||||
LEFT JOIN ${dataSourceSchema}."message" ON "messageParticipant"."messageId" = ${dataSourceSchema}."message"."id"
|
||||
LEFT JOIN ${dataSourceSchema}."messageChannelMessageAssociation" ON ${dataSourceSchema}."messageChannelMessageAssociation"."messageId" = ${dataSourceSchema}."message"."id"
|
||||
WHERE ${dataSourceSchema}."messageChannelMessageAssociation"."messageChannelId" = $1
|
||||
AND "messageParticipant"."personId" IS NULL
|
||||
AND "messageParticipant"."workspaceMemberId" IS NULL`,
|
||||
[messageChannelId],
|
||||
workspaceId,
|
||||
transactionManager,
|
||||
);
|
||||
|
||||
return messageParticipants;
|
||||
}
|
||||
|
||||
public async getWithoutPersonIdAndWorkspaceMemberId(
|
||||
workspaceId: string,
|
||||
transactionManager?: EntityManager,
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||
@ -24,6 +26,7 @@ import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-ob
|
||||
MessageModule,
|
||||
MessageParticipantModule,
|
||||
SetMessageChannelSyncStatusModule,
|
||||
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
||||
],
|
||||
providers: [
|
||||
GmailMessagesImportService,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { Inject, Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { EntityManager } from 'typeorm';
|
||||
import { EntityManager, Repository } from 'typeorm';
|
||||
|
||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||
@ -31,6 +32,10 @@ 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';
|
||||
|
||||
@Injectable()
|
||||
export class GmailMessagesImportService {
|
||||
@ -49,6 +54,8 @@ export class GmailMessagesImportService {
|
||||
private readonly messageQueueService: MessageQueueService,
|
||||
private readonly messageService: MessageService,
|
||||
private readonly messageParticipantService: MessageParticipantService,
|
||||
@InjectRepository(FeatureFlagEntity, 'core')
|
||||
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
||||
) {}
|
||||
|
||||
async fetchMessageContentFromCache(
|
||||
@ -171,6 +178,16 @@ export class GmailMessagesImportService {
|
||||
|
||||
const messageQueries = createQueriesFromMessageIds(messageIdsToFetch);
|
||||
|
||||
const isContactCreationForSentAndReceivedEmailsEnabledFeatureFlag =
|
||||
await this.featureFlagRepository.findOneBy({
|
||||
workspaceId: workspaceId,
|
||||
key: FeatureFlagKeys.IsContactCreationForSentAndReceivedEmailsEnabled,
|
||||
value: true,
|
||||
});
|
||||
|
||||
const isContactCreationForSentAndReceivedEmailsEnabled =
|
||||
isContactCreationForSentAndReceivedEmailsEnabledFeatureFlag?.value;
|
||||
|
||||
try {
|
||||
const messagesToSave =
|
||||
await this.fetchMessagesByBatchesService.fetchAllMessages(
|
||||
@ -214,8 +231,9 @@ export class GmailMessagesImportService {
|
||||
messageId,
|
||||
shouldCreateContact:
|
||||
gmailMessageChannel.isContactAutoCreationEnabled &&
|
||||
message.participants.find((p) => p.role === 'from')
|
||||
?.handle === connectedAccount.handle,
|
||||
(isContactCreationForSentAndReceivedEmailsEnabled ||
|
||||
message.participants.find((p) => p.role === 'from')
|
||||
?.handle === connectedAccount.handle),
|
||||
}))
|
||||
: [];
|
||||
});
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { Injectable, Inject } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { EntityManager } from 'typeorm';
|
||||
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';
|
||||
@ -18,6 +19,10 @@ 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';
|
||||
|
||||
@Injectable()
|
||||
export class SaveMessagesAndEnqueueContactCreationService {
|
||||
@ -27,6 +32,8 @@ export class SaveMessagesAndEnqueueContactCreationService {
|
||||
private readonly messageQueueService: MessageQueueService,
|
||||
private readonly messageService: MessageService,
|
||||
private readonly messageParticipantService: MessageParticipantService,
|
||||
@InjectRepository(FeatureFlagEntity, 'core')
|
||||
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
||||
) {}
|
||||
|
||||
async saveMessagesAndEnqueueContactCreationJob(
|
||||
@ -40,6 +47,16 @@ export class SaveMessagesAndEnqueueContactCreationService {
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
const isContactCreationForSentAndReceivedEmailsEnabledFeatureFlag =
|
||||
await this.featureFlagRepository.findOneBy({
|
||||
workspaceId: workspaceId,
|
||||
key: FeatureFlagKeys.IsContactCreationForSentAndReceivedEmailsEnabled,
|
||||
value: true,
|
||||
});
|
||||
|
||||
const isContactCreationForSentAndReceivedEmailsEnabled =
|
||||
isContactCreationForSentAndReceivedEmailsEnabledFeatureFlag?.value;
|
||||
|
||||
const participantsWithMessageId = await workspaceDataSource?.transaction(
|
||||
async (transactionManager: EntityManager) => {
|
||||
const messageExternalIdsAndIdsMap =
|
||||
@ -62,8 +79,9 @@ export class SaveMessagesAndEnqueueContactCreationService {
|
||||
messageId,
|
||||
shouldCreateContact:
|
||||
messageChannel.isContactAutoCreationEnabled &&
|
||||
message.participants.find((p) => p.role === 'from')
|
||||
?.handle === connectedAccount.handle,
|
||||
(isContactCreationForSentAndReceivedEmailsEnabled ||
|
||||
message.participants.find((p) => p.role === 'from')
|
||||
?.handle === connectedAccount.handle),
|
||||
}))
|
||||
: [];
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user