use actix_web::{web, Responder}; use askama::Template; use chrono::{Datelike, Months, NaiveDate, Utc}; use sqlx::PgPool; use crate::{ models::{Area, Role, User}, utils::{ApplicationError, TemplateResponse}, }; #[derive(Template)] #[template(path = "export/events.html")] struct EventExportTemplate { user: User, areas: Option>, daterange: (NaiveDate, NaiveDate), current_month: (NaiveDate, NaiveDate), current_quarter: (NaiveDate, NaiveDate), next_month: (NaiveDate, NaiveDate), next_quarter: (NaiveDate, NaiveDate), } #[actix_web::get("/export/events")] pub async fn get( user: web::ReqData, pool: web::Data, ) -> Result { if user.role != Role::Admin && user.role != Role::AreaManager { return Err(ApplicationError::Unauthorized); } let areas = if user.role == Role::Admin { Some(Area::read_all(pool.get_ref()).await?) } else { None }; let today = Utc::now().date_naive(); let today_plus_month = today.checked_add_months(Months::new(1)).unwrap(); let today_plus_three_month = today.checked_add_months(Months::new(3)).unwrap(); let template = EventExportTemplate { user: user.into_inner(), areas, daterange: ( first_day_of_month(&today).unwrap(), last_day_of_month(&today).unwrap(), ), current_month: ( first_day_of_month(&today).unwrap(), last_day_of_month(&today).unwrap(), ), next_month: ( first_day_of_month(&today_plus_month).unwrap(), last_day_of_month(&today_plus_month).unwrap(), ), current_quarter: ( first_day_of_quarter(&today).unwrap(), last_day_of_quarter(&today).unwrap(), ), next_quarter: ( first_day_of_quarter(&today_plus_three_month).unwrap(), last_day_of_quarter(&today_plus_three_month).unwrap(), ), }; Ok(template.to_response()?) } fn first_day_of_month(date: &NaiveDate) -> Option { NaiveDate::from_ymd_opt(date.year(), date.month0() + 1, 1) } fn last_day_of_month(date: &NaiveDate) -> Option { let month0 = date.month0() + 1; let year = if month0 > 11 { date.year() + 1 } else { date.year() }; let month = (month0 % 12) + 1; NaiveDate::from_ymd_opt(year, month, 1)?.pred_opt() } fn first_day_of_quarter(date: &NaiveDate) -> Option { let start_month = (date.quarter() * 3) - 2; NaiveDate::from_ymd_opt(date.year(), start_month, 1) } fn last_day_of_quarter(date: &NaiveDate) -> Option { let quarter = date.quarter(); let (year, next_month) = if quarter == 4 { (date.year() + 1, 1) } else { (date.year(), (quarter * 3) + 1) }; NaiveDate::from_ymd_opt(year, next_month, 1)?.pred_opt() }