diff --git a/backend/app/Controllers/TeacherController.php b/backend/app/Controllers/TeacherController.php index 0f55b7d..9923b4d 100644 --- a/backend/app/Controllers/TeacherController.php +++ b/backend/app/Controllers/TeacherController.php @@ -109,7 +109,7 @@ class TeacherController // Total Unique Active Students $studentsCount = (int)Database::selectOne( - "SELECT COUNT(DISTINCT lp.user_id) as total FROM lesson_progress lp + "SELECT COUNT(DISTINCT lp.student_id) as total FROM lesson_progress lp JOIN lessons l ON lp.lesson_id = l.id JOIN courses c ON l.course_id = c.id WHERE c.teacher_id = ?", diff --git a/backend/app/Services/VideoService.php b/backend/app/Services/VideoService.php index 9f695b7..24a969c 100644 --- a/backend/app/Services/VideoService.php +++ b/backend/app/Services/VideoService.php @@ -63,6 +63,25 @@ class VideoService Database::query("ALTER TABLE lessons ADD COLUMN encoding_status ENUM('pending', 'processing', 'ready', 'failed') NOT NULL DEFAULT 'ready' AFTER is_free_preview"); } + // Progress is used by the student player. Create only this additive + // table at runtime so production does not need the destructive full schema. + Database::query("CREATE TABLE IF NOT EXISTS lesson_progress ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + student_id BIGINT UNSIGNED NOT NULL, + lesson_id BIGINT UNSIGNED NOT NULL, + position_seconds INT UNSIGNED NOT NULL DEFAULT 0, + watched_seconds INT UNSIGNED NOT NULL DEFAULT 0, + completion_percentage DECIMAL(5,2) NOT NULL DEFAULT 0.00, + is_completed TINYINT(1) NOT NULL DEFAULT 0, + last_seen_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP, + completed_at TIMESTAMP NULL DEFAULT NULL, + PRIMARY KEY (id), + UNIQUE KEY idx_progress_student_lesson (student_id, lesson_id), + KEY idx_progress_lesson (lesson_id), + CONSTRAINT fk_progress_student FOREIGN KEY (student_id) REFERENCES students (id) ON DELETE CASCADE, + CONSTRAINT fk_progress_lesson FOREIGN KEY (lesson_id) REFERENCES lessons (id) ON DELETE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"); + self::$schemaChecked = true; } catch (\Throwable $e) { error_log("VideoService schema ensure note: " . $e->getMessage());