headless_lms_models/
certificate_configuration_to_requirements.rs1use 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 pub course_instance_id: Option<Uuid>,
13}
14
15#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
16#[cfg_attr(feature = "ts_rs", derive(TS))]
17pub struct CertificateAllRequirements {
18 pub certificate_configuration_id: Uuid,
19 pub course_module_ids: Vec<Uuid>,
20 pub course_instance_ids: Vec<Uuid>,
21}
22
23impl CertificateAllRequirements {
24 pub fn is_default_certificate_configuration(&self) -> bool {
26 self.course_module_ids.len() == 1 && self.course_instance_ids.len() == 1
27 }
28
29 pub fn requires_only_one_course_module_and_does_not_require_course_instance(&self) -> bool {
30 self.course_module_ids.len() == 1 && self.course_instance_ids.is_empty()
31 }
32
33 pub async fn has_user_completed_all_requirements(
35 &self,
36 conn: &mut PgConnection,
37 user_id: Uuid,
38 ) -> ModelResult<bool> {
39 let all_users_completions =
40 crate::course_module_completions::get_all_by_user_id(conn, user_id).await?;
41 let all_completed_course_instance_ids = all_users_completions
42 .iter()
43 .map(|o| o.course_instance_id)
44 .collect::<Vec<_>>();
45 let all_completed_course_module_ids = all_users_completions
46 .iter()
47 .map(|o| o.course_module_id)
48 .collect::<Vec<_>>();
49 let all_required_course_instances_completed = self
51 .course_instance_ids
52 .iter()
53 .all(|id| all_completed_course_instance_ids.contains(id));
54 let all_required_course_modules_completed = self
55 .course_module_ids
56 .iter()
57 .all(|id| all_completed_course_module_ids.contains(id));
58 let result =
59 all_required_course_instances_completed && all_required_course_modules_completed;
60 if !result {
61 let missing_course_instance_ids = self
62 .course_instance_ids
63 .iter()
64 .filter(|id| !all_completed_course_instance_ids.contains(id))
65 .collect::<Vec<_>>();
66 let missing_course_module_ids = self
67 .course_module_ids
68 .iter()
69 .filter(|id| !all_completed_course_module_ids.contains(id))
70 .collect::<Vec<_>>();
71 warn!(
72 "User {} has not completed all requirements for certificate configuration {}. Missing course instance ids: {:?}, missing course module ids: {:?}.",
73 user_id,
74 self.certificate_configuration_id,
75 missing_course_instance_ids,
76 missing_course_module_ids
77 )
78 }
79 Ok(result)
80 }
81}
82
83pub async fn get_all_requirements_for_certificate_configuration(
84 conn: &mut PgConnection,
85 certificate_configuration_id: Uuid,
86) -> ModelResult<CertificateAllRequirements> {
87 let requirements = sqlx::query_as!(
88 CertificateConfigurationToRequirement,
89 r#"
90SELECT *
91FROM certificate_configuration_to_requirements
92WHERE certificate_configuration_id = $1
93AND deleted_at IS NULL
94 "#,
95 certificate_configuration_id
96 )
97 .fetch_all(conn)
98 .await?;
99 let course_module_ids = requirements
100 .iter()
101 .filter_map(|r| r.course_module_id)
102 .collect();
103 let course_instance_ids = requirements
104 .iter()
105 .filter_map(|r| r.course_instance_id)
106 .collect();
107 Ok(CertificateAllRequirements {
108 certificate_configuration_id,
109 course_module_ids,
110 course_instance_ids,
111 })
112}
113
114pub async fn insert(
115 conn: &mut PgConnection,
116 certificate_configuration_id: Uuid,
117 course_module_id: Option<Uuid>,
118 course_instance_id: Option<Uuid>,
119) -> ModelResult<CertificateConfigurationToRequirement> {
120 let row = sqlx::query_as!(
121 CertificateConfigurationToRequirement,
122 r#"
123INSERT INTO certificate_configuration_to_requirements (
124 certificate_configuration_id,
125 course_module_id,
126 course_instance_id
127 )
128VALUES ($1, $2, $3)
129RETURNING *
130 "#,
131 certificate_configuration_id,
132 course_module_id,
133 course_instance_id
134 )
135 .fetch_one(conn)
136 .await?;
137 Ok(row)
138}