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