[Emails migration] Fix email field migration (#7065)

Fix email field migration

- Remove deprecated field of type Email
- Add standard emails field on person to person views in position 4
This commit is contained in:
Marie 2024-09-16 19:35:13 +02:00 committed by GitHub
parent b0c9b9ebe2
commit dcac832616
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 192 additions and 0 deletions

View File

@ -0,0 +1,161 @@
import { InjectRepository } from '@nestjs/typeorm';
import chalk from 'chalk';
import { isDefined } from 'class-validator';
import { Command } from 'nest-commander';
import { Repository } from 'typeorm';
import {
ActiveWorkspacesCommandOptions,
ActiveWorkspacesCommandRunner,
} from 'src/database/commands/active-workspaces.command';
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service';
import { PERSON_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { ViewService } from 'src/modules/view/services/view.service';
@Command({
name: 'upgrade-0.30:fix-email-field-migration',
description:
'Fix migration - delete deprecated email fields and add emails to person views',
})
export class FixEmailFieldsToEmailsCommand extends ActiveWorkspacesCommandRunner {
constructor(
@InjectRepository(Workspace, 'core')
protected readonly workspaceRepository: Repository<Workspace>,
@InjectRepository(FieldMetadataEntity, 'metadata')
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
private readonly fieldMetadataService: FieldMetadataService,
private readonly typeORMService: TypeORMService,
private readonly dataSourceService: DataSourceService,
private readonly viewService: ViewService,
) {
super(workspaceRepository);
}
async executeActiveWorkspacesCommand(
_passedParam: string[],
_options: ActiveWorkspacesCommandOptions,
workspaceIds: string[],
): Promise<void> {
this.logger.log('Running command to fix migration');
for (const workspaceId of workspaceIds) {
let dataSourceMetadata;
this.logger.log(`Running command for workspace ${workspaceId}`);
try {
dataSourceMetadata =
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId(
workspaceId,
);
if (!dataSourceMetadata) {
throw new Error(
`Could not find dataSourceMetadata for workspace ${workspaceId}`,
);
}
const workspaceDataSource =
await this.typeORMService.connectToDataSource(dataSourceMetadata);
if (!workspaceDataSource) {
throw new Error(
`Could not connect to dataSource for workspace ${workspaceId}`,
);
}
} catch (error) {
this.logger.log(
chalk.red(
`Could not connect to workspace data source for workspace ${workspaceId}`,
),
);
continue;
}
try {
const deprecatedPersonEmailFieldsMetadata =
await this.fieldMetadataRepository.findBy({
standardId: PERSON_STANDARD_FIELD_IDS.email,
workspaceId: workspaceId,
});
const migratedEmailFieldMetadata = await this.fieldMetadataRepository
.findBy({
standardId: PERSON_STANDARD_FIELD_IDS.emails,
workspaceId: workspaceId,
})
.then((fields) => fields[0]);
const personEmailFieldWasMigratedButHasDuplicate =
deprecatedPersonEmailFieldsMetadata.length > 0 &&
isDefined(migratedEmailFieldMetadata);
if (!personEmailFieldWasMigratedButHasDuplicate) {
this.logger.log(
chalk.yellow('No fields to migrate for workspace ' + workspaceId),
);
continue;
}
for (const deprecatedEmailFieldMetadata of deprecatedPersonEmailFieldsMetadata) {
await this.fieldMetadataService.deleteOneField(
{ id: deprecatedEmailFieldMetadata.id },
workspaceId,
);
this.logger.log(
chalk.green(`Deleted email field for workspace ${workspaceId}.`),
);
}
const personObjectMetadaIdForWorkspace =
migratedEmailFieldMetadata.objectMetadataId;
if (!isDefined(personObjectMetadaIdForWorkspace)) {
this.logger.log(
chalk.red(
`Could not find person object for workspace ${workspaceId}. Could not add emails to person view`,
),
);
continue;
}
const personViewsIds =
await this.viewService.getViewsIdsForObjectMetadataId({
workspaceId,
objectMetadataId: personObjectMetadaIdForWorkspace as string,
});
await this.viewService.addFieldToViews({
workspaceId: workspaceId,
fieldId: migratedEmailFieldMetadata.id,
viewsIds: personViewsIds,
positions: personViewsIds.reduce((acc, personView) => {
if (!personView.id) {
return acc;
}
acc[personView.id] = 4;
return acc;
}, []),
});
this.logger.log(chalk.green(`Added emails to view ${workspaceId}.`));
} catch (error) {
this.logger.log(
chalk.red(
`Running command on workspace ${workspaceId} failed with error: ${error}`,
),
);
continue;
} finally {
this.logger.log(
chalk.green(`Finished running command for workspace ${workspaceId}.`),
);
}
this.logger.log(chalk.green(`Command completed!`));
}
}
}

View File

@ -4,6 +4,7 @@ import { Command } from 'nest-commander';
import { Repository } from 'typeorm';
import { ActiveWorkspacesCommandRunner } from 'src/database/commands/active-workspaces.command';
import { FixEmailFieldsToEmailsCommand } from 'src/database/commands/upgrade-version/0-30/0-30-fix-email-field-migration.command';
import { MigrateEmailFieldsToEmailsCommand } from 'src/database/commands/upgrade-version/0-30/0-30-migrate-email-fields-to-emails.command';
import { SetStaleMessageSyncBackToPendingCommand } from 'src/database/commands/upgrade-version/0-30/0-30-set-stale-message-sync-back-to-pending';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
@ -24,6 +25,7 @@ export class UpgradeTo0_30Command extends ActiveWorkspacesCommandRunner {
private readonly syncWorkspaceMetadataCommand: SyncWorkspaceMetadataCommand,
private readonly migrateEmailFieldsToEmails: MigrateEmailFieldsToEmailsCommand,
private readonly setStaleMessageSyncBackToPendingCommand: SetStaleMessageSyncBackToPendingCommand,
private readonly fixEmailFieldsToEmailsCommand: FixEmailFieldsToEmailsCommand,
) {
super(workspaceRepository);
}
@ -51,5 +53,10 @@ export class UpgradeTo0_30Command extends ActiveWorkspacesCommandRunner {
options,
workspaceIds,
);
await this.fixEmailFieldsToEmailsCommand.executeActiveWorkspacesCommand(
passedParam,
options,
workspaceIds,
);
}
}

View File

@ -1,6 +1,7 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { FixEmailFieldsToEmailsCommand } from 'src/database/commands/upgrade-version/0-30/0-30-fix-email-field-migration.command';
import { MigrateEmailFieldsToEmailsCommand } from 'src/database/commands/upgrade-version/0-30/0-30-migrate-email-fields-to-emails.command';
import { SetStaleMessageSyncBackToPendingCommand } from 'src/database/commands/upgrade-version/0-30/0-30-set-stale-message-sync-back-to-pending';
import { UpgradeTo0_30Command } from 'src/database/commands/upgrade-version/0-30/0-30-upgrade-version.command';
@ -32,6 +33,7 @@ import { ViewModule } from 'src/modules/view/view.module';
UpgradeTo0_30Command,
MigrateEmailFieldsToEmailsCommand,
SetStaleMessageSyncBackToPendingCommand,
FixEmailFieldsToEmailsCommand,
],
})
export class UpgradeTo0_30CommandModule {}

View File

@ -98,4 +98,26 @@ export class ViewService {
);
}
}
async getViewsIdsForObjectMetadataId({
workspaceId,
objectMetadataId,
}: {
workspaceId: string;
objectMetadataId: string;
}) {
const viewRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace(
workspaceId,
'view',
);
return viewRepository
.find({
where: {
objectMetadataId: objectMetadataId,
},
})
.then((views) => views.map((view) => view.id));
}
}