Migrate domainName field from text type to links type (#6410)

Closes #5759.
This commit is contained in:
Marie
2024-07-30 11:47:37 +02:00
committed by GitHub
parent fb0fd99a38
commit 8e35edad30
44 changed files with 888 additions and 217 deletions

View File

@ -20,6 +20,7 @@ export class CompanyRepository {
public async getExistingCompaniesByDomainNames(
domainNames: string[],
workspaceId: string,
companyDomainNameColumnName: string,
transactionManager?: EntityManager,
): Promise<{ id: string; domainName: string }[]> {
const dataSourceSchema =
@ -27,7 +28,7 @@ export class CompanyRepository {
const existingCompanies =
await this.workspaceDataSourceService.executeRawQuery(
`SELECT id, "domainName" FROM ${dataSourceSchema}.company WHERE "domainName" = ANY($1)`,
`SELECT id, "${companyDomainNameColumnName}" AS "domainName" FROM ${dataSourceSchema}.company WHERE REGEXP_REPLACE("${companyDomainNameColumnName}", '^https?://', '') = ANY($1)`,
[domainNames],
workspaceId,
transactionManager,
@ -56,6 +57,7 @@ export class CompanyRepository {
public async createCompany(
workspaceId: string,
companyToCreate: CompanyToCreate,
companyDomainNameColumnName,
transactionManager?: EntityManager,
): Promise<void> {
const dataSourceSchema =
@ -67,11 +69,11 @@ export class CompanyRepository {
);
await this.workspaceDataSourceService.executeRawQuery(
`INSERT INTO ${dataSourceSchema}.company (id, "domainName", name, "addressAddressCity", position)
`INSERT INTO ${dataSourceSchema}.company (id, "${companyDomainNameColumnName}", name, "addressAddressCity", position)
VALUES ($1, $2, $3, $4, $5)`,
[
companyToCreate.id,
companyToCreate.domainName,
'https://' + companyToCreate.domainName,
companyToCreate.name ?? '',
companyToCreate.city ?? '',
lastCompanyPosition + 1,

View File

@ -48,7 +48,7 @@ export class CompanyWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.domainName,
type: FieldMetadataType.TEXT,
type: FieldMetadataType.LINKS,
label: 'Domain Name',
description:
'The company website URL. We use this url to fetch the company icon',

View File

@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
@ -24,6 +25,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta
WorkspaceDataSourceModule,
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
TypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'),
TypeOrmModule.forFeature([FieldMetadataEntity], 'metadata'),
],
providers: [
CreateCompanyService,

View File

@ -7,8 +7,13 @@ import compact from 'lodash.compact';
import { EntityManager, Repository } from 'typeorm';
import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event';
import {
FieldMetadataEntity,
FieldMetadataType,
} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
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 { COMPANY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { CONTACTS_CREATION_BATCH_SIZE } from 'src/modules/contact-creation-manager/constants/contacts-creation-batch-size.constant';
@ -36,12 +41,15 @@ export class CreateCompanyAndContactService {
private readonly eventEmitter: EventEmitter2,
@InjectRepository(ObjectMetadataEntity, 'metadata')
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(FieldMetadataEntity, 'metadata')
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
) {}
private async createCompaniesAndPeople(
connectedAccount: ConnectedAccountWorkspaceEntity,
contactsToCreate: Contact[],
workspaceId: string,
companyDomainNameColumnName: string,
transactionManager?: EntityManager,
): Promise<PersonWorkspaceEntity[]> {
if (!contactsToCreate || contactsToCreate.length === 0) {
@ -103,6 +111,7 @@ export class CreateCompanyAndContactService {
const companiesObject = await this.createCompaniesService.createCompanies(
domainNamesToCreate,
workspaceId,
companyDomainNameColumnName,
transactionManager,
);
@ -146,11 +155,24 @@ export class CreateCompanyAndContactService {
throw new Error('Object metadata not found');
}
const domainNameFieldMetadata = await this.fieldMetadataRepository.findOne({
where: {
workspaceId: workspaceId,
standardId: COMPANY_STANDARD_FIELD_IDS.domainName,
},
});
const companyDomainNameColumnName =
domainNameFieldMetadata?.type === FieldMetadataType.LINKS
? 'domainNamePrimaryLinkUrl'
: 'domainName';
for (const contactsBatch of contactsBatches) {
const createdPeople = await this.createCompaniesAndPeople(
connectedAccount,
contactsBatch,
workspaceId,
companyDomainNameColumnName,
);
for (const createdPerson of createdPeople) {

View File

@ -8,6 +8,7 @@ import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repos
import { CompanyRepository } from 'src/modules/company/repositories/company.repository';
import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { getCompanyNameFromDomainName } from 'src/modules/contact-creation-manager/utils/get-company-name-from-domain-name.util';
import { getCompanyDomainName } from 'src/utils/getCompanyDomainName';
@Injectable()
export class CreateCompanyService {
private readonly httpService: AxiosInstance;
@ -24,6 +25,7 @@ export class CreateCompanyService {
async createCompanies(
domainNames: string[],
workspaceId: string,
companyDomainNameColumnName: string,
transactionManager?: EntityManager,
): Promise<{
[domainName: string]: string;
@ -38,6 +40,7 @@ export class CreateCompanyService {
await this.companyRepository.getExistingCompaniesByDomainNames(
uniqueDomainNames,
workspaceId,
companyDomainNameColumnName,
transactionManager,
);
@ -61,7 +64,7 @@ export class CreateCompanyService {
(domainName) =>
!existingCompanies.some(
(company: { domainName: string }) =>
company.domainName === domainName,
getCompanyDomainName(company) === domainName,
),
);
@ -69,6 +72,7 @@ export class CreateCompanyService {
companiesObject[domainName] = await this.createCompany(
domainName,
workspaceId,
companyDomainNameColumnName,
transactionManager,
);
}
@ -79,6 +83,7 @@ export class CreateCompanyService {
private async createCompany(
domainName: string,
workspaceId: string,
companyDomainNameColumnName,
transactionManager?: EntityManager,
): Promise<string> {
const companyId = v4();
@ -93,6 +98,7 @@ export class CreateCompanyService {
name,
city,
},
companyDomainNameColumnName,
transactionManager,
);

View File

@ -17,6 +17,7 @@ export class ViewService {
fieldId,
viewsIds,
positions,
size,
}: {
workspaceId: string;
fieldId: string;
@ -24,6 +25,7 @@ export class ViewService {
positions?: {
[key: string]: number;
}[];
size?: number;
}) {
const viewFieldRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace(
@ -51,6 +53,7 @@ export class ViewService {
fieldMetadataId: fieldId,
isVisible: true,
...(isDefined(position) && { position: position }),
...(isDefined(size) && { size: size }),
});
await viewFieldRepository.save(newViewField);