'use strict'; module.exports = { async up(queryInterface, Sequelize) { await queryInterface.createTable('quiz_attempts', { attempt_id: { type: Sequelize.BIGINT, primaryKey: true, autoIncrement: true }, uuid: { type: Sequelize.UUID, defaultValue: Sequelize.UUIDV4, unique: true }, user_id: { type: Sequelize.BIGINT, allowNull: false, references: { model: 'users', key: 'user_id' }, onDelete: 'CASCADE' }, quiz_id: { type: Sequelize.BIGINT, allowNull: true, references: { model: 'unit_quizzes', key: 'quiz_id' }, onDelete: 'SET NULL' }, assessment_id: { type: Sequelize.BIGINT, allowNull: true, references: { model: 'course_assessments', key: 'assessment_id' }, onDelete: 'SET NULL' }, answers: { type: Sequelize.JSONB, allowNull: false, defaultValue: {} }, total_points: { type: Sequelize.INTEGER, allowNull: false, defaultValue: 0 }, earned_points: { type: Sequelize.INTEGER, allowNull: false, defaultValue: 0 }, score: { type: Sequelize.INTEGER, allowNull: false, defaultValue: 0 }, passed: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: false }, attempt_number: { type: Sequelize.INTEGER, allowNull: false, defaultValue: 1, comment: '1-based counter per user + quiz (or user + assessment). Derived at insert time from prior attempt count.', }, passing_score: { type: Sequelize.INTEGER, allowNull: true, comment: 'Snapshot of the required passing score at the time of submission.', }, course_id: { type: Sequelize.BIGINT, allowNull: true, references: { model: 'courses', key: 'course_id' }, onDelete: 'SET NULL', comment: 'Denormalized course reference for fast per-course attempt queries.', }, createdAt: { type: Sequelize.DATE, allowNull: false }, updatedAt: { type: Sequelize.DATE, allowNull: false }, }); await queryInterface.addIndex('quiz_attempts', ['user_id']); await queryInterface.addIndex('quiz_attempts', ['quiz_id']); await queryInterface.addIndex('quiz_attempts', ['assessment_id']); await queryInterface.addIndex('quiz_attempts', { fields: ['course_id'], name: 'idx_qa_course_id' }); }, async down(queryInterface) { await queryInterface.dropTable('quiz_attempts'); }, };