koprogo_api/infrastructure/web/handlers/
stats_handlers.rs1use crate::infrastructure::web::{AppState, AuthenticatedUser};
2use actix_web::{get, web, HttpResponse, Responder};
3
4#[get("/stats/dashboard")]
7pub async fn get_dashboard_stats(
8 state: web::Data<AppState>,
9 user: AuthenticatedUser,
10) -> impl Responder {
11 if !user.is_superadmin() {
12 return HttpResponse::Forbidden().json(serde_json::json!({
13 "error": "Only SuperAdmin can access dashboard statistics"
14 }));
15 }
16
17 match state.stats_use_cases.get_admin_dashboard_stats().await {
18 Ok(stats) => HttpResponse::Ok().json(stats),
19 Err(e) => HttpResponse::InternalServerError().json(serde_json::json!({
20 "error": format!("Failed to fetch dashboard statistics: {}", e)
21 })),
22 }
23}
24
25#[get("/stats/owner")]
28pub async fn get_owner_stats(
29 state: web::Data<AppState>,
30 user: AuthenticatedUser,
31) -> impl Responder {
32 if user.role != "owner" && !user.is_superadmin() {
33 return HttpResponse::Forbidden().json(serde_json::json!({
34 "error": "Only Owner can access these statistics"
35 }));
36 }
37
38 match state
39 .stats_use_cases
40 .get_owner_stats_by_user_id(user.user_id)
41 .await
42 {
43 Ok(stats) => HttpResponse::Ok().json(stats),
44 Err(e) => HttpResponse::InternalServerError().json(serde_json::json!({
45 "error": format!("Failed to fetch owner dashboard statistics: {}", e)
46 })),
47 }
48}
49
50#[get("/stats/owner/dues-by-acp")]
62pub async fn get_owner_dues_by_acp(
63 state: web::Data<AppState>,
64 user: AuthenticatedUser,
65) -> impl Responder {
66 if user.role != "owner" && !user.is_superadmin() {
69 return HttpResponse::Forbidden().json(serde_json::json!({
70 "error": "Only Owner can access these statistics"
71 }));
72 }
73
74 match state
75 .stats_use_cases
76 .get_owner_dues_by_acp(user.user_id)
77 .await
78 {
79 Ok(dues) => HttpResponse::Ok().json(dues),
80 Err(e) => HttpResponse::InternalServerError().json(serde_json::json!({
81 "error": format!("Failed to fetch owner dues by ACP: {}", e)
82 })),
83 }
84}
85
86#[get("/stats/syndic")]
89pub async fn get_syndic_stats(
90 state: web::Data<AppState>,
91 user: AuthenticatedUser,
92) -> impl Responder {
93 if user.role != "syndic" && user.role != "accountant" && !user.is_superadmin() {
94 return HttpResponse::Forbidden().json(serde_json::json!({
95 "error": "Only Syndic and Accountant can access these statistics"
96 }));
97 }
98
99 let Some(org_id) = user.organization_id else {
100 return HttpResponse::BadRequest().json(serde_json::json!({
101 "error": "User has no organization"
102 }));
103 };
104
105 match state.stats_use_cases.get_syndic_stats(org_id).await {
106 Ok(stats) => HttpResponse::Ok().json(stats),
107 Err(e) => HttpResponse::InternalServerError().json(serde_json::json!({
108 "error": format!("Failed to fetch syndic dashboard statistics: {}", e)
109 })),
110 }
111}
112
113#[get("/stats/syndic/urgent-tasks")]
116pub async fn get_syndic_urgent_tasks(
117 state: web::Data<AppState>,
118 user: AuthenticatedUser,
119) -> impl Responder {
120 if user.role != "syndic" && user.role != "accountant" && !user.is_superadmin() {
121 return HttpResponse::Forbidden().json(serde_json::json!({
122 "error": "Only Syndic and Accountant can access these tasks"
123 }));
124 }
125
126 let Some(org_id) = user.organization_id else {
127 return HttpResponse::BadRequest().json(serde_json::json!({
128 "error": "User has no organization"
129 }));
130 };
131
132 match state.stats_use_cases.get_syndic_urgent_tasks(org_id).await {
133 Ok(tasks) => HttpResponse::Ok().json(tasks),
134 Err(e) => HttpResponse::InternalServerError().json(serde_json::json!({
135 "error": format!("Failed to fetch urgent tasks: {}", e)
136 })),
137 }
138}
139
140#[get("/stats/seed-data")]
143pub async fn get_seed_data_stats(
144 state: web::Data<AppState>,
145 user: AuthenticatedUser,
146) -> impl Responder {
147 if !user.is_superadmin() {
148 return HttpResponse::Forbidden().json(serde_json::json!({
149 "error": "Only SuperAdmin can access seed data statistics"
150 }));
151 }
152
153 match state.stats_use_cases.get_seed_data_stats().await {
154 Ok(stats) => HttpResponse::Ok().json(stats),
155 Err(e) => HttpResponse::InternalServerError().json(serde_json::json!({
156 "error": format!("Failed to fetch seed data statistics: {}", e)
157 })),
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 #[test]
164 fn test_role_check_superadmin_passes() {
165 let allowed_roles = ["superadmin"];
166 assert!(allowed_roles.contains(&"superadmin"));
167 assert!(!allowed_roles.contains(&"owner"));
168 }
169
170 #[test]
171 fn test_role_check_syndic_and_accountant() {
172 let allowed_roles = ["syndic", "accountant", "superadmin"];
173 assert!(allowed_roles.contains(&"syndic"));
174 assert!(allowed_roles.contains(&"accountant"));
175 assert!(!allowed_roles.contains(&"owner"));
176 }
177
178 #[test]
179 fn test_role_check_owner() {
180 let allowed_roles = ["owner", "superadmin"];
181 assert!(allowed_roles.contains(&"owner"));
182 assert!(!allowed_roles.contains(&"syndic"));
183 }
184}