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