headless_lms_server/programs/seed/seed_courses/
seed_switching_course_instances_course.rs1use crate::{
2 prelude::*,
3 programs::seed::{
4 builder::{
5 chapter::ChapterBuilder,
6 context::SeedContext,
7 course::{CourseBuilder, CourseInstanceConfig},
8 exercise::{ExerciseBuilder, ExerciseIds},
9 module::ModuleBuilder,
10 page::PageBuilder,
11 },
12 seed_courses::CommonCourseData,
13 seed_helpers::paragraph,
14 seed_users::SeedUsersResult,
15 },
16};
17use anyhow::Result;
18use chrono::{TimeZone, Utc};
19use headless_lms_models::roles::UserRole;
20use serde_json::json;
21
22pub async fn seed_switching_course_instances_course(
23 course_id: Uuid,
24 course_name: &str,
25 course_slug: &str,
26 common_course_data: CommonCourseData,
27 can_add_chatbot: bool,
28 seed_users_result: SeedUsersResult,
29) -> Result<Uuid> {
30 let CommonCourseData {
31 db_pool,
32 organization_id: org,
33 teacher_user_id,
34 student_user_id: _student,
35 langs_user_id: _langs_user_id,
36 example_normal_user_ids: _users,
37 jwt_key: _jwt_key,
38 base_url: _base_url,
39 } = common_course_data;
40
41 let mut conn = db_pool.acquire().await?;
42 let cx = SeedContext {
43 teacher: teacher_user_id,
44 org,
45 base_course_ns: course_id,
46 };
47
48 info!(
49 "Inserting switching course instances course {}",
50 course_name
51 );
52
53 let course = CourseBuilder::new(course_name, course_slug)
54 .desc("Sample course.")
55 .chatbot(can_add_chatbot)
56 .course_id(course_id)
57 .instance(CourseInstanceConfig {
58 name: None,
59 description: None,
60 support_email: None,
61 teacher_in_charge_name: "admin".to_string(),
62 teacher_in_charge_email: "admin@example.com".to_string(),
63 opening_time: None,
64 closing_time: None,
65 instance_id: Some(cx.v5(b"instance:default")),
66 })
67 .instance(CourseInstanceConfig {
68 name: Some("Non-default instance".to_string()),
69 description: Some("This is a non-default instance".to_string()),
70 support_email: Some("contact@example.com".to_string()),
71 teacher_in_charge_name: "admin".to_string(),
72 teacher_in_charge_email: "admin@example.com".to_string(),
73 opening_time: None,
74 closing_time: None,
75 instance_id: Some(cx.v5(b"instance:non-default")),
76 })
77 .role(seed_users_result.teacher_user_id, UserRole::Teacher)
78 .module(
79 ModuleBuilder::new()
80 .order(0)
81 .register_to_open_university(false)
82 .automatic_completion(Some(1), Some(1), false)
83 .chapter(
84 ChapterBuilder::new(1, "The Basics")
85 .opens(Utc::now())
86 .deadline(Utc.with_ymd_and_hms(2225, 1, 1, 23, 59, 59).unwrap())
87 .fixed_ids(cx.v5(b"chapter:1"), cx.v5(b"chapter:1:instance"))
88 .page(
89 PageBuilder::new("/chapter-1/page-1", "Page One")
90 .block(paragraph(
91 "This is a simple introduction to the basics.",
92 cx.v5(b"page:1:1:block:intro"),
93 ))
94 .exercise(ExerciseBuilder::example_exercise(
95 "Simple multiple choice",
96 ExerciseIds {
97 exercise_id: cx.v5(b"exercise:1:1:e"),
98 slide_id: cx.v5(b"exercise:1:1:s"),
99 task_id: cx.v5(b"exercise:1:1:t"),
100 block_id: cx.v5(b"exercise:1:1:b"),
101 },
102 vec![paragraph(
103 "What is 2 + 2?",
104 cx.v5(b"exercise:1:1:prompt"),
105 )],
106 json!([
107 {
108 "name": "3",
109 "correct": false,
110 "id": cx.v5(b"exercise:1:1:option:1")
111 },
112 {
113 "name": "4",
114 "correct": true,
115 "id": cx.v5(b"exercise:1:1:option:2")
116 },
117 {
118 "name": "5",
119 "correct": false,
120 "id": cx.v5(b"exercise:1:1:option:3")
121 }
122 ]),
123 false,
124 None,
125 None,
126 )),
127 ),
128 ),
129 )
130 .module(
131 ModuleBuilder::new()
132 .order(1)
133 .name("Another module")
134 .automatic_completion(Some(1), Some(1), false)
135 .ects(5.0)
136 .chapter(
137 ChapterBuilder::new(2, "Another chapter")
138 .fixed_ids(cx.v5(b"chapter:2"), cx.v5(b"chapter:2:instance"))
139 .page(
140 PageBuilder::new("/chapter-2/page-1", "Simple Page")
141 .block(paragraph(
142 "This is another simple page with basic content.",
143 cx.v5(b"page:2:1:block:intro"),
144 ))
145 .exercise(ExerciseBuilder::example_exercise(
146 "Simple question",
147 ExerciseIds {
148 exercise_id: cx.v5(b"exercise:2:1:e"),
149 slide_id: cx.v5(b"exercise:2:1:s"),
150 task_id: cx.v5(b"exercise:2:1:t"),
151 block_id: cx.v5(b"exercise:2:1:b"),
152 },
153 vec![paragraph(
154 "What color is the sky?",
155 cx.v5(b"exercise:2:1:prompt"),
156 )],
157 json!([
158 {
159 "name": "Red",
160 "correct": false,
161 "id": cx.v5(b"exercise:2:1:option:1")
162 },
163 {
164 "name": "Blue",
165 "correct": true,
166 "id": cx.v5(b"exercise:2:1:option:2")
167 },
168 {
169 "name": "Green",
170 "correct": false,
171 "id": cx.v5(b"exercise:2:1:option:3")
172 }
173 ]),
174 false,
175 None,
176 None,
177 )),
178 ),
179 ),
180 )
181 .module(
182 ModuleBuilder::new()
183 .order(2)
184 .name("Bonus module")
185 .register_to_open_university(true)
186 .automatic_completion(None, Some(1), false)
187 .chapter(
188 ChapterBuilder::new(3, "Bonus chapter")
189 .fixed_ids(cx.v5(b"chapter:3"), cx.v5(b"chapter:3:instance"))
190 .page(
191 PageBuilder::new("/chapter-3/page-1", "Bonus Page")
192 .block(paragraph(
193 "This is a bonus page with simple content.",
194 cx.v5(b"page:3:1:block:intro"),
195 ))
196 .exercise(ExerciseBuilder::example_exercise(
197 "Bonus question",
198 ExerciseIds {
199 exercise_id: cx.v5(b"exercise:3:1:e"),
200 slide_id: cx.v5(b"exercise:3:1:s"),
201 task_id: cx.v5(b"exercise:3:1:t"),
202 block_id: cx.v5(b"exercise:3:1:b"),
203 },
204 vec![paragraph(
205 "What is the capital of France?",
206 cx.v5(b"exercise:3:1:assignment"),
207 )],
208 json!([
209 {
210 "name": "London",
211 "correct": false,
212 "id": cx.v5(b"exercise:3:1:option:1")
213 },
214 {
215 "name": "Paris",
216 "correct": true,
217 "id": cx.v5(b"exercise:3:1:option:2")
218 },
219 {
220 "name": "Berlin",
221 "correct": false,
222 "id": cx.v5(b"exercise:3:1:option:3")
223 }
224 ]),
225 false,
226 None,
227 None,
228 )),
229 ),
230 ),
231 );
232
233 let (course, _default_instance, _last_module) = course.seed(&mut conn, &cx).await?;
234
235 Ok(course.id)
236}