add trailer reservation funcitonality; Fixes #443
This commit is contained in:
@ -39,6 +39,7 @@ mod misc;
|
||||
mod notification;
|
||||
mod planned;
|
||||
mod stat;
|
||||
pub(crate) mod trailerreservation;
|
||||
|
||||
#[derive(FromForm, Debug)]
|
||||
struct LoginForm<'r> {
|
||||
@ -200,6 +201,7 @@ pub fn config(rocket: Rocket<Build>) -> Rocket<Build> {
|
||||
.mount("/stat", stat::routes())
|
||||
.mount("/boatdamage", boatdamage::routes())
|
||||
.mount("/boatreservation", boatreservation::routes())
|
||||
.mount("/trailerreservation", trailerreservation::routes())
|
||||
.mount("/cox", cox::routes())
|
||||
.mount("/admin", admin::routes())
|
||||
.mount("/board", board::routes())
|
||||
|
211
src/tera/trailerreservation.rs
Normal file
211
src/tera/trailerreservation.rs
Normal file
@ -0,0 +1,211 @@
|
||||
use chrono::NaiveDate;
|
||||
use rocket::{
|
||||
form::Form,
|
||||
get, post,
|
||||
request::FlashMessage,
|
||||
response::{Flash, Redirect},
|
||||
routes, FromForm, Route, State,
|
||||
};
|
||||
use rocket_dyn_templates::Template;
|
||||
use sqlx::SqlitePool;
|
||||
use tera::Context;
|
||||
|
||||
use crate::{
|
||||
model::{
|
||||
log::Log,
|
||||
trailer::Trailer,
|
||||
trailerreservation::{TrailerReservation, TrailerReservationToAdd},
|
||||
user::{DonauLinzUser, User, UserWithDetails},
|
||||
},
|
||||
tera::log::KioskCookie,
|
||||
};
|
||||
|
||||
#[get("/")]
|
||||
async fn index_kiosk(
|
||||
db: &State<SqlitePool>,
|
||||
flash: Option<FlashMessage<'_>>,
|
||||
_kiosk: KioskCookie,
|
||||
) -> Template {
|
||||
let trailerreservations = TrailerReservation::all_future(db).await;
|
||||
|
||||
let mut context = Context::new();
|
||||
if let Some(msg) = flash {
|
||||
context.insert("flash", &msg.into_inner());
|
||||
}
|
||||
|
||||
context.insert("trailerreservations", &trailerreservations);
|
||||
context.insert("trailers", &Trailer::all(db).await);
|
||||
context.insert("user", &User::all(db).await);
|
||||
context.insert("show_kiosk_header", &true);
|
||||
|
||||
Template::render("trailerreservations", context.into_json())
|
||||
}
|
||||
|
||||
#[get("/", rank = 2)]
|
||||
async fn index(
|
||||
db: &State<SqlitePool>,
|
||||
flash: Option<FlashMessage<'_>>,
|
||||
user: DonauLinzUser,
|
||||
) -> Template {
|
||||
let trailerreservations = TrailerReservation::all_future(db).await;
|
||||
|
||||
let mut context = Context::new();
|
||||
if let Some(msg) = flash {
|
||||
context.insert("flash", &msg.into_inner());
|
||||
}
|
||||
|
||||
context.insert("trailerreservations", &trailerreservations);
|
||||
context.insert("trailers", &Trailer::all(db).await);
|
||||
context.insert("user", &User::all(db).await);
|
||||
context.insert(
|
||||
"loggedin_user",
|
||||
&UserWithDetails::from_user(user.into(), db).await,
|
||||
);
|
||||
|
||||
Template::render("trailerreservations", context.into_json())
|
||||
}
|
||||
|
||||
#[derive(Debug, FromForm)]
|
||||
pub struct FormTrailerReservationToAdd<'r> {
|
||||
pub trailer_id: i64,
|
||||
pub start_date: &'r str,
|
||||
pub end_date: &'r str,
|
||||
pub time_desc: &'r str,
|
||||
pub usage: &'r str,
|
||||
pub user_id_applicant: Option<i64>,
|
||||
}
|
||||
|
||||
#[post("/new", data = "<data>", rank = 2)]
|
||||
async fn create<'r>(
|
||||
db: &State<SqlitePool>,
|
||||
data: Form<FormTrailerReservationToAdd<'r>>,
|
||||
user: DonauLinzUser,
|
||||
) -> Flash<Redirect> {
|
||||
let user_applicant: User = user.into();
|
||||
let trailer = Trailer::find_by_id(db, data.trailer_id as i32)
|
||||
.await
|
||||
.unwrap();
|
||||
let trailerreservation_to_add = TrailerReservationToAdd {
|
||||
trailer: &trailer,
|
||||
start_date: NaiveDate::parse_from_str(data.start_date, "%Y-%m-%d").unwrap(),
|
||||
end_date: NaiveDate::parse_from_str(data.end_date, "%Y-%m-%d").unwrap(),
|
||||
time_desc: data.time_desc,
|
||||
usage: data.usage,
|
||||
user_applicant: &user_applicant,
|
||||
};
|
||||
match TrailerReservation::create(db, trailerreservation_to_add).await {
|
||||
Ok(_) => Flash::success(
|
||||
Redirect::to("/trailerreservation"),
|
||||
"Reservierung erfolgreich hinzugefügt",
|
||||
),
|
||||
Err(e) => Flash::error(Redirect::to("/trailerreservation"), format!("Fehler: {e}")),
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/new", data = "<data>")]
|
||||
async fn create_from_kiosk<'r>(
|
||||
db: &State<SqlitePool>,
|
||||
data: Form<FormTrailerReservationToAdd<'r>>,
|
||||
_kiosk: KioskCookie,
|
||||
) -> Flash<Redirect> {
|
||||
let user_applicant: User = User::find_by_id(db, data.user_id_applicant.unwrap() as i32)
|
||||
.await
|
||||
.unwrap();
|
||||
let trailer = Trailer::find_by_id(db, data.trailer_id as i32)
|
||||
.await
|
||||
.unwrap();
|
||||
let trailerreservation_to_add = TrailerReservationToAdd {
|
||||
trailer: &trailer,
|
||||
start_date: NaiveDate::parse_from_str(data.start_date, "%Y-%m-%d").unwrap(),
|
||||
end_date: NaiveDate::parse_from_str(data.end_date, "%Y-%m-%d").unwrap(),
|
||||
time_desc: data.time_desc,
|
||||
usage: data.usage,
|
||||
user_applicant: &user_applicant,
|
||||
};
|
||||
match TrailerReservation::create(db, trailerreservation_to_add).await {
|
||||
Ok(_) => Flash::success(
|
||||
Redirect::to("/trailerreservation"),
|
||||
"Reservierung erfolgreich hinzugefügt",
|
||||
),
|
||||
Err(e) => Flash::error(Redirect::to("/trailerreservation"), format!("Fehler: {e}")),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromForm, Debug)]
|
||||
pub struct ReservationEditForm {
|
||||
pub(crate) id: i32,
|
||||
pub(crate) time_desc: String,
|
||||
pub(crate) usage: String,
|
||||
}
|
||||
|
||||
#[post("/", data = "<data>")]
|
||||
async fn update(
|
||||
db: &State<SqlitePool>,
|
||||
data: Form<ReservationEditForm>,
|
||||
user: User,
|
||||
) -> Flash<Redirect> {
|
||||
let Some(reservation) = TrailerReservation::find_by_id(db, data.id).await else {
|
||||
return Flash::error(
|
||||
Redirect::to("/trailerreservation"),
|
||||
format!("Reservation with ID {} does not exist!", data.id),
|
||||
);
|
||||
};
|
||||
|
||||
if user.id != reservation.user_id_applicant && !user.has_role(db, "admin").await {
|
||||
return Flash::error(
|
||||
Redirect::to("/trailerreservation"),
|
||||
"Not allowed to update reservation (only admins + creator do so).".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
Log::create(
|
||||
db,
|
||||
format!(
|
||||
"{} updated reservation from {reservation:?} to {data:?}",
|
||||
user.name
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
reservation.update(db, data.into_inner()).await;
|
||||
|
||||
Flash::success(
|
||||
Redirect::to("/trailerreservation"),
|
||||
"Reservierung erfolgreich bearbeitet",
|
||||
)
|
||||
}
|
||||
|
||||
#[get("/<reservation_id>/delete")]
|
||||
async fn delete<'r>(
|
||||
db: &State<SqlitePool>,
|
||||
reservation_id: i32,
|
||||
user: DonauLinzUser,
|
||||
) -> Flash<Redirect> {
|
||||
let reservation = TrailerReservation::find_by_id(db, reservation_id)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
if user.id == reservation.user_id_applicant || user.has_role(db, "admin").await {
|
||||
reservation.delete(db).await;
|
||||
Flash::success(
|
||||
Redirect::to("/trailerreservation"),
|
||||
"Reservierung erfolgreich gelöscht",
|
||||
)
|
||||
} else {
|
||||
Flash::error(
|
||||
Redirect::to("/trailerreservation"),
|
||||
"Nur der Reservierer darf die Reservierung löschen.".to_string(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn routes() -> Vec<Route> {
|
||||
routes![
|
||||
index,
|
||||
index_kiosk,
|
||||
create,
|
||||
create_from_kiosk,
|
||||
delete,
|
||||
update
|
||||
]
|
||||
}
|
Reference in New Issue
Block a user