diff --git a/src/model/logbook.rs b/src/model/logbook.rs index c7bf488..aa45763 100644 --- a/src/model/logbook.rs +++ b/src/model/logbook.rs @@ -57,6 +57,7 @@ pub struct LogbookWithBoatAndRowers { pub enum LogbookUpdateError { NotYourEntry, TooManyRowers(usize, usize), + RowerCreateError(i64, String), } pub enum LogbookCreateError { @@ -66,6 +67,7 @@ pub enum LogbookCreateError { TooManyRowers(usize, usize), ShipmasterAlreadyOnWater, RowerAlreadyOnWater(User), + RowerCreateError(i64, String), } impl Logbook { @@ -164,8 +166,8 @@ ORDER BY departure DESC pub async fn create(db: &SqlitePool, log: LogToAdd) -> Result<(), LogbookCreateError> { let Some(boat) = Boat::find_by_id(db, log.boat_id).await else { - return Err(LogbookCreateError::BoatNotFound); - }; + return Err(LogbookCreateError::BoatNotFound); + }; if boat.is_locked(db).await { return Err(LogbookCreateError::BoatLocked); @@ -217,7 +219,11 @@ ORDER BY departure DESC .await.unwrap(); for rower in &log.rower { - Rower::create(&mut tx, inserted_row.id, *rower).await; + Rower::create(&mut tx, inserted_row.id, *rower) + .await + .map_err(|e| { + return LogbookCreateError::RowerCreateError(*rower, e.to_string()); + })?; } tx.commit().await.unwrap(); @@ -289,7 +295,9 @@ ORDER BY departure DESC self.remove_rowers(&mut tx).await; for rower in &log.rower { - Rower::create(&mut tx, self.id, *rower).await; + Rower::create(&mut tx, self.id, *rower).await.map_err(|e| { + return LogbookUpdateError::RowerCreateError(*rower, e.to_string()); + })?; } tx.commit().await.unwrap(); diff --git a/src/model/rower.rs b/src/model/rower.rs index 333acf3..f54b7a3 100644 --- a/src/model/rower.rs +++ b/src/model/rower.rs @@ -25,14 +25,69 @@ WHERE id in (SELECT rower_id FROM rower WHERE logbook_id=?) .unwrap() } - pub async fn create(db: &mut Transaction<'_, Sqlite>, logbook_id: i64, rower_id: i64) { - let _ = sqlx::query!( + pub async fn create( + db: &mut Transaction<'_, Sqlite>, + logbook_id: i64, + rower_id: i64, + ) -> Result<(), String> { + //TODO: Check if rower is allowed to row + + sqlx::query!( "INSERT INTO rower(logbook_id, rower_id) VALUES (?,?)", logbook_id, rower_id ) .execute(db) .await - .unwrap(); + .map_err(|e| return e.to_string())?; + + Ok(()) + } +} + +#[cfg(test)] +mod test { + use sqlx::SqlitePool; + + use super::Logbook; + use crate::model::{rower::Rower, user::User}; + use crate::testdb; + + #[sqlx::test] + fn test_for_log() { + let pool = testdb!(); + + let logbook = Logbook::find_by_id(&pool, 3).await.unwrap(); + let rowers = Rower::for_log(&pool, &logbook).await; + let expected = User::find_by_id(&pool, 3).await.unwrap(); + assert_eq!(rowers, vec![expected]); + } + + #[sqlx::test] + fn test_for_log_none() { + let pool = testdb!(); + + let logbook = Logbook::find_by_id(&pool, 2).await.unwrap(); + let rowers = Rower::for_log(&pool, &logbook).await; + assert_eq!(rowers, vec![]); + } + + #[sqlx::test] + fn test_create() { + let pool = testdb!(); + + let logbook = Logbook::find_by_id(&pool, 3).await.unwrap(); + + let mut tx = pool.begin().await.unwrap(); + Rower::create(&mut tx, logbook.id, 2).await.unwrap(); + tx.commit().await.unwrap(); + let rowers = Rower::for_log(&pool, &logbook).await; + assert_eq!( + rowers, + vec![ + User::find_by_id(&pool, 2).await.unwrap(), + User::find_by_id(&pool, 3).await.unwrap() + ] + ); } } diff --git a/src/model/user.rs b/src/model/user.rs index c6233ae..ca0e1ba 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -27,6 +27,12 @@ pub struct User { pub last_access: Option, } +impl PartialEq for User { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + } +} + #[derive(Debug)] pub enum LoginError { InvalidAuthenticationCombo, diff --git a/src/tera/cox.rs b/src/tera/cox.rs index 965f4b1..ad4a344 100644 --- a/src/tera/cox.rs +++ b/src/tera/cox.rs @@ -453,7 +453,7 @@ mod test { assert_eq!(flash_cookie.value(), "7:successDanke für's helfen!"); let req = client.get("/cox/join/1"); - let response = req.dispatch().await; + let _ = req.dispatch().await; let req = client.get("/cox/remove/1"); let response = req.dispatch().await; diff --git a/src/tera/log.rs b/src/tera/log.rs index 6715f1e..1eacdff 100644 --- a/src/tera/log.rs +++ b/src/tera/log.rs @@ -129,6 +129,7 @@ async fn create_logbook(db: &SqlitePool, data: Form) -> Flash Flash::error(Redirect::to("/log"), format!("Boot gesperrt")), Err(LogbookCreateError::BoatNotFound) => Flash::error(Redirect::to("/log"), format!("Boot gibt's ned")), Err(LogbookCreateError::TooManyRowers(expected, actual)) => Flash::error(Redirect::to("/log"), format!("Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)")), + Err(LogbookCreateError::RowerCreateError(rower, e)) => Flash::error(Redirect::to("/log"), format!("Fehler bei Ruderer {rower}: {e}")), } } @@ -159,10 +160,10 @@ async fn home_logbook( ) -> Flash { let logbook: Option = Logbook::find_by_id(db, logbook_id).await; let Some(logbook) = logbook else { - return Flash::error( - Redirect::to("/admin/log"), - format!("Log with ID {} does not exist!", logbook_id), - ) + return Flash::error( + Redirect::to("/admin/log"), + format!("Log with ID {} does not exist!", logbook_id), + ); }; match logbook.home(db, user, data.into_inner()).await {