headless_lms_models/
user_course_settings.rs1use crate::{course_instance_enrollments::CourseInstanceEnrollment, prelude::*};
2
3#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
4#[cfg_attr(feature = "ts_rs", derive(TS))]
5pub struct UserCourseSettings {
6 pub user_id: Uuid,
7 pub course_language_group_id: Uuid,
8 pub created_at: DateTime<Utc>,
9 pub updated_at: DateTime<Utc>,
10 pub deleted_at: Option<DateTime<Utc>>,
11 pub current_course_id: Uuid,
12 pub current_course_instance_id: Uuid,
13}
14
15pub async fn upsert_user_course_settings_for_enrollment(
17 conn: &mut PgConnection,
18 course_instance_enrollment: &CourseInstanceEnrollment,
19) -> ModelResult<UserCourseSettings> {
20 let user_course_settings = sqlx::query_as!(
21 UserCourseSettings,
22 "
23INSERT INTO user_course_settings (
24 user_id,
25 course_language_group_id,
26 current_course_id,
27 current_course_instance_id
28 )
29SELECT $1,
30 course_language_group_id,
31 $2,
32 $3
33FROM courses
34WHERE id = $2
35 AND deleted_at IS NULL ON CONFLICT (user_id, course_language_group_id) DO
36UPDATE
37SET current_course_id = $2,
38 current_course_instance_id = $3,
39 deleted_at = NULL
40RETURNING *;
41 ",
42 course_instance_enrollment.user_id,
43 course_instance_enrollment.course_id,
44 course_instance_enrollment.course_instance_id
45 )
46 .fetch_one(conn)
47 .await?;
48 Ok(user_course_settings)
49}
50
51pub async fn get_user_course_settings(
52 conn: &mut PgConnection,
53 user_id: Uuid,
54 course_language_group_id: Uuid,
55) -> ModelResult<UserCourseSettings> {
56 let user_course_settings = sqlx::query_as!(
57 UserCourseSettings,
58 "
59SELECT *
60FROM user_course_settings
61WHERE user_id = $1
62 AND course_language_group_id = $2
63 AND deleted_at IS NULL;
64 ",
65 user_id,
66 course_language_group_id
67 )
68 .fetch_one(conn)
69 .await?;
70 Ok(user_course_settings)
71}
72
73pub async fn get_user_course_settings_by_course_id(
74 conn: &mut PgConnection,
75 user_id: Uuid,
76 course_id: Uuid,
77) -> ModelResult<Option<UserCourseSettings>> {
78 let user_course_settings = sqlx::query_as!(
79 UserCourseSettings,
80 "
81SELECT ucs.*
82FROM courses c
83 JOIN user_course_settings ucs ON (
84 ucs.course_language_group_id = c.course_language_group_id
85 )
86WHERE c.id = $1
87 AND ucs.user_id = $2
88 AND c.deleted_at IS NULL
89 AND ucs.deleted_at IS NULL;
90 ",
91 course_id,
92 user_id,
93 )
94 .fetch_optional(conn)
95 .await?;
96 Ok(user_course_settings)
97}
98
99pub async fn get_all_by_user_and_multiple_current_courses(
110 conn: &mut PgConnection,
111 course_ids: &[Uuid],
112 user_id: Uuid,
113) -> ModelResult<Vec<UserCourseSettings>> {
114 let res = sqlx::query_as!(
115 UserCourseSettings,
116 "
117SELECT *
118FROM user_course_settings
119WHERE current_course_id = ANY($1)
120 AND user_id = $2
121 AND deleted_at IS NULL
122 ",
123 course_ids,
124 user_id,
125 )
126 .fetch_all(conn)
127 .await?;
128 Ok(res)
129}
130
131#[cfg(test)]
132mod test {
133 use super::*;
134 use crate::{
135 course_instance_enrollments::{self, NewCourseInstanceEnrollment},
136 course_instances::{self, NewCourseInstance},
137 test_helper::*,
138 };
139
140 #[tokio::test]
141 async fn upserts_user_course_settings() {
142 insert_data!(:tx, :user, :org, :course, :instance);
143
144 let enrollment = course_instance_enrollments::insert_enrollment_if_it_doesnt_exist(
145 tx.as_mut(),
146 NewCourseInstanceEnrollment {
147 course_id: course,
148 course_instance_id: instance.id,
149 user_id: user,
150 },
151 )
152 .await
153 .unwrap();
154 let settings = upsert_user_course_settings_for_enrollment(tx.as_mut(), &enrollment)
155 .await
156 .unwrap();
157 assert_eq!(settings.current_course_id, enrollment.course_id);
158 assert_eq!(
159 settings.current_course_instance_id,
160 enrollment.course_instance_id
161 );
162
163 let instance_2 = course_instances::insert(
164 tx.as_mut(),
165 PKeyPolicy::Generate,
166 NewCourseInstance {
167 course_id: course,
168 name: Some("instance-2"),
169 description: None,
170 teacher_in_charge_name: "teacher",
171 teacher_in_charge_email: "teacher@example.com",
172 support_email: None,
173 opening_time: None,
174 closing_time: None,
175 },
176 )
177 .await
178 .unwrap()
179 .id;
180 let enrollment_2 = course_instance_enrollments::insert_enrollment_if_it_doesnt_exist(
181 tx.as_mut(),
182 NewCourseInstanceEnrollment {
183 course_id: course,
184 course_instance_id: instance_2,
185 user_id: user,
186 },
187 )
188 .await
189 .unwrap();
190 let settings_2 = upsert_user_course_settings_for_enrollment(tx.as_mut(), &enrollment_2)
191 .await
192 .unwrap();
193 assert_eq!(
194 settings_2.current_course_instance_id,
195 enrollment_2.course_instance_id
196 );
197 }
198}