From e34e341ddc44202d23e346567edb9a75d91da75c Mon Sep 17 00:00:00 2001 From: bosiraphael <71827178+bosiraphael@users.noreply.github.com> Date: Mon, 19 Feb 2024 17:29:38 +0100 Subject: [PATCH] 3938 change email auto import to contact ive sent email to (#3995) * done * working * wip * merge main * almost done * improvement --- ...e-companies-and-contacts-after-sync.job.ts | 2 +- .../message-participant.module.ts | 4 +- .../message-participant.service.ts | 54 +++++++++++++++---- .../repositories/message/message.service.ts | 18 ++++++- .../repositories/person/person.service.ts | 18 +++++++ .../create-companies-and-contacts.service.ts | 16 +++++- 6 files changed, 96 insertions(+), 16 deletions(-) diff --git a/packages/twenty-server/src/workspace/messaging/jobs/create-companies-and-contacts-after-sync.job.ts b/packages/twenty-server/src/workspace/messaging/jobs/create-companies-and-contacts-after-sync.job.ts index 1071397d2..116c6d228 100644 --- a/packages/twenty-server/src/workspace/messaging/jobs/create-companies-and-contacts-after-sync.job.ts +++ b/packages/twenty-server/src/workspace/messaging/jobs/create-companies-and-contacts-after-sync.job.ts @@ -43,7 +43,7 @@ export class CreateCompaniesAndContactsAfterSyncJob } const messageParticipantsWithoutPersonIdAndWorkspaceMemberId = - await this.messageParticipantService.getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberId( + await this.messageParticipantService.getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberIdAndMessageOutgoing( messageChannelId, workspaceId, ); diff --git a/packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.module.ts b/packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.module.ts index 24864f192..9f924dc41 100644 --- a/packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.module.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.module.ts @@ -1,11 +1,11 @@ import { Module } from '@nestjs/common'; -import { CreateCompaniesAndContactsModule } from 'src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.module'; import { MessageParticipantService } from 'src/workspace/messaging/repositories/message-participant/message-participant.service'; import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module'; +import { PersonModule } from 'src/workspace/messaging/repositories/person/person.module'; @Module({ - imports: [WorkspaceDataSourceModule, CreateCompaniesAndContactsModule], + imports: [WorkspaceDataSourceModule, PersonModule], providers: [MessageParticipantService], exports: [MessageParticipantService], }) diff --git a/packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.service.ts b/packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.service.ts index d380bd729..3cb8ccc65 100644 --- a/packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.service.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.service.ts @@ -9,11 +9,13 @@ import { ParticipantWithId, Participant, } from 'src/workspace/messaging/types/gmail-message'; +import { PersonService } from 'src/workspace/messaging/repositories/person/person.service'; @Injectable() export class MessageParticipantService { constructor( private readonly workspaceDataSourceService: WorkspaceDataSourceService, + private readonly personService: PersonService, ) {} public async getByHandles( @@ -66,7 +68,7 @@ export class MessageParticipantService { ); } - public async getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberId( + public async getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberIdAndMessageOutgoing( messageChannelId: string, workspaceId: string, transactionManager?: EntityManager, @@ -88,11 +90,12 @@ export class MessageParticipantService { "messageParticipant"."workspaceMemberId", "messageParticipant"."messageId" FROM ${dataSourceSchema}."messageParticipant" "messageParticipant" - LEFT JOIN ${dataSourceSchema}."message" ON "messageParticipant"."messageId" = ${dataSourceSchema}."message"."id" + 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`, + AND "messageParticipant"."workspaceMemberId" IS NULL + AND ${dataSourceSchema}."message"."direction" = 'outgoing'`, [messageChannelId], workspaceId, transactionManager, @@ -101,6 +104,39 @@ export class MessageParticipantService { return messageParticipants; } + public async getByHandlesWithoutPersonIdAndWorkspaceMemberId( + handles: string[], + workspaceId: string, + transactionManager?: EntityManager, + ): Promise { + if (!workspaceId) { + throw new Error('WorkspaceId is required'); + } + + 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" + WHERE "messageParticipant"."personId" IS NULL + AND "messageParticipant"."workspaceMemberId" IS NULL + AND "messageParticipant"."handle" = ANY($1)`, + [handles], + workspaceId, + transactionManager, + ); + + return messageParticipants; + } + public async saveMessageParticipants( participants: Participant[], messageId: string, @@ -173,13 +209,11 @@ export class MessageParticipantService { const handles = participants.map((participant) => participant.handle); - const participantPersonIds = - await this.workspaceDataSourceService.executeRawQuery( - `SELECT id, email FROM ${dataSourceSchema}."person" WHERE "email" = ANY($1)`, - [handles], - workspaceId, - transactionManager, - ); + const participantPersonIds = await this.personService.getByEmails( + handles, + workspaceId, + transactionManager, + ); const messageParticipantsToUpdate = participants.map((participant) => [ participant.id, diff --git a/packages/twenty-server/src/workspace/messaging/repositories/message/message.service.ts b/packages/twenty-server/src/workspace/messaging/repositories/message/message.service.ts index dc88ad75c..38e266cb0 100644 --- a/packages/twenty-server/src/workspace/messaging/repositories/message/message.service.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/message/message.service.ts @@ -203,12 +203,28 @@ export class MessageService { workspaceId, ); - if (isContactAutoCreationEnabled) { + if (isContactAutoCreationEnabled && messageDirection === 'outgoing') { await this.createCompaniesAndContactsService.createCompaniesAndContacts( message.participants, workspaceId, manager, ); + + const handles = message.participants.map( + (participant) => participant.handle, + ); + + const messageParticipantsWithoutPersonIdAndWorkspaceMemberId = + await this.messageParticipantService.getByHandlesWithoutPersonIdAndWorkspaceMemberId( + handles, + workspaceId, + ); + + await this.messageParticipantService.updateMessageParticipantsAfterPeopleCreation( + messageParticipantsWithoutPersonIdAndWorkspaceMemberId, + workspaceId, + manager, + ); } await this.messageParticipantService.saveMessageParticipants( diff --git a/packages/twenty-server/src/workspace/messaging/repositories/person/person.service.ts b/packages/twenty-server/src/workspace/messaging/repositories/person/person.service.ts index 50f18aba8..d78f6c422 100644 --- a/packages/twenty-server/src/workspace/messaging/repositories/person/person.service.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/person/person.service.ts @@ -3,6 +3,8 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service'; +import { ObjectRecord } from 'src/workspace/workspace-sync-metadata/types/object-record'; +import { PersonObjectMetadata } from 'src/workspace/workspace-sync-metadata/standard-objects/person.object-metadata'; // TODO: Move outside of the messaging module @Injectable() @@ -11,6 +13,22 @@ export class PersonService { private readonly workspaceDataSourceService: WorkspaceDataSourceService, ) {} + async getByEmails( + emails: string[], + workspaceId: string, + transactionManager?: EntityManager, + ): Promise[]> { + const dataSourceSchema = + this.workspaceDataSourceService.getSchemaName(workspaceId); + + return await this.workspaceDataSourceService.executeRawQuery( + `SELECT * FROM ${dataSourceSchema}.person WHERE email = ANY($1)`, + [emails], + workspaceId, + transactionManager, + ); + } + async createPeople( peopleToCreate: { id: string; diff --git a/packages/twenty-server/src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.service.ts b/packages/twenty-server/src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.service.ts index 9d953df9e..4ef1d2671 100644 --- a/packages/twenty-server/src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.service.ts +++ b/packages/twenty-server/src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.service.ts @@ -24,10 +24,22 @@ export class CreateCompaniesAndContactsService { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); + const uniqueHandles = Array.from( + new Set(participants.map((participant) => participant.handle)), + ); + + const uniqueParticipants = uniqueHandles.map((handle) => { + const participant = participants.find( + (participant) => participant.handle === handle, + ); + + return participant; + }) as Participant[]; + const alreadyCreatedContacts = await this.workspaceDataSourceService.executeRawQuery( `SELECT email FROM ${dataSourceSchema}."person" WHERE "email" = ANY($1)`, - [participants.map((participant) => participant.handle)], + [uniqueParticipants.map((participant) => participant.handle)], workspaceId, transactionManager, ); @@ -36,7 +48,7 @@ export class CreateCompaniesAndContactsService { ({ email }) => email, ); - const filteredParticipants = participants.filter( + const filteredParticipants = uniqueParticipants.filter( (participant) => !alreadyCreatedContactEmails.includes(participant.handle) && participant.handle.includes('@'),