verify, that boat is not on water on adding log entry; Fixes #625 (#697)
Some checks failed
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled

Reviewed-on: #697
This commit is contained in:
2024-08-21 17:05:41 +02:00
parent 4bb0e54635
commit 36276e5415
6 changed files with 143 additions and 3 deletions

View File

@ -1,5 +1,6 @@
use std::ops::DerefMut;
use chrono::NaiveDateTime;
use itertools::Itertools;
use rocket::serde::{Deserialize, Serialize};
use rocket::FromForm;
@ -391,6 +392,39 @@ ORDER BY amount_seats DESC
.await
.ok()
}
pub async fn on_water_between(
&self,
db: &mut Transaction<'_, Sqlite>,
dep: NaiveDateTime,
arr: NaiveDateTime,
) -> bool {
let dep = dep.format("%Y-%m-%dT%H:%M").to_string();
let arr = arr.format("%Y-%m-%dT%H:%M").to_string();
sqlx::query!(
"SELECT COUNT(*) AS overlap_count
FROM logbook
WHERE boat_id = ?
AND (
(departure <= ? AND arrival >= ?) -- Existing entry covers the entire new period
OR (departure >= ? AND departure < ?) -- Existing entry starts during the new period
OR (arrival > ? AND arrival <= ?) -- Existing entry ends during the new period
);",
self.id,
arr,
arr,
dep,
dep,
dep,
arr
)
.fetch_one(db.deref_mut())
.await
.unwrap()
.overlap_count
> 0
}
}
#[cfg(test)]

View File

@ -142,6 +142,7 @@ pub enum LogbookUpdateError {
TooFast(i64, i64),
AlreadyFinalized,
ExternalSteeringPersonMustSteerOrShipmaster,
BoatAlreadyOnWater,
}
#[derive(Debug, PartialEq)]
@ -196,6 +197,7 @@ impl From<LogbookUpdateError> for LogbookCreateError {
LogbookUpdateError::ExternalSteeringPersonMustSteerOrShipmaster => {
LogbookCreateError::ExternalSteeringPersonMustSteerOrShipmaster
}
LogbookUpdateError::BoatAlreadyOnWater => LogbookCreateError::BoatAlreadyOnWater,
}
}
}
@ -573,6 +575,12 @@ ORDER BY departure DESC
return Err(LogbookUpdateError::ArrivalNotAfterDeparture);
}
if !boat.external {
if boat.on_water_between(db, dep, arr).await {
return Err(LogbookUpdateError::BoatAlreadyOnWater);
};
}
let duration_in_mins = (arr.and_utc().timestamp() - dep.and_utc().timestamp()) / 60;
// Not possible to row < 1 min / 500 m = < 2 min / km
let possible_distance_km = duration_in_mins / 2;

View File

@ -1106,7 +1106,7 @@ mod test {
fn test_cox() {
let pool = testdb!();
let res = User::cox(&pool).await;
assert_eq!(res.len(), 3);
assert_eq!(res.len(), 4);
}
#[sqlx::test]