dont-repeatedly-get-price #1043

Merged
philipp merged 2 commits from dont-repeatedly-get-price into staging 2025-05-17 16:24:02 +02:00
3 changed files with 34 additions and 42 deletions

View File

@ -367,7 +367,6 @@ ORDER BY departure DESC
min_distance: i32, min_distance: i32,
year: i32, year: i32,
filter: Filter, filter: Filter,
exclude_last_log: bool,
) -> Vec<LogbookWithBoatAndRowers> { ) -> Vec<LogbookWithBoatAndRowers> {
let logs: Vec<Logbook> = sqlx::query_as( let logs: Vec<Logbook> = sqlx::query_as(
&format!(" &format!("
@ -399,9 +398,6 @@ ORDER BY departure DESC
} }
} }
} }
if exclude_last_log {
ret.pop();
}
ret ret
} }

View File

@ -2,7 +2,7 @@ use std::cmp;
use chrono::{Datelike, Local, NaiveDate}; use chrono::{Datelike, Local, NaiveDate};
use serde::Serialize; use serde::Serialize;
use sqlx::{Sqlite, SqlitePool, Transaction}; use sqlx::{Acquire, Sqlite, SqlitePool, Transaction};
use crate::model::{ use crate::model::{
logbook::{Filter, Logbook, LogbookWithBoatAndRowers}, logbook::{Filter, Logbook, LogbookWithBoatAndRowers},
@ -141,11 +141,7 @@ impl Status {
} }
} }
pub(crate) async fn for_user_tx( pub(crate) async fn for_user_tx(db: &mut Transaction<'_, Sqlite>, user: &User) -> Option<Self> {
db: &mut Transaction<'_, Sqlite>,
user: &User,
exclude_last_log: bool,
) -> Option<Self> {
let Ok(agebracket) = AgeBracket::try_from(user) else { let Ok(agebracket) = AgeBracket::try_from(user) else {
return None; return None;
}; };
@ -164,7 +160,6 @@ impl Status {
agebracket.required_dist_single_day_in_km(), agebracket.required_dist_single_day_in_km(),
year, year,
Filter::SingleDayOnly, Filter::SingleDayOnly,
exclude_last_log,
) )
.await; .await;
let multi_day_trips_over_required_distance = let multi_day_trips_over_required_distance =
@ -174,7 +169,6 @@ impl Status {
agebracket.required_dist_multi_day_in_km(), agebracket.required_dist_multi_day_in_km(),
year, year,
Filter::MultiDayOnly, Filter::MultiDayOnly,
exclude_last_log,
) )
.await; .await;
@ -195,7 +189,7 @@ impl Status {
pub(crate) async fn for_user(db: &SqlitePool, user: &User) -> Option<Self> { pub(crate) async fn for_user(db: &SqlitePool, user: &User) -> Option<Self> {
let mut tx = db.begin().await.unwrap(); let mut tx = db.begin().await.unwrap();
let ret = Self::for_user_tx(&mut tx, user, false).await; let ret = Self::for_user_tx(&mut tx, user).await;
tx.commit().await.unwrap(); tx.commit().await.unwrap();
ret ret
} }
@ -204,11 +198,19 @@ impl Status {
db: &mut Transaction<'_, Sqlite>, db: &mut Transaction<'_, Sqlite>,
user: &User, user: &User,
) -> bool { ) -> bool {
if let Some(status) = Self::for_user_tx(db, user, false).await { if let Some(status) = Self::for_user_tx(db, user).await {
// if user has agebracket... // if user has agebracket...
if status.achieved { if status.achieved {
// ... and has achieved the 'Fahrtenabzeichen' // ... and has achieved the 'Fahrtenabzeichen'
let without_last_entry = Self::for_user_tx(db, user, true).await.unwrap(); let mut without_last = db.begin().await.unwrap();
let last = Logbook::completed_with_user_tx(&mut without_last, user).await;
let last = last.last().unwrap();
sqlx::query!("DELETE FROM logbook WHERE id=?", last.logbook.id)
.execute(&mut *without_last)
.await
.unwrap(); //Okay, because we can only create a Logbook of a valid id
let without_last_entry = Self::for_user_tx(&mut without_last, user).await.unwrap();
if !without_last_entry.achieved { if !without_last_entry.achieved {
// ... and this wasn't the case before the last logentry // ... and this wasn't the case before the last logentry
return true; return true;

View File

@ -1,21 +1,20 @@
use std::{fmt::Display, ops::DerefMut}; use std::{fmt::Display, ops::DerefMut};
use argon2::{Argon2, PasswordHasher, password_hash::SaltString}; use argon2::{password_hash::SaltString, Argon2, PasswordHasher};
use chrono::{Datelike, Local, NaiveDate}; use chrono::{Datelike, Local, NaiveDate};
use log::info; use log::info;
use rocket::async_trait; use rocket::async_trait;
use rocket::{ use rocket::{
Request,
http::{Cookie, Status}, http::{Cookie, Status},
request::{FromRequest, Outcome}, request::{FromRequest, Outcome},
time::{Duration, OffsetDateTime}, time::{Duration, OffsetDateTime},
Request,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
use super::activity::{ActivityBuilder, ReasonAuth}; use super::activity::{ActivityBuilder, ReasonAuth};
use super::{ use super::{
Day,
log::Log, log::Log,
logbook::Logbook, logbook::Logbook,
mail::Mail, mail::Mail,
@ -24,6 +23,7 @@ use super::{
role::Role, role::Role,
stat::Stat, stat::Stat,
tripdetails::TripDetails, tripdetails::TripDetails,
Day,
}; };
use crate::AMOUNT_DAYS_TO_SHOW_TRIPS_AHEAD; use crate::AMOUNT_DAYS_TO_SHOW_TRIPS_AHEAD;
use scheckbuch::ScheckbuchUser; use scheckbuch::ScheckbuchUser;
@ -950,21 +950,17 @@ mod test {
#[sqlx::test] #[sqlx::test]
fn wrong_pw() { fn wrong_pw() {
let pool = testdb!(); let pool = testdb!();
assert!( assert!(User::login(&pool, "admin".into(), "admi".into())
User::login(&pool, "admin".into(), "admi".into())
.await .await
.is_err() .is_err());
);
} }
#[sqlx::test] #[sqlx::test]
fn wrong_username() { fn wrong_username() {
let pool = testdb!(); let pool = testdb!();
assert!( assert!(User::login(&pool, "admi".into(), "admin".into())
User::login(&pool, "admi".into(), "admin".into())
.await .await
.is_err() .is_err());
);
} }
#[sqlx::test] #[sqlx::test]
@ -984,11 +980,9 @@ mod test {
let pool = testdb!(); let pool = testdb!();
let user = User::find_by_id(&pool, 1).await.unwrap(); let user = User::find_by_id(&pool, 1).await.unwrap();
assert!( assert!(User::login(&pool, "admin".into(), "abc".into())
User::login(&pool, "admin".into(), "abc".into())
.await .await
.is_err() .is_err());
);
user.update_pw(&pool, "abc".into()).await; user.update_pw(&pool, "abc".into()).await;