forked from twentyhq/twenty
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create convert record positions to integers command (twentyhq#5287)
## Context Positions are used within a view to display and sort the different records of standard/custom object. When we add a new record and want to put it before the existing first record, we have to use float values to insert them in the DB and respect the desired order. We are adding a new command that can be executed to flatten those positions. --------- Co-authored-by: bosiraphael <[email protected]>
- Loading branch information
1 parent
0b690a0
commit 71c73a5
Showing
2 changed files
with
132 additions
and
0 deletions.
There are no files selected for viewing
128 changes: 128 additions & 0 deletions
128
...-manager/workspace-sync-metadata/commands/convert-record-positions-to-integers.command.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import { Logger } from '@nestjs/common'; | ||
import { InjectDataSource } from '@nestjs/typeorm'; | ||
|
||
import { Command, CommandRunner, Option } from 'nest-commander'; | ||
import { DataSource } from 'typeorm'; | ||
|
||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; | ||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; | ||
|
||
interface RunCommandOptions { | ||
workspaceId?: string; | ||
} | ||
|
||
@Command({ | ||
name: 'workspace:convert-record-positions-to-integers', | ||
description: 'Convert record positions to integers', | ||
}) | ||
export class ConvertRecordPositionsToIntegers extends CommandRunner { | ||
private readonly logger = new Logger(ConvertRecordPositionsToIntegers.name); | ||
|
||
constructor( | ||
@InjectDataSource('metadata') | ||
private readonly metadataDataSource: DataSource, | ||
private readonly workspaceDataSourceService: WorkspaceDataSourceService, | ||
) { | ||
super(); | ||
} | ||
|
||
async run(_passedParam: string[], options: RunCommandOptions): Promise<void> { | ||
const queryRunner = this.metadataDataSource.createQueryRunner(); | ||
const workspaceId = options.workspaceId; | ||
|
||
if (!workspaceId || typeof workspaceId !== 'string') { | ||
this.logger.error('Workspace id is required'); | ||
|
||
return; | ||
} | ||
|
||
const customObjectMetadataCollection = await this.metadataDataSource | ||
.getRepository(ObjectMetadataEntity) | ||
.findBy({ | ||
workspaceId, | ||
isCustom: true, | ||
}); | ||
|
||
const customObjectTableNames = customObjectMetadataCollection.map( | ||
(metadata) => metadata.nameSingular, | ||
); | ||
|
||
await queryRunner.connect(); | ||
await queryRunner.startTransaction(); | ||
|
||
const transactionManager = queryRunner.manager; | ||
|
||
this.logger.log('Converting record positions to integers'); | ||
|
||
try { | ||
await this.convertRecordPositionsToIntegers( | ||
customObjectTableNames, | ||
workspaceId, | ||
transactionManager, | ||
); | ||
|
||
await queryRunner.commitTransaction(); | ||
} catch (error) { | ||
await queryRunner.rollbackTransaction(); | ||
this.logger.error('Error converting record positions to integers', error); | ||
} finally { | ||
await queryRunner.release(); | ||
this.logger.log('Record positions converted to integers'); | ||
} | ||
} | ||
|
||
private async convertRecordPositionsToIntegers( | ||
customObjectTableNames: string[], | ||
workspaceId: string, | ||
transactionManager: any, | ||
): Promise<void> { | ||
const dataSourceSchema = | ||
this.workspaceDataSourceService.getSchemaName(workspaceId); | ||
|
||
for (const tableName of ['company', 'person', 'opportunity']) { | ||
await this.convertRecordPositionsToIntegersForTable( | ||
tableName, | ||
dataSourceSchema, | ||
workspaceId, | ||
transactionManager, | ||
); | ||
} | ||
|
||
for (const tableName of customObjectTableNames) { | ||
await this.convertRecordPositionsToIntegersForTable( | ||
`_${tableName}`, | ||
dataSourceSchema, | ||
workspaceId, | ||
transactionManager, | ||
); | ||
} | ||
} | ||
|
||
private async convertRecordPositionsToIntegersForTable( | ||
tableName: string, | ||
dataSourceSchema: string, | ||
workspaceId: string, | ||
transactionManager: any, | ||
): Promise<void> { | ||
await this.workspaceDataSourceService.executeRawQuery( | ||
`UPDATE ${dataSourceSchema}.${tableName} SET position = subquery.position | ||
FROM ( | ||
SELECT id, ROW_NUMBER() OVER (ORDER BY position) as position | ||
FROM ${dataSourceSchema}.${tableName} | ||
) as subquery | ||
WHERE ${dataSourceSchema}.${tableName}.id = subquery.id`, | ||
[], | ||
workspaceId, | ||
transactionManager, | ||
); | ||
} | ||
|
||
@Option({ | ||
flags: '-w, --workspace-id [workspace_id]', | ||
description: 'workspace id', | ||
required: true, | ||
}) | ||
parseWorkspaceId(value: string): string { | ||
return value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters