clean code with clippy

This commit is contained in:
philipp 2023-07-25 13:22:11 +02:00
parent 3765541674
commit a7789af713
10 changed files with 243 additions and 463 deletions

View File

@ -1,3 +1,4 @@
use rocket::FromForm;
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, SqlitePool};
@ -18,36 +19,46 @@ pub struct Boat {
external: bool,
}
#[derive(FromForm)]
pub struct BoatToAdd<'r> {
pub name: &'r str,
pub amount_seats: i64,
pub year_built: Option<i64>,
pub boatbuilder: Option<&'r str>,
pub default_shipmaster_only_steering: bool,
pub skull: bool,
pub external: bool,
pub location_id: Option<i64>,
pub owner: Option<i64>,
}
#[derive(FromForm)]
pub struct BoatToUpdate<'r> {
pub id: i32,
pub name: &'r str,
pub amount_seats: i64,
pub year_built: Option<i64>,
pub boatbuilder: Option<&'r str>,
pub default_shipmaster_only_steering: bool,
pub skull: bool,
pub external: bool,
pub location_id: Option<i64>,
pub owner: Option<i64>,
}
impl Boat {
pub async fn find_by_id(db: &SqlitePool, id: i32) -> Option<Self> {
sqlx::query_as!(
Self,
"
SELECT id, name, amount_seats, location_id, owner, year_built, boatbuilder, default_shipmaster_only_steering, skull, external
"SELECT id, name, amount_seats, location_id, owner, year_built, boatbuilder, default_shipmaster_only_steering, skull, external
FROM boat
WHERE id like ?
",
WHERE id like ?",
id
)
.fetch_one(db)
.await
.ok()
}
//
// pub async fn find_by_name(db: &SqlitePool, name: &str) -> Option<Self> {
// sqlx::query_as!(
// User,
// "
//SELECT id, name, pw, is_cox, is_admin, is_guest, deleted, last_access
//FROM user
//WHERE name like ?
// ",
// name
// )
// .fetch_one(db)
// .await
// .ok()
// }
pub async fn is_locked(&self, db: &SqlitePool) -> bool {
sqlx::query!("SELECT * FROM boat_damage WHERE boat_id=? AND lock_boat=true AND user_id_verified is null", self.id).fetch_optional(db).await.unwrap().is_some()
@ -78,58 +89,35 @@ ORDER BY amount_seats DESC
.unwrap() //TODO: fixme
}
pub async fn create(
db: &SqlitePool,
name: &str,
amount_seats: i64,
year_built: Option<i64>,
boatbuilder: Option<&str>,
default_shipmaster_only_steering: bool,
skull: bool,
external: bool,
location_id: Option<i64>,
owner: Option<i64>,
) -> bool {
pub async fn create(db: &SqlitePool, boat: BoatToAdd<'_>) -> bool {
sqlx::query!(
"INSERT INTO boat(name, amount_seats, year_built, boatbuilder, default_shipmaster_only_steering, skull, external, location_id, owner) VALUES (?,?,?,?,?,?,?,?,?)",
name,
amount_seats,
year_built,
boatbuilder,
default_shipmaster_only_steering,
skull,
external,
location_id,
owner
boat.name,
boat.amount_seats,
boat.year_built,
boat.boatbuilder,
boat.default_shipmaster_only_steering,
boat.skull,
boat.external,
boat.location_id,
boat.owner
)
.execute(db)
.await.is_ok()
}
pub async fn update(
&self,
db: &SqlitePool,
name: &str,
amount_seats: i64,
year_built: Option<i64>,
boatbuilder: Option<&str>,
default_shipmaster_only_steering: bool,
skull: bool,
external: bool,
location_id: Option<i64>,
owner: Option<i64>,
) -> bool {
pub async fn update(&self, db: &SqlitePool, boat: BoatToUpdate<'_>) -> bool {
sqlx::query!(
"UPDATE boat SET name=?, amount_seats=?, year_built=?, boatbuilder=?, default_shipmaster_only_steering=?, skull=?, external=?, location_id=?, owner=? WHERE id=?",
name,
amount_seats,
year_built,
boatbuilder,
default_shipmaster_only_steering,
skull,
external,
location_id,
owner,
boat.name,
boat.amount_seats,
boat.year_built,
boat.boatbuilder,
boat.default_shipmaster_only_steering,
boat.skull,
boat.external,
boat.location_id,
boat.owner,
self.id
)
.execute(db)
@ -141,13 +129,16 @@ ORDER BY amount_seats DESC
sqlx::query!("DELETE FROM boat WHERE id=?", self.id)
.execute(db)
.await
.unwrap(); //Okay, because we can only create a User of a valid id
.unwrap(); //Okay, because we can only create a Boat of a valid id
}
}
#[cfg(test)]
mod test {
use crate::{model::boat::Boat, testdb};
use crate::{
model::boat::{Boat, BoatToAdd},
testdb,
};
use sqlx::SqlitePool;
@ -179,15 +170,17 @@ mod test {
assert_eq!(
Boat::create(
&pool,
"new-boat-name".into(),
42,
None,
"Best Boatbuilder".into(),
true,
true,
false,
Some(1),
None
BoatToAdd {
name: "new-boat-name".into(),
amount_seats: 42,
year_built: None,
boatbuilder: "Best Boatbuilder".into(),
default_shipmaster_only_steering: true,
skull: true,
external: false,
location_id: Some(1),
owner: None
}
)
.await,
true
@ -201,15 +194,17 @@ mod test {
assert_eq!(
Boat::create(
&pool,
"Haichenbach".into(),
42,
None,
"Best Boatbuilder".into(),
true,
true,
false,
Some(1),
None
BoatToAdd {
name: "Haichenbach".into(),
amount_seats: 42,
year_built: None,
boatbuilder: "Best Boatbuilder".into(),
default_shipmaster_only_steering: true,
skull: true,
external: false,
location_id: Some(1),
owner: None
}
)
.await,
false

View File

@ -24,20 +24,14 @@ impl Location {
}
pub async fn all(db: &SqlitePool) -> Vec<Self> {
sqlx::query_as!(
Self,
"
SELECT id, name
FROM location
"
)
sqlx::query_as!(Self, "SELECT id, name FROM location")
.fetch_all(db)
.await
.unwrap() //TODO: fixme
}
pub async fn create(db: &SqlitePool, name: &str) -> bool {
sqlx::query!("INSERT INTO location(name) VALUES (?)", name,)
sqlx::query!("INSERT INTO location(name) VALUES (?)", name)
.execute(db)
.await
.is_ok()

View File

@ -1,6 +1,7 @@
use chrono::NaiveDateTime;
use rocket::FromForm;
use serde::Serialize;
use sqlx::{FromRow, SqlitePool};
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
use super::{boat::Boat, rower::Rower, user::User};
@ -19,6 +20,29 @@ pub struct Logbook {
pub logtype: Option<i64>,
}
#[derive(FromForm)]
pub struct LogToAdd {
pub boat_id: i32,
pub shipmaster: i64,
pub shipmaster_only_steering: bool,
pub departure: String,
pub arrival: Option<String>,
pub destination: Option<String>,
pub distance_in_km: Option<i64>,
pub comments: Option<String>,
pub logtype: Option<i64>,
pub rower: Vec<i64>,
}
#[derive(FromForm)]
pub struct LogToFinalize {
pub destination: String,
pub distance_in_km: i64,
pub comments: Option<String>,
pub logtype: Option<i64>,
pub rower: Vec<i64>,
}
#[derive(Serialize)]
pub struct LogbookWithBoatAndRowers {
#[serde(flatten)]
@ -56,21 +80,6 @@ impl Logbook {
.ok()
}
// pub async fn find_by_name(db: &SqlitePool, name: &str) -> Option<Self> {
// sqlx::query_as!(
// User,
// "
//SELECT id, name, pw, is_cox, is_admin, is_guest, deleted, last_access
//FROM user
//WHERE name like ?
// ",
// name
// )
// .fetch_one(db)
// .await
// .ok()
// }
//
pub async fn on_water(db: &SqlitePool) -> Vec<LogbookWithBoatAndRowers> {
let logs = sqlx::query_as!(
Logbook,
@ -123,20 +132,8 @@ impl Logbook {
ret
}
pub async fn create(
db: &SqlitePool,
boat_id: i32,
shipmaster: i64,
shipmaster_only_steering: bool,
departure: NaiveDateTime,
arrival: Option<NaiveDateTime>,
destination: Option<String>,
distance_in_km: Option<i64>,
comments: Option<String>,
logtype: Option<i64>,
rower: Vec<i64>,
) -> Result<(), LogbookCreateError> {
let boat = match Boat::find_by_id(db, boat_id).await {
pub async fn create(db: &SqlitePool, log: LogToAdd) -> Result<(), LogbookCreateError> {
let boat = match Boat::find_by_id(db, log.boat_id).await {
Some(b) => b,
None => {
return Err(LogbookCreateError::BoatNotFound);
@ -151,27 +148,44 @@ impl Logbook {
return Err(LogbookCreateError::BoatAlreadyOnWater);
}
if rower.len() > boat.amount_seats as usize - 1 {
if log.rower.len() > boat.amount_seats as usize - 1 {
return Err(LogbookCreateError::TooManyRowers(
boat.amount_seats as usize,
rower.len() + 1,
log.rower.len() + 1,
));
}
let mut tx = db.begin().await.unwrap();
let departure = NaiveDateTime::parse_from_str(&log.departure, "%Y-%m-%dT%H:%M").unwrap();
let arrival = log
.arrival
.map(|a| NaiveDateTime::parse_from_str(&a, "%Y-%m-%dT%H:%M").unwrap());
let inserted_row = sqlx::query!(
"INSERT INTO logbook(boat_id, shipmaster, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype) VALUES (?,?,?,?,?,?,?,?,?) RETURNING id",
boat_id, shipmaster, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype
log.boat_id,
log.shipmaster,
log.shipmaster_only_steering,
departure,
arrival,
log.destination,
log.distance_in_km,
log.comments,
log.logtype
)
.fetch_one(db)
.fetch_one(&mut tx)
.await.unwrap();
for rower in &rower {
Rower::create(db, inserted_row.id, *rower).await;
for rower in &log.rower {
Rower::create(&mut tx, inserted_row.id, *rower).await;
}
tx.commit().await.unwrap();
Ok(())
}
async fn remove_rowers(&self, db: &SqlitePool) {
async fn remove_rowers(&self, db: &mut Transaction<'_, Sqlite>) {
sqlx::query!("DELETE FROM rower WHERE logbook_id=?", self.id)
.execute(db)
.await
@ -182,11 +196,7 @@ impl Logbook {
&self,
db: &SqlitePool,
user: &User,
destination: String,
distance_in_km: i64,
comments: Option<String>,
logtype: Option<i64>,
rower: Vec<i64>,
log: LogToFinalize,
) -> Result<(), LogbookUpdateError> {
if user.id != self.shipmaster {
return Err(LogbookUpdateError::NotYourEntry);
@ -194,35 +204,37 @@ impl Logbook {
let boat = Boat::find_by_id(db, self.boat_id as i32).await.unwrap(); //ok
if rower.len() > boat.amount_seats as usize - 1 {
if log.rower.len() > boat.amount_seats as usize - 1 {
return Err(LogbookUpdateError::TooManyRowers(
boat.amount_seats as usize,
rower.len() + 1,
log.rower.len() + 1,
));
}
//TODO: check current date
let arrival = format!("{}", chrono::offset::Local::now().format("%Y-%m-%d %H:%M"));
let mut tx = db.begin().await.unwrap();
sqlx::query!(
"UPDATE logbook SET destination=?, distance_in_km=?, comments=?, logtype=?, arrival=? WHERE id=?",
destination,
distance_in_km,
comments,
logtype,
log.destination,
log.distance_in_km,
log.comments,
log.logtype,
arrival,
self.id
)
.execute(db)
.execute(&mut tx)
.await.unwrap(); //TODO: fixme
self.remove_rowers(db).await;
self.remove_rowers(&mut tx).await;
for rower in &rower {
Rower::create(db, self.id, *rower).await;
for rower in &log.rower {
Rower::create(&mut tx, self.id, *rower).await;
}
tx.commit().await.unwrap();
Ok(())
}

View File

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, SqlitePool};
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
use super::{logbook::Logbook, user::User};
@ -10,21 +10,6 @@ pub struct Rower {
}
impl Rower {
//pub async fn find_by_id(db: &SqlitePool, id: i32) -> Option<Self> {
// sqlx::query_as!(
// Self,
// "
//SELECT id,boat_id,shipmaster,shipmaster_only_steering,departure,arrival,destination,distance_in_km,comments,logtype
//FROM logbook
//WHERE id like ?
// ",
// id
// )
// .fetch_one(db)
// .await
// .ok()
//}
pub async fn for_log(db: &SqlitePool, log: &Logbook) -> Vec<User> {
sqlx::query_as!(
User,
@ -40,9 +25,7 @@ impl Rower {
.unwrap()
}
pub async fn create(db: &SqlitePool, logbook_id: i64, rower_id: i64) {
//Check if boat is not locked
//Check if boat is already on water
pub async fn create(db: &mut Transaction<'_, Sqlite>, logbook_id: i64, rower_id: i64) {
let _ = sqlx::query!(
"INSERT INTO rower(logbook_id, rower_id) VALUES (?,?)",
logbook_id,
@ -52,83 +35,4 @@ impl Rower {
.await
.unwrap();
}
// pub async fn delete(&self, db: &SqlitePool) {
// sqlx::query!("DELETE FROM boat WHERE id=?", self.id)
// .execute(db)
// .await
// .unwrap(); //Okay, because we can only create a User of a valid id
// }
}
//
//#[cfg(test)]
//mod test {
// use crate::{model::boat::Boat, testdb};
//
// use sqlx::SqlitePool;
//
// #[sqlx::test]
// fn test_find_correct_id() {
// let pool = testdb!();
// let boat = Boat::find_by_id(&pool, 1).await.unwrap();
// assert_eq!(boat.id, 1);
// }
//
// #[sqlx::test]
// fn test_find_wrong_id() {
// let pool = testdb!();
// let boat = Boat::find_by_id(&pool, 1337).await;
// assert!(boat.is_none());
// }
//
// #[sqlx::test]
// fn test_all() {
// let pool = testdb!();
// let res = Boat::all(&pool).await;
// assert!(res.len() > 3);
// }
//
// #[sqlx::test]
// fn test_succ_create() {
// let pool = testdb!();
//
// assert_eq!(
// Boat::create(
// &pool,
// "new-boat-name".into(),
// 42,
// None,
// "Best Boatbuilder".into(),
// true,
// true,
// false,
// Some(1),
// None
// )
// .await,
// true
// );
// }
//
// #[sqlx::test]
// fn test_duplicate_name_create() {
// let pool = testdb!();
//
// assert_eq!(
// Boat::create(
// &pool,
// "Haichenbach".into(),
// 42,
// None,
// "Best Boatbuilder".into(),
// true,
// true,
// false,
// Some(1),
// None
// )
// .await,
// false
// );
// }
//}

View File

@ -1,17 +1,31 @@
use chrono::NaiveDate;
use rocket::FromForm;
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, SqlitePool};
#[derive(FromRow, Debug, Serialize, Deserialize)]
pub struct TripDetails {
pub id: i64,
planned_starting_time: String,
max_people: i64,
day: String,
notes: Option<String>,
pub planned_starting_time: String,
pub max_people: i64,
pub day: String,
pub notes: Option<String>,
pub allow_guests: bool,
trip_type_id: Option<i64>,
always_show: bool,
pub trip_type_id: Option<i64>,
pub always_show: bool,
}
#[derive(FromForm, Serialize)]
pub struct TripDetailsToAdd<'r> {
//TODO: properly parse `planned_starting_time`
pub planned_starting_time: &'r str,
pub max_people: i32,
pub day: String,
//#[field(validate = range(1..))] TODO: fixme
pub notes: Option<&'r str>,
pub trip_type: Option<i64>,
pub allow_guests: bool,
pub always_show: bool,
}
impl TripDetails {
@ -31,25 +45,16 @@ WHERE id like ?
}
/// Creates a new entry in `trip_details` and returns its id.
pub async fn create(
db: &SqlitePool,
planned_starting_time: &str,
max_people: i32,
day: &str,
notes: Option<&str>,
allow_guests: bool,
trip_type_id: Option<i64>,
always_show: bool,
) -> i64 {
pub async fn create(db: &SqlitePool, tripdetails: TripDetailsToAdd<'_>) -> i64 {
let query = sqlx::query!(
"INSERT INTO trip_details(planned_starting_time, max_people, day, notes, allow_guests, trip_type_id, always_show) VALUES(?, ?, ?, ?, ?, ?, ?)" ,
planned_starting_time,
max_people,
day,
notes,
allow_guests,
trip_type_id,
always_show
tripdetails.planned_starting_time,
tripdetails.max_people,
tripdetails.day,
tripdetails.notes,
tripdetails.allow_guests,
tripdetails.trip_type,
tripdetails.always_show
)
.execute(db)
.await
@ -87,7 +92,7 @@ ORDER BY day;",
#[cfg(test)]
mod test {
use crate::testdb;
use crate::{model::tripdetails::TripDetailsToAdd, testdb};
use super::TripDetails;
use sqlx::SqlitePool;
@ -113,13 +118,15 @@ mod test {
assert_eq!(
TripDetails::create(
&pool,
"10:00".into(),
2,
"1970-01-01".into(),
None,
false,
None,
false
TripDetailsToAdd {
planned_starting_time: "10:00".into(),
max_people: 2,
day: "1970-01-01".into(),
notes: None,
allow_guests: false,
trip_type: None,
always_show: false
}
)
.await,
3,
@ -127,13 +134,15 @@ mod test {
assert_eq!(
TripDetails::create(
&pool,
"10:00".into(),
2,
"1970-01-01".into(),
None,
false,
None,
false
TripDetailsToAdd {
planned_starting_time: "10:00".into(),
max_people: 2,
day: "1970-01-01".into(),
notes: None,
allow_guests: false,
trip_type: None,
always_show: false
}
)
.await,
4,

View File

@ -148,15 +148,15 @@ ORDER BY last_access DESC
}
pub async fn login(db: &SqlitePool, name: &str, pw: &str) -> Result<Self, LoginError> {
Log::create(db, format!("User '{name}' is trying to login...").into()).await;
Log::create(db, format!("User '{name}' is trying to login...")).await;
let name = name.trim(); // just to make sure...
let Some(user) = User::find_by_name(db, name).await else {
Log::create(db, format!("Username ({name}) not found").into()).await;
Log::create(db, format!("Username ({name}) not found")).await;
return Err(LoginError::InvalidAuthenticationCombo); // Username not found
};
if user.deleted {
Log::create(db, format!("User ({name}) already deleted.").into()).await;
Log::create(db, format!("User ({name}) already deleted.")).await;
return Err(LoginError::InvalidAuthenticationCombo); //User existed sometime ago; has
//been deleted
}
@ -165,10 +165,10 @@ ORDER BY last_access DESC
Some(user_pw) => {
let password_hash = &Self::get_hashed_pw(pw);
if password_hash == user_pw {
Log::create(db, format!("User {name} successfully logged in").into()).await;
Log::create(db, format!("User {name} successfully logged in")).await;
return Ok(user);
}
Log::create(db, format!("User {name} supplied the wrong PW").into()).await;
Log::create(db, format!("User {name} supplied the wrong PW")).await;
Err(LoginError::InvalidAuthenticationCombo)
}
None => {

View File

@ -1,5 +1,5 @@
use crate::model::{
boat::Boat,
boat::{Boat, BoatToAdd, BoatToUpdate},
location::Location,
user::{AdminUser, User},
};
@ -8,7 +8,7 @@ use rocket::{
get, post,
request::FlashMessage,
response::{Flash, Redirect},
routes, FromForm, Route, State,
routes, Route, State,
};
use rocket_dyn_templates::{tera::Context, Template};
use sqlx::SqlitePool;
@ -50,96 +50,39 @@ async fn delete(db: &State<SqlitePool>, _admin: AdminUser, boat: i32) -> Flash<R
}
}
#[derive(FromForm)]
struct BoatEditForm<'r> {
id: i32,
name: &'r str,
amount_seats: i64,
year_built: Option<i64>,
boatbuilder: Option<&'r str>,
default_shipmaster_only_steering: bool,
skull: bool,
external: bool,
location_id: Option<i64>,
owner: Option<i64>,
}
#[post("/boat", data = "<data>")]
async fn update(
db: &State<SqlitePool>,
data: Form<BoatEditForm<'_>>,
data: Form<BoatToUpdate<'_>>,
_admin: AdminUser,
) -> Flash<Redirect> {
let boat = Boat::find_by_id(db, data.id).await;
let Some(boat) = boat else {
return Flash::error(
Redirect::to("/admin/boat"),
format!("Boat with ID {} does not exist!", data.id),
"Boat does not exist!",
)
};
if !boat
.update(
db,
data.name,
data.amount_seats,
data.year_built,
data.boatbuilder,
data.default_shipmaster_only_steering,
data.skull,
data.external,
data.location_id,
data.owner,
)
.await
{
return Flash::error(
Redirect::to("/admin/boat"),
format!("Boat with ID {} could not be updated!", data.id),
);
if !boat.update(db, data.into_inner()).await {
return Flash::error(Redirect::to("/admin/boat"), "Boat could not be updated!");
}
Flash::success(Redirect::to("/admin/boat"), "Successfully updated boat")
}
#[derive(FromForm)]
struct BoatAddForm<'r> {
name: &'r str,
amount_seats: i64,
year_built: Option<i64>,
boatbuilder: Option<&'r str>,
default_shipmaster_only_steering: bool,
skull: bool,
external: bool,
location_id: Option<i64>,
owner: Option<i64>,
}
#[post("/boat/new", data = "<data>")]
async fn create(
db: &State<SqlitePool>,
data: Form<BoatAddForm<'_>>,
data: Form<BoatToAdd<'_>>,
_admin: AdminUser,
) -> Flash<Redirect> {
if Boat::create(
db,
data.name,
data.amount_seats,
data.year_built,
data.boatbuilder,
data.default_shipmaster_only_steering,
data.skull,
data.external,
data.location_id,
data.owner,
)
.await
{
if Boat::create(db, data.into_inner()).await {
Flash::success(Redirect::to("/admin/boat"), "Successfully created boat")
} else {
Flash::error(
Redirect::to("/admin/boat"),
format!("Error while creating boat {} in DB", data.name),
"Error while creating the boat in DB",
)
}
}

View File

@ -4,22 +4,22 @@ use rocket::{
response::{Flash, Redirect},
routes, FromForm, Route, State,
};
use serde::Serialize;
use sqlx::SqlitePool;
use crate::model::{planned_event::PlannedEvent, tripdetails::TripDetails, user::AdminUser};
use crate::model::{
planned_event::PlannedEvent,
tripdetails::{TripDetails, TripDetailsToAdd},
user::AdminUser,
};
//TODO: add constraints (e.g. planned_amount_cox > 0)
#[derive(FromForm)]
#[derive(FromForm, Serialize)]
struct AddPlannedEventForm<'r> {
day: &'r str,
name: &'r str,
planned_amount_cox: i32,
allow_guests: bool,
planned_starting_time: &'r str,
max_people: i32,
always_show: bool,
notes: Option<&'r str>,
trip_type: Option<i64>,
#[serde(flatten)]
tripdetails: TripDetailsToAdd<'r>,
}
#[post("/planned-event", data = "<data>")]
@ -28,17 +28,9 @@ async fn create(
data: Form<AddPlannedEventForm<'_>>,
_admin: AdminUser,
) -> Flash<Redirect> {
let trip_details_id = TripDetails::create(
db,
data.planned_starting_time,
data.max_people,
data.day,
data.notes,
data.allow_guests,
data.trip_type,
data.always_show,
)
.await;
let data = data.into_inner();
let trip_details_id = TripDetails::create(db, data.tripdetails).await;
let trip_details = TripDetails::find_by_id(db, trip_details_id).await.unwrap(); //Okay, bc. we
//just created

View File

@ -10,52 +10,29 @@ use crate::model::{
log::Log,
planned_event::PlannedEvent,
trip::{CoxHelpError, Trip, TripDeleteError, TripUpdateError},
tripdetails::TripDetails,
tripdetails::{TripDetails, TripDetailsToAdd},
user::CoxUser,
};
#[derive(FromForm)]
struct AddTripForm<'r> {
day: String,
//TODO: properly parse `planned_starting_time`
planned_starting_time: &'r str,
#[field(validate = range(1..))]
max_people: i32,
notes: Option<&'r str>,
trip_type: Option<i64>,
allow_guests: bool,
always_show: bool,
}
#[post("/trip", data = "<data>")]
async fn create(
db: &State<SqlitePool>,
data: Form<AddTripForm<'_>>,
data: Form<TripDetailsToAdd<'_>>,
cox: CoxUser,
) -> Flash<Redirect> {
let trip_details_id = TripDetails::create(
db,
data.planned_starting_time,
data.max_people,
&data.day,
data.notes,
data.allow_guests,
data.trip_type,
data.always_show,
)
.await;
let trip_details_id = TripDetails::create(db, data.into_inner()).await;
let trip_details = TripDetails::find_by_id(db, trip_details_id).await.unwrap(); //Okay, bc just
//created
Trip::new_own(db, &cox, trip_details).await;
Trip::new_own(db, &cox, trip_details).await; //TODO: fix
Log::create(
db,
format!(
"Cox {} created trip on {} @ {} for {} rower",
cox.name, data.day, data.planned_starting_time, data.max_people,
),
)
.await;
//Log::create(
// db,
// format!(
// "Cox {} created trip on {} @ {} for {} rower",
// cox.name, trip_details.day, trip_details.planned_starting_time, trip_details.max_people,
// ),
//)
//.await;
Flash::success(Redirect::to("/"), "Ausfahrt erfolgreich erstellt.")
}
@ -402,7 +379,7 @@ mod test {
login.dispatch().await;
let req = client.get("/join/1");
let response = req.dispatch().await;
let _ = req.dispatch().await;
let req = client.get("/cox/join/1");
let response = req.dispatch().await;

View File

@ -1,10 +1,9 @@
use chrono::NaiveDateTime;
use rocket::{
form::Form,
get, post,
request::FlashMessage,
response::{Flash, Redirect},
routes, FromForm, Route, State,
routes, Route, State,
};
use rocket_dyn_templates::Template;
use sqlx::SqlitePool;
@ -12,7 +11,7 @@ use tera::Context;
use crate::model::{
boat::Boat,
logbook::{Logbook, LogbookCreateError},
logbook::{LogToAdd, LogToFinalize, Logbook, LogbookCreateError},
logtype::LogType,
user::{AdminUser, User},
};
@ -47,40 +46,15 @@ async fn index(
Template::render("log", context.into_json())
}
#[derive(FromForm)]
struct LogAddForm {
boat_id: i32,
shipmaster: i64,
shipmaster_only_steering: bool,
departure: String,
arrival: Option<String>,
destination: Option<String>,
distance_in_km: Option<i64>,
comments: Option<String>,
logtype: Option<i64>,
rower: Vec<i64>,
}
#[post("/", data = "<data>")]
async fn create(
db: &State<SqlitePool>,
data: Form<LogAddForm>,
data: Form<LogToAdd>,
_adminuser: AdminUser,
) -> Flash<Redirect> {
match Logbook::create(
db,
data.boat_id,
data.shipmaster,
data.shipmaster_only_steering,
NaiveDateTime::parse_from_str(&data.departure, "%Y-%m-%dT%H:%M").unwrap(), //TODO: fix
data.arrival
.clone()
.map(|a| NaiveDateTime::parse_from_str(&a, "%Y-%m-%dT%H:%M").unwrap()), //TODO: fix
data.destination.clone(), //TODO: fix
data.distance_in_km,
data.comments.clone(), //TODO: fix
data.logtype,
data.rower.clone(), //TODO: fix
data.into_inner()
)
.await
{
@ -92,19 +66,10 @@ async fn create(
}
}
#[derive(FromForm)]
struct LogHomeForm {
destination: String,
distance_in_km: i64,
comments: Option<String>,
logtype: Option<i64>,
rower: Vec<i64>,
}
#[post("/<logbook_id>", data = "<data>")]
async fn home(
db: &State<SqlitePool>,
data: Form<LogHomeForm>,
data: Form<LogToFinalize>,
logbook_id: i32,
_adminuser: AdminUser,
) -> Flash<Redirect> {
@ -116,18 +81,7 @@ async fn home(
)
};
match logbook
.home(
db,
&_adminuser.user,
data.destination.clone(), //TODO: fixme
data.distance_in_km,
data.comments.clone(), //TODO: fixme
data.logtype,
data.rower.clone(), //TODO: fixme
)
.await
{
match logbook.home(db, &_adminuser.user, data.into_inner()).await {
Ok(_) => Flash::success(Redirect::to("/log"), "Successfully updated log"),
Err(_) => Flash::error(
Redirect::to("/log"),