2023-08-02 14:29:19 +02:00
use crate ::model ::{ boat ::Boat , user ::User } ;
use chrono ::NaiveDateTime ;
use rocket ::serde ::{ Deserialize , Serialize } ;
use rocket ::FromForm ;
use sqlx ::{ FromRow , SqlitePool } ;
2023-10-05 08:59:13 +02:00
use super ::log ::Log ;
2023-08-02 14:29:19 +02:00
#[ derive(FromRow, Debug, Serialize, Deserialize) ]
pub struct BoatDamage {
pub id : i64 ,
pub boat_id : i64 ,
pub desc : String ,
pub user_id_created : i64 ,
pub created_at : NaiveDateTime ,
pub user_id_fixed : Option < i64 > ,
pub fixed_at : Option < NaiveDateTime > ,
pub user_id_verified : Option < i64 > ,
pub verified_at : Option < NaiveDateTime > ,
pub lock_boat : bool ,
}
#[ derive(FromRow, Debug, Serialize, Deserialize) ]
pub struct BoatDamageWithDetails {
#[ serde(flatten) ]
boat_damage : BoatDamage ,
user_created : User ,
user_fixed : Option < User > ,
user_verified : Option < User > ,
boat : Boat ,
2023-10-23 22:26:33 +02:00
verified : bool ,
2023-08-02 14:29:19 +02:00
}
2023-10-05 08:59:13 +02:00
#[ derive(Debug) ]
2023-08-02 14:29:19 +02:00
pub struct BoatDamageToAdd < ' r > {
pub boat_id : i64 ,
pub desc : & ' r str ,
pub user_id_created : i32 ,
pub lock_boat : bool ,
}
2023-10-05 08:59:13 +02:00
#[ derive(FromForm, Debug) ]
2023-08-02 14:29:19 +02:00
pub struct BoatDamageFixed < ' r > {
pub desc : & ' r str ,
pub user_id_fixed : i32 ,
}
2023-10-05 08:59:13 +02:00
#[ derive(FromForm, Debug) ]
2023-08-02 14:29:19 +02:00
pub struct BoatDamageVerified < ' r > {
pub desc : & ' r str ,
pub user_id_verified : i32 ,
}
impl BoatDamage {
pub async fn find_by_id ( db : & SqlitePool , id : i32 ) -> Option < Self > {
sqlx ::query_as! (
Self ,
" SELECT id, boat_id, desc, user_id_created, created_at, user_id_fixed, fixed_at, user_id_verified, verified_at, lock_boat
FROM boat_damage
WHERE id like ? " ,
id
)
. fetch_one ( db )
. await
. ok ( )
}
pub async fn all ( db : & SqlitePool ) -> Vec < BoatDamageWithDetails > {
let boatdamages = sqlx ::query_as! (
BoatDamage ,
"
SELECT id , boat_id , desc , user_id_created , created_at , user_id_fixed , fixed_at , user_id_verified , verified_at , lock_boat
FROM boat_damage
ORDER BY created_at DESC
"
)
. fetch_all ( db )
. await
. unwrap ( ) ; //TODO: fixme
let mut res = Vec ::new ( ) ;
for boat_damage in boatdamages {
let user_fixed = match boat_damage . user_id_fixed {
Some ( id ) = > {
let user = User ::find_by_id ( db , id as i32 ) . await ;
Some ( user . unwrap ( ) )
}
None = > None ,
} ;
let user_verified = match boat_damage . user_id_verified {
Some ( id ) = > {
let user = User ::find_by_id ( db , id as i32 ) . await ;
Some ( user . unwrap ( ) )
}
None = > None ,
} ;
res . push ( BoatDamageWithDetails {
boat : Boat ::find_by_id ( db , boat_damage . boat_id as i32 )
. await
. unwrap ( ) ,
user_created : User ::find_by_id ( db , boat_damage . user_id_created as i32 )
. await
. unwrap ( ) ,
user_fixed ,
2023-10-23 22:26:33 +02:00
verified : user_verified . is_some ( ) ,
2023-08-02 14:29:19 +02:00
user_verified ,
boat_damage ,
2023-09-06 14:39:36 +02:00
} ) ;
2023-08-02 14:29:19 +02:00
}
res
}
pub async fn create ( db : & SqlitePool , boatdamage : BoatDamageToAdd < '_ > ) -> Result < ( ) , String > {
2023-10-05 08:59:13 +02:00
Log ::create ( db , format! ( " New boat damage: {boatdamage:?} " ) ) . await ;
2023-08-02 14:29:19 +02:00
sqlx ::query! (
" INSERT INTO boat_damage(boat_id, desc, user_id_created, lock_boat) VALUES (?,?,?, ?) " ,
boatdamage . boat_id ,
boatdamage . desc ,
boatdamage . user_id_created ,
boatdamage . lock_boat
)
. execute ( db )
. await
. map_err ( | e | e . to_string ( ) ) ? ;
Ok ( ( ) )
}
pub async fn fixed ( & self , db : & SqlitePool , boat : BoatDamageFixed < '_ > ) -> Result < ( ) , String > {
2023-10-05 08:59:13 +02:00
Log ::create ( db , format! ( " Fixed boat damage: {boat:?} " ) ) . await ;
2023-08-02 14:29:19 +02:00
sqlx ::query! (
" UPDATE boat_damage SET desc=?, user_id_fixed=?, fixed_at=CURRENT_TIMESTAMP WHERE id=? " ,
boat . desc ,
boat . user_id_fixed ,
self . id
)
. execute ( db )
. await
. map_err ( | e | e . to_string ( ) ) ? ;
let user = User ::find_by_id ( db , boat . user_id_fixed ) . await . unwrap ( ) ;
if user . is_tech {
return self
. verified (
db ,
BoatDamageVerified {
desc : boat . desc ,
user_id_verified : user . id as i32 ,
} ,
)
. await ;
}
Ok ( ( ) )
}
pub async fn verified (
& self ,
db : & SqlitePool ,
boat : BoatDamageVerified < '_ > ,
) -> Result < ( ) , String > {
2023-10-05 08:59:13 +02:00
if let Some ( verifier ) = User ::find_by_id ( db , boat . user_id_verified ) . await {
if ! verifier . is_tech {
Log ::create ( db , format! ( " User {verifier:?} tried to verify boat {boat:?} . The user is no tech. Manually craftted request? " ) ) . await ;
return Err ( " You are not allowed to verify the boat! " . into ( ) ) ;
}
} else {
Log ::create ( db , format! ( " Someone tried to verify the boat {boat:?} with user_id= {} which does not exist. Manually craftted request? " , boat . user_id_verified ) ) . await ;
return Err ( " Could not find user " . into ( ) ) ;
}
Log ::create ( db , format! ( " Verified boat damage: {boat:?} " ) ) . await ;
2023-08-02 14:29:19 +02:00
sqlx ::query! (
" UPDATE boat_damage SET desc=?, user_id_verified=?, verified_at=CURRENT_TIMESTAMP WHERE id=? " ,
boat . desc ,
boat . user_id_verified ,
self . id
)
. execute ( db )
. await . map_err ( | e | e . to_string ( ) ) ? ;
Ok ( ( ) )
}
}