refactor: correct output of event export

This commit is contained in:
Max Hohlfeld 2025-06-04 15:24:27 +02:00
parent f953b6d208
commit d1e1ccd906
5 changed files with 95 additions and 105 deletions

View File

@ -0,0 +1,4 @@
CREATE TYPE simpleAssignment AS (
name text,
function function
);

View File

@ -1,4 +1,4 @@
use crate::models::{ExportEventRow, Function}; use crate::models::{ExportEventRow, Function, SimpleAssignment};
use actix_http::header::CONTENT_DISPOSITION; use actix_http::header::CONTENT_DISPOSITION;
use actix_web::{http::header::ContentDisposition, web, HttpResponse, Responder}; use actix_web::{http::header::ContentDisposition, web, HttpResponse, Responder};
use chrono::{Datelike, NaiveDate}; use chrono::{Datelike, NaiveDate};
@ -35,117 +35,87 @@ fn read(rows: Vec<ExportEventRow>) -> Vec<EventExportEntry> {
let mut entries = Vec::new(); let mut entries = Vec::new();
for r in rows { for r in rows {
let date = r let create_new_entry = |n: Option<&str>, f: Option<&str>| EventExportEntry {
.start_timestamp date: r
.format(DateTimeFormat::DayMonthYear.into()); .start_timestamp
let weekday = r.start_timestamp.weekday(); .format(DateTimeFormat::DayMonthYear.into())
let start_time = r .to_string(),
.start_timestamp weekday: r.start_timestamp.weekday().to_string(),
.time() start_time: r
.format(DateTimeFormat::HourMinute.into()); .start_timestamp
let end_time = r .time()
.end_timestamp .format(DateTimeFormat::HourMinute.into())
.time() .to_string(),
.format(DateTimeFormat::HourMinute.into()); end_time: r
let hours = (r.end_timestamp - r.start_timestamp).as_seconds_f32() / 3600.0 + 1.0; .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())),
};
let mut event_new: Vec<EventExportEntry> = Vec::new(); if let Some(assigned_wh) = r
.assignments
let mut assigned_posten: i16 = 0; .iter()
let mut assigned_wachhabender = false; .find(|a| a.function == Function::Wachhabender)
let mut assigned_fuehrungassistent = false; {
entries.push(create_new_entry(
for (assigned_name, assigned_function) in r.assignments { Some(&assigned_wh.name),
match assigned_function { Some(&assigned_wh.function.short_display()),
Function::Posten => { ));
assigned_posten += 1; } else {
}
Function::Wachhabender => {
assigned_wachhabender = true;
}
Function::Fuehrungsassistent => {
assigned_fuehrungassistent = true;
}
};
event_new.push(EventExportEntry {
date: date.to_string(),
weekday: weekday.to_string(),
start_time: start_time.to_string(),
end_time: end_time.to_string(),
hours,
location: r.location_name.to_string(),
name: r.event_name.to_string(),
assigned_name: Some(assigned_name.trim().to_string()),
assigned_function: Some(assigned_function.to_string()),
});
}
if !assigned_wachhabender {
let function = if r.voluntary_wachhabender { let function = if r.voluntary_wachhabender {
"WH" "WH"
} else { } else {
"BF-WH" "BF-WH"
}; };
event_new.push(EventExportEntry { entries.push(create_new_entry(None, Some(function)));
date: date.to_string(),
weekday: weekday.to_string(),
start_time: start_time.to_string(),
end_time: end_time.to_string(),
hours,
location: r.location_name.to_string(),
name: r.event_name.to_string(),
assigned_name: None,
assigned_function: Some(function.to_string()),
});
} }
if !assigned_fuehrungassistent && r.voluntary_fuehrungsassistent { if let Some(assigned_fuass) = r
event_new.push(EventExportEntry { .assignments
date: date.to_string(), .iter()
weekday: weekday.to_string(), .find(|a| a.function == Function::Fuehrungsassistent)
start_time: start_time.to_string(), {
end_time: end_time.to_string(), entries.push(create_new_entry(
hours, Some(&assigned_fuass.name),
location: r.location_name.to_string(), Some(&assigned_fuass.function.short_display()),
name: r.event_name.to_string(), ));
assigned_name: None, } else if r.voluntary_fuehrungsassistent {
assigned_function: Some("FüAss".to_string()), entries.push(create_new_entry(
}); None,
Some(&Function::Fuehrungsassistent.short_display()),
));
} }
if assigned_posten < r.amount_of_posten { let assigned_po: Vec<&SimpleAssignment> = r
for _ in 0..(r.amount_of_posten - assigned_posten) { .assignments
event_new.push(EventExportEntry { .iter()
date: date.to_string(), .filter(|a| a.function == Function::Posten)
weekday: weekday.to_string(), .collect();
start_time: start_time.to_string(),
end_time: end_time.to_string(), for i in 0..r.amount_of_posten {
hours, if let Some(po) = assigned_po.get(i as usize) {
location: r.location_name.to_string(), entries.push(create_new_entry(
name: r.event_name.to_string(), Some(&po.name),
assigned_name: None, Some(&po.function.short_display()),
assigned_function: Some("PO".to_string()), ));
}); } else {
entries.push(create_new_entry(
None,
Some(&Function::Posten.short_display()),
));
} }
} }
for v in r.vehicles { for v in r.vehicles {
event_new.push(EventExportEntry { entries.push(create_new_entry(Some(&v), Some("Fzg")));
date: date.to_string(),
weekday: weekday.to_string(),
start_time: start_time.to_string(),
end_time: end_time.to_string(),
hours,
location: r.location_name.to_string(),
name: r.event_name.to_string(),
assigned_name: Some(v.to_string()),
assigned_function: Some(String::from("Fzg")),
});
} }
entries.append(&mut event_new);
} }
entries entries

View File

@ -1,5 +1,8 @@
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use sqlx::{query, PgPool}; use sqlx::{
postgres::{PgHasArrayType, PgTypeInfo},
query, PgPool,
};
use crate::utils::ApplicationError; use crate::utils::ApplicationError;
@ -13,10 +16,23 @@ pub struct ExportEventRow {
pub voluntary_wachhabender: bool, pub voluntary_wachhabender: bool,
pub location_name: String, pub location_name: String,
pub event_name: String, pub event_name: String,
pub assignments: Vec<(String, Function)>, pub assignments: Vec<SimpleAssignment>,
pub vehicles: Vec<String>, pub vehicles: Vec<String>,
} }
#[derive(Debug, sqlx::Type)]
#[sqlx(type_name = "function", no_pg_array)]
pub struct SimpleAssignment {
pub name: String,
pub function: Function,
}
impl PgHasArrayType for SimpleAssignment {
fn array_type_info() -> sqlx::postgres::PgTypeInfo {
PgTypeInfo::with_name("simpleAssignment[]")
}
}
impl ExportEventRow { impl ExportEventRow {
pub async fn read(pool: &PgPool) -> Result<Vec<ExportEventRow>, ApplicationError> { pub async fn read(pool: &PgPool) -> Result<Vec<ExportEventRow>, ApplicationError> {
let rows = query!( let rows = query!(
@ -30,7 +46,7 @@ impl ExportEventRow {
event.name as eventName, event.name as eventName,
array ( array (
select select
row (user_.name, assignment.function) row (user_.name, assignment.function) ::simpleAssignment
from from
assignment assignment
join availability on join availability on
@ -38,7 +54,7 @@ impl ExportEventRow {
join user_ on join user_ on
availability.userid = user_.id availability.userid = user_.id
where where
assignment.eventId = event.id) as \"assignments: Vec<(String, Function)>\", assignment.eventId = event.id) as \"assignments: Vec<SimpleAssignment>\",
array ( array (
select select
vehicle.station || ' ' || vehicle.radiocallname vehicle.station || ' ' || vehicle.radiocallname

View File

@ -44,11 +44,11 @@ impl Default for Function {
} }
impl Function { impl Function {
pub fn short_display(&self) -> &'static str { pub fn short_display(&self) -> String {
match self { match self {
Function::Posten => "PO", Function::Posten => "PO".to_string(),
Function::Fuehrungsassistent => "FüAss", Function::Fuehrungsassistent => "FüAss".to_string(),
Function::Wachhabender => "WH", Function::Wachhabender => "WH".to_string(),
} }
} }
} }

View File

@ -30,7 +30,7 @@ pub use availability_changeset::{
pub use clothing::Clothing; pub use clothing::Clothing;
pub use event::Event; pub use event::Event;
pub use event_changeset::{EventChangeset, EventContext}; pub use event_changeset::{EventChangeset, EventContext};
pub use export_event_row::ExportEventRow; pub use export_event_row::{ExportEventRow, SimpleAssignment};
pub use function::Function; pub use function::Function;
pub use location::Location; pub use location::Location;
pub use password_reset::{NoneToken, PasswordReset, Token}; pub use password_reset::{NoneToken, PasswordReset, Token};