Skip to main content

headless_lms_server/programs/seed/seed_courses/
seed_graded.rs

1use crate::programs::seed::builder::certificate::CertificateBuilder;
2use crate::programs::seed::builder::chapter::ChapterBuilder;
3use crate::programs::seed::builder::context::SeedContext;
4use crate::programs::seed::builder::course::{CourseBuilder, CourseInstanceConfig};
5use crate::programs::seed::builder::module::{
6    CompletionBuilder, CompletionRegisteredBuilder, ModuleBuilder,
7};
8use crate::programs::seed::builder::page::PageBuilder;
9use crate::programs::seed::seed_courses::CommonCourseData;
10use crate::programs::seed::seed_helpers::paragraph;
11use anyhow::{Context, Result};
12use chrono::Utc;
13use headless_lms_base::config::ApplicationConfiguration;
14use headless_lms_models::certificate_configuration_to_requirements;
15use headless_lms_models::certificate_configurations::{
16    DatabaseCertificateConfiguration, insert as insert_certificate_configuration,
17};
18use headless_lms_models::course_instance_enrollments;
19use headless_lms_models::file_uploads;
20use headless_lms_models::roles::UserRole;
21use headless_lms_models::study_registry_registrars::get_or_create_default_registrar;
22use tracing::info;
23use uuid::Uuid;
24
25use super::super::seed_users::SeedUsersResult;
26
27pub async fn seed_graded_course(
28    app_config: ApplicationConfiguration,
29    course_id: Uuid,
30    course_name: &str,
31    course_slug: &str,
32    common_course_data: CommonCourseData,
33    seed_users_result: SeedUsersResult,
34) -> Result<Uuid> {
35    let CommonCourseData {
36        db_pool,
37        organization_id: org,
38        teacher_user_id,
39        student_user_id: _student,
40        langs_user_id: _langs_user_id,
41        example_normal_user_ids,
42        jwt_key: _jwt_key,
43        base_url: _base_url,
44    } = common_course_data;
45
46    let mut conn = db_pool.acquire().await?;
47    let cx = SeedContext {
48        teacher: teacher_user_id,
49        org,
50        base_course_ns: course_id,
51    };
52
53    info!("Inserting sample course {}", course_name);
54
55    // Build the graded module
56    let registrar_id = get_or_create_default_registrar(&mut conn).await?;
57
58    let mut module = ModuleBuilder::new()
59        .order(0)
60        .register_to_open_university(false)
61        .automatic_completion(Some(1), Some(1), false)
62        .default_registrar(registrar_id);
63
64    for (i, uid) in example_normal_user_ids.iter().enumerate() {
65        module = module.completion(
66            CompletionBuilder::new(*uid)
67                .grade(5)
68                .passed(true)
69                .registered(
70                    CompletionRegisteredBuilder::new().real_student_number(format!("52-{:03}", i)),
71                ),
72        );
73    }
74
75    // Build the actual course
76    let course_builder = CourseBuilder::new(course_name, course_slug)
77        .desc("A sample graded course that pre-seeds module completions for demo users.")
78        .chatbot(false)
79        .course_id(course_id)
80        .instance(CourseInstanceConfig {
81            name: None,
82            description: None,
83            support_email: None,
84            teacher_in_charge_name: "admin".to_string(),
85            teacher_in_charge_email: "admin@example.com".to_string(),
86            opening_time: None,
87            closing_time: None,
88            instance_id: Some(cx.v5(b"instance:graded")),
89        })
90        .role(seed_users_result.teacher_user_id, UserRole::Teacher)
91        .module(
92            module.chapter(
93                ChapterBuilder::new(1, "The Basics")
94                    .opens(Utc::now())
95                    .fixed_ids(cx.v5(b"chapter:1"), cx.v5(b"chapter:1:instance"))
96                    .page(
97                        PageBuilder::new("/chapter-1/page-1", "Welcome").block(paragraph(
98                            "This is the graded example course.",
99                            cx.v5(b"page:1:1"),
100                        )),
101                    ),
102            ),
103        );
104
105    // Insert course
106    let (course, default_instance, last_module) =
107        course_builder.seed(&mut conn, &app_config, &cx).await?;
108
109    // Enroll users to default instance
110    for uid in example_normal_user_ids.iter() {
111        course_instance_enrollments::insert(&mut conn, *uid, course.id, default_instance.id)
112            .await?;
113    }
114
115    let background_svg_path = "svgs/certificate-background.svg".to_string();
116
117    let background_svg_file_upload_id = file_uploads::insert(
118        &mut conn,
119        &format!("background-{}.svg", last_module.id),
120        &background_svg_path,
121        "image/svg+xml",
122        None,
123        None,
124    )
125    .await?;
126
127    let configuration = DatabaseCertificateConfiguration {
128        id: Uuid::new_v5(&course_id, b"graded-course-certificate-configuration"),
129        certificate_owner_name_y_pos: None,
130        certificate_owner_name_x_pos: None,
131        certificate_owner_name_font_size: None,
132        certificate_owner_name_text_color: None,
133        certificate_owner_name_text_anchor: None,
134        certificate_validate_url_y_pos: None,
135        certificate_validate_url_x_pos: None,
136        certificate_validate_url_font_size: None,
137        certificate_validate_url_text_color: None,
138        certificate_validate_url_text_anchor: None,
139        certificate_date_y_pos: None,
140        certificate_date_x_pos: None,
141        certificate_date_font_size: None,
142        certificate_date_text_color: None,
143        certificate_date_text_anchor: None,
144        certificate_locale: None,
145        paper_size: None,
146        background_svg_path,
147        background_svg_file_upload_id,
148        overlay_svg_path: None,
149        overlay_svg_file_upload_id: None,
150        render_certificate_grade: true,
151        certificate_grade_y_pos: None,
152        certificate_grade_x_pos: None,
153        certificate_grade_font_size: None,
154        certificate_grade_text_color: None,
155        certificate_grade_text_anchor: None,
156    };
157
158    let database_configuration = insert_certificate_configuration(&mut conn, &configuration)
159        .await
160        .context("insert certificate configuration")?;
161
162    certificate_configuration_to_requirements::insert(
163        &mut conn,
164        database_configuration.id,
165        Some(last_module.id),
166    )
167    .await?;
168
169    // Now that the module has a configuration, generate certificates for the demo users
170    for uid in example_normal_user_ids.iter() {
171        CertificateBuilder::new(*uid)
172            .default_configuration_for_module(last_module.id)
173            .name_on_certificate(format!("Demo User {}", uid))
174            .seed(&mut conn)
175            .await?;
176    }
177
178    Ok(course_id)
179}