diff --git a/src/model/planned_event.rs b/src/model/event.rs similarity index 83% rename from src/model/planned_event.rs rename to src/model/event.rs index 422f14f..c0c8349 100644 --- a/src/model/planned_event.rs +++ b/src/model/event.rs @@ -3,7 +3,7 @@ use std::io::Write; use chrono::NaiveDate; use ics::{ properties::{DtStart, Summary}, - Event, ICalendar, + ICalendar, }; use serde::Serialize; use sqlx::{FromRow, Row, SqlitePool}; @@ -11,10 +11,10 @@ use sqlx::{FromRow, Row, SqlitePool}; use super::{notification::Notification, tripdetails::TripDetails, triptype::TripType, user::User}; #[derive(Serialize, Clone, FromRow, Debug, PartialEq)] -pub struct PlannedEvent { +pub struct Event { pub id: i64, pub name: String, - planned_amount_cox: i64, + pub(crate) planned_amount_cox: i64, trip_details_id: i64, pub planned_starting_time: String, pub(crate) max_people: i64, @@ -22,14 +22,14 @@ pub struct PlannedEvent { pub notes: Option, pub allow_guests: bool, trip_type_id: Option, - always_show: bool, - is_locked: bool, + pub(crate) always_show: bool, + pub(crate) is_locked: bool, } #[derive(Serialize, Debug)] -pub struct PlannedEventWithUserAndTriptype { +pub struct EventWithUserAndTriptype { #[serde(flatten)] - pub planned_event: PlannedEvent, + pub event: Event, trip_type: Option, cox_needed: bool, cox: Vec, @@ -73,7 +73,7 @@ FROM user_trip WHERE trip_details_id = {} .collect() } - pub async fn all_cox(db: &SqlitePool, trip_details_id: i64) -> Vec { + pub async fn all_cox(db: &SqlitePool, event_id: i64) -> Vec { //TODO: switch to join sqlx::query!( " @@ -82,7 +82,7 @@ SELECT (SELECT created_at FROM user WHERE cox_id = id) as registered_at FROM trip WHERE planned_event_id = ? ", - trip_details_id + event_id ) .fetch_all(db) .await @@ -94,7 +94,7 @@ FROM trip WHERE planned_event_id = ? is_guest: false, is_real_guest: false, }) - .collect() //Okay, as PlannedEvent can only be created with proper DB backing + .collect() //Okay, as Event can only be created with proper DB backing } } @@ -107,7 +107,7 @@ pub struct EventUpdate<'a> { pub is_locked: bool, } -impl PlannedEvent { +impl Event { pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option { sqlx::query_as!( Self, @@ -128,19 +128,16 @@ WHERE planned_event.id like ? pub async fn get_pinned_for_day( db: &SqlitePool, day: NaiveDate, - ) -> Vec { + ) -> Vec { let mut events = Self::get_for_day(db, day).await; - events.retain(|e| e.planned_event.always_show); + events.retain(|e| e.event.always_show); events } - pub async fn get_for_day( - db: &SqlitePool, - day: NaiveDate, - ) -> Vec { + pub async fn get_for_day(db: &SqlitePool, day: NaiveDate) -> Vec { let day = format!("{day}"); let events = sqlx::query_as!( - PlannedEvent, + Event, "SELECT planned_event.id, planned_event.name, planned_amount_cox, trip_details_id, planned_starting_time, always_show, max_people, day, notes, allow_guests, trip_type_id, is_locked FROM planned_event INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id @@ -158,20 +155,20 @@ WHERE day=?", if let Some(trip_type_id) = event.trip_type_id { trip_type = TripType::find_by_id(db, trip_type_id).await; } - ret.push(PlannedEventWithUserAndTriptype { + ret.push(EventWithUserAndTriptype { cox_needed: event.planned_amount_cox > cox.len() as i64, cox, rower: Registration::all_rower(db, event.trip_details_id).await, - planned_event: event, + event, trip_type, }); } ret } - pub async fn all(db: &SqlitePool) -> Vec { + pub async fn all(db: &SqlitePool) -> Vec { sqlx::query_as!( - PlannedEvent, + Event, "SELECT planned_event.id, planned_event.name, planned_amount_cox, trip_details_id, planned_starting_time, always_show, max_people, day, notes, allow_guests, trip_type_id, is_locked FROM planned_event INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id", @@ -198,11 +195,27 @@ INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id", is_rower.amount > 0 } + pub async fn find_by_trip_details(db: &SqlitePool, tripdetails_id: i64) -> Option { + sqlx::query_as!( + Self, + " +SELECT planned_event.id, planned_event.name, planned_amount_cox, trip_details_id, planned_starting_time, always_show, max_people, day, notes, allow_guests, trip_type_id, is_locked +FROM planned_event +INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id +WHERE trip_details.id=? + ", + tripdetails_id + ) + .fetch_one(db) + .await + .ok() + } + pub async fn create( db: &SqlitePool, name: &str, planned_amount_cox: i32, - trip_details: TripDetails, + trip_details: &TripDetails, ) { sqlx::query!( "INSERT INTO planned_event(name, planned_amount_cox, trip_details_id) VALUES(?, ?, ?)", @@ -260,7 +273,7 @@ INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id", ), "Absage Ausfahrt", None, - Some(&format!("remove_trip_by_planned_event:{}", self.id)), + Some(&format!("remove_trip_by_event:{}", self.id)), ) .await; } @@ -298,11 +311,7 @@ INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id", &format!("remove_user_trip_with_trip_details_id:{}", tripdetails.id), ) .await; - Notification::delete_by_action( - db, - &format!("remove_trip_by_planned_event:{}", self.id), - ) - .await; + Notification::delete_by_action(db, &format!("remove_trip_by_event:{}", self.id)).await; } } @@ -328,7 +337,7 @@ INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id", sqlx::query!("DELETE FROM planned_event WHERE id = ?", self.id) .execute(db) .await - .unwrap(); //Okay, as PlannedEvent can only be created with proper DB backing + .unwrap(); //Okay, as Event can only be created with proper DB backing Ok(()) } @@ -336,9 +345,10 @@ INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id", pub async fn get_ics_feed(db: &SqlitePool) -> String { let mut calendar = ICalendar::new("2.0", "ics-rs"); - let events = PlannedEvent::all(db).await; + let events = Event::all(db).await; for event in events { - let mut vevent = Event::new(format!("{}@rudernlinz.at", event.id), "19900101T180000"); + let mut vevent = + ics::Event::new(format!("{}@rudernlinz.at", event.id), "19900101T180000"); vevent.push(DtStart::new(format!( "{}T{}00", event.day.replace('-', ""), @@ -363,7 +373,7 @@ INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id", mod test { use crate::{model::tripdetails::TripDetails, testdb}; - use super::PlannedEvent; + use super::Event; use chrono::NaiveDate; use sqlx::SqlitePool; @@ -371,8 +381,7 @@ mod test { fn test_get_day() { let pool = testdb!(); - let res = - PlannedEvent::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await; + let res = Event::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await; assert_eq!(res.len(), 1); } @@ -382,22 +391,20 @@ mod test { let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap(); - PlannedEvent::create(&pool, "new-event".into(), 2, trip_details).await; + Event::create(&pool, "new-event".into(), 2, &trip_details).await; - let res = - PlannedEvent::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await; + let res = Event::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await; assert_eq!(res.len(), 2); } #[sqlx::test] fn test_delete() { let pool = testdb!(); - let planned_event = PlannedEvent::find_by_id(&pool, 1).await.unwrap(); + let planned_event = Event::find_by_id(&pool, 1).await.unwrap(); planned_event.delete(&pool).await.unwrap(); - let res = - PlannedEvent::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await; + let res = Event::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await; assert_eq!(res.len(), 0); } @@ -405,7 +412,7 @@ mod test { fn test_ics() { let pool = testdb!(); - let actual = PlannedEvent::get_ics_feed(&pool).await; + let actual = Event::get_ics_feed(&pool).await; assert_eq!("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:ics-rs\r\nBEGIN:VEVENT\r\nUID:1@rudernlinz.at\r\nDTSTAMP:19900101T180000\r\nDTSTART:19700101T100000\r\nSUMMARY:test-planned-event\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n", actual); } } diff --git a/src/model/mod.rs b/src/model/mod.rs index a927799..0380975 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -3,7 +3,7 @@ use serde::Serialize; use sqlx::SqlitePool; use self::{ - planned_event::{PlannedEvent, PlannedEventWithUserAndTriptype}, + event::{Event, EventWithUserAndTriptype}, trip::{Trip, TripWithUserAndType}, waterlevel::Waterlevel, weather::Weather, @@ -13,6 +13,7 @@ pub mod boat; pub mod boatdamage; pub mod boathouse; pub mod boatreservation; +pub mod event; pub mod family; pub mod location; pub mod log; @@ -20,7 +21,6 @@ pub mod logbook; pub mod logtype; pub mod mail; pub mod notification; -pub mod planned_event; pub mod role; pub mod rower; pub mod stat; @@ -35,7 +35,7 @@ pub mod weather; #[derive(Serialize, Debug)] pub struct Day { day: NaiveDate, - planned_events: Vec, + events: Vec, trips: Vec, is_pinned: bool, max_waterlevel: Option, @@ -47,7 +47,7 @@ impl Day { if is_pinned { Self { day, - planned_events: PlannedEvent::get_pinned_for_day(db, day).await, + events: Event::get_pinned_for_day(db, day).await, trips: Trip::get_pinned_for_day(db, day).await, is_pinned, max_waterlevel: Waterlevel::max_waterlevel_for_day(db, day).await, @@ -56,7 +56,7 @@ impl Day { } else { Self { day, - planned_events: PlannedEvent::get_for_day(db, day).await, + events: Event::get_for_day(db, day).await, trips: Trip::get_for_day(db, day).await, is_pinned, max_waterlevel: Waterlevel::max_waterlevel_for_day(db, day).await, @@ -67,7 +67,7 @@ impl Day { pub async fn new_guest(db: &SqlitePool, day: NaiveDate, is_pinned: bool) -> Self { let mut day = Self::new(db, day, is_pinned).await; - day.planned_events.retain(|e| e.planned_event.allow_guests); + day.events.retain(|e| e.event.allow_guests); day.trips.retain(|t| t.trip.allow_guests); day diff --git a/src/model/notification.rs b/src/model/notification.rs index 841ad3c..9bb242e 100644 --- a/src/model/notification.rs +++ b/src/model/notification.rs @@ -7,7 +7,7 @@ use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; use super::{role::Role, user::User}; -#[derive(FromRow, Debug, Serialize, Deserialize)] +#[derive(FromRow, Debug, Serialize, Deserialize, Clone)] pub struct Notification { pub id: i64, pub user_id: i64, @@ -153,7 +153,7 @@ ORDER BY read_at DESC, created_at DESC; } } // Cox read notification about cancelled event - let re = Regex::new(r"^remove_trip_by_planned_event:(\d+)$").unwrap(); + let re = Regex::new(r"^remove_trip_by_event:(\d+)$").unwrap(); if let Some(caps) = re.captures(action) { if let Some(matched) = caps.get(1) { if let Ok(number) = matched.as_str().parse::() { @@ -180,3 +180,114 @@ ORDER BY read_at DESC, created_at DESC; .unwrap(); } } + +#[cfg(test)] +mod test { + use crate::{ + model::{ + event::{Event, EventUpdate, Registration}, + notification::Notification, + trip::Trip, + tripdetails::{TripDetails, TripDetailsToAdd}, + user::{CoxUser, User}, + usertrip::UserTrip, + }, + testdb, + }; + + use sqlx::SqlitePool; + + #[sqlx::test] + fn event_canceled() { + let pool = testdb!(); + + // Create event + let add_tripdetails = TripDetailsToAdd { + planned_starting_time: "10:00", + max_people: 4, + day: "1970-02-01".into(), + notes: None, + trip_type: None, + allow_guests: false, + always_show: false, + }; + let tripdetails_id = TripDetails::create(&pool, add_tripdetails).await; + let trip_details = TripDetails::find_by_id(&pool, tripdetails_id) + .await + .unwrap(); + Event::create(&pool, "new-event".into(), 2, &trip_details).await; + let event = Event::find_by_trip_details(&pool, trip_details.id) + .await + .unwrap(); + + // Rower + Cox joins + let rower = User::find_by_name(&pool, "rower").await.unwrap(); + UserTrip::create(&pool, &rower, &trip_details, None) + .await + .unwrap(); + let cox = CoxUser::new(&pool, User::find_by_name(&pool, "cox").await.unwrap()) + .await + .unwrap(); + Trip::new_join(&pool, &cox, &event).await.unwrap(); + + // Cancel Event + let cancel_update = EventUpdate { + name: &event.name, + planned_amount_cox: event.planned_amount_cox as i32, + max_people: 0, + notes: event.notes.as_deref(), + always_show: event.always_show, + is_locked: event.is_locked, + }; + event.update(&pool, &cancel_update).await; + + // Rower received notification + let notifications = Notification::for_user(&pool, &rower).await; + let rower_notification = notifications[0].clone(); + assert_eq!(rower_notification.category, "Absage Ausfahrt"); + assert_eq!( + rower_notification.action_after_reading.as_deref(), + Some("remove_user_trip_with_trip_details_id:3") + ); + + // Cox received notification + let notifications = Notification::for_user(&pool, &cox.user).await; + let cox_notification = notifications[0].clone(); + assert_eq!(cox_notification.category, "Absage Ausfahrt"); + assert_eq!( + cox_notification.action_after_reading.as_deref(), + Some("remove_trip_by_event:2") + ); + + // Notification removed if cancellation is cancelled + let update = EventUpdate { + name: &event.name, + planned_amount_cox: event.planned_amount_cox as i32, + max_people: 3, + notes: event.notes.as_deref(), + always_show: event.always_show, + is_locked: event.is_locked, + }; + event.update(&pool, &update).await; + assert!(Notification::for_user(&pool, &rower).await.is_empty()); + assert!(Notification::for_user(&pool, &cox.user).await.is_empty()); + + // Cancel event again + event.update(&pool, &cancel_update).await; + + // Rower is removed if notification is accepted + assert!(event.is_rower_registered(&pool, &rower).await); + rower_notification.mark_read(&pool).await; + assert!(!event.is_rower_registered(&pool, &rower).await); + + // Cox is removed if notification is accepted + let registration = Registration::all_cox(&pool, event.id).await; + assert_eq!(registration.len(), 1); + assert_eq!(registration[0].name, "cox"); + + cox_notification.mark_read(&pool).await; + + let registration = Registration::all_cox(&pool, event.id).await; + assert!(registration.is_empty()); + } +} diff --git a/src/model/trip.rs b/src/model/trip.rs index 9493d3f..c0f4bac 100644 --- a/src/model/trip.rs +++ b/src/model/trip.rs @@ -3,8 +3,8 @@ use serde::Serialize; use sqlx::SqlitePool; use super::{ + event::{Event, Registration}, notification::Notification, - planned_event::{PlannedEvent, Registration}, tripdetails::TripDetails, triptype::TripType, user::{CoxUser, User}, @@ -133,28 +133,28 @@ WHERE trip.id=? .ok() } - /// Cox decides to help in a planned event. + /// Cox decides to help in a event. pub async fn new_join( db: &SqlitePool, cox: &CoxUser, - planned_event: &PlannedEvent, + event: &Event, ) -> Result<(), CoxHelpError> { - if planned_event.is_rower_registered(db, cox).await { + if event.is_rower_registered(db, cox).await { return Err(CoxHelpError::AlreadyRegisteredAsRower); } - if planned_event.trip_details(db).await.is_locked { + if event.trip_details(db).await.is_locked { return Err(CoxHelpError::DetailsLocked); } - if planned_event.max_people == 0 { + if event.max_people == 0 { return Err(CoxHelpError::CanceledEvent); } match sqlx::query!( "INSERT INTO trip (cox_id, planned_event_id) VALUES(?, ?)", cox.id, - planned_event.id + event.id ) .execute(db) .await @@ -281,16 +281,16 @@ WHERE day=? pub async fn delete_by_planned_event( db: &SqlitePool, cox: &CoxUser, - planned_event: &PlannedEvent, + event: &Event, ) -> Result<(), TripHelpDeleteError> { - if planned_event.trip_details(db).await.is_locked { + if event.trip_details(db).await.is_locked { return Err(TripHelpDeleteError::DetailsLocked); } let affected_rows = sqlx::query!( "DELETE FROM trip WHERE cox_id = ? AND planned_event_id = ?", cox.id, - planned_event.id + event.id ) .execute(db) .await @@ -374,7 +374,7 @@ pub enum TripUpdateError { mod test { use crate::{ model::{ - planned_event::PlannedEvent, + event::Event, trip::{self, TripDeleteError}, tripdetails::TripDetails, user::{CoxUser, User}, @@ -425,7 +425,7 @@ mod test { .await .unwrap(); - let planned_event = PlannedEvent::find_by_id(&pool, 1).await.unwrap(); + let planned_event = Event::find_by_id(&pool, 1).await.unwrap(); assert!(Trip::new_join(&pool, &cox, &planned_event).await.is_ok()); } @@ -441,7 +441,7 @@ mod test { .await .unwrap(); - let planned_event = PlannedEvent::find_by_id(&pool, 1).await.unwrap(); + let planned_event = Event::find_by_id(&pool, 1).await.unwrap(); Trip::new_join(&pool, &cox, &planned_event).await.unwrap(); assert!(Trip::new_join(&pool, &cox, &planned_event).await.is_err()); @@ -542,7 +542,7 @@ mod test { .await .unwrap(); - let planned_event = PlannedEvent::find_by_id(&pool, 1).await.unwrap(); + let planned_event = Event::find_by_id(&pool, 1).await.unwrap(); Trip::new_join(&pool, &cox, &planned_event).await.unwrap(); diff --git a/src/model/user.rs b/src/model/user.rs index add8755..026c1d3 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -823,7 +823,7 @@ ORDER BY last_access DESC for date in TripDetails::pinned_days(db, self.amount_days_to_show(db).await - 1).await { if self.has_role(db, "scheckbuch").await { let day = Day::new_guest(db, date, true).await; - if !day.planned_events.is_empty() { + if !day.events.is_empty() { days.push(day); } } else { @@ -1124,15 +1124,15 @@ impl<'r> FromRequest<'r> for VorstandUser { } #[derive(Debug, Serialize, Deserialize)] -pub struct PlannedEventUser(pub(crate) User); +pub struct EventUser(pub(crate) User); -impl From for User { - fn from(val: PlannedEventUser) -> Self { +impl From for User { + fn from(val: EventUser) -> Self { val.0 } } -impl Deref for PlannedEventUser { +impl Deref for EventUser { type Target = User; fn deref(&self) -> &Self::Target { @@ -1183,7 +1183,7 @@ impl UserWithMembershipPdf { } #[async_trait] -impl<'r> FromRequest<'r> for PlannedEventUser { +impl<'r> FromRequest<'r> for EventUser { type Error = LoginError; async fn from_request(req: &'r Request<'_>) -> request::Outcome { @@ -1191,7 +1191,7 @@ impl<'r> FromRequest<'r> for PlannedEventUser { match User::from_request(req).await { Outcome::Success(user) => { if user.has_role(db, "planned_event").await { - Outcome::Success(PlannedEventUser(user)) + Outcome::Success(EventUser(user)) } else { Outcome::Error((Status::Forbidden, LoginError::NotACox)) } diff --git a/src/model/usertrip.rs b/src/model/usertrip.rs index 440a6b4..1befabc 100644 --- a/src/model/usertrip.rs +++ b/src/model/usertrip.rs @@ -150,7 +150,7 @@ pub enum UserTripDeleteError { mod test { use crate::{ model::{ - planned_event::PlannedEvent, trip::Trip, tripdetails::TripDetails, user::CoxUser, + event::Event, trip::Trip, tripdetails::TripDetails, user::CoxUser, usertrip::UserTripError, }, testdb, @@ -240,8 +240,8 @@ mod test { .await .unwrap(); - let planned_event = PlannedEvent::find_by_id(&pool, 1).await.unwrap(); - Trip::new_join(&pool, &cox, &planned_event).await.unwrap(); + let event = Event::find_by_id(&pool, 1).await.unwrap(); + Trip::new_join(&pool, &cox, &event).await.unwrap(); let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap(); let result = UserTrip::create(&pool, &cox, &trip_details, None) diff --git a/src/tera/admin/planned_event.rs b/src/tera/admin/planned_event.rs index f98b8c9..7fa5303 100644 --- a/src/tera/admin/planned_event.rs +++ b/src/tera/admin/planned_event.rs @@ -8,14 +8,14 @@ use serde::Serialize; use sqlx::SqlitePool; use crate::model::{ - planned_event::{self, PlannedEvent}, + event::{self, Event}, tripdetails::{TripDetails, TripDetailsToAdd}, - user::PlannedEventUser, + user::EventUser, }; //TODO: add constraints (e.g. planned_amount_cox > 0) #[derive(FromForm, Serialize)] -struct AddPlannedEventForm<'r> { +struct AddEventForm<'r> { name: &'r str, planned_amount_cox: i32, tripdetails: TripDetailsToAdd<'r>, @@ -24,8 +24,8 @@ struct AddPlannedEventForm<'r> { #[post("/planned-event", data = "")] async fn create( db: &State, - data: Form>, - _admin: PlannedEventUser, + data: Form>, + _admin: EventUser, ) -> Flash { let data = data.into_inner(); @@ -34,14 +34,14 @@ async fn create( //just created //the object - PlannedEvent::create(db, data.name, data.planned_amount_cox, trip_details).await; + Event::create(db, data.name, data.planned_amount_cox, &trip_details).await; Flash::success(Redirect::to("/planned"), "Event hinzugefügt") } //TODO: add constraints (e.g. planned_amount_cox > 0) #[derive(FromForm)] -struct UpdatePlannedEventForm<'r> { +struct UpdateEventForm<'r> { id: i64, name: &'r str, planned_amount_cox: i32, @@ -54,10 +54,10 @@ struct UpdatePlannedEventForm<'r> { #[put("/planned-event", data = "")] async fn update( db: &State, - data: Form>, - _admin: PlannedEventUser, + data: Form>, + _admin: EventUser, ) -> Flash { - let update = planned_event::EventUpdate { + let update = event::EventUpdate { name: data.name, planned_amount_cox: data.planned_amount_cox, max_people: data.max_people, @@ -65,7 +65,7 @@ async fn update( always_show: data.always_show, is_locked: data.is_locked, }; - match PlannedEvent::find_by_id(db, data.id).await { + match Event::find_by_id(db, data.id).await { Some(planned_event) => { planned_event.update(db, &update).await; Flash::success(Redirect::to("/planned"), "Event erfolgreich bearbeitet") @@ -75,9 +75,9 @@ async fn update( } #[get("/planned-event//delete")] -async fn delete(db: &State, id: i64, _admin: PlannedEventUser) -> Flash { - let Some(event) = PlannedEvent::find_by_id(db, id).await else { - return Flash::error(Redirect::to("/planned"), "PlannedEvent does not exist"); +async fn delete(db: &State, id: i64, _admin: EventUser) -> Flash { + let Some(event) = Event::find_by_id(db, id).await else { + return Flash::error(Redirect::to("/planned"), "Event does not exist"); }; match event.delete(db).await { @@ -105,7 +105,7 @@ mod test { fn test_delete() { let db = testdb!(); - let _ = PlannedEvent::find_by_id(&db, 1).await.unwrap(); + let _ = Event::find_by_id(&db, 1).await.unwrap(); let rocket = rocket::build().manage(db.clone()); let rocket = crate::tera::config(rocket); @@ -130,7 +130,7 @@ mod test { assert_eq!(flash_cookie.value(), "7:successEvent gelöscht"); - let event = PlannedEvent::find_by_id(&db, 1).await; + let event = Event::find_by_id(&db, 1).await; assert_eq!(event, None); } @@ -159,16 +159,16 @@ mod test { .get("_flash") .expect("Expected flash cookie"); - assert_eq!(flash_cookie.value(), "5:errorPlannedEvent does not exist"); + assert_eq!(flash_cookie.value(), "5:errorEvent does not exist"); - let _ = PlannedEvent::find_by_id(&db, 1).await.unwrap(); + let _ = Event::find_by_id(&db, 1).await.unwrap(); } #[sqlx::test] fn test_update() { let db = testdb!(); - let event = PlannedEvent::find_by_id(&db, 1).await.unwrap(); + let event = Event::find_by_id(&db, 1).await.unwrap(); assert_eq!(event.notes, Some("trip_details for a planned event".into())); let rocket = rocket::build().manage(db.clone()); @@ -200,7 +200,7 @@ mod test { "7:successEvent erfolgreich bearbeitet" ); - let event = PlannedEvent::find_by_id(&db, 1).await.unwrap(); + let event = Event::find_by_id(&db, 1).await.unwrap(); assert_eq!(event.notes, Some("new-planned-event-text".into())); } @@ -267,7 +267,7 @@ mod test { assert_eq!(flash_cookie.value(), "7:successEvent hinzugefügt"); - let event = PlannedEvent::find_by_id(&db, 2).await.unwrap(); + let event = Event::find_by_id(&db, 2).await.unwrap(); assert_eq!(event.name, "my-cool-new-event"); } } diff --git a/src/tera/cox.rs b/src/tera/cox.rs index af11683..6b47cf4 100644 --- a/src/tera/cox.rs +++ b/src/tera/cox.rs @@ -7,8 +7,8 @@ use rocket::{ use sqlx::SqlitePool; use crate::model::{ + event::Event, log::Log, - planned_event::PlannedEvent, trip::{self, CoxHelpError, Trip, TripDeleteError, TripHelpDeleteError, TripUpdateError}, tripdetails::{TripDetails, TripDetailsToAdd}, user::CoxUser, @@ -82,7 +82,7 @@ async fn update( #[get("/join/")] async fn join(db: &State, planned_event_id: i64, cox: CoxUser) -> Flash { - if let Some(planned_event) = PlannedEvent::find_by_id(db, planned_event_id).await { + if let Some(planned_event) = Event::find_by_id(db, planned_event_id).await { match Trip::new_join(db, &cox, &planned_event).await { Ok(_) => { Log::create( @@ -137,7 +137,7 @@ async fn remove_trip(db: &State, trip_id: i64, cox: CoxUser) -> Flas #[get("/remove/")] async fn remove(db: &State, planned_event_id: i64, cox: CoxUser) -> Flash { - if let Some(planned_event) = PlannedEvent::find_by_id(db, planned_event_id).await { + if let Some(planned_event) = Event::find_by_id(db, planned_event_id).await { match Trip::delete_by_planned_event(db, &cox, &planned_event).await { Ok(_) => { Log::create( diff --git a/src/tera/misc.rs b/src/tera/misc.rs index 100890f..5cf48ff 100644 --- a/src/tera/misc.rs +++ b/src/tera/misc.rs @@ -1,12 +1,12 @@ use rocket::{get, http::ContentType, routes, Route, State}; use sqlx::SqlitePool; -use crate::model::planned_event::PlannedEvent; +use crate::model::event::Event; #[get("/cal")] async fn cal(db: &State) -> (ContentType, String) { //TODO: add unit test once proper functionality is there - (ContentType::Calendar, PlannedEvent::get_ics_feed(db).await) + (ContentType::Calendar, Event::get_ics_feed(db).await) } pub fn routes() -> Vec { diff --git a/templates/planned.html.tera b/templates/planned.html.tera index 4c19e06..4188098 100644 --- a/templates/planned.html.tera +++ b/templates/planned.html.tera @@ -58,11 +58,11 @@

Ausfahrten

{% include "includes/buttons" %} {% for day in days %} - {% set amount_trips = day.planned_events | length + day.trips | length %} + {% set amount_trips = day.events | length + day.trips | length %} {% set_global day_cox_needed = false %} - {% if day.planned_events | length > 0 %} - {% for planned_event in day.planned_events %} - {% if planned_event.cox_needed %} + {% if day.events | length > 0 %} + {% for event in day.events %} + {% if event.cox_needed %} {% set_global day_cox_needed = true %} {% endif %} {% endfor %} @@ -88,82 +88,82 @@ {% endif %} - {% if day.planned_events | length > 0 or day.trips | length > 0 %} + {% if day.events | length > 0 or day.trips | length > 0 %}
{# --- START Events --- #} - {% if day.planned_events | length > 0 %} - {% for planned_event in day.planned_events | sort(attribute="planned_starting_time") %} - {% set amount_cur_cox = planned_event.cox | length %} - {% set amount_cox_missing = planned_event.planned_amount_cox - amount_cur_cox %} + {% if day.events | length > 0 %} + {% for event in day.events | sort(attribute="planned_starting_time") %} + {% set amount_cur_cox = event.cox | length %} + {% set amount_cox_missing = event.planned_amount_cox - amount_cur_cox %}
+ style="order: {{ event.planned_starting_time | replace(from=":", to="") }}">
- {% if planned_event.max_people == 0 %} + {% if event.max_people == 0 %} ⚠ Absage - {{ planned_event.planned_starting_time }} + {{ event.planned_starting_time }} Uhr - ({{ planned_event.name }} - {%- if planned_event.trip_type %} - - {{ planned_event.trip_type.icon | safe }} {{ planned_event.trip_type.name }} + ({{ event.name }} + {%- if event.trip_type %} + - {{ event.trip_type.icon | safe }} {{ event.trip_type.name }} {%- endif -%} ) {% else %} - {{ planned_event.planned_starting_time }} + {{ event.planned_starting_time }} Uhr - ({{ planned_event.name }} - {%- if planned_event.trip_type %} - - {{ planned_event.trip_type.icon | safe }} {{ planned_event.trip_type.name }} + ({{ event.name }} + {%- if event.trip_type %} + - {{ event.trip_type.icon | safe }} {{ event.trip_type.name }} {%- endif -%} ) {% endif %}
- + Details
{# --- START Row Buttons --- #} {% set_global cur_user_participates = false %} - {% for rower in planned_event.rower %} + {% for rower in event.rower %} {% if rower.name == loggedin_user.name %} {% set_global cur_user_participates = true %} {% endif %} {% endfor %} {% if cur_user_participates %} - Abmelden {% endif %} - {% if planned_event.max_people > planned_event.rower | length and cur_user_participates == false %} - event.rower | length and cur_user_participates == false %} + Mitrudern + {% if event.trip_type %}onclick="return confirm('{{ event.trip_type.question }}');"{% endif %}>Mitrudern {% endif %} {# --- END Row Buttons --- #} {# --- START Cox Buttons --- #} {% if "cox" in loggedin_user.roles %} {% set_global cur_user_participates = false %} - {% for cox in planned_event.cox %} + {% for cox in event.cox %} {% if cox.name == loggedin_user.name %} {% set_global cur_user_participates = true %} {% endif %} {% endfor %} {% if cur_user_participates %} - {% include "includes/cox-icon" %} Abmelden - {% elif planned_event.planned_amount_cox > 0 %} - 0 %} + + {% if event.trip_type %}onclick="return confirm('{{ event.trip_type.question }}');"{% endif %}> {% include "includes/cox-icon" %} Steuern @@ -174,30 +174,30 @@
{# --- START Sidebar Content --- #}