From bdaf8ff20ed2914cc100f7f1fc384cdd6acb9089 Mon Sep 17 00:00:00 2001 From: Max Hohlfeld Date: Wed, 2 Jul 2025 10:14:40 +0200 Subject: [PATCH] feat: finish implementing assignment validation --- cli/src/db.rs | 4 ++-- db/src/models/assignment.rs | 1 + db/src/models/assignment_changeset.rs | 27 ++++++++++++++--------- web/src/endpoints/assignment/post_new.rs | 10 +++------ web/src/endpoints/user/post_edit.rs | 8 +++++-- web/src/endpoints/vehicle/get_overview.rs | 2 +- 6 files changed, 29 insertions(+), 23 deletions(-) diff --git a/cli/src/db.rs b/cli/src/db.rs index 0aebbacf..ba197a4d 100644 --- a/cli/src/db.rs +++ b/cli/src/db.rs @@ -1,10 +1,9 @@ use anyhow::Context; -use chrono::{Local, NaiveDateTime, Utc}; +use chrono::Local; use sqlx::migrate::Migrate; use sqlx::{migrate::Migrator, Executor}; use std::fs::File; use std::io::Write; -use std::time::SystemTime; use std::{ collections::HashMap, path::{Path, PathBuf}, @@ -37,6 +36,7 @@ enum Command { } #[async_std::main] +#[allow(unused)] async fn main() { let cli = Cli::parse(); let config = load_config(&cli.environment).expect("Could not load config!"); diff --git a/db/src/models/assignment.rs b/db/src/models/assignment.rs index 2301422e..ba1981cb 100644 --- a/db/src/models/assignment.rs +++ b/db/src/models/assignment.rs @@ -3,6 +3,7 @@ use sqlx::{PgPool, query}; use super::{AssignmentChangeset, Function, Result}; +#[derive(Debug)] pub struct Assignment { pub event_id: i32, pub availability_id: i32, diff --git a/db/src/models/assignment_changeset.rs b/db/src/models/assignment_changeset.rs index ca2e7186..bdc0f556 100644 --- a/db/src/models/assignment_changeset.rs +++ b/db/src/models/assignment_changeset.rs @@ -31,7 +31,7 @@ impl<'a> AsyncValidate<'a> for AssignmentChangeset { Availability::read_by_id_including_user(context.pool, context.availability_id).await? else { return Err(AsyncValidateError::new( - "Angegebener Verfügbarkeit des Nutzers existiert nicht!", + "Angegebener Verfügbarkeit des Nutzers existiert nicht.", )); }; @@ -39,7 +39,7 @@ impl<'a> AsyncValidate<'a> for AssignmentChangeset { Event::read_by_id_including_location(context.pool, context.event_id).await? else { return Err(AsyncValidateError::new( - "Angegebenes Event existiert nicht!", + "Angegebene Veranstaltung existiert nicht.", )); }; @@ -65,7 +65,7 @@ fn availability_user_inside_event_area( if user.area_id != location.area_id { return Err(AsyncValidateError::new( - "Nutzer der Verfügbarkeit ist nicht im gleichen Bereich wie der Ort der Veranstaltung!", + "Nutzer der Verfügbarkeit ist nicht im gleichen Bereich wie der Ort der Veranstaltung.", )); } @@ -78,7 +78,7 @@ fn available_time_fits( ) -> Result<(), AsyncValidateError> { if value.0 < availability.start || value.1 > availability.end { return Err(AsyncValidateError::new( - "time not made available can't be assigned", + "Die verfügbar gemachte Zeit passt nicht zu der zugewiesenen Zeit für die Veranstaltung.", )); } @@ -93,7 +93,7 @@ fn user_of_availability_has_function( if !user_function.contains(value) { return Err(AsyncValidateError::new( - "user has not the required function for this assignment", + "Nutzer der Verfügbarkeit besitzt nicht die benötigte Funktion um für diese Position zugewiesen zu werden.", )); } @@ -106,12 +106,15 @@ async fn event_has_free_slot_for_function( event: &Event, pool: &PgPool, ) -> Result<(), AsyncValidateError> { + debug!(?event, "event parameter"); let assignments_for_event: Vec = Assignment::read_all_by_event(pool, event.id) .await? .into_iter() - .filter(|a| a.availability_id != availability.id && a.event_id != event.id) + .filter(|a| a.availability_id != availability.id) .collect(); + debug!(?assignments_for_event, "existing assignments for event"); + let assignments_with_function = assignments_for_event .iter() .filter(|a| a.function == *value) @@ -119,7 +122,7 @@ async fn event_has_free_slot_for_function( debug!( assignments_with_function, - "existing assignments for function" + "amount of existing assignments for function" ); if match *value { @@ -130,7 +133,7 @@ async fn event_has_free_slot_for_function( Function::Wachhabender => event.voluntary_wachhabender && assignments_with_function >= 1, } { return Err(AsyncValidateError::new( - "event already has enough assignments for this function", + "Veranstaltung hat bereits genug Zuweisungen für diese Funktion.", )); } @@ -146,7 +149,7 @@ async fn availability_not_already_assigned( let list: Vec = Assignment::read_all_by_availability(pool, availability.id) .await? .into_iter() - .filter(|a| a.availability_id != availability.id && a.event_id != event.id) + .filter(|a| a.event_id != event.id) .collect(); let has_start_time_during_assignment = |a: &Assignment| a.start >= time.0 && a.start <= time.1; @@ -157,7 +160,7 @@ async fn availability_not_already_assigned( .any(|a| has_start_time_during_assignment(a) || has_end_time_during_assignment(a)) { return Err(AsyncValidateError::new( - "availability is already assigned for that time", + "Die Verfügbarkeit des Nutzers wurde bereits zu einer anderen Veranstaltung zugewiesen.", )); } @@ -173,7 +176,9 @@ fn user_is_admin_or_area_manager_of_event_area( user.role == Role::AreaManager && user.area_id == event.location.as_ref().unwrap().area_id; if !user_is_admin && !user_is_area_manager_event_area { - return Err(AsyncValidateError::new("TODO: admin or areamanager")); + return Err(AsyncValidateError::new( + "Du verfügst nicht über die Berechtigung, Zuweisungen zu Veranstaltungen vorzunehmen.", + )); } Ok(()) diff --git a/web/src/endpoints/assignment/post_new.rs b/web/src/endpoints/assignment/post_new.rs index c01a55d4..68ec8d22 100644 --- a/web/src/endpoints/assignment/post_new.rs +++ b/web/src/endpoints/assignment/post_new.rs @@ -85,7 +85,6 @@ mod tests { use chrono::NaiveDateTime; use fake::{Fake, Faker}; use sqlx::PgPool; - use tracing::info; use crate::utils::test_helper::{ assert_snapshot, test_post, DbTestContext, NaiveDateTimeExt, RequestConfig, @@ -248,10 +247,7 @@ mod tests { assert_eq!(StatusCode::UNPROCESSABLE_ENTITY, response.status()); } - #[db_test] - fn fails_when_end_time_lies_before_start_time(context: &DbTestContext) { - assert!(false) - } + // fn fails_when_end_time_lies_before_start_time(context: &DbTestContext) -> not possible as event has the same constraint #[db_test] fn fails_when_availability_time_already_assigned(context: &DbTestContext) { @@ -262,6 +258,7 @@ mod tests { arrange(&context.db_pool).await; arrange_event(&context.db_pool, start, end, 1).await; + arrange_event(&context.db_pool, start, end, 1).await; arrange_availability(&context.db_pool, start, end).await; let assignment_changeset = AssignmentChangeset { @@ -273,7 +270,7 @@ mod tests { .await .unwrap(); - let config = RequestConfig::new("/assignments/new?availability=1&function=1&event=1") + let config = RequestConfig::new("/assignments/new?availability=1&function=1&event=2") .with_role(Role::Admin); let response = test_post::<_, _, String>(&context.db_pool, app, &config, None).await; @@ -303,7 +300,6 @@ mod tests { #[db_test] fn fails_when_event_already_has_enough_assignments_for_function(context: &DbTestContext) { let app = context.app().await; - info!("Hallo welt"); let start = NaiveDateTime::from_ymd_and_hms(2025, 01, 10, 10, 0, 0).unwrap(); let end = NaiveDateTime::from_ymd_and_hms(2025, 01, 10, 20, 0, 0).unwrap(); diff --git a/web/src/endpoints/user/post_edit.rs b/web/src/endpoints/user/post_edit.rs index 39b27cf1..16b31edd 100644 --- a/web/src/endpoints/user/post_edit.rs +++ b/web/src/endpoints/user/post_edit.rs @@ -88,6 +88,7 @@ mod tests { faker::{internet::en::SafeEmail, name::en::Name}, Fake, Faker, }; + use tracing::debug; #[db_test] async fn works_when_user_is_admin(context: &DbTestContext) { @@ -172,11 +173,14 @@ mod tests { is_posten: None, is_wachhabender: None, is_fuehrungsassistent: Some(true), - area: Some(2), + area: Some(1), }; let response = test_post(&context.db_pool, app, &config, Some(form)).await; - assert_eq!(StatusCode::FOUND, response.status()); + let (status, body) = response.into_status_and_body().await; + debug!(body); + + assert_eq!(StatusCode::FOUND, status); let updated_user = User::read_by_id(&context.db_pool, 1) .await diff --git a/web/src/endpoints/vehicle/get_overview.rs b/web/src/endpoints/vehicle/get_overview.rs index db3661bc..bd8b1cb4 100644 --- a/web/src/endpoints/vehicle/get_overview.rs +++ b/web/src/endpoints/vehicle/get_overview.rs @@ -41,7 +41,7 @@ mod tests { use crate::utils::test_helper::{ assert_snapshot, read_body, test_get, DbTestContext, RequestConfig, StatusCode, }; - use brass_db::models::{Role, User, Vehicle}; + use brass_db::models::{Role, Vehicle}; use brass_macros::db_test; #[db_test]