Merge branch 'staging' into 'log-2022'

# Conflicts:
#   src/model/logbook.rs
This commit is contained in:
PhilippHofer 2023-11-18 11:22:50 +00:00
commit 53ed032c25
3 changed files with 39 additions and 22 deletions

View File

@ -1,4 +1,4 @@
use chrono::{Datelike, NaiveDateTime}; use chrono::{NaiveDateTime, Utc, Datelike};
use rocket::FromForm; use rocket::FromForm;
use serde::Serialize; use serde::Serialize;
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
@ -99,6 +99,7 @@ pub enum LogbookUpdateError {
ShipmasterNotInRowers, ShipmasterNotInRowers,
SteeringPersonNotInRowers, SteeringPersonNotInRowers,
UserNotAllowedToUseBoat, UserNotAllowedToUseBoat,
OnlyAllowedToEndTripsEndingToday,
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -120,6 +121,7 @@ pub enum LogbookCreateError {
ShipmasterNotInRowers, ShipmasterNotInRowers,
NotYourEntry, NotYourEntry,
ArrivalSetButNotRemainingTwo, ArrivalSetButNotRemainingTwo,
OnlyAllowedToEndTripsEndingToday,
} }
impl From<LogbookUpdateError> for LogbookCreateError { impl From<LogbookUpdateError> for LogbookCreateError {
@ -140,6 +142,9 @@ impl From<LogbookUpdateError> for LogbookCreateError {
LogbookUpdateError::UserNotAllowedToUseBoat => { LogbookUpdateError::UserNotAllowedToUseBoat => {
LogbookCreateError::UserNotAllowedToUseBoat LogbookCreateError::UserNotAllowedToUseBoat
} }
LogbookUpdateError::OnlyAllowedToEndTripsEndingToday => {
LogbookCreateError::OnlyAllowedToEndTripsEndingToday
}
} }
} }
} }
@ -446,13 +451,8 @@ ORDER BY departure DESC
} }
if !boat.shipmaster_allowed(user).await && self.shipmaster != user.id { if !boat.shipmaster_allowed(user).await && self.shipmaster != user.id {
//second part: //second part: shipmaster has entered a different user, then the user should be able to
//shipmaster has //`home` it
//entered a
//different user,
//then the user
//should be able
//to `home` it
return Err(LogbookUpdateError::UserNotAllowedToUseBoat); return Err(LogbookUpdateError::UserNotAllowedToUseBoat);
} }
@ -468,6 +468,10 @@ ORDER BY departure DESC
if arr.timestamp() <= dep.timestamp() { if arr.timestamp() <= dep.timestamp() {
return Err(LogbookUpdateError::ArrivalNotAfterDeparture); return Err(LogbookUpdateError::ArrivalNotAfterDeparture);
} }
let today = Utc::now().date_naive();
if arr.date() != today && !user.is_admin {
return Err(LogbookUpdateError::OnlyAllowedToEndTripsEndingToday);
}
Log::create_with_tx(db, format!("New trip: {log:?}")).await; Log::create_with_tx(db, format!("New trip: {log:?}")).await;
@ -793,6 +797,8 @@ mod test {
let logbook = Logbook::find_by_id(&pool, 1).await.unwrap(); let logbook = Logbook::find_by_id(&pool, 1).await.unwrap();
let user = User::find_by_id(&pool, 2).await.unwrap(); let user = User::find_by_id(&pool, 2).await.unwrap();
let current_date = chrono::Local::now().format("%Y-%m-%d").to_string();
logbook logbook
.home( .home(
&pool, &pool,
@ -806,8 +812,8 @@ mod test {
shipmaster: Some(2), shipmaster: Some(2),
steering_person: Some(2), steering_person: Some(2),
shipmaster_only_steering: false, shipmaster_only_steering: false,
departure: "1990-01-01T10:00".into(), departure: format!("{}T10:00", current_date),
arrival: "1990-01-01T12:00".into(), arrival: format!("{}T12:00", current_date),
}, },
) )
.await .await

View File

@ -182,6 +182,7 @@ async fn create_logbook(
Err(LogbookCreateError::ShipmasterNotInRowers) => Flash::error(Redirect::to("/log"), "Schiffsführer nicht in Liste der Ruderer!"), Err(LogbookCreateError::ShipmasterNotInRowers) => Flash::error(Redirect::to("/log"), "Schiffsführer nicht in Liste der Ruderer!"),
Err(LogbookCreateError::NotYourEntry) => Flash::error(Redirect::to("/log"), "Nicht deine Ausfahrt!"), Err(LogbookCreateError::NotYourEntry) => Flash::error(Redirect::to("/log"), "Nicht deine Ausfahrt!"),
Err(LogbookCreateError::ArrivalSetButNotRemainingTwo) => Flash::error(Redirect::to("/log"), "Ankunftszeit gesetzt aber nicht Distanz + Strecke"), Err(LogbookCreateError::ArrivalSetButNotRemainingTwo) => Flash::error(Redirect::to("/log"), "Ankunftszeit gesetzt aber nicht Distanz + Strecke"),
Err(LogbookCreateError::OnlyAllowedToEndTripsEndingToday) => Flash::error(Redirect::to("/log"), format!("Nur Ausfahrten, die heute enden dürfen eingetragen werden. Für einen Nachtrag schreibe alle Daten Philipp (Tel. nr. siehe Signal oder it@rudernlinz.at).")),
} }
} }
@ -251,6 +252,7 @@ async fn home_logbook(
match logbook.home(db, &user.user, data.into_inner()).await { match logbook.home(db, &user.user, data.into_inner()).await {
Ok(_) => Flash::success(Redirect::to("/log"), "Ausfahrt korrekt eingetragen"), Ok(_) => Flash::success(Redirect::to("/log"), "Ausfahrt korrekt eingetragen"),
Err(LogbookUpdateError::TooManyRowers(expected, actual)) => Flash::error(Redirect::to("/log"), format!("Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)")), Err(LogbookUpdateError::TooManyRowers(expected, actual)) => Flash::error(Redirect::to("/log"), format!("Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)")),
Err(LogbookUpdateError::OnlyAllowedToEndTripsEndingToday) => Flash::error(Redirect::to("/log"), format!("Nur Ausfahrten, die heute enden dürfen eingetragen werden. Für einen Nachtrag schreibe alle Daten Philipp (Tel. nr. siehe Signal oder it@rudernlinz.at).")),
Err(e) => Flash::error( Err(e) => Flash::error(
Redirect::to("/log"), Redirect::to("/log"),
format!("Eintrag {logbook_id} konnte nicht abgesendet werden (Fehler: {e:?})!"), format!("Eintrag {logbook_id} konnte nicht abgesendet werden (Fehler: {e:?})!"),
@ -522,11 +524,12 @@ mod test {
.header(ContentType::Form) // Set the content type to form .header(ContentType::Form) // Set the content type to form
.body("name=admin&password=admin"); // Add the form data to the request body; .body("name=admin&password=admin"); // Add the form data to the request body;
login.dispatch().await; login.dispatch().await;
let current_date = chrono::Local::now().format("%Y-%m-%d").to_string();
let req = client let req = client.post("/log").header(ContentType::Form).body(format!(
.post("/log") "boat_id=1&shipmaster=4&departure={0}T10:00&steering_person=4&rowers[]=4",
.header(ContentType::Form) current_date
.body("boat_id=1&shipmaster=4&departure=2199-12-31T10:00&steering_person=4&rowers[]=4"); ));
let response = req.dispatch().await; let response = req.dispatch().await;
assert_eq!(response.status(), Status::SeeOther); assert_eq!(response.status(), Status::SeeOther);
@ -554,10 +557,12 @@ mod test {
let req = client.get("/log/kiosk/ekrv2019/Linz"); let req = client.get("/log/kiosk/ekrv2019/Linz");
let _ = req.dispatch().await; let _ = req.dispatch().await;
let current_date = chrono::Local::now().format("%Y-%m-%d").to_string();
let req = client let req = client
.post("/log/1") .post("/log/1")
.header(ContentType::Form) .header(ContentType::Form)
.body("destination=Ottensheim&distance_in_km=25&shipmaster=2&steering_person=2&departure=1990-01-01T10:00&arrival=1990-01-01T12:00&rowers[]=2"); .body(format!("destination=Ottensheim&distance_in_km=25&shipmaster=2&steering_person=2&departure={0}T10:00&arrival={0}T12:00&rowers[]=2", current_date));
let response = req.dispatch().await; let response = req.dispatch().await;
assert_eq!(response.status(), Status::SeeOther); assert_eq!(response.status(), Status::SeeOther);
@ -664,9 +669,10 @@ mod test {
.unwrap() .unwrap()
.id; .id;
let shipmaster_id = User::find_by_name(&db, "rower2".into()).await.unwrap().id; let shipmaster_id = User::find_by_name(&db, "rower2".into()).await.unwrap().id;
let current_date = chrono::Local::now().format("%Y-%m-%d").to_string();
let req = client.post("/log").header(ContentType::Form).body(format!( let req = client.post("/log").header(ContentType::Form).body(format!(
"boat_id={boat_id}&shipmaster={shipmaster_id}&departure=1199-12-31T10:00&steering_person={shipmaster_id}&rowers[]={shipmaster_id}" "boat_id={boat_id}&shipmaster={shipmaster_id}&departure={0}T10:00&steering_person={shipmaster_id}&rowers[]={shipmaster_id}", current_date
)); ));
let response = req.dispatch().await; let response = req.dispatch().await;
@ -695,7 +701,7 @@ mod test {
let req = client let req = client
.post(format!("/log/{log_id}")) .post(format!("/log/{log_id}"))
.header(ContentType::Form) .header(ContentType::Form)
.body(format!("destination=Ottensheim&distance_in_km=25&shipmaster={shipmaster_id}&steering_person={shipmaster_id}&departure=1990-01-01T10:00&arrival=1990-01-01T12:00&rowers[]={shipmaster_id}")); .body(format!("destination=Ottensheim&distance_in_km=25&shipmaster={shipmaster_id}&steering_person={shipmaster_id}&departure={0}T10:00&arrival={0}T12:00&rowers[]={shipmaster_id}", current_date));
let response = req.dispatch().await; let response = req.dispatch().await;
assert_eq!(response.status(), Status::SeeOther); assert_eq!(response.status(), Status::SeeOther);
@ -882,11 +888,12 @@ mod test {
.header(ContentType::Form) // Set the content type to form .header(ContentType::Form) // Set the content type to form
.body("name=rower2&password=rower"); // Add the form data to the request body; .body("name=rower2&password=rower"); // Add the form data to the request body;
login.dispatch().await; login.dispatch().await;
let current_date = chrono::Local::now().format("%Y-%m-%d").to_string();
let req = client let req = client
.post("/log/1") .post("/log/1")
.header(ContentType::Form) .header(ContentType::Form)
.body("destination=Ottensheim&distance_in_km=25&shipmaster=1&steering_person=1&departure=1199-12-12T10:00&arrival=1199-12-12T12:00&rowers[]=1"); .body(format!("destination=Ottensheim&distance_in_km=25&shipmaster=1&steering_person=1&departure={0}T10:00&arrival={0}T12:00&rowers[]=1", current_date));
let response = req.dispatch().await; let response = req.dispatch().await;
assert_eq!(response.status(), Status::SeeOther); assert_eq!(response.status(), Status::SeeOther);
@ -912,8 +919,10 @@ mod test {
let boat_id = Boat::find_by_name(db, boat_name).await.unwrap().id; let boat_id = Boat::find_by_name(db, boat_name).await.unwrap().id;
let shipmaster_id = User::find_by_name(db, &shipmaster_name).await.unwrap().id; let shipmaster_id = User::find_by_name(db, &shipmaster_name).await.unwrap().id;
let current_date = chrono::Local::now().format("%Y-%m-%d").to_string();
let req = client.post("/log").header(ContentType::Form).body(format!( let req = client.post("/log").header(ContentType::Form).body(format!(
"boat_id={boat_id}&shipmaster={shipmaster_id}&departure=1199-12-31T10:00&steering_person={shipmaster_id}&rowers[]={shipmaster_id}" "boat_id={boat_id}&shipmaster={shipmaster_id}&departure={current_date}T10:00&steering_person={shipmaster_id}&rowers[]={shipmaster_id}"
)); ));
let response = req.dispatch().await; let response = req.dispatch().await;
@ -935,7 +944,7 @@ mod test {
let req = client let req = client
.post(format!("/log/{log_id}")) .post(format!("/log/{log_id}"))
.header(ContentType::Form) .header(ContentType::Form)
.body(format!("destination=Ottensheim&distance_in_km=25&shipmaster={shipmaster_id}&steering_person={shipmaster_id}&departure=1199-12-31T10:00&arrival=1199-12-31T12:00&rowers[]={shipmaster_id}")); .body(format!("destination=Ottensheim&distance_in_km=25&shipmaster={shipmaster_id}&steering_person={shipmaster_id}&departure={current_date}T10:00&arrival={current_date}T12:00&rowers[]={shipmaster_id}"));
let response = req.dispatch().await; let response = req.dispatch().await;
assert_eq!(response.status(), Status::SeeOther); assert_eq!(response.status(), Status::SeeOther);
@ -962,8 +971,10 @@ mod test {
let boat_id = Boat::find_by_name(db, boat_name).await.unwrap().id; let boat_id = Boat::find_by_name(db, boat_name).await.unwrap().id;
let shipmaster_id = User::find_by_name(db, &shipmaster_name).await.unwrap().id; let shipmaster_id = User::find_by_name(db, &shipmaster_name).await.unwrap().id;
let current_date = chrono::Local::now().format("%Y-%m-%d").to_string();
let req = client.post("/log").header(ContentType::Form).body(format!( let req = client.post("/log").header(ContentType::Form).body(format!(
"boat_id={boat_id}&shipmaster={shipmaster_id}&departure=2199-12-31T10:00&steering_person={shipmaster_id}&rowers[]={shipmaster_id}" "boat_id={boat_id}&shipmaster={shipmaster_id}&departure={current_date}T10:00&steering_person={shipmaster_id}&rowers[]={shipmaster_id}"
)); ));
let response = req.dispatch().await; let response = req.dispatch().await;

View File

@ -2,7 +2,7 @@
<div class="max-w-screen-xl w-full flex justify-between items-center"> <div class="max-w-screen-xl w-full flex justify-between items-center">
<div> <div>
<span class="text-[#ff0000]">&hearts;</span> <span class="text-[#ff0000]">&hearts;</span>
ASKÖ Ruderverein Donau Linz <small class="text-primary-100">&copy; {{ now() | date(format="%Y") }}</smalL> Erstellt vom ASKÖ Ruderverein Donau Linz <a onclick="alert('Wir suchen kreative und motivierte Köpfe, die diesen Ruderassistenten mitgestalten möchten. Das Backend ist in Rust (Rocket), das Frontend in TypeScript und Teraform, wobei wir mit dem Gedanken spielen, zu Svelte(Kit) zu wechseln.\n\nWenn du Lust hast, deine Skills in ein Projekt zu stecken, das Wellen schlagen wird, dann komm an Bord! Wir sind offen für frische Ideen, haben jedoch auch selber noch genügend; langweilig wird uns bestimmt nicht.\n\nWirf den Anker bei uns ausi und melde dich bei Marie oder Philipp oder it@rudernlinz.at für eine Zukunft ohne optische Kenterung in Form von hässlichen Alerts ;)');" style="text-decoration:underline">... und dir?</a>
</div> </div>
<div> <div>