clean code with clippy
This commit is contained in:
parent
3765541674
commit
a7789af713
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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(())
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
// );
|
||||
// }
|
||||
//}
|
||||
|
@ -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,
|
||||
|
@ -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 => {
|
||||
|
@ -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",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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"),
|
||||
|
Loading…
Reference in New Issue
Block a user