diff --git a/Cargo.toml b/Cargo.toml index 25d0235..bdbbba3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,4 +23,4 @@ config = "0.15" tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["env-filter", "time", "fmt", "std"] } dotenv = "0.15.0" -time = { version = "0.3.41", features = ["formatting"] } +time = { version = "0.3.37", features = ["formatting"] } diff --git a/src/graphql/queries/attendance_queries.rs b/src/graphql/queries/attendance_queries.rs index 5208a70..ff605dd 100644 --- a/src/graphql/queries/attendance_queries.rs +++ b/src/graphql/queries/attendance_queries.rs @@ -48,4 +48,4 @@ impl AttendanceQueries { Ok(rows) } -} +} \ No newline at end of file diff --git a/src/graphql/queries/member_queries.rs b/src/graphql/queries/member_queries.rs index efa2ecf..6acffbb 100644 --- a/src/graphql/queries/member_queries.rs +++ b/src/graphql/queries/member_queries.rs @@ -1,6 +1,8 @@ use async_graphql::{ComplexObject, Context, Object, Result}; use sqlx::PgPool; use std::sync::Arc; +use chrono::NaiveDate; + use crate::models::{ attendance::{AttendanceInfo, AttendanceSummaryInfo}, @@ -106,5 +108,89 @@ impl Member { .fetch_all(pool.as_ref()) .await .unwrap_or_default() + + + } + + async fn present_count_by_date( + &self, + ctx: &Context<'_>, + start_date: NaiveDate, + end_date:NaiveDate, + ) -> Result{ + + if end_date < start_date { + return Err("end_date must be >= start_date".into()); + } + + let pool = ctx.data::>().expect("Pool must be in context."); + + let records : i64 = sqlx::query_scalar( + " + SELECT COUNT(att.is_present) + FROM attendance att + INNER JOIN member m ON att.member_id = m.member_id + WHERE att.member_id = $3 + AND att.is_present = true + AND att.date BETWEEN $1 AND $2" + ) + .bind(start_date) + .bind(end_date) + .bind(self.member_id) + .fetch_one(pool.as_ref()) + .await?; + + Ok(records) + + } + + async fn absent_count_by_date( + &self, + ctx: &Context<'_>, + start_date: NaiveDate, + end_date:NaiveDate, + ) -> Result{ + + if end_date < start_date { + return Err("end_date must be >= start_date".into()); + } + + let pool = ctx.data::>().expect("Pool must be in context."); + + let working_days : i64 = sqlx::query_scalar( + " + SELECT COUNT(*) AS working_days + FROM ( + SELECT date + FROM attendance + where date between $1 and $2 GROUP BY date + HAVING BOOL_or(is_present = true) + ) AS working_dates; + " + ) + + .bind(start_date) + .bind(end_date) + .bind(self.member_id) + .fetch_one(pool.as_ref()) + .await?; + + let present : i64 = sqlx::query_scalar( + " + SELECT COUNT(att.is_present) + FROM attendance att + INNER JOIN member m ON att.member_id = m.member_id + WHERE att.member_id = $3 + AND att.is_present = true + AND att.date BETWEEN $1 AND $2" + ) + .bind(start_date) + .bind(end_date) + .bind(self.member_id) + .fetch_one(pool.as_ref()) + .await?; + + Ok(working_days-present) + } } diff --git a/src/main.rs b/src/main.rs index c72289e..dc71d78 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,9 @@ pub mod graphql; pub mod models; pub mod routes; + + + /// Handles all over environment variables in one place. // TODO: Replace with `Config.rs` crate. struct Config { @@ -44,7 +47,7 @@ impl Config { } #[tokio::main] -async fn main() { +async fn main() { let config = Config::from_env(); setup_tracing(&config.env); @@ -64,7 +67,7 @@ async fn main() { let router = setup_router(schema, cors, config.env == "development"); info!("Starting Root..."); - let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", config.port)) + let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{}",config.port)) .await .unwrap(); axum::serve(listener, router).await.unwrap();