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 .map(|o| o.course_module_id)
41 .collect::<Vec<_>>();
42 let all_required_course_modules_completed = self
44 .course_module_ids
45 .iter()
46 .all(|id| all_completed_course_module_ids.contains(id));
47 let result = all_required_course_modules_completed;
48 if !result {
49 let missing_course_module_ids = self
50 .course_module_ids
51 .iter()
52 .filter(|id| !all_completed_course_module_ids.contains(id))
53 .collect::<Vec<_>>();
54 warn!(
55 "User {} has not completed all requirements for certificate configuration {}. Missing course module ids: {:?}.",
56 user_id, self.certificate_configuration_id, missing_course_module_ids
57 )
58 }
59 Ok(result)
60 }
61}
62
63pub async fn get_all_requirements_for_certificate_configuration(
64 conn: &mut PgConnection,
65 certificate_configuration_id: Uuid,
66) -> ModelResult<CertificateAllRequirements> {
67 let requirements = sqlx::query_as!(
68 CertificateConfigurationToRequirement,
69 r#"
70SELECT *
71FROM certificate_configuration_to_requirements
72WHERE certificate_configuration_id = $1
73AND deleted_at IS NULL
74 "#,
75 certificate_configuration_id
76 )
77 .fetch_all(conn)
78 .await?;
79 let course_module_ids = requirements
80 .iter()
81 .filter_map(|r| r.course_module_id)
82 .collect();
83
84 Ok(CertificateAllRequirements {
85 certificate_configuration_id,
86 course_module_ids,
87 })
88}
89
90pub async fn insert(
91 conn: &mut PgConnection,
92 certificate_configuration_id: Uuid,
93 course_module_id: Option<Uuid>,
94) -> ModelResult<CertificateConfigurationToRequirement> {
95 let row = sqlx::query_as!(
96 CertificateConfigurationToRequirement,
97 r#"
98INSERT INTO certificate_configuration_to_requirements (
99 certificate_configuration_id,
100 course_module_id
101 )
102VALUES ($1, $2)
103RETURNING *
104 "#,
105 certificate_configuration_id,
106 course_module_id,
107 )
108 .fetch_one(conn)
109 .await?;
110 Ok(row)
111}
112
113pub async fn link_configuration_to_module_if_missing(
114 conn: &mut PgConnection,
115 certificate_configuration_id: Uuid,
116 course_module_id: Uuid,
117) -> ModelResult<()> {
118 sqlx::query!(
119 r#"
120 INSERT INTO certificate_configuration_to_requirements (
121 certificate_configuration_id,
122 course_module_id
123 )
124 SELECT $1, $2
125 WHERE NOT EXISTS (
126 SELECT 1
127 FROM certificate_configuration_to_requirements
128 WHERE certificate_configuration_id = $1
129 AND course_module_id = $2
130 AND deleted_at IS NULL
131 )
132 "#,
133 certificate_configuration_id,
134 course_module_id
135 )
136 .execute(conn)
137 .await?;
138
139 Ok(())
140}