'use strict'; module.exports = { async up(queryInterface, Sequelize) { await queryInterface.createTable('notification_templates', { notification_template_id: { type: Sequelize.BIGINT, primaryKey: true, autoIncrement: true }, type: { type: Sequelize.STRING(100), allowNull: false, unique: true }, notify_type: { type: Sequelize.STRING(64), allowNull: false }, scope: { type: Sequelize.ENUM('admin', 'user', 'both'), allowNull: false }, label: { type: Sequelize.STRING(150), allowNull: false }, status: { type: Sequelize.ENUM('draft', 'sent'), allowNull: false, defaultValue: 'draft' }, title: { type: Sequelize.STRING(255), allowNull: true }, message: { type: Sequelize.TEXT, allowNull: true }, draft_title: { type: Sequelize.STRING(255), allowNull: true }, draft_message: { type: Sequelize.TEXT, allowNull: true }, last_sent_at: { type: Sequelize.DATE, allowNull: true }, is_system: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: false }, createdAt: { type: Sequelize.DATE, allowNull: false }, updatedAt: { type: Sequelize.DATE, allowNull: false }, }); const now = new Date(); // Ported straight from data/notifications.data.js's NOTIFICATION_REGISTRY — // seeded already-published (status: 'sent', content in the live title/message // columns) because these types fire in production right now via cron/event // triggers. Seeding them as drafts would make every trigger site throw // "no published version yet" the moment this migration lands. await queryInterface.bulkInsert('notification_templates', [ { type: 'task_overdue', notify_type: 'task_overdue', scope: 'admin', is_system: true, label: 'Tasks Overdue (Admin)', status: 'sent', title: 'Tasks Overdue', message: '{{count}} {{task_word}} automatically marked as overdue.', createdAt: now, updatedAt: now, }, { type: 'user_registration', notify_type: 'user_registration', scope: 'admin', is_system: true, label: 'New User Registered', status: 'sent', title: 'New User Registered', message: 'A new user registered in {{groupName}}.', createdAt: now, updatedAt: now, }, { type: 'nogrp_user_registered', notify_type: 'nogrp_user_registered', scope: 'admin', is_system: true, label: 'New Unaffiliated User', status: 'sent', title: 'New Unaffiliated User', message: 'A new user ({{userEmail}}) registered via {{regType}} without a group code and was placed in the default group.', createdAt: now, updatedAt: now, }, { type: 'task_requirements_updated', notify_type: 'task', scope: 'user', is_system: true, label: 'Task Requirements Updated', status: 'sent', title: 'Task Updated', message: 'The requirements for "{{taskName}}" have been updated by your administrator.', createdAt: now, updatedAt: now, }, { type: 'user_task_overdue', notify_type: 'task', scope: 'user', is_system: true, label: 'Tasks Overdue (User)', status: 'sent', title: 'Tasks Overdue', message: '{{task_label}} passed their deadline and been marked as overdue.', createdAt: now, updatedAt: now, }, { type: 'task_reminder', notify_type: 'task', scope: 'user', is_system: true, label: 'Task Deadline Approaching', status: 'sent', title: 'Task Deadline Approaching', message: '"{{taskName}}" is due on {{deadline}}.', createdAt: now, updatedAt: now, }, { type: 'course_unlocked', notify_type: 'course', scope: 'user', is_system: true, label: 'New Course Available', status: 'sent', title: 'New Course Available', message: '"{{courseTitle}}" has been added to your learning library.', createdAt: now, updatedAt: now, }, { type: 'course_completed', notify_type: 'course', scope: 'user', is_system: true, label: 'Course Completed', status: 'sent', title: 'Course Completed', message: 'Great job! You\'ve completed "{{courseTitle}}". Your certificate will be issued within the next hour.', createdAt: now, updatedAt: now, }, { type: 'certificate_issued', notify_type: 'course', scope: 'user', is_system: true, label: 'Certificate Issued', status: 'sent', title: 'Certificate Issued', message: 'Congratulations! Your certificate for "{{courseTitle}}" is ready.', createdAt: now, updatedAt: now, }, { type: 'welcome', notify_type: 'announcement', scope: 'user', is_system: true, label: 'Welcome Message', status: 'sent', title: 'Welcome to Philproperties', message: '{{greeting}}{{group_suffix}}', createdAt: now, updatedAt: now, }, { type: 'nogrp_welcome', notify_type: 'announcement', scope: 'user', is_system: true, label: "Not in a Group Yet", status: 'sent', title: "You're Not in a Group Yet", message: 'You are currently in the default group. Contact an administrator to be assigned to your team.', createdAt: now, updatedAt: now, }, { type: 'assessment_updated', notify_type: 'assessment', scope: 'user', is_system: true, label: 'Assessment Updated', status: 'sent', title: 'Assessment Updated', message: 'The administrator has updated the "{{assessmentTitle}}" in "{{courseTitle}}". Your current session is still valid — continue where you left off.', createdAt: now, updatedAt: now, }, { type: 'tier_expired', notify_type: 'tier_expired', scope: 'user', is_system: true, label: 'Subscription Expired', status: 'sent', title: 'Subscription Expired', message: 'Your {{planLabel}} plan has expired. Renew to keep access.', createdAt: now, updatedAt: now, }, ]); }, async down(queryInterface) { await queryInterface.dropTable('notification_templates'); await queryInterface.sequelize.query(`DROP TYPE IF EXISTS "enum_notification_templates_scope";`); await queryInterface.sequelize.query(`DROP TYPE IF EXISTS "enum_notification_templates_status";`); }, };