Skip to main content

headless_lms_models/
user_course_exercise_service_variables.rs

1use std::collections::HashMap;
2
3use utoipa::ToSchema;
4
5use crate::{exercise_tasks::ExerciseTask, prelude::*, user_exercise_states::UserExerciseState};
6
7#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, ToSchema)]
8
9pub struct UserCourseExerciseServiceVariable {
10    pub id: Uuid,
11    pub created_at: DateTime<Utc>,
12    pub updated_at: DateTime<Utc>,
13    pub deleted_at: Option<DateTime<Utc>>,
14    pub exercise_service_slug: String,
15    pub user_id: Uuid,
16    pub course_id: Option<Uuid>,
17    pub exam_id: Option<Uuid>,
18    pub variable_key: String,
19    pub variable_value: serde_json::Value,
20}
21
22pub(crate) async fn get_all_variables_for_user_and_course_or_exam(
23    conn: &mut PgConnection,
24    user_id: Uuid,
25    instance_or_exam_id: CourseOrExamId,
26) -> ModelResult<Vec<UserCourseExerciseServiceVariable>> {
27    let (course_id, exam_id) = instance_or_exam_id.to_course_and_exam_ids();
28    let res = sqlx::query_as!(
29        UserCourseExerciseServiceVariable,
30        r#"
31SELECT *
32FROM user_course_exercise_service_variables
33WHERE deleted_at IS NULL
34  AND user_id = $1
35  AND (course_id = $2 OR course_id IS NULL)
36  AND (exam_id = $3 OR exam_id IS NULL);
37    "#,
38        user_id,
39        course_id,
40        exam_id
41    )
42    .fetch_all(conn)
43    .await?;
44    Ok(res)
45}
46
47pub async fn get_all_user_variables_for_user_and_course_and_exercise_type(
48    conn: &mut PgConnection,
49    user_id: Uuid,
50    course_id: Uuid,
51    exercise_type: &str,
52) -> ModelResult<Vec<UserCourseExerciseServiceVariable>> {
53    let res = sqlx::query_as!(
54        UserCourseExerciseServiceVariable,
55        r#"
56SELECT *
57FROM user_course_exercise_service_variables
58WHERE deleted_at IS NULL
59  AND user_id = $1
60  AND course_id = $2
61  AND exercise_service_slug = $3;
62    "#,
63        user_id,
64        course_id,
65        exercise_type
66    )
67    .fetch_all(conn)
68    .await?;
69    Ok(res)
70}
71
72pub(crate) async fn insert_after_exercise_task_graded(
73    conn: &mut PgConnection,
74    set_user_variables: &Option<HashMap<String, serde_json::Value>>,
75    exercise_task: &ExerciseTask,
76    user_exercise_state: &UserExerciseState,
77) -> ModelResult<()> {
78    if let Some(set_user_variables) = set_user_variables {
79        for (k, v) in set_user_variables {
80            sqlx::query!(
81                r#"
82INSERT INTO user_course_exercise_service_variables (
83    exercise_service_slug,
84    user_id,
85    course_id,
86    exam_id,
87    variable_key,
88    variable_value
89  )
90VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (
91    variable_key,
92    user_id,
93    course_id,
94    exercise_service_slug,
95    exam_id,
96    deleted_at
97  ) DO
98UPDATE
99SET variable_value = $6;
100    "#,
101                exercise_task.exercise_type,
102                user_exercise_state.user_id,
103                user_exercise_state.course_id,
104                user_exercise_state.exam_id,
105                k,
106                v
107            )
108            .execute(&mut *conn)
109            .await?;
110        }
111        Ok(())
112    } else {
113        Ok(())
114    }
115}