const { DataTypes } = require("sequelize"); const sequelize = require("../../config/db.config"); const { mdl_UserGroups } = require('../users/user_groups.mdl'); const TaskList = sequelize.define('TaskList', { task_list_id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true, hidden: true }, name: { type: DataTypes.STRING, allowNull: false, validate: { notEmpty: true }, filterable: true }, description: { type: DataTypes.TEXT, allowNull: true, hidden: true, filterable: false }, // ── Audit trails ──────────────────────────────────────────────────────── createdBy: { type: DataTypes.INTEGER, allowNull: true, filterable: true }, updatedBy: { type: DataTypes.INTEGER, allowNull: true, filterable: true }, deletedBy: { type: DataTypes.INTEGER, allowNull: true, filterable: true }, }, { tableName: 'task_lists', paranoid: true, timestamps: true, }); // ─── Junction: TaskList ↔ UserGroups ────────────────────────────────────────── const TaskListGroup = sequelize.define('TaskListGroup', { id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true }, task_list_id: { type: DataTypes.UUID, allowNull: false, references: { model: 'task_lists', key: 'task_list_id' }, onDelete: 'CASCADE', }, group_id: { type: DataTypes.BIGINT, allowNull: false, references: { model: 'user_groups', key: 'group_id' }, onDelete: 'CASCADE', }, assignedAt: { type: DataTypes.DATE, defaultValue: DataTypes.NOW, allowNull: false, filterable: true }, assignedBy: { type: DataTypes.BIGINT, allowNull: true, filterable: true }, }, { tableName: 'task_list_groups', timestamps: false, indexes: [ { unique: true, fields: ['task_list_id', 'group_id'], name: 'uq_task_list_group' }, { fields: ['task_list_id'], name: 'idx_tlg_task_list_id' }, { fields: ['group_id'], name: 'idx_tlg_group_id' }, ], }); const Task = sequelize.define('Task', { task_id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true, hidden: true }, task_list_id: { type: DataTypes.UUID, allowNull: false, references: { model: 'task_lists', key: 'task_list_id' }, hidden: true, filterable: false }, name: { type: DataTypes.STRING, allowNull: false, validate: { notEmpty: true }, order: 1, filterable: true }, description: { type: DataTypes.TEXT, allowNull: true, hidden: true, filterable: false }, deadline: { type: DataTypes.DATE, allowNull: true, order: 2, filterable: true }, status: { type: DataTypes.ENUM('pending', 'in_progress', 'completed', 'overdue'), defaultValue: 'pending', allowNull: false, filterable: true }, // ── Audit trails ──────────────────────────────────────────────────────── createdBy: { type: DataTypes.INTEGER, allowNull: true, filterable: true }, updatedBy: { type: DataTypes.INTEGER, allowNull: true, filterable: true }, deletedBy: { type: DataTypes.INTEGER, allowNull: true, filterable: true }, }, { tableName: 'tasks', paranoid: true, timestamps: true, }); const TaskRequirement = sequelize.define('TaskRequirement', { requirement_id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true }, task_id: { type: DataTypes.UUID, allowNull: false, references: { model: 'tasks', key: 'task_id' } }, type: { type: DataTypes.ENUM('visit_link', 'upload_file', 'read_course', 'read_unit', 'read_lesson'), allowNull: false, filterable: true }, // ── visit_link ────────────────────────────────────────────────────────── link_url: { type: DataTypes.STRING, allowNull: true, filterable: false }, link_label: { type: DataTypes.STRING, allowNull: true, filterable: false }, // ── upload_file ───────────────────────────────────────────────────────── allowed_file_types: { type: DataTypes.JSONB, allowNull: true, filterable: false }, max_file_count: { type: DataTypes.INTEGER, allowNull: true, defaultValue: 1, filterable: false }, // ── read_course / read_unit / read_lesson ──────────────────────────────── reference_id: { type: DataTypes.UUID, allowNull: true, comment: 'course_id | unit_id | lesson_id depending on type', filterable: false }, reference_label: { type: DataTypes.STRING, allowNull: true, comment: 'Cached display name so we do not always join', filterable: false }, order: { type: DataTypes.INTEGER, defaultValue: 0, filterable: true }, // ── Audit trails ──────────────────────────────────────────────────────── createdBy: { type: DataTypes.INTEGER, allowNull: true }, updatedBy: { type: DataTypes.INTEGER, allowNull: true }, deletedBy: { type: DataTypes.INTEGER, allowNull: true }, }, { tableName: 'task_requirements', paranoid: true, timestamps: true, }); TaskList.hasMany(Task, { foreignKey: 'task_list_id', as: 'tasks' }); Task.belongsTo(TaskList, { foreignKey: 'task_list_id', as: 'taskList' }); Task.hasMany(TaskRequirement, { foreignKey: 'task_id', as: 'requirements' }); TaskRequirement.belongsTo(Task, { foreignKey: 'task_id', as: 'task' }); // TaskList ↔ UserGroups (many-to-many through TaskListGroup) TaskList.belongsToMany(mdl_UserGroups, { through: TaskListGroup, foreignKey: 'task_list_id', otherKey: 'group_id', as: 'groups', }); mdl_UserGroups.belongsToMany(TaskList, { through: TaskListGroup, foreignKey: 'group_id', otherKey: 'task_list_id', as: 'taskLists', }); module.exports = { Task, TaskList, TaskRequirement, TaskListGroup, mdl_UserGroups };