'use strict'; module.exports = { async up(queryInterface, Sequelize) { await queryInterface.createTable('email_broadcasts', { email_broadcast_id: { type: Sequelize.BIGINT, primaryKey: true, autoIncrement: true }, email_template_id: { type: Sequelize.BIGINT, allowNull: false, references: { model: 'email_templates', key: 'email_template_id' } }, target_type: { type: Sequelize.ENUM('admin', 'user', 'both', 'task_list', 'course', 'tier_plan'), allowNull: false }, target_id: { type: Sequelize.STRING(64), allowNull: true }, status: { type: Sequelize.ENUM('queued', 'sending', 'completed', 'canceled'), allowNull: false, defaultValue: 'queued' }, total_recipients: { type: Sequelize.INTEGER, allowNull: false, defaultValue: 0 }, sent_count: { type: Sequelize.INTEGER, allowNull: false, defaultValue: 0 }, failed_count: { type: Sequelize.INTEGER, allowNull: false, defaultValue: 0 }, started_at: { type: Sequelize.DATE, allowNull: true }, completed_at: { type: Sequelize.DATE, allowNull: true }, createdBy: { type: Sequelize.BIGINT, allowNull: true }, createdAt: { type: Sequelize.DATE, allowNull: false }, updatedAt: { type: Sequelize.DATE, allowNull: false }, }); await queryInterface.addIndex('email_broadcasts', ['status']); await queryInterface.createTable('email_broadcast_recipients', { email_broadcast_recipient_id: { type: Sequelize.BIGINT, primaryKey: true, autoIncrement: true }, email_broadcast_id: { type: Sequelize.BIGINT, allowNull: false, references: { model: 'email_broadcasts', key: 'email_broadcast_id' } }, user_id: { type: Sequelize.BIGINT, allowNull: true }, email: { type: Sequelize.STRING(255), allowNull: false }, name: { type: Sequelize.STRING(255), allowNull: true }, status: { type: Sequelize.ENUM('pending', 'sent', 'failed'), allowNull: false, defaultValue: 'pending' }, error: { type: Sequelize.TEXT, allowNull: true }, sent_at: { type: Sequelize.DATE, allowNull: true }, createdAt: { type: Sequelize.DATE, allowNull: false }, updatedAt: { type: Sequelize.DATE, allowNull: false }, }); // The cron's core query: "give me the next pending batch for a broadcast". await queryInterface.addIndex('email_broadcast_recipients', ['email_broadcast_id', 'status']); }, async down(queryInterface) { await queryInterface.dropTable('email_broadcast_recipients'); await queryInterface.dropTable('email_broadcasts'); await queryInterface.sequelize.query(`DROP TYPE IF EXISTS "enum_email_broadcast_recipients_status";`); await queryInterface.sequelize.query(`DROP TYPE IF EXISTS "enum_email_broadcasts_status";`); await queryInterface.sequelize.query(`DROP TYPE IF EXISTS "enum_email_broadcasts_target_type";`); }, };