use serde::{Deserialize, Serialize}; use sqlx::{FromRow, SqlitePool}; #[derive(FromRow, Debug, Serialize, Deserialize)] pub struct Boat { pub id: i64, pub name: String, pub amount_seats: i64, pub location_id: i64, pub owner: Option, pub year_built: Option, pub boatbuilder: Option, #[serde(default = "bool::default")] default_shipmaster_only_steering: bool, #[serde(default = "bool::default")] skull: bool, #[serde(default = "bool::default")] external: bool, } impl Boat { pub async fn find_by_id(db: &SqlitePool, id: i32) -> Option { sqlx::query_as!( Self, " SELECT id, name, amount_seats, location_id, owner, year_built, boatbuilder, default_shipmaster_only_steering, skull, external FROM boat WHERE id like ? ", id ) .fetch_one(db) .await .ok() } // // pub async fn find_by_name(db: &SqlitePool, name: &str) -> Option { // 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() } pub async fn on_water(&self, db: &SqlitePool) -> bool { sqlx::query!( "SELECT * FROM logbook WHERE boat_id=? AND arrival is null", self.id ) .fetch_optional(db) .await .unwrap() .is_some() } pub async fn all(db: &SqlitePool) -> Vec { sqlx::query_as!( Boat, " SELECT id, name, amount_seats, location_id, owner, year_built, boatbuilder, default_shipmaster_only_steering, skull, external FROM boat ORDER BY amount_seats DESC " ) .fetch_all(db) .await .unwrap() //TODO: fixme } pub async fn create( db: &SqlitePool, name: &str, amount_seats: i64, year_built: Option, boatbuilder: Option<&str>, default_shipmaster_only_steering: bool, skull: bool, external: bool, location_id: Option, owner: Option, ) -> 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 ) .execute(db) .await.is_ok() } pub async fn update( &self, db: &SqlitePool, name: &str, amount_seats: i64, year_built: Option, boatbuilder: Option<&str>, default_shipmaster_only_steering: bool, skull: bool, external: bool, location_id: Option, owner: Option, ) -> 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, self.id ) .execute(db) .await .is_ok() } 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 ); } }