headless_lms_models/
certificate_configuration_to_requirements.rs

1use crate::prelude::*;
2
3#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
4#[cfg_attr(feature = "ts_rs", derive(TS))]
5pub struct CertificateConfigurationToRequirement {
6    pub id: Uuid,
7    pub created_at: DateTime<Utc>,
8    pub updated_at: DateTime<Utc>,
9    pub deleted_at: Option<DateTime<Utc>>,
10    pub certificate_configuration_id: Uuid,
11    pub course_module_id: Option<Uuid>,
12}
13
14#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
15#[cfg_attr(feature = "ts_rs", derive(TS))]
16pub struct CertificateAllRequirements {
17    pub certificate_configuration_id: Uuid,
18    pub course_module_ids: Vec<Uuid>,
19}
20
21impl CertificateAllRequirements {
22    /** A certificate configuration is a default configuration if the requirement is only for one course module. These types of configurations are regarded as the default because they are the most commonly used ones. */
23    pub fn is_default_certificate_configuration(&self) -> bool {
24        self.course_module_ids.len() == 1
25    }
26
27    /** Checks if the user has completed all requirements to be eligible for a certificate. */
28    pub async fn has_user_completed_all_requirements(
29        &self,
30        conn: &mut PgConnection,
31        user_id: Uuid,
32    ) -> ModelResult<bool> {
33        let all_users_completions =
34            crate::course_module_completions::get_all_by_user_id(conn, user_id).await?;
35
36        let all_completed_course_module_ids = all_users_completions
37            .iter()
38            .map(|o| o.course_module_id)
39            .collect::<Vec<_>>();
40        // Compare the vecs of completed stuff to the requirements
41        let all_required_course_modules_completed = self
42            .course_module_ids
43            .iter()
44            .all(|id| all_completed_course_module_ids.contains(id));
45        let result = all_required_course_modules_completed;
46        if !result {
47            let missing_course_module_ids = self
48                .course_module_ids
49                .iter()
50                .filter(|id| !all_completed_course_module_ids.contains(id))
51                .collect::<Vec<_>>();
52            warn!(
53                "User {} has not completed all requirements for certificate configuration {}. Missing course module ids: {:?}.",
54                user_id, self.certificate_configuration_id, missing_course_module_ids
55            )
56        }
57        Ok(result)
58    }
59}
60
61pub async fn get_all_requirements_for_certificate_configuration(
62    conn: &mut PgConnection,
63    certificate_configuration_id: Uuid,
64) -> ModelResult<CertificateAllRequirements> {
65    let requirements = sqlx::query_as!(
66        CertificateConfigurationToRequirement,
67        r#"
68SELECT *
69FROM certificate_configuration_to_requirements
70WHERE certificate_configuration_id = $1
71AND deleted_at IS NULL
72        "#,
73        certificate_configuration_id
74    )
75    .fetch_all(conn)
76    .await?;
77    let course_module_ids = requirements
78        .iter()
79        .filter_map(|r| r.course_module_id)
80        .collect();
81
82    Ok(CertificateAllRequirements {
83        certificate_configuration_id,
84        course_module_ids,
85    })
86}
87
88pub async fn insert(
89    conn: &mut PgConnection,
90    certificate_configuration_id: Uuid,
91    course_module_id: Option<Uuid>,
92) -> ModelResult<CertificateConfigurationToRequirement> {
93    let row = sqlx::query_as!(
94        CertificateConfigurationToRequirement,
95        r#"
96INSERT INTO certificate_configuration_to_requirements (
97    certificate_configuration_id,
98    course_module_id
99  )
100VALUES ($1, $2)
101RETURNING *
102        "#,
103        certificate_configuration_id,
104        course_module_id,
105    )
106    .fetch_one(conn)
107    .await?;
108    Ok(row)
109}