/*********************************************************************************************************************************************************************** * File Name: media_playback_position.mdl.js * Type of Program: Model * Description: Per-user "where did I last leave off" position for a video/audio block, entirely * decoupled from CompletionRequirement — tracked for ANY video/audio block regardless * of whether the lesson has a watch-type completion requirement configured. Powers * resume-on-reopen only; carries no completion/anti-cheat semantics (that's * CompletionRequirementProgress's job, see completion_requirement_progress.mdl.js). * * MediaPlaybackPosition — UPSERT key: (user_id, lesson_id, block_id). Last-write-wins, not a * ratcheted max — a deliberate rewind-and-stop should resume there, not * snap back to a previously-reached high-water mark. * * Author: Kenneth Obsequio (@lash0000) * Date Created: Jul. 17, 2026 ***********************************************************************************************************************************************************************/ const { DataTypes } = require('sequelize'); const sequelize = require('../../config/db.config'); const MediaPlaybackPosition = sequelize.define('MediaPlaybackPosition', { position_id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true, }, user_id: { type: DataTypes.BIGINT, allowNull: false, references: { model: 'users', key: 'user_id' }, onDelete: 'CASCADE', }, lesson_id: { type: DataTypes.BIGINT, allowNull: false, references: { model: 'lessons', key: 'lesson_id' }, onDelete: 'CASCADE', }, block_id: { type: DataTypes.STRING, allowNull: false, comment: 'The block\'s own id within LessonPage.blocks JSONB — no DB-level FK, blocks are not their own table.', }, percent: { type: DataTypes.INTEGER, allowNull: false, comment: 'Last-known % position, 0-100. Last-write-wins — not a ratcheted max.', }, }, { tableName: 'media_playback_positions', timestamps: true, paranoid: false, // position rows are never soft-deleted, matches CompletionRequirementProgress indexes: [ { unique: true, fields: ['user_id', 'lesson_id', 'block_id'], name: 'uq_mpp_user_lesson_block', }, { fields: ['user_id', 'lesson_id'], name: 'idx_mpp_user_lesson' }, ], }); module.exports = MediaPlaybackPosition;