From b8099bcdb9e0387e8df5266b6b153a258eec5454 Mon Sep 17 00:00:00 2001 From: lynaDev2 Date: Mon, 29 Jun 2026 15:50:24 +0000 Subject: [PATCH] feat(migration): add Location entity migration --- backend/src/migrations/AddLocationEntity.ts | 141 ++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 backend/src/migrations/AddLocationEntity.ts diff --git a/backend/src/migrations/AddLocationEntity.ts b/backend/src/migrations/AddLocationEntity.ts new file mode 100644 index 0000000..89c3410 --- /dev/null +++ b/backend/src/migrations/AddLocationEntity.ts @@ -0,0 +1,141 @@ +import { + MigrationInterface, + QueryRunner, + Table, + TableColumn, + TableForeignKey, + TableIndex, +} from 'typeorm'; + +export class AddLocationEntity1751290000000 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + // Create locations table + await queryRunner.createTable( + new Table({ + name: 'locations', + columns: [ + { + name: 'id', + type: 'uuid', + isPrimary: true, + generationStrategy: 'uuid', + default: 'uuid_generate_v4()', + }, + { + name: 'name', + type: 'varchar', + }, + { + name: 'address', + type: 'varchar', + }, + { + name: 'city', + type: 'varchar', + }, + { + name: 'country', + type: 'varchar', + default: "'Nigeria'", + }, + { + name: 'timezone', + type: 'varchar', + default: "'Africa/Lagos'", + }, + { + name: 'isActive', + type: 'boolean', + default: true, + }, + { + name: 'createdAt', + type: 'timestamp', + default: 'CURRENT_TIMESTAMP', + }, + { + name: 'updatedAt', + type: 'timestamp', + default: 'CURRENT_TIMESTAMP', + }, + ], + }), + true, + ); + + // Add locationId column to workspaces + await queryRunner.addColumn( + 'workspaces', + new TableColumn({ + name: 'locationId', + type: 'uuid', + isNullable: true, + }), + ); + + // Create index + await queryRunner.createIndex( + 'workspaces', + new TableIndex({ + name: 'IDX_WORKSPACE_LOCATION', + columnNames: ['locationId'], + }), + ); + + // Create foreign key + await queryRunner.createForeignKey( + 'workspaces', + new TableForeignKey({ + columnNames: ['locationId'], + referencedTableName: 'locations', + referencedColumnNames: ['id'], + onDelete: 'SET NULL', + }), + ); + + // Seed default location and assign existing workspaces + await queryRunner.query(` + INSERT INTO locations + ("id", "name", "address", "city", "country", "timezone", "isActive", "createdAt", "updatedAt") + VALUES + ( + uuid_generate_v4(), + 'Default Location', + 'Unknown Address', + 'Unknown City', + 'Nigeria', + 'Africa/Lagos', + true, + NOW(), + NOW() + ); + `); + + await queryRunner.query(` + UPDATE workspaces + SET "locationId" = ( + SELECT id + FROM locations + WHERE name = 'Default Location' + LIMIT 1 + ) + WHERE "locationId" IS NULL; + `); + } + + public async down(queryRunner: QueryRunner): Promise { + const table = await queryRunner.getTable('workspaces'); + + const foreignKey = table?.foreignKeys.find( + fk => fk.columnNames.indexOf('locationId') !== -1, + ); + + if (foreignKey) { + await queryRunner.dropForeignKey('workspaces', foreignKey); + } + + await queryRunner.dropIndex('workspaces', 'IDX_WORKSPACE_LOCATION'); + await queryRunner.dropColumn('workspaces', 'locationId'); + await queryRunner.dropTable('locations'); + } +} \ No newline at end of file