headless_lms_server/controllers/main_frontend/
global_stats.rs1use crate::{domain::authorization::authorize, prelude::*};
4
5use models::library::TimeGranularity;
6use models::library::global_stats::{
7 CourseCompletionStats, DomainCompletionStats, GlobalCourseModuleStatEntry, GlobalStatEntry,
8};
9use std::collections::HashMap;
10
11#[instrument(skip(pool))]
18async fn get_number_of_people_completed_a_course(
19 pool: web::Data<PgPool>,
20 user: AuthUser,
21 query: web::Query<HashMap<String, String>>,
22) -> ControllerResult<web::Json<Vec<GlobalStatEntry>>> {
23 let mut conn = pool.acquire().await?;
24 let token = authorize(
25 &mut conn,
26 Act::ViewStats,
27 Some(user.id),
28 Res::GlobalPermissions,
29 )
30 .await?;
31
32 let granularity = query
33 .get("granularity")
34 .map(|s| s.parse().unwrap_or(TimeGranularity::Year))
35 .unwrap_or(TimeGranularity::Year);
36
37 let res = models::library::global_stats::get_number_of_people_completed_a_course(
38 &mut conn,
39 granularity,
40 )
41 .await?;
42
43 token.authorized_ok(web::Json(res))
44}
45
46#[instrument(skip(pool))]
53async fn get_number_of_people_registered_completion_to_study_registry(
54 pool: web::Data<PgPool>,
55 user: AuthUser,
56 query: web::Query<HashMap<String, String>>,
57) -> ControllerResult<web::Json<Vec<GlobalStatEntry>>> {
58 let mut conn = pool.acquire().await?;
59 let token = authorize(
60 &mut conn,
61 Act::ViewStats,
62 Some(user.id),
63 Res::GlobalPermissions,
64 )
65 .await?;
66
67 let granularity = query
68 .get("granularity")
69 .map(|s| s.parse().unwrap_or(TimeGranularity::Year))
70 .unwrap_or(TimeGranularity::Year);
71
72 let res = models::library::global_stats::get_number_of_people_registered_completion_to_study_registry(&mut conn, granularity).await?;
73
74 token.authorized_ok(web::Json(res))
75}
76
77#[instrument(skip(pool))]
84async fn get_number_of_people_done_at_least_one_exercise(
85 pool: web::Data<PgPool>,
86 user: AuthUser,
87 query: web::Query<HashMap<String, String>>,
88) -> ControllerResult<web::Json<Vec<GlobalStatEntry>>> {
89 let mut conn = pool.acquire().await?;
90 let token = authorize(
91 &mut conn,
92 Act::ViewStats,
93 Some(user.id),
94 Res::GlobalPermissions,
95 )
96 .await?;
97
98 let granularity = query
99 .get("granularity")
100 .map(|s| s.parse().unwrap_or(TimeGranularity::Year))
101 .unwrap_or(TimeGranularity::Year);
102
103 let res = models::library::global_stats::get_number_of_people_done_at_least_one_exercise(
104 &mut conn,
105 granularity,
106 )
107 .await?;
108
109 token.authorized_ok(web::Json(res))
110}
111
112#[instrument(skip(pool))]
119async fn get_number_of_people_started_course(
120 pool: web::Data<PgPool>,
121 user: AuthUser,
122 query: web::Query<HashMap<String, String>>,
123) -> ControllerResult<web::Json<Vec<GlobalStatEntry>>> {
124 let mut conn = pool.acquire().await?;
125 let token = authorize(
126 &mut conn,
127 Act::ViewStats,
128 Some(user.id),
129 Res::GlobalPermissions,
130 )
131 .await?;
132
133 let granularity = query
134 .get("granularity")
135 .map(|s| s.parse().unwrap_or(TimeGranularity::Year))
136 .unwrap_or(TimeGranularity::Year);
137
138 let res =
139 models::library::global_stats::get_number_of_people_started_course(&mut conn, granularity)
140 .await?;
141
142 token.authorized_ok(web::Json(res))
143}
144
145#[instrument(skip(pool))]
152async fn get_course_module_stats_by_completions_registered_to_study_registry(
153 pool: web::Data<PgPool>,
154 user: AuthUser,
155 query: web::Query<HashMap<String, String>>,
156) -> ControllerResult<web::Json<Vec<GlobalCourseModuleStatEntry>>> {
157 let mut conn = pool.acquire().await?;
158 let token = authorize(
159 &mut conn,
160 Act::ViewStats,
161 Some(user.id),
162 Res::GlobalPermissions,
163 )
164 .await?;
165
166 let granularity = query
167 .get("granularity")
168 .map(|s| s.parse().unwrap_or(TimeGranularity::Year))
169 .unwrap_or(TimeGranularity::Year);
170
171 let res = models::library::global_stats::get_course_module_stats_by_completions_registered_to_study_registry(&mut conn, granularity).await?;
172
173 token.authorized_ok(web::Json(res))
174}
175
176#[instrument(skip(pool))]
183async fn get_completion_stats_by_email_domain(
184 pool: web::Data<PgPool>,
185 user: AuthUser,
186 query: web::Query<HashMap<String, String>>,
187) -> ControllerResult<web::Json<Vec<DomainCompletionStats>>> {
188 let mut conn = pool.acquire().await?;
189 let token = authorize(
190 &mut conn,
191 Act::ViewStats,
192 Some(user.id),
193 Res::GlobalPermissions,
194 )
195 .await?;
196
197 let year = query.get("year").and_then(|y| y.parse::<i32>().ok());
198
199 let res = models::library::global_stats::get_completion_stats_by_email_domain(&mut conn, year)
200 .await?;
201
202 token.authorized_ok(web::Json(res))
203}
204
205#[instrument(skip(pool))]
213async fn get_course_completion_stats_for_email_domain(
214 pool: web::Data<PgPool>,
215 user: AuthUser,
216 query: web::Query<HashMap<String, String>>,
217) -> ControllerResult<web::Json<Vec<CourseCompletionStats>>> {
218 let mut conn = pool.acquire().await?;
219 let token = authorize(
220 &mut conn,
221 Act::ViewStats,
222 Some(user.id),
223 Res::GlobalPermissions,
224 )
225 .await?;
226
227 let email_domain = query
228 .get("email_domain")
229 .ok_or_else(|| {
230 ControllerError::new(
231 ControllerErrorType::BadRequest,
232 "email_domain is required".to_string(),
233 None,
234 )
235 })?
236 .to_string();
237
238 let year = query.get("year").and_then(|y| y.parse::<i32>().ok());
239
240 let res = models::library::global_stats::get_course_completion_stats_for_email_domain(
241 &mut conn,
242 email_domain,
243 year,
244 )
245 .await?;
246
247 token.authorized_ok(web::Json(res))
248}
249
250pub fn _add_routes(cfg: &mut ServiceConfig) {
258 cfg.route(
259 "/number-of-people-completed-a-course",
260 web::get().to(get_number_of_people_completed_a_course),
261 )
262 .route(
263 "/number-of-people-registered-completion-to-study-registry",
264 web::get().to(get_number_of_people_registered_completion_to_study_registry),
265 )
266 .route(
267 "/number-of-people-done-at-least-one-exercise",
268 web::get().to(get_number_of_people_done_at_least_one_exercise),
269 )
270 .route(
271 "/number-of-people-started-course",
272 web::get().to(get_number_of_people_started_course),
273 )
274 .route(
275 "/course-module-stats-by-completions-registered-to-study-registry",
276 web::get().to(get_course_module_stats_by_completions_registered_to_study_registry),
277 )
278 .route(
279 "/completion-stats-by-email-domain",
280 web::get().to(get_completion_stats_by_email_domain),
281 )
282 .route(
283 "/course-completion-stats-for-email-domain",
284 web::get().to(get_course_completion_stats_for_email_domain),
285 );
286}