import { MigrationInterface, QueryRunner, Table, TableForeignKey, TableIndex, } from 'typeorm'; import { NOTIFICATION_SCENARIOS } from '../../notifications/constants/notification-scenarios.constants'; import { NotificationScenarioKey } from '../../notifications/enums/notification-scenario-key.enum'; /** Keys that exist on the enum created in this migration (deposit key is seeded later). */ const INITIAL_NOTIFICATION_KEYS = [ NotificationScenarioKey.RESERVE_CREATED, NotificationScenarioKey.RESERVE_CONFIRMED, NotificationScenarioKey.RESERVE_CANCELLED, NotificationScenarioKey.RESERVE_REMINDER_SENT, NotificationScenarioKey.CAMPAIGN_SENT, NotificationScenarioKey.CAMPAIGN_FAILED, ]; export class AddNotifications1721500000000 implements MigrationInterface { name = 'AddNotifications1721500000000'; public async up(queryRunner: QueryRunner): Promise { await queryRunner.query(` CREATE TYPE "notification_scenario_key_enum" AS ENUM ( 'reserve_created', 'reserve_confirmed', 'reserve_cancelled', 'reserve_reminder_sent', 'campaign_sent', 'campaign_failed' ) `); await queryRunner.createTable( new Table({ name: 'notification_scenario_settings', columns: [ { name: 'id', type: 'uuid', isPrimary: true, generationStrategy: 'uuid', default: 'gen_random_uuid()', }, { name: 'key', type: 'notification_scenario_key_enum', isUnique: true, }, { name: 'title', type: 'varchar', length: '300', isNullable: true }, { name: 'body', type: 'text', isNullable: true }, { name: 'isActive', type: 'boolean', default: true }, { name: 'createdAt', type: 'timestamp', default: 'now()' }, { name: 'updatedAt', type: 'timestamp', default: 'now()' }, ], }), true, ); await queryRunner.createIndex( 'notification_scenario_settings', new TableIndex({ name: 'IDX_notification_scenario_settings_key', columnNames: ['key'], isUnique: true, }), ); await queryRunner.createTable( new Table({ name: 'notifications', columns: [ { name: 'id', type: 'uuid', isPrimary: true, generationStrategy: 'uuid', default: 'gen_random_uuid()', }, { name: 'salonId', type: 'uuid' }, { name: 'userId', type: 'uuid' }, { name: 'scenarioKey', type: 'notification_scenario_key_enum', }, { name: 'title', type: 'varchar', length: '300' }, { name: 'body', type: 'text' }, { name: 'link', type: 'varchar', length: '500', isNullable: true }, { name: 'relatedEntityType', type: 'varchar', length: '50', isNullable: true, }, { name: 'relatedEntityId', type: 'uuid', isNullable: true, }, { name: 'isRead', type: 'boolean', default: false }, { name: 'createdAt', type: 'timestamp', default: 'now()' }, { name: 'updatedAt', type: 'timestamp', default: 'now()' }, ], }), true, ); await queryRunner.createIndex( 'notifications', new TableIndex({ name: 'IDX_notifications_salonId_createdAt', columnNames: ['salonId', 'createdAt'], }), ); await queryRunner.createIndex( 'notifications', new TableIndex({ name: 'IDX_notifications_userId_isRead_createdAt', columnNames: ['userId', 'isRead', 'createdAt'], }), ); await queryRunner.createIndex( 'notifications', new TableIndex({ name: 'IDX_notifications_scenarioKey', columnNames: ['scenarioKey'], }), ); await queryRunner.createForeignKey( 'notifications', new TableForeignKey({ name: 'FK_notifications_salonId', columnNames: ['salonId'], referencedTableName: 'salons', referencedColumnNames: ['id'], onDelete: 'CASCADE', }), ); await queryRunner.createForeignKey( 'notifications', new TableForeignKey({ name: 'FK_notifications_userId', columnNames: ['userId'], referencedTableName: 'users', referencedColumnNames: ['id'], onDelete: 'CASCADE', }), ); for (const key of INITIAL_NOTIFICATION_KEYS) { const scenario = NOTIFICATION_SCENARIOS.find((item) => item.key === key); if (!scenario) { continue; } await queryRunner.query( ` INSERT INTO notification_scenario_settings (key, title, body, "isActive") VALUES ($1, $2, $3, true) ON CONFLICT (key) DO NOTHING `, [scenario.key, scenario.defaultTitle, scenario.defaultBody], ); } } public async down(queryRunner: QueryRunner): Promise { await queryRunner.dropTable('notifications', true); await queryRunner.dropTable('notification_scenario_settings', true); await queryRunner.query('DROP TYPE "notification_scenario_key_enum"'); } }