6255 move services from messaging common module into the correct module and refactor them (#6409)
Closes #6255 - Move files from `messaging/common` into the correct module - Remove common module between calendar and messaging `calendar-messaging-participant-manager` - Update and fix massaging and calendar participant matching - Create `MatchParticipantModule` --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
co-authored by
Charles Bochet
parent
3060eb4e1e
commit
d0db3b765f
+6
-5
@@ -3,7 +3,8 @@ import { Scope } from '@nestjs/common';
|
||||
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||
import { MessagingMessageParticipantService } from 'src/modules/messaging/message-participant-manager/services/messaging-message-participant.service';
|
||||
import { MatchParticipantService } from 'src/modules/match-participant/match-participant.service';
|
||||
import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
|
||||
|
||||
export type MessageParticipantMatchParticipantJobData = {
|
||||
workspaceId: string;
|
||||
@@ -18,16 +19,16 @@ export type MessageParticipantMatchParticipantJobData = {
|
||||
})
|
||||
export class MessageParticipantMatchParticipantJob {
|
||||
constructor(
|
||||
private readonly messageParticipantService: MessagingMessageParticipantService,
|
||||
private readonly matchParticipantService: MatchParticipantService<MessageParticipantWorkspaceEntity>,
|
||||
) {}
|
||||
|
||||
@Process(MessageParticipantMatchParticipantJob.name)
|
||||
async handle(data: MessageParticipantMatchParticipantJobData): Promise<void> {
|
||||
const { workspaceId, email, personId, workspaceMemberId } = data;
|
||||
const { email, personId, workspaceMemberId } = data;
|
||||
|
||||
await this.messageParticipantService.matchMessageParticipants(
|
||||
workspaceId,
|
||||
await this.matchParticipantService.matchParticipantsAfterPersonOrWorkspaceMemberCreation(
|
||||
email,
|
||||
'messageParticipant',
|
||||
personId,
|
||||
workspaceMemberId,
|
||||
);
|
||||
|
||||
+7
-6
@@ -1,9 +1,10 @@
|
||||
import { Scope } from '@nestjs/common';
|
||||
|
||||
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||
import { MessagingMessageParticipantService } from 'src/modules/messaging/message-participant-manager/services/messaging-message-participant.service';
|
||||
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
||||
import { MatchParticipantService } from 'src/modules/match-participant/match-participant.service';
|
||||
import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
|
||||
|
||||
export type MessageParticipantUnmatchParticipantJobData = {
|
||||
workspaceId: string;
|
||||
@@ -18,18 +19,18 @@ export type MessageParticipantUnmatchParticipantJobData = {
|
||||
})
|
||||
export class MessageParticipantUnmatchParticipantJob {
|
||||
constructor(
|
||||
private readonly messageParticipantService: MessagingMessageParticipantService,
|
||||
private readonly matchParticipantService: MatchParticipantService<MessageParticipantWorkspaceEntity>,
|
||||
) {}
|
||||
|
||||
@Process(MessageParticipantUnmatchParticipantJob.name)
|
||||
async handle(
|
||||
data: MessageParticipantUnmatchParticipantJobData,
|
||||
): Promise<void> {
|
||||
const { workspaceId, email, personId, workspaceMemberId } = data;
|
||||
const { email, personId, workspaceMemberId } = data;
|
||||
|
||||
await this.messageParticipantService.unmatchMessageParticipants(
|
||||
workspaceId,
|
||||
await this.matchParticipantService.unmatchParticipants(
|
||||
email,
|
||||
'messageParticipant',
|
||||
personId,
|
||||
workspaceMemberId,
|
||||
);
|
||||
|
||||
-6
@@ -1,9 +1,5 @@
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||
@@ -35,8 +31,6 @@ export class MessagingCreateCompanyAndContactAfterSyncJob {
|
||||
private readonly messageChannelService: MessageChannelRepository,
|
||||
@InjectObjectMetadataRepository(MessageParticipantWorkspaceEntity)
|
||||
private readonly messageParticipantRepository: MessageParticipantRepository,
|
||||
@InjectRepository(FeatureFlagEntity, 'core')
|
||||
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
||||
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
||||
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||
) {}
|
||||
|
||||
+3
-3
@@ -7,9 +7,9 @@ import { Repository } from 'typeorm';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
|
||||
import { TimelineActivityRepository } from 'src/modules/timeline/repositiories/timeline-activity.repository';
|
||||
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
|
||||
import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
|
||||
|
||||
@Injectable()
|
||||
export class MessageParticipantListener {
|
||||
@@ -25,9 +25,9 @@ export class MessageParticipantListener {
|
||||
public async handleMessageParticipantMatched(payload: {
|
||||
workspaceId: string;
|
||||
workspaceMemberId: string;
|
||||
messageParticipants: MessageParticipantWorkspaceEntity[];
|
||||
participants: MessageParticipantWorkspaceEntity[];
|
||||
}): Promise<void> {
|
||||
const messageParticipants = payload.messageParticipants ?? [];
|
||||
const messageParticipants = payload.participants ?? [];
|
||||
|
||||
// TODO: move to a job?
|
||||
|
||||
|
||||
+2
-2
@@ -7,9 +7,9 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat
|
||||
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||
import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
import { AddPersonIdAndWorkspaceMemberIdService } from 'src/modules/calendar-messaging-participant-manager/services/add-person-id-and-workspace-member-id/add-person-id-and-workspace-member-id.service';
|
||||
import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
|
||||
import { ContactCreationManagerModule } from 'src/modules/contact-creation-manager/contact-creation-manager.module';
|
||||
import { MatchParticipantModule } from 'src/modules/match-participant/match-participant.module';
|
||||
import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module';
|
||||
import { MessageParticipantMatchParticipantJob } from 'src/modules/messaging/message-participant-manager/jobs/message-participant-match-participant.job';
|
||||
import { MessageParticipantUnmatchParticipantJob } from 'src/modules/messaging/message-participant-manager/jobs/message-participant-unmatch-participant.job';
|
||||
@@ -32,6 +32,7 @@ import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-o
|
||||
TypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'),
|
||||
TwentyORMModule.forFeature([CalendarChannelWorkspaceEntity]),
|
||||
MessagingCommonModule,
|
||||
MatchParticipantModule,
|
||||
],
|
||||
providers: [
|
||||
MessagingMessageParticipantService,
|
||||
@@ -41,7 +42,6 @@ import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-o
|
||||
MessageParticipantListener,
|
||||
MessageParticipantPersonListener,
|
||||
MessageParticipantWorkspaceMemberListener,
|
||||
AddPersonIdAndWorkspaceMemberIdService,
|
||||
],
|
||||
exports: [MessagingMessageParticipantService],
|
||||
})
|
||||
|
||||
+23
-159
@@ -1,181 +1,45 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
|
||||
import { EntityManager } from 'typeorm';
|
||||
|
||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||
import { PersonRepository } from 'src/modules/person/repositories/person.repository';
|
||||
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
import { getFlattenedValuesAndValuesStringForBatchRawQuery } from 'src/modules/calendar/calendar-event-import-manager/utils/get-flattened-values-and-values-string-for-batch-raw-query.util';
|
||||
import { AddPersonIdAndWorkspaceMemberIdService } from 'src/modules/calendar-messaging-participant-manager/services/add-person-id-and-workspace-member-id/add-person-id-and-workspace-member-id.service';
|
||||
import { MessageParticipantRepository } from 'src/modules/messaging/common/repositories/message-participant.repository';
|
||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||
import { MatchParticipantService } from 'src/modules/match-participant/match-participant.service';
|
||||
import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
|
||||
import { ParticipantWithMessageId } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message';
|
||||
|
||||
@Injectable()
|
||||
export class MessagingMessageParticipantService {
|
||||
constructor(
|
||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||
@InjectObjectMetadataRepository(MessageParticipantWorkspaceEntity)
|
||||
private readonly messageParticipantRepository: MessageParticipantRepository,
|
||||
@InjectObjectMetadataRepository(PersonWorkspaceEntity)
|
||||
private readonly personRepository: PersonRepository,
|
||||
private readonly addPersonIdAndWorkspaceMemberIdService: AddPersonIdAndWorkspaceMemberIdService,
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
private readonly twentyORMManager: TwentyORMManager,
|
||||
private readonly matchParticipantService: MatchParticipantService<MessageParticipantWorkspaceEntity>,
|
||||
) {}
|
||||
|
||||
public async updateMessageParticipantsAfterPeopleCreation(
|
||||
createdPeople: PersonWorkspaceEntity[],
|
||||
workspaceId: string,
|
||||
transactionManager?: EntityManager,
|
||||
): Promise<MessageParticipantWorkspaceEntity[]> {
|
||||
const participants = await this.messageParticipantRepository.getByHandles(
|
||||
createdPeople.map((person) => person.email),
|
||||
workspaceId,
|
||||
transactionManager,
|
||||
);
|
||||
|
||||
if (!participants) return [];
|
||||
|
||||
const dataSourceSchema =
|
||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||
|
||||
const handles = participants.map((participant) => participant.handle);
|
||||
|
||||
const participantPersonIds = await this.personRepository.getByEmails(
|
||||
handles,
|
||||
workspaceId,
|
||||
transactionManager,
|
||||
);
|
||||
|
||||
const messageParticipantsToUpdate = participants.map((participant) => ({
|
||||
id: participant.id,
|
||||
personId: participantPersonIds.find(
|
||||
(e: { id: string; email: string }) => e.email === participant.handle,
|
||||
)?.id,
|
||||
}));
|
||||
|
||||
if (messageParticipantsToUpdate.length === 0) return [];
|
||||
|
||||
const { flattenedValues, valuesString } =
|
||||
getFlattenedValuesAndValuesStringForBatchRawQuery(
|
||||
messageParticipantsToUpdate,
|
||||
{
|
||||
id: 'uuid',
|
||||
personId: 'uuid',
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
await this.workspaceDataSourceService.executeRawQuery(
|
||||
`UPDATE ${dataSourceSchema}."messageParticipant" AS "messageParticipant" SET "personId" = "data"."personId"
|
||||
FROM (VALUES ${valuesString}) AS "data"("id", "personId")
|
||||
WHERE "messageParticipant"."id" = "data"."id"
|
||||
RETURNING *`,
|
||||
flattenedValues,
|
||||
workspaceId,
|
||||
transactionManager,
|
||||
)
|
||||
).flat();
|
||||
}
|
||||
|
||||
public async saveMessageParticipants(
|
||||
participants: ParticipantWithMessageId[],
|
||||
workspaceId: string,
|
||||
transactionManager?: EntityManager,
|
||||
): Promise<MessageParticipantWorkspaceEntity[]> {
|
||||
if (!participants) return [];
|
||||
|
||||
const dataSourceSchema =
|
||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||
|
||||
const messageParticipantsToSave =
|
||||
await this.addPersonIdAndWorkspaceMemberIdService.addPersonIdAndWorkspaceMemberId(
|
||||
participants,
|
||||
workspaceId,
|
||||
transactionManager,
|
||||
): Promise<void> {
|
||||
const messageParticipantRepository =
|
||||
await this.twentyORMManager.getRepository<MessageParticipantWorkspaceEntity>(
|
||||
'messageParticipant',
|
||||
);
|
||||
|
||||
const { flattenedValues, valuesString } =
|
||||
getFlattenedValuesAndValuesStringForBatchRawQuery(
|
||||
messageParticipantsToSave,
|
||||
{
|
||||
messageId: 'uuid',
|
||||
role: `${dataSourceSchema}."messageParticipant_role_enum"`,
|
||||
handle: 'text',
|
||||
displayName: 'text',
|
||||
personId: 'uuid',
|
||||
workspaceMemberId: 'uuid',
|
||||
},
|
||||
);
|
||||
const savedParticipants = await messageParticipantRepository.save(
|
||||
participants.map((participant) => {
|
||||
return {
|
||||
messageId: participant.messageId,
|
||||
role: participant.role,
|
||||
handle: participant.handle,
|
||||
displayName: participant.displayName,
|
||||
};
|
||||
}),
|
||||
{},
|
||||
transactionManager,
|
||||
);
|
||||
|
||||
if (messageParticipantsToSave.length === 0) return [];
|
||||
|
||||
return await this.workspaceDataSourceService.executeRawQuery(
|
||||
`INSERT INTO ${dataSourceSchema}."messageParticipant" ("messageId", "role", "handle", "displayName", "personId", "workspaceMemberId") VALUES ${valuesString} RETURNING *`,
|
||||
flattenedValues,
|
||||
workspaceId,
|
||||
await this.matchParticipantService.matchParticipants(
|
||||
savedParticipants,
|
||||
'messageParticipant',
|
||||
transactionManager,
|
||||
);
|
||||
}
|
||||
|
||||
public async matchMessageParticipants(
|
||||
workspaceId: string,
|
||||
email: string,
|
||||
personId?: string,
|
||||
workspaceMemberId?: string,
|
||||
) {
|
||||
const messageParticipantsToUpdate =
|
||||
await this.messageParticipantRepository.getByHandles(
|
||||
[email],
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
const messageParticipantIdsToUpdate = messageParticipantsToUpdate.map(
|
||||
(participant) => participant.id,
|
||||
);
|
||||
|
||||
if (personId) {
|
||||
const updatedMessageParticipants =
|
||||
await this.messageParticipantRepository.updateParticipantsPersonIdAndReturn(
|
||||
messageParticipantIdsToUpdate,
|
||||
personId,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
this.eventEmitter.emit(`messageParticipant.matched`, {
|
||||
workspaceId,
|
||||
workspaceMemberId: null,
|
||||
messageParticipants: updatedMessageParticipants,
|
||||
});
|
||||
}
|
||||
if (workspaceMemberId) {
|
||||
await this.messageParticipantRepository.updateParticipantsWorkspaceMemberId(
|
||||
messageParticipantIdsToUpdate,
|
||||
workspaceMemberId,
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public async unmatchMessageParticipants(
|
||||
workspaceId: string,
|
||||
handle: string,
|
||||
personId?: string,
|
||||
workspaceMemberId?: string,
|
||||
) {
|
||||
if (personId) {
|
||||
await this.messageParticipantRepository.removePersonIdByHandle(
|
||||
handle,
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
if (workspaceMemberId) {
|
||||
await this.messageParticipantRepository.removeWorkspaceMemberIdByHandle(
|
||||
handle,
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user