notification

This commit is contained in:
2026-07-09 20:58:19 +03:30
parent 0732964753
commit c485ee326c
21 changed files with 1402 additions and 1 deletions
@@ -0,0 +1,161 @@
import {
MigrationInterface,
QueryRunner,
Table,
TableForeignKey,
TableIndex,
} from 'typeorm';
import { NOTIFICATION_SCENARIOS } from '../../notifications/constants/notification-scenarios.constants';
export class AddNotifications1721500000000 implements MigrationInterface {
name = 'AddNotifications1721500000000';
public async up(queryRunner: QueryRunner): Promise<void> {
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 scenario of NOTIFICATION_SCENARIOS) {
await queryRunner.query(
`
INSERT INTO notification_scenario_settings (key, title, body, "isActive")
VALUES ($1, $2, $3, true)
`,
[scenario.key, scenario.defaultTitle, scenario.defaultBody],
);
}
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable('notifications', true);
await queryRunner.dropTable('notification_scenario_settings', true);
await queryRunner.query('DROP TYPE "notification_scenario_key_enum"');
}
}