4008 dont create a contact company if it matches the persons domain (#4088)
* Add SettingsAccountsEmailsBlocklistInput story * prevent contact creation from the same company * add todo * improvements * Delete packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistInput.stories.tsx * refactor * modify after review * improve code * create utils * fix * Fix getAllByWorkspaceId to throw NotFoundException when no workspace member found * fix after merge * use map * modify after review
This commit is contained in:
@ -1,5 +1,7 @@
|
|||||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { EntityManager } from 'typeorm';
|
||||||
|
|
||||||
import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service';
|
import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service';
|
||||||
import { WorkspaceMemberObjectMetadata } from 'src/workspace/workspace-sync-metadata/standard-objects/workspace-member.object-metadata';
|
import { WorkspaceMemberObjectMetadata } from 'src/workspace/workspace-sync-metadata/standard-objects/workspace-member.object-metadata';
|
||||||
import { ObjectRecord } from 'src/workspace/workspace-sync-metadata/types/object-record';
|
import { ObjectRecord } from 'src/workspace/workspace-sync-metadata/types/object-record';
|
||||||
@ -24,7 +26,7 @@ export class WorkspaceMemberService {
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
return result.rows;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getByIdOrFail(
|
public async getByIdOrFail(
|
||||||
@ -47,4 +49,22 @@ export class WorkspaceMemberService {
|
|||||||
|
|
||||||
return workspaceMembers[0];
|
return workspaceMembers[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getAllByWorkspaceId(
|
||||||
|
workspaceId: string,
|
||||||
|
transactionManager?: EntityManager,
|
||||||
|
): Promise<ObjectRecord<WorkspaceMemberObjectMetadata>[]> {
|
||||||
|
const dataSourceSchema =
|
||||||
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
|
const workspaceMembers =
|
||||||
|
await this.workspaceDataSourceService.executeRawQuery(
|
||||||
|
`SELECT * FROM ${dataSourceSchema}."workspaceMember"`,
|
||||||
|
[],
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
|
||||||
|
return workspaceMembers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { PersonModule } from 'src/workspace/messaging/repositories/person/person.module';
|
import { PersonModule } from 'src/workspace/messaging/repositories/person/person.module';
|
||||||
|
import { WorkspaceMemberModule } from 'src/workspace/messaging/repositories/workspace-member/workspace-member.module';
|
||||||
import { CreateCompaniesAndContactsService } from 'src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.service';
|
import { CreateCompaniesAndContactsService } from 'src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.service';
|
||||||
import { CreateCompanyModule } from 'src/workspace/messaging/services/create-company/create-company.module';
|
import { CreateCompanyModule } from 'src/workspace/messaging/services/create-company/create-company.module';
|
||||||
import { CreateContactModule } from 'src/workspace/messaging/services/create-contact/create-contact.module';
|
import { CreateContactModule } from 'src/workspace/messaging/services/create-contact/create-contact.module';
|
||||||
@ -11,6 +12,7 @@ import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/wo
|
|||||||
WorkspaceDataSourceModule,
|
WorkspaceDataSourceModule,
|
||||||
CreateContactModule,
|
CreateContactModule,
|
||||||
CreateCompanyModule,
|
CreateCompanyModule,
|
||||||
|
WorkspaceMemberModule,
|
||||||
PersonModule,
|
PersonModule,
|
||||||
],
|
],
|
||||||
providers: [CreateCompaniesAndContactsService],
|
providers: [CreateCompaniesAndContactsService],
|
||||||
|
|||||||
@ -7,6 +7,9 @@ import { getDomainNameFromHandle } from 'src/workspace/messaging/utils/get-domai
|
|||||||
import { CreateCompanyService } from 'src/workspace/messaging/services/create-company/create-company.service';
|
import { CreateCompanyService } from 'src/workspace/messaging/services/create-company/create-company.service';
|
||||||
import { CreateContactService } from 'src/workspace/messaging/services/create-contact/create-contact.service';
|
import { CreateContactService } from 'src/workspace/messaging/services/create-contact/create-contact.service';
|
||||||
import { PersonService } from 'src/workspace/messaging/repositories/person/person.service';
|
import { PersonService } from 'src/workspace/messaging/repositories/person/person.service';
|
||||||
|
import { WorkspaceMemberService } from 'src/workspace/messaging/repositories/workspace-member/workspace-member.service';
|
||||||
|
import { getUniqueParticipantsAndHandles } from 'src/workspace/messaging/utils/get-unique-participants-and-handles.util';
|
||||||
|
import { filterOutParticipantsFromCompanyOrWorkspace } from 'src/workspace/messaging/utils/filter-out-participants-from-company-or-workspace.util';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CreateCompaniesAndContactsService {
|
export class CreateCompaniesAndContactsService {
|
||||||
@ -14,6 +17,7 @@ export class CreateCompaniesAndContactsService {
|
|||||||
private readonly personService: PersonService,
|
private readonly personService: PersonService,
|
||||||
private readonly createContactService: CreateContactService,
|
private readonly createContactService: CreateContactService,
|
||||||
private readonly createCompaniesService: CreateCompanyService,
|
private readonly createCompaniesService: CreateCompanyService,
|
||||||
|
private readonly workspaceMemberService: WorkspaceMemberService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createCompaniesAndContacts(
|
async createCompaniesAndContacts(
|
||||||
@ -22,31 +26,26 @@ export class CreateCompaniesAndContactsService {
|
|||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
transactionManager?: EntityManager,
|
transactionManager?: EntityManager,
|
||||||
) {
|
) {
|
||||||
const selfDomainName = getDomainNameFromHandle(selfHandle);
|
if (participants.length === 0) {
|
||||||
|
|
||||||
// TODO: use isWorkEmail so we can create a contact even if the email is a personal email
|
|
||||||
const participantsFromOtherCompanies = participants.filter(
|
|
||||||
(participant) =>
|
|
||||||
getDomainNameFromHandle(participant.handle) !== selfDomainName,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!participantsFromOtherCompanies.length) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uniqueHandles = Array.from(
|
const workspaceMembers =
|
||||||
new Set(
|
await this.workspaceMemberService.getAllByWorkspaceId(
|
||||||
participantsFromOtherCompanies.map((participant) => participant.handle),
|
workspaceId,
|
||||||
),
|
transactionManager,
|
||||||
);
|
|
||||||
|
|
||||||
const uniqueParticipants = uniqueHandles.map((handle) => {
|
|
||||||
const participant = participantsFromOtherCompanies.find(
|
|
||||||
(participant) => participant.handle === handle,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return participant;
|
// TODO: use isWorkEmail so we can create a contact even if the email is a personal email ex: @gmail.com
|
||||||
}) as Participant[];
|
const participantsFromOtherCompanies =
|
||||||
|
filterOutParticipantsFromCompanyOrWorkspace(
|
||||||
|
participants,
|
||||||
|
selfHandle,
|
||||||
|
workspaceMembers,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { uniqueParticipants, uniqueHandles } =
|
||||||
|
getUniqueParticipantsAndHandles(participantsFromOtherCompanies);
|
||||||
|
|
||||||
const alreadyCreatedContacts = await this.personService.getByEmails(
|
const alreadyCreatedContacts = await this.personService.getByEmails(
|
||||||
uniqueHandles,
|
uniqueHandles,
|
||||||
|
|||||||
@ -0,0 +1,27 @@
|
|||||||
|
import { Participant } from 'src/workspace/messaging/types/gmail-message';
|
||||||
|
import { getDomainNameFromHandle } from 'src/workspace/messaging/utils/get-domain-name-from-handle.util';
|
||||||
|
import { WorkspaceMemberObjectMetadata } from 'src/workspace/workspace-sync-metadata/standard-objects/workspace-member.object-metadata';
|
||||||
|
import { ObjectRecord } from 'src/workspace/workspace-sync-metadata/types/object-record';
|
||||||
|
|
||||||
|
export function filterOutParticipantsFromCompanyOrWorkspace(
|
||||||
|
participants: Participant[],
|
||||||
|
selfHandle: string,
|
||||||
|
workspaceMembers: ObjectRecord<WorkspaceMemberObjectMetadata>[],
|
||||||
|
): Participant[] {
|
||||||
|
const selfDomainName = getDomainNameFromHandle(selfHandle);
|
||||||
|
|
||||||
|
const workspaceMembersMap = workspaceMembers.reduce(
|
||||||
|
(map, workspaceMember) => {
|
||||||
|
map[workspaceMember.userEmail] = true;
|
||||||
|
|
||||||
|
return map;
|
||||||
|
},
|
||||||
|
new Map<string, boolean>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return participants.filter(
|
||||||
|
(participant) =>
|
||||||
|
getDomainNameFromHandle(participant.handle) !== selfDomainName &&
|
||||||
|
!workspaceMembersMap[participant.handle],
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
import { Participant } from 'src/workspace/messaging/types/gmail-message';
|
||||||
|
|
||||||
|
export function getUniqueParticipantsAndHandles(participants: Participant[]): {
|
||||||
|
uniqueParticipants: Participant[];
|
||||||
|
uniqueHandles: string[];
|
||||||
|
} {
|
||||||
|
if (participants.length === 0) {
|
||||||
|
return { uniqueParticipants: [], uniqueHandles: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
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[];
|
||||||
|
|
||||||
|
return { uniqueParticipants, uniqueHandles };
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user