Skip to content
This repository was archived by the owner on Feb 24, 2025. It is now read-only.

Commit 256dea6

Browse files
committed
fix: use format! instead of + putting string
1 parent 0428c45 commit 256dea6

File tree

8 files changed

+177
-13
lines changed

8 files changed

+177
-13
lines changed

src/calc/mod.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,121 @@
1+
use crate::{
2+
models::{activities::Activity, users::User},
3+
routers::users::time::UserActivityTime,
4+
};
5+
use bson::{doc, from_document};
6+
use futures::stream::TryStreamExt;
7+
use mongodb::{Collection, Database};
8+
use polars::{df, frame::DataFrame, prelude::NamedFrom, series::Series};
9+
use std::sync::Arc;
10+
use tokio::sync::Mutex;
111

12+
async fn export(db: Arc<Mutex<Database>>) -> Result<DataFrame, String> {
13+
let db = db.lock().await;
14+
let mut df = df!(
15+
"_id" => &["".to_string()],
16+
"id" => &["0".to_string()],
17+
"name" => &["Example".to_string()],
18+
"class" => &["".to_string()],
19+
"on_campus" => &[0.0],
20+
"off_campus" => &[0.0],
21+
"social_practice" => &[0.0],
22+
"total" => &[0.0]
23+
)
24+
.unwrap();
25+
26+
let users_collection: Collection<User> = db.collection("users");
27+
let activities_collection: Collection<Activity> = db.collection("activities");
28+
29+
let mut users = users_collection.find(doc! {}, None).await.unwrap();
30+
31+
while let Some(doc) = users.try_next().await.unwrap() {
32+
let pipeline = vec![
33+
doc! {
34+
"$match": {
35+
"$or": [
36+
{ "members._id": doc._id.clone() },
37+
{ "members._id": doc._id.to_hex() }
38+
]
39+
}
40+
},
41+
doc! {
42+
"$unwind": "$members"
43+
},
44+
doc! {
45+
"$match": {
46+
"$or": [
47+
{ "members._id": doc._id.clone() },
48+
{ "members._id": doc._id.to_hex() }
49+
]
50+
}
51+
},
52+
doc! {
53+
"$group": {
54+
"_id": "$members.mode",
55+
"totalDuration": { "$sum": "$members.duration" }
56+
}
57+
},
58+
doc! {
59+
"$group": {
60+
"_id": null,
61+
"on_campus": {
62+
"$sum": {
63+
"$cond": [{ "$eq": ["$_id", "on-campus"] }, "$totalDuration", 0.0]
64+
}
65+
},
66+
"off_campus": {
67+
"$sum": {
68+
"$cond": [{ "$eq": ["$_id", "off-campus"] }, "$totalDuration", 0.0]
69+
}
70+
},
71+
"social_practice": {
72+
"$sum": {
73+
"$cond": [{ "$eq": ["$_id", "social-practice"] }, "$totalDuration", 0.0]
74+
}
75+
},
76+
"total": { "$sum": "$totalDuration" }
77+
}
78+
},
79+
doc! {
80+
"$project": {
81+
"_id": 0,
82+
"on_campus": 1,
83+
"off_campus": 1,
84+
"social_practice": 1,
85+
"total": 1
86+
}
87+
},
88+
];
89+
let cursor = activities_collection.aggregate(pipeline, None).await;
90+
if let Err(_) = cursor {
91+
return Err("Failed to get cursor".to_string());
92+
}
93+
let mut cursor = cursor.unwrap();
94+
let result = cursor.try_next().await;
95+
if let Err(_) = result {
96+
return Err("Failed to get result".to_string());
97+
}
98+
let result = result.unwrap();
99+
if let None = result {
100+
return Err("Failed to get result".to_string());
101+
}
102+
let result = result.unwrap();
103+
let result: UserActivityTime = from_document(result).unwrap();
104+
let extend = DataFrame::new(vec![
105+
Series::new("_id", vec![doc._id.clone().to_hex()]),
106+
Series::new("id", vec![doc.id.clone()]),
107+
Series::new("name", vec![doc.name.clone()]),
108+
Series::new("class", vec!["".to_string()]),
109+
Series::new("on_campus", vec![result.on_campus]),
110+
Series::new("off_campus", vec![result.off_campus]),
111+
Series::new("social_practice", vec![result.social_practice]),
112+
Series::new("total", vec![result.total]),
113+
]);
114+
if let Err(_) = extend {
115+
return Err("Failed to create DataFrame".to_string());
116+
}
117+
let extend = extend.unwrap();
118+
df.extend(&extend).unwrap();
119+
}
120+
Ok(df)
121+
}

src/routers/activities/members/read.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ pub async fn read_member(
6060
if let Err(e) = same {
6161
return create_error(
6262
StatusCode::INTERNAL_SERVER_ERROR,
63-
"Cannot validate user".to_string() + &e,
63+
format!("Failed to validate user: {}", e),
6464
);
6565
}
6666
if !same.unwrap() {

src/routers/activities/members/update.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ pub async fn update_member_impression(
169169
if let Err(e) = activity {
170170
return create_error(
171171
StatusCode::NOT_FOUND,
172-
"Activity not found".to_string() + &e.to_string(),
172+
format!("Activity not found: {}", e.to_string()),
173173
);
174174
}
175175
let member = bson::from_document::<ActivityMember>(activity.unwrap());

src/routers/activities/read.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub async fn read_all(
6262
if let Err(e) = count {
6363
return create_error(
6464
StatusCode::INTERNAL_SERVER_ERROR,
65-
"Failed to read activity: ".to_string() + &e.to_string(),
65+
format!("Failed to read activity: {}", e.to_string()),
6666
);
6767
}
6868
let pipeline = vec![
@@ -97,7 +97,7 @@ pub async fn read_all(
9797
if let Err(e) = cursor {
9898
return create_error(
9999
StatusCode::INTERNAL_SERVER_ERROR,
100-
"Failed to read activity: ".to_string() + &e.to_string(),
100+
format!("Failed to read activity: {}", e.to_string()),
101101
);
102102
}
103103
let mut cursor = cursor.unwrap();
@@ -107,7 +107,7 @@ pub async fn read_all(
107107
if let Err(e) = doc_result {
108108
return create_error(
109109
StatusCode::INTERNAL_SERVER_ERROR,
110-
"Failed to read activity: ".to_string() + &e.to_string(),
110+
format!("Failed to read activity: {}", e.to_string()),
111111
);
112112
}
113113
if let Ok(Some(document)) = doc_result {
@@ -116,7 +116,7 @@ pub async fn read_all(
116116
Err(e) => {
117117
return create_error(
118118
StatusCode::INTERNAL_SERVER_ERROR,
119-
"Failed to read activity: ".to_string() + &e.to_string(),
119+
format!("Failed to read activity: {}", e.to_string()),
120120
)
121121
}
122122
}
@@ -163,7 +163,7 @@ pub async fn read_one(
163163
if let Err(e) = result {
164164
return create_error(
165165
StatusCode::INTERNAL_SERVER_ERROR,
166-
"Failed to read activity: ".to_string() + &e.to_string(),
166+
format!("Failed to read activity: {}", e.to_string()),
167167
);
168168
}
169169
let result: Option<Activity> = result.unwrap();

src/routers/activities/remove.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub async fn remove_activity(
3636
if let Err(e) = activity {
3737
return create_error(
3838
StatusCode::INTERNAL_SERVER_ERROR,
39-
"Failed to find activity: ".to_string() + &e.to_string(),
39+
format!("Failed to find activity: {}", e.to_string()),
4040
);
4141
}
4242
let activity = activity.unwrap();
@@ -54,7 +54,7 @@ pub async fn remove_activity(
5454
if let Err(e) = result {
5555
return create_error(
5656
StatusCode::INTERNAL_SERVER_ERROR,
57-
"Failed to delete activity: ".to_string() + &e.to_string(),
57+
format!("Failed to delete activity: {}", e.to_string()),
5858
);
5959
}
6060
let result = result.unwrap();

src/routers/activities/update.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub async fn update_activity_name(
3939
if let Err(e) = activity {
4040
return create_error(
4141
StatusCode::INTERNAL_SERVER_ERROR,
42-
"Failed to find activity: ".to_string() + &e.to_string(),
42+
format!("Failed to find activity: {}", e.to_string()),
4343
);
4444
}
4545
let activity = activity.unwrap();
@@ -58,7 +58,7 @@ pub async fn update_activity_name(
5858
if let Err(e) = result {
5959
return create_error(
6060
StatusCode::INTERNAL_SERVER_ERROR,
61-
"Failed to update activity: ".to_string() + &e.to_string(),
61+
format!("Failed to update activity: {}", e.to_string()),
6262
);
6363
}
6464
let response: SuccessResponse<Vec<Activity>, ()> = SuccessResponse {
@@ -96,7 +96,7 @@ pub async fn update_activity_description(
9696
if let Err(e) = activity {
9797
return create_error(
9898
StatusCode::INTERNAL_SERVER_ERROR,
99-
"Failed to find activity: ".to_string() + &e.to_string(),
99+
format!("Failed to find activity: {}", e.to_string()),
100100
);
101101
}
102102
let activity = activity.unwrap();
@@ -119,7 +119,7 @@ pub async fn update_activity_description(
119119
if let Err(e) = result {
120120
return create_error(
121121
StatusCode::INTERNAL_SERVER_ERROR,
122-
"Failed to update activity: ".to_string() + &e.to_string(),
122+
format!("Failed to update activity: {}", e.to_string()),
123123
);
124124
}
125125
let response: SuccessResponse<Vec<Activity>, ()> = SuccessResponse {

src/routers/exports/mod.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use crate::{
2+
models::{groups::GroupPermission, response::create_error},
3+
utils::jwt::UserData,
4+
};
5+
use axum::{
6+
extract::Extension,
7+
http::StatusCode,
8+
response::{IntoResponse, Json},
9+
};
10+
use bson::doc;
11+
use mongodb::Database;
12+
use serde::{Deserialize, Serialize};
13+
use std::sync::Arc;
14+
use tokio::sync::Mutex;
15+
16+
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
17+
#[serde(rename_all = "kebab-case")]
18+
pub enum ExportFormat {
19+
CSV,
20+
JSON,
21+
Excel,
22+
}
23+
24+
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
25+
pub struct ExportActivityTimesOptions {
26+
pub start: u64, // Unix timestamp
27+
pub end: u64, // Unix timestamp
28+
pub format: ExportFormat,
29+
}
30+
31+
pub async fn export_activity_times(
32+
Extension(db): Extension<Arc<Mutex<Database>>>,
33+
user: UserData,
34+
Json(options): Json<ExportActivityTimesOptions>,
35+
) -> impl IntoResponse {
36+
if !user.perms.contains(&GroupPermission::Admin)
37+
&& !user.perms.contains(&GroupPermission::Inspector)
38+
{
39+
return create_error(StatusCode::FORBIDDEN, "Permission denied".to_string());
40+
}
41+
42+
(StatusCode::OK, Json("".to_string()))
43+
}

src/routers/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod activities;
22
pub mod auth;
3+
pub mod exports;
34
pub mod users;

0 commit comments

Comments
 (0)