brass/web/src/endpoints/export/get_events_data.rs

187 lines
5.5 KiB
Rust

use crate::models::{ExportEventRow, Function, SimpleAssignment};
use actix_http::header::CONTENT_DISPOSITION;
use actix_web::{http::header::ContentDisposition, web, HttpResponse, Responder};
use chrono::{Datelike, NaiveDate};
use rust_xlsxwriter::workbook::Workbook;
use serde::Deserialize;
use sqlx::PgPool;
use crate::{
models::{Role, User},
utils::{ApplicationError, DateTimeFormat},
};
#[derive(Deserialize)]
struct ExportQuery {
start: NaiveDate,
end: NaiveDate,
area: Option<i32>,
}
#[derive(PartialEq)]
struct EventExportEntry {
date: String,
weekday: String,
start_time: String,
end_time: String,
hours: f32,
location: String,
name: String,
assigned_name: Option<String>,
assigned_function: Option<String>,
}
fn read(rows: Vec<ExportEventRow>) -> Vec<EventExportEntry> {
let mut entries = Vec::new();
for r in rows {
let create_new_entry = |n: Option<&str>, f: Option<&str>| EventExportEntry {
date: r
.start_timestamp
.format(DateTimeFormat::DayMonthYear.into())
.to_string(),
weekday: r.start_timestamp.weekday().to_string(),
start_time: r
.start_timestamp
.time()
.format(DateTimeFormat::HourMinute.into())
.to_string(),
end_time: r
.end_timestamp
.time()
.format(DateTimeFormat::HourMinute.into())
.to_string(),
hours: (r.end_timestamp - r.start_timestamp).as_seconds_f32() / 3600.0 + 1.0,
location: r.location_name.to_string(),
name: r.event_name.to_string(),
assigned_name: n.and_then(|s| Some(s.to_string())),
assigned_function: f.and_then(|s| Some(s.to_string())),
};
if let Some(assigned_wh) = r
.assignments
.iter()
.find(|a| a.function == Function::Wachhabender)
{
entries.push(create_new_entry(
Some(&assigned_wh.name),
Some(&assigned_wh.function.short_display()),
));
} else {
let function = if r.voluntary_wachhabender {
"WH"
} else {
"BF-WH"
};
entries.push(create_new_entry(None, Some(function)));
}
if let Some(assigned_fuass) = r
.assignments
.iter()
.find(|a| a.function == Function::Fuehrungsassistent)
{
entries.push(create_new_entry(
Some(&assigned_fuass.name),
Some(&assigned_fuass.function.short_display()),
));
} else if r.voluntary_fuehrungsassistent {
entries.push(create_new_entry(
None,
Some(&Function::Fuehrungsassistent.short_display()),
));
}
let assigned_po: Vec<&SimpleAssignment> = r
.assignments
.iter()
.filter(|a| a.function == Function::Posten)
.collect();
for i in 0..r.amount_of_posten {
if let Some(po) = assigned_po.get(i as usize) {
entries.push(create_new_entry(
Some(&po.name),
Some(&po.function.short_display()),
));
} else {
entries.push(create_new_entry(
None,
Some(&Function::Posten.short_display()),
));
}
}
for v in r.vehicles {
entries.push(create_new_entry(Some(&v), Some("Fzg")));
}
}
entries
}
#[actix_web::get("/export/eventsdata")]
pub async fn get(
pool: web::Data<PgPool>,
user: web::ReqData<User>,
query: web::Query<ExportQuery>,
) -> Result<impl Responder, ApplicationError> {
if user.role != Role::Admin && user.role != Role::AreaManager {
return Err(ApplicationError::Unauthorized);
}
let rows_to_export = ExportEventRow::read(pool.get_ref()).await?;
let entries = read(rows_to_export);
let mut workbook = Workbook::new();
let worksheet = workbook.add_worksheet();
// let time_format = Format::new();
// time_format.set_num_format(num_format)
const HEADER: [&str; 10] = [
"Datum",
"Wochentag",
"Beginn",
"Ende",
"Stunden",
"Ort",
"VA",
"Namen",
"Fkt",
"Reserve",
];
worksheet.write_row(2, 0, HEADER).unwrap();
for (i, entry) in entries.iter().enumerate() {
let i = (i + 3) as u32;
worksheet.write(i, 0, &entry.date).unwrap();
worksheet.write(i, 1, &entry.weekday).unwrap();
worksheet.write(i, 2, &entry.start_time).unwrap();
worksheet.write(i, 3, &entry.end_time).unwrap();
worksheet.write(i, 4, entry.hours).unwrap();
worksheet
.write(i, 4, format!("{:.1}", entry.hours))
.unwrap();
worksheet.write(i, 5, &entry.location).unwrap();
worksheet.write(i, 6, &entry.name).unwrap();
worksheet.write(i, 7, entry.assigned_name.as_ref()).unwrap();
worksheet
.write(i, 8, entry.assigned_function.as_ref())
.unwrap();
}
worksheet.autofit();
let buffer = workbook.save_to_buffer().unwrap();
return Ok(HttpResponse::Ok()
.content_type("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
.insert_header((
CONTENT_DISPOSITION,
ContentDisposition::attachment("export.xlsx"),
))
.body(buffer));
}