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