77eceee2f3
- Introduced a new module for progress tracking in the LMS service. - Implemented `calculate_course_completion` function to compute total lessons, completed lessons, and progress percentage for a user in a specific course. - Updated the main.rs file to include the new progress tracking module. - Enhanced the Excel import functionality in the Question Bank to support various question types and improved error handling. - Added a new dependency on the `xlsx` library for handling Excel files in the frontend. - Modified the course settings page to include a branded certificate template with additional organization details. - Updated the package.json and package-lock.json files to include the new `xlsx` dependency. - Changed the default state for ingestRag in the Admin Shared Materials page to true.
73 lines
2.4 KiB
Rust
73 lines
2.4 KiB
Rust
use sqlx::{PgPool, Row};
|
|
use uuid::Uuid;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct CourseCompletionMetrics {
|
|
pub total_lessons: i64,
|
|
pub completed_lessons: i64,
|
|
pub progress_percentage: f64,
|
|
pub completed: bool,
|
|
}
|
|
|
|
pub async fn calculate_course_completion(
|
|
pool: &PgPool,
|
|
user_id: Uuid,
|
|
course_id: Uuid,
|
|
) -> Result<CourseCompletionMetrics, sqlx::Error> {
|
|
let row = sqlx::query(
|
|
r#"
|
|
SELECT
|
|
COALESCE(totals.total_lessons, 0)::bigint AS total_lessons,
|
|
LEAST(
|
|
COALESCE(totals.total_lessons, 0)::bigint,
|
|
COALESCE(graded.graded_done, 0)::bigint + COALESCE(ungraded.ungraded_done, 0)::bigint
|
|
) AS completed_lessons
|
|
FROM (SELECT 1) seed
|
|
LEFT JOIN LATERAL (
|
|
SELECT COUNT(*)::bigint AS total_lessons
|
|
FROM lessons l
|
|
JOIN modules m ON m.id = l.module_id
|
|
WHERE m.course_id = $2
|
|
) totals ON TRUE
|
|
LEFT JOIN LATERAL (
|
|
SELECT COUNT(DISTINCT ug.lesson_id)::bigint AS graded_done
|
|
FROM user_grades ug
|
|
JOIN lessons l ON l.id = ug.lesson_id
|
|
JOIN modules m ON m.id = l.module_id
|
|
WHERE ug.user_id = $1
|
|
AND m.course_id = $2
|
|
AND l.is_graded = true
|
|
AND (ug.score * 100.0) >= COALESCE(l.passing_percentage::double precision, 60.0)
|
|
) graded ON TRUE
|
|
LEFT JOIN LATERAL (
|
|
SELECT COUNT(DISTINCT li.lesson_id)::bigint AS ungraded_done
|
|
FROM lesson_interactions li
|
|
JOIN lessons l ON l.id = li.lesson_id
|
|
JOIN modules m ON m.id = l.module_id
|
|
WHERE li.user_id = $1
|
|
AND li.event_type = 'complete'
|
|
AND m.course_id = $2
|
|
AND l.is_graded = false
|
|
) ungraded ON TRUE
|
|
"#,
|
|
)
|
|
.bind(user_id)
|
|
.bind(course_id)
|
|
.fetch_one(pool)
|
|
.await?;
|
|
|
|
let total_lessons = row.get::<i64, _>("total_lessons");
|
|
let completed_lessons = row.get::<i64, _>("completed_lessons");
|
|
let progress_percentage = if total_lessons > 0 {
|
|
(completed_lessons as f64 / total_lessons as f64) * 100.0
|
|
} else {
|
|
0.0
|
|
};
|
|
|
|
Ok(CourseCompletionMetrics {
|
|
total_lessons,
|
|
completed_lessons,
|
|
progress_percentage,
|
|
completed: total_lessons > 0 && completed_lessons >= total_lessons,
|
|
})
|
|
} |