2023-10-02 12:39:05 +02:00
use chrono ::{ NaiveDateTime , TimeZone } ;
2023-09-29 12:39:45 +02:00
use chrono_tz ::Europe ::Vienna ;
2023-07-25 13:22:11 +02:00
use rocket ::FromForm ;
2023-07-24 13:01:39 +02:00
use serde ::Serialize ;
2023-07-25 13:22:11 +02:00
use sqlx ::{ FromRow , Sqlite , SqlitePool , Transaction } ;
2023-07-23 12:17:57 +02:00
2023-07-24 13:01:39 +02:00
use super ::{ boat ::Boat , rower ::Rower , user ::User } ;
2023-07-23 16:49:14 +02:00
2023-07-31 19:10:34 +02:00
#[ derive(FromRow, Serialize, Clone, Debug) ]
2023-07-23 12:17:57 +02:00
pub struct Logbook {
pub id : i64 ,
pub boat_id : i64 ,
pub shipmaster : i64 ,
#[ serde(default = " bool::default " ) ]
pub shipmaster_only_steering : bool ,
2023-08-05 16:27:51 +02:00
pub departure : NaiveDateTime ,
pub arrival : Option < NaiveDateTime > ,
2023-07-23 12:17:57 +02:00
pub destination : Option < String > ,
pub distance_in_km : Option < i64 > ,
pub comments : Option < String > ,
pub logtype : Option < i64 > ,
}
2023-07-31 19:10:34 +02:00
impl PartialEq for Logbook {
fn eq ( & self , other : & Self ) -> bool {
self . id = = other . id
}
}
2023-09-23 18:12:48 +02:00
#[ derive(FromForm, Debug) ]
2023-07-25 13:22:11 +02:00
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 > ,
2023-09-23 18:12:48 +02:00
pub rowers : Vec < i64 > ,
2023-07-25 13:22:11 +02:00
}
2023-10-01 15:53:45 +02:00
#[ derive(FromForm, Debug) ]
2023-07-25 13:22:11 +02:00
pub struct LogToFinalize {
pub destination : String ,
pub distance_in_km : i64 ,
pub comments : Option < String > ,
pub logtype : Option < i64 > ,
2023-09-23 18:26:04 +02:00
pub rowers : Vec < i64 > ,
2023-07-25 13:22:11 +02:00
}
2023-09-23 18:12:48 +02:00
#[ derive(Serialize, Debug) ]
2023-07-24 13:01:39 +02:00
pub struct LogbookWithBoatAndRowers {
#[ serde(flatten) ]
pub logbook : Logbook ,
pub boat : Boat ,
pub shipmaster_user : User ,
pub rowers : Vec < User > ,
2023-07-23 12:17:57 +02:00
}
2023-07-31 19:10:34 +02:00
#[ derive(Debug, PartialEq) ]
2023-07-23 16:49:14 +02:00
pub enum LogbookUpdateError {
NotYourEntry ,
2023-07-24 20:56:46 +02:00
TooManyRowers ( usize , usize ) ,
2023-07-31 16:59:15 +02:00
RowerCreateError ( i64 , String ) ,
2023-09-24 09:48:01 +02:00
ArrivalNotAfterDeparture ,
2023-07-23 16:49:14 +02:00
}
2023-09-24 09:55:51 +02:00
#[ derive(Debug, PartialEq) ]
pub enum LogbookDeleteError {
NotYourEntry ,
}
2023-07-31 19:10:34 +02:00
#[ derive(Debug, PartialEq) ]
2023-07-23 16:49:14 +02:00
pub enum LogbookCreateError {
2023-09-29 12:39:45 +02:00
ArrivalSetButNoDestination ,
2023-10-01 15:53:45 +02:00
UserNotAllowedToUseBoat ,
2023-09-29 12:39:45 +02:00
ArrivalSetButNoDistance ,
2023-07-23 16:49:14 +02:00
BoatAlreadyOnWater ,
2023-07-23 19:45:48 +02:00
BoatLocked ,
2023-07-24 13:01:39 +02:00
BoatNotFound ,
TooManyRowers ( usize , usize ) ,
2023-07-27 15:00:52 +02:00
ShipmasterAlreadyOnWater ,
2023-07-27 15:24:29 +02:00
RowerAlreadyOnWater ( User ) ,
2023-07-31 16:59:15 +02:00
RowerCreateError ( i64 , String ) ,
2023-09-24 09:12:27 +02:00
SamePersonShipmasterAndRower ,
2023-09-24 09:48:01 +02:00
ArrivalNotAfterDeparture ,
2023-07-23 16:49:14 +02:00
}
2023-07-23 12:17:57 +02:00
impl Logbook {
2023-07-23 16:49:14 +02:00
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 ( )
}
2023-07-24 13:01:39 +02:00
pub async fn on_water ( db : & SqlitePool ) -> Vec < LogbookWithBoatAndRowers > {
2023-07-30 22:17:47 +02:00
let rows = sqlx ::query! (
"
2023-09-29 12:39:45 +02:00
SELECT id , boat_id , shipmaster , shipmaster_only_steering , departure , arrival , destination , distance_in_km , comments , logtype
2023-07-30 22:17:47 +02:00
FROM logbook
WHERE arrival is null
ORDER BY departure DESC
"
)
. fetch_all ( db )
. await
. unwrap ( ) ; //TODO: fixme
let logs : Vec < Logbook > = rows
. into_iter ( )
. map ( | row | Logbook {
id : row . id ,
boat_id : row . boat_id ,
shipmaster : row . shipmaster ,
shipmaster_only_steering : row . shipmaster_only_steering ,
2023-09-29 12:39:45 +02:00
departure : row . departure ,
2023-07-30 22:17:47 +02:00
arrival : row . arrival ,
destination : row . destination ,
distance_in_km : row . distance_in_km ,
comments : row . comments ,
logtype : row . logtype ,
} )
. collect ( ) ;
2023-07-24 13:01:39 +02:00
let mut ret = Vec ::new ( ) ;
for log in logs {
ret . push ( LogbookWithBoatAndRowers {
rowers : Rower ::for_log ( db , & log ) . await ,
boat : Boat ::find_by_id ( db , log . boat_id as i32 ) . await . unwrap ( ) ,
shipmaster_user : User ::find_by_id ( db , log . shipmaster as i32 ) . await . unwrap ( ) ,
logbook : log ,
2023-07-25 13:32:20 +02:00
} ) ;
2023-07-24 13:01:39 +02:00
}
ret
2023-07-23 12:17:57 +02:00
}
2023-07-24 13:01:39 +02:00
pub async fn completed ( db : & SqlitePool ) -> Vec < LogbookWithBoatAndRowers > {
let logs = sqlx ::query_as! (
Logbook ,
2023-07-23 12:17:57 +02:00
"
2023-07-24 13:01:39 +02:00
SELECT id , boat_id , shipmaster , shipmaster_only_steering , departure , arrival , destination , distance_in_km , comments , logtype
2023-07-23 12:17:57 +02:00
FROM logbook
WHERE arrival is not null
2023-07-24 13:01:39 +02:00
ORDER BY departure DESC
2023-07-23 12:17:57 +02:00
"
)
. fetch_all ( db )
. await
2023-07-24 13:01:39 +02:00
. unwrap ( ) ; //TODO: fixme
let mut ret = Vec ::new ( ) ;
for log in logs {
ret . push ( LogbookWithBoatAndRowers {
rowers : Rower ::for_log ( db , & log ) . await ,
boat : Boat ::find_by_id ( db , log . boat_id as i32 ) . await . unwrap ( ) ,
shipmaster_user : User ::find_by_id ( db , log . shipmaster as i32 ) . await . unwrap ( ) ,
logbook : log ,
2023-07-25 13:32:20 +02:00
} ) ;
2023-07-24 13:01:39 +02:00
}
ret
2023-07-23 12:17:57 +02:00
}
2023-10-01 15:53:45 +02:00
pub async fn create (
db : & SqlitePool ,
log : LogToAdd ,
created_by_user : & User ,
) -> Result < ( ) , LogbookCreateError > {
2023-07-25 13:32:20 +02:00
let Some ( boat ) = Boat ::find_by_id ( db , log . boat_id ) . await else {
2023-07-31 16:59:15 +02:00
return Err ( LogbookCreateError ::BoatNotFound ) ;
} ;
2023-07-24 13:01:39 +02:00
if boat . is_locked ( db ) . await {
return Err ( LogbookCreateError ::BoatLocked ) ;
}
if boat . on_water ( db ) . await {
return Err ( LogbookCreateError ::BoatAlreadyOnWater ) ;
}
2023-09-24 09:48:01 +02:00
2023-10-01 15:53:45 +02:00
let shipmaster = User ::find_by_id ( db , log . shipmaster as i32 ) . await . unwrap ( ) ;
if shipmaster . on_water ( db ) . await {
2023-07-27 15:24:29 +02:00
return Err ( LogbookCreateError ::ShipmasterAlreadyOnWater ) ;
2023-07-27 15:00:52 +02:00
}
2023-07-30 20:40:15 +02:00
2023-09-24 09:48:01 +02:00
if let Some ( arrival ) = & log . arrival {
2023-09-29 12:39:45 +02:00
let dep = NaiveDateTime ::parse_from_str ( & log . departure , " %Y-%m-%dT%H:%M " ) . unwrap ( ) ;
2023-10-02 12:39:05 +02:00
let arr = NaiveDateTime ::parse_from_str ( arrival , " %Y-%m-%dT%H:%M " ) . unwrap ( ) ;
2023-09-24 09:48:01 +02:00
if arr < = dep {
return Err ( LogbookCreateError ::ArrivalNotAfterDeparture ) ;
}
2023-09-29 12:39:45 +02:00
if log . destination . is_none ( ) {
return Err ( LogbookCreateError ::ArrivalSetButNoDestination ) ;
}
if log . distance_in_km . is_none ( ) {
return Err ( LogbookCreateError ::ArrivalSetButNoDistance ) ;
}
2023-09-24 09:48:01 +02:00
}
2023-09-23 18:12:48 +02:00
if log . rowers . len ( ) > boat . amount_seats as usize - 1 {
2023-07-24 13:01:39 +02:00
return Err ( LogbookCreateError ::TooManyRowers (
boat . amount_seats as usize ,
2023-09-23 18:12:48 +02:00
log . rowers . len ( ) + 1 ,
2023-07-24 13:01:39 +02:00
) ) ;
}
2023-09-23 18:12:48 +02:00
for rower in & log . rowers {
2023-07-27 15:24:29 +02:00
let user = User ::find_by_id ( db , * rower as i32 ) . await . unwrap ( ) ;
2023-09-24 09:12:27 +02:00
if * rower = = log . shipmaster {
return Err ( LogbookCreateError ::SamePersonShipmasterAndRower ) ;
}
2023-07-27 15:24:29 +02:00
if user . on_water ( db ) . await {
return Err ( LogbookCreateError ::RowerAlreadyOnWater ( user ) ) ;
}
}
2023-10-01 15:53:45 +02:00
if ! boat . shipmaster_allowed ( created_by_user ) . await {
return Err ( LogbookCreateError ::UserNotAllowedToUseBoat ) ;
}
2023-09-29 12:39:45 +02:00
//let departure = format!("{}+02:00", &log.departure);
2023-07-25 13:22:11 +02:00
let mut tx = db . begin ( ) . await . unwrap ( ) ;
2023-09-29 12:39:45 +02:00
//let departure = NaiveDateTime::parse_from_str(&log.departure, "%Y-%m-%dT%H:%M").unwrap();
//let departure_vienna = chrono::Utc
// .from_local_datetime(&departure)
// .single()
// .unwrap();
//let departure_utc = departure_vienna.with_timezone(&Vienna);
//let arrival = log.arrival.map(|a| {
// let arr = NaiveDateTime::parse_from_str(&a, "%Y-%m-%dT%H:%M").unwrap();
// let arr_vienna = Vienna.from_local_datetime(&arr).single().unwrap();
// arr_vienna
// .with_timezone(&chrono::Utc)
// .format("%Y-%m-%d %H:%M")
//});
//let arrival = log.arrival.map(|a| format!("{}+02:00", a));
2023-07-24 13:01:39 +02:00
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 " ,
2023-07-25 13:22:11 +02:00
log . boat_id ,
log . shipmaster ,
log . shipmaster_only_steering ,
2023-09-29 12:39:45 +02:00
log . departure ,
log . arrival ,
2023-07-25 13:22:11 +02:00
log . destination ,
log . distance_in_km ,
log . comments ,
log . logtype
2023-07-23 12:17:57 +02:00
)
2023-07-25 13:22:11 +02:00
. fetch_one ( & mut tx )
2023-07-24 13:01:39 +02:00
. await . unwrap ( ) ;
2023-09-23 18:12:48 +02:00
for rower in & log . rowers {
2023-07-31 16:59:15 +02:00
Rower ::create ( & mut tx , inserted_row . id , * rower )
. await
2023-09-06 14:39:36 +02:00
. map_err ( | e | LogbookCreateError ::RowerCreateError ( * rower , e . to_string ( ) ) ) ? ;
2023-07-24 13:01:39 +02:00
}
2023-07-25 13:22:11 +02:00
tx . commit ( ) . await . unwrap ( ) ;
2023-07-23 16:49:14 +02:00
Ok ( ( ) )
2023-07-23 12:17:57 +02:00
}
2023-07-23 16:49:14 +02:00
2023-07-30 20:40:15 +02:00
pub async fn distances ( db : & SqlitePool ) -> Vec < ( String , i64 ) > {
2023-07-26 12:56:19 +02:00
let result = sqlx ::query! ( " SELECT destination, distance_in_km FROM logbook WHERE id IN (SELECT MIN(id) FROM logbook GROUP BY destination) AND destination IS NOT NULL AND distance_in_km IS NOT NULL; " )
. fetch_all ( db )
. await
. unwrap ( ) ;
2023-07-30 20:40:15 +02:00
result
. into_iter ( )
. filter_map ( | r | {
if let ( Some ( destination ) , Some ( distance_in_km ) ) = ( r . destination , r . distance_in_km )
{
Some ( ( destination , distance_in_km ) )
} else {
None
}
} )
. collect ( )
2023-07-26 12:56:19 +02:00
}
2023-07-25 13:22:11 +02:00
async fn remove_rowers ( & self , db : & mut Transaction < '_ , Sqlite > ) {
2023-07-24 20:56:46 +02:00
sqlx ::query! ( " DELETE FROM rower WHERE logbook_id=? " , self . id )
. execute ( db )
. await
. unwrap ( ) ;
}
2023-10-01 13:48:21 +02:00
#[ cfg(test) ]
pub async fn highest_id ( db : & SqlitePool ) -> i32 {
sqlx ::query! ( " SELECT max(id) as id FROM logbook " )
. fetch_one ( db )
. await
. unwrap ( )
. id
. unwrap ( )
}
2023-07-23 16:49:14 +02:00
pub async fn home (
& self ,
db : & SqlitePool ,
user : & User ,
2023-07-25 13:22:11 +02:00
log : LogToFinalize ,
2023-07-23 16:49:14 +02:00
) -> Result < ( ) , LogbookUpdateError > {
if user . id ! = self . shipmaster {
return Err ( LogbookUpdateError ::NotYourEntry ) ;
}
2023-07-24 20:56:46 +02:00
let boat = Boat ::find_by_id ( db , self . boat_id as i32 ) . await . unwrap ( ) ; //ok
2023-09-23 18:26:04 +02:00
if log . rowers . len ( ) > boat . amount_seats as usize - 1 {
2023-07-24 20:56:46 +02:00
return Err ( LogbookUpdateError ::TooManyRowers (
boat . amount_seats as usize ,
2023-09-23 18:26:04 +02:00
log . rowers . len ( ) + 1 ,
2023-07-24 20:56:46 +02:00
) ) ;
}
2023-09-29 12:39:45 +02:00
let arrival = chrono ::offset ::Utc ::now ( ) . naive_utc ( ) ;
let arrival = Vienna . from_utc_datetime ( & arrival ) ;
if arrival . timestamp ( ) + 60 * 60 * 2 < = self . departure . timestamp ( ) {
//TODO: fixme
2023-09-24 09:48:01 +02:00
return Err ( LogbookUpdateError ::ArrivalNotAfterDeparture ) ;
}
2023-07-23 16:49:14 +02:00
2023-07-25 13:22:11 +02:00
let mut tx = db . begin ( ) . await . unwrap ( ) ;
2023-07-23 16:49:14 +02:00
sqlx ::query! (
" UPDATE logbook SET destination=?, distance_in_km=?, comments=?, logtype=?, arrival=? WHERE id=? " ,
2023-07-25 13:22:11 +02:00
log . destination ,
log . distance_in_km ,
log . comments ,
log . logtype ,
2023-07-23 16:49:14 +02:00
arrival ,
self . id
)
2023-07-25 13:22:11 +02:00
. execute ( & mut tx )
2023-07-23 16:49:14 +02:00
. await . unwrap ( ) ; //TODO: fixme
2023-07-24 20:56:46 +02:00
2023-07-25 13:22:11 +02:00
self . remove_rowers ( & mut tx ) . await ;
2023-07-24 20:56:46 +02:00
2023-09-23 18:26:04 +02:00
for rower in & log . rowers {
2023-09-06 14:39:36 +02:00
Rower ::create ( & mut tx , self . id , * rower )
. await
. map_err ( | e | LogbookUpdateError ::RowerCreateError ( * rower , e . to_string ( ) ) ) ? ;
2023-07-24 20:56:46 +02:00
}
2023-07-25 13:22:11 +02:00
tx . commit ( ) . await . unwrap ( ) ;
2023-07-23 16:49:14 +02:00
Ok ( ( ) )
}
2023-09-24 09:55:51 +02:00
pub async fn delete ( & self , db : & SqlitePool , user : & User ) -> Result < ( ) , LogbookDeleteError > {
if user . is_admin | | user . id = = self . shipmaster {
sqlx ::query! ( " DELETE FROM logbook WHERE id=? " , self . id )
. execute ( db )
. await
. unwrap ( ) ; //Okay, because we can only create a Logbook of a valid id
return Ok ( ( ) ) ;
}
Err ( LogbookDeleteError ::NotYourEntry )
2023-08-05 16:27:51 +02:00
}
2023-07-23 12:17:57 +02:00
}
2023-07-31 19:10:34 +02:00
#[ cfg(test) ]
mod test {
use super ::{ LogToAdd , Logbook , LogbookCreateError , LogbookUpdateError } ;
use crate ::model ::user ::User ;
use crate ::testdb ;
use sqlx ::SqlitePool ;
#[ sqlx::test ]
fn test_find_correct_id ( ) {
let pool = testdb! ( ) ;
let logbook = Logbook ::find_by_id ( & pool , 1 ) . await . unwrap ( ) ;
assert_eq! ( logbook . id , 1 ) ;
}
#[ sqlx::test ]
fn test_find_wrong_id ( ) {
let pool = testdb! ( ) ;
let logbook = Logbook ::find_by_id ( & pool , 1337 ) . await ;
assert_eq! ( logbook , None ) ;
}
#[ sqlx::test ]
fn test_on_water ( ) {
let pool = testdb! ( ) ;
let logbook = Logbook ::find_by_id ( & pool , 1 ) . await . unwrap ( ) ;
2023-07-31 20:09:03 +02:00
let logbook_with_details = Logbook ::on_water ( & pool ) . await ;
2023-07-31 19:10:34 +02:00
2023-07-31 20:09:03 +02:00
assert_eq! ( logbook_with_details [ 0 ] . logbook , logbook ) ;
2023-07-31 19:10:34 +02:00
}
#[ sqlx::test ]
fn test_completed ( ) {
let pool = testdb! ( ) ;
let completed = Logbook ::completed ( & pool ) . await ;
assert_eq! (
completed [ 0 ] . logbook ,
Logbook ::find_by_id ( & pool , 3 ) . await . unwrap ( )
) ;
assert_eq! (
completed [ 1 ] . logbook ,
Logbook ::find_by_id ( & pool , 2 ) . await . unwrap ( )
) ;
}
//#[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! ( ) ;
Logbook ::create (
& pool ,
LogToAdd {
boat_id : 3 ,
2023-10-01 15:53:45 +02:00
shipmaster : 4 ,
2023-07-31 19:10:34 +02:00
shipmaster_only_steering : false ,
departure : " 2128-05-20T12:00 " . into ( ) ,
arrival : None ,
destination : None ,
distance_in_km : None ,
comments : None ,
logtype : None ,
2023-09-23 18:26:04 +02:00
rowers : Vec ::new ( ) ,
2023-07-31 19:10:34 +02:00
} ,
2023-10-01 15:53:45 +02:00
& User ::find_by_id ( & pool , 4 ) . await . unwrap ( ) ,
2023-07-31 19:10:34 +02:00
)
. await
. unwrap ( )
}
#[ sqlx::test ]
fn test_create_boat_not_found ( ) {
let pool = testdb! ( ) ;
let res = Logbook ::create (
& pool ,
LogToAdd {
boat_id : 999 ,
shipmaster : 5 ,
shipmaster_only_steering : false ,
departure : " 2128-05-20T12:00 " . into ( ) ,
arrival : None ,
destination : None ,
distance_in_km : None ,
comments : None ,
logtype : None ,
2023-09-23 18:26:04 +02:00
rowers : Vec ::new ( ) ,
2023-07-31 19:10:34 +02:00
} ,
2023-10-01 15:53:45 +02:00
& User ::find_by_id ( & pool , 4 ) . await . unwrap ( ) ,
2023-07-31 19:10:34 +02:00
)
. await ;
assert_eq! ( res , Err ( LogbookCreateError ::BoatNotFound ) ) ;
}
#[ sqlx::test ]
fn test_create_boat_locked ( ) {
let pool = testdb! ( ) ;
let res = Logbook ::create (
& pool ,
LogToAdd {
boat_id : 5 ,
shipmaster : 5 ,
shipmaster_only_steering : false ,
departure : " 2128-05-20T12:00 " . into ( ) ,
arrival : None ,
destination : None ,
distance_in_km : None ,
comments : None ,
logtype : None ,
2023-09-23 18:26:04 +02:00
rowers : Vec ::new ( ) ,
2023-07-31 19:10:34 +02:00
} ,
2023-10-01 15:53:45 +02:00
& User ::find_by_id ( & pool , 4 ) . await . unwrap ( ) ,
2023-07-31 19:10:34 +02:00
)
. await ;
assert_eq! ( res , Err ( LogbookCreateError ::BoatLocked ) ) ;
}
#[ sqlx::test ]
fn test_create_boat_on_water ( ) {
let pool = testdb! ( ) ;
let res = Logbook ::create (
& pool ,
LogToAdd {
boat_id : 2 ,
shipmaster : 5 ,
shipmaster_only_steering : false ,
departure : " 2128-05-20T12:00 " . into ( ) ,
arrival : None ,
destination : None ,
distance_in_km : None ,
comments : None ,
logtype : None ,
2023-09-23 18:26:04 +02:00
rowers : Vec ::new ( ) ,
2023-07-31 19:10:34 +02:00
} ,
2023-10-01 15:53:45 +02:00
& User ::find_by_id ( & pool , 5 ) . await . unwrap ( ) ,
2023-07-31 19:10:34 +02:00
)
. await ;
assert_eq! ( res , Err ( LogbookCreateError ::BoatAlreadyOnWater ) ) ;
}
2023-09-24 09:48:01 +02:00
#[ sqlx::test ]
fn test_create_boat_on_water_wrong_arrival ( ) {
let pool = testdb! ( ) ;
let res = Logbook ::create (
& pool ,
LogToAdd {
boat_id : 3 ,
shipmaster : 5 ,
shipmaster_only_steering : false ,
2023-09-29 13:36:36 +02:00
departure : " 2128-05-20T12:00 " . into ( ) ,
arrival : Some ( " 2128-05-20T11:00 " . into ( ) ) ,
2023-09-24 09:48:01 +02:00
destination : None ,
distance_in_km : None ,
comments : None ,
logtype : None ,
rowers : Vec ::new ( ) ,
} ,
2023-10-01 15:53:45 +02:00
& User ::find_by_id ( & pool , 5 ) . await . unwrap ( ) ,
2023-09-24 09:48:01 +02:00
)
. await ;
assert_eq! ( res , Err ( LogbookCreateError ::ArrivalNotAfterDeparture ) ) ;
}
2023-07-31 19:10:34 +02:00
#[ sqlx::test ]
fn test_create_shipmaster_on_water ( ) {
let pool = testdb! ( ) ;
let res = Logbook ::create (
& pool ,
LogToAdd {
boat_id : 3 ,
shipmaster : 2 ,
shipmaster_only_steering : false ,
departure : " 2128-05-20T12:00 " . into ( ) ,
arrival : None ,
destination : None ,
distance_in_km : None ,
comments : None ,
logtype : None ,
2023-09-23 18:26:04 +02:00
rowers : Vec ::new ( ) ,
2023-07-31 19:10:34 +02:00
} ,
2023-10-01 15:53:45 +02:00
& User ::find_by_id ( & pool , 2 ) . await . unwrap ( ) ,
2023-07-31 19:10:34 +02:00
)
. await ;
assert_eq! ( res , Err ( LogbookCreateError ::ShipmasterAlreadyOnWater ) ) ;
}
2023-09-24 09:12:27 +02:00
#[ sqlx::test ]
fn test_create_same_person_cox_and_rower ( ) {
let pool = testdb! ( ) ;
let res = Logbook ::create (
& pool ,
LogToAdd {
boat_id : 3 ,
shipmaster : 5 ,
shipmaster_only_steering : false ,
departure : " 2128-05-20T12:00 " . into ( ) ,
arrival : None ,
destination : None ,
distance_in_km : None ,
comments : None ,
logtype : None ,
rowers : vec ! [ 5 ] ,
} ,
2023-10-01 15:53:45 +02:00
& User ::find_by_id ( & pool , 5 ) . await . unwrap ( ) ,
2023-09-24 09:12:27 +02:00
)
. await ;
assert_eq! ( res , Err ( LogbookCreateError ::SamePersonShipmasterAndRower ) ) ;
}
2023-07-31 19:10:34 +02:00
#[ sqlx::test ]
fn test_create_too_many_rowers ( ) {
let pool = testdb! ( ) ;
let res = Logbook ::create (
& pool ,
LogToAdd {
boat_id : 1 ,
shipmaster : 5 ,
shipmaster_only_steering : false ,
departure : " 2128-05-20T12:00 " . into ( ) ,
arrival : None ,
destination : None ,
distance_in_km : None ,
comments : None ,
logtype : None ,
2023-09-23 18:26:04 +02:00
rowers : vec ! [ 1 ] ,
2023-07-31 19:10:34 +02:00
} ,
2023-10-01 15:53:45 +02:00
& User ::find_by_id ( & pool , 5 ) . await . unwrap ( ) ,
2023-07-31 19:10:34 +02:00
)
. await ;
assert_eq! ( res , Err ( LogbookCreateError ::TooManyRowers ( 1 , 2 ) ) ) ;
}
#[ sqlx::test ]
fn test_distances ( ) {
let pool = testdb! ( ) ;
let res = Logbook ::distances ( & pool ) . await ;
assert_eq! (
res ,
vec! [
( " Ottensheim " . into ( ) , 25 as i64 ) ,
( " Ottensheim + Regattastrecke " . into ( ) , 29 as i64 ) ,
]
) ;
}
#[ sqlx::test ]
fn test_succ_home ( ) {
let pool = testdb! ( ) ;
let logbook = Logbook ::find_by_id ( & pool , 1 ) . await . unwrap ( ) ;
let user = User ::find_by_id ( & pool , 2 ) . await . unwrap ( ) ;
logbook
. home (
& pool ,
& user ,
super ::LogToFinalize {
destination : " new-destination " . into ( ) ,
distance_in_km : 42 ,
comments : Some ( " Perfect water " . into ( ) ) ,
logtype : None ,
2023-09-23 18:26:04 +02:00
rowers : vec ! [ ] ,
2023-07-31 19:10:34 +02:00
} ,
)
. await
. unwrap ( ) ;
}
#[ sqlx::test ]
fn test_home_wrong_user ( ) {
let pool = testdb! ( ) ;
let logbook = Logbook ::find_by_id ( & pool , 1 ) . await . unwrap ( ) ;
let user = User ::find_by_id ( & pool , 1 ) . await . unwrap ( ) ;
let res = logbook
. home (
& pool ,
& user ,
super ::LogToFinalize {
destination : " new-destination " . into ( ) ,
distance_in_km : 42 ,
comments : Some ( " Perfect water " . into ( ) ) ,
logtype : None ,
2023-09-23 18:26:04 +02:00
rowers : vec ! [ ] ,
2023-07-31 19:10:34 +02:00
} ,
)
. await ;
assert_eq! ( res , Err ( LogbookUpdateError ::NotYourEntry ) ) ;
}
#[ sqlx::test ]
fn test_home_too_many_rower ( ) {
let pool = testdb! ( ) ;
let logbook = Logbook ::find_by_id ( & pool , 1 ) . await . unwrap ( ) ;
let user = User ::find_by_id ( & pool , 2 ) . await . unwrap ( ) ;
let res = logbook
. home (
& pool ,
& user ,
super ::LogToFinalize {
destination : " new-destination " . into ( ) ,
distance_in_km : 42 ,
comments : Some ( " Perfect water " . into ( ) ) ,
logtype : None ,
2023-09-23 18:26:04 +02:00
rowers : vec ! [ 1 ] ,
2023-07-31 19:10:34 +02:00
} ,
)
. await ;
assert_eq! ( res , Err ( LogbookUpdateError ::TooManyRowers ( 1 , 2 ) ) ) ;
}
}