From a484785027bf6f78c9e2eb1e3f05dbf761b0f340 Mon Sep 17 00:00:00 2001 From: Philipp Hofer Date: Fri, 25 Apr 2025 15:41:46 +0200 Subject: [PATCH 1/2] first ideas of separate user structs, working on #911 --- src/model/user/fee.rs | 117 +++++++++++++++++++ src/model/user/mod.rs | 221 +++++------------------------------ src/model/user/scheckbuch.rs | 84 +++++++++++++ 3 files changed, 233 insertions(+), 189 deletions(-) create mode 100644 src/model/user/scheckbuch.rs diff --git a/src/model/user/fee.rs b/src/model/user/fee.rs index 0228892..4f3febf 100644 --- a/src/model/user/fee.rs +++ b/src/model/user/fee.rs @@ -1,5 +1,11 @@ use super::User; +use crate::{ + model::family::Family, BOAT_STORAGE, EINSCHREIBGEBUEHR, FAMILY_THREE_OR_MORE, FAMILY_TWO, + FOERDERND, REGULAR, RENNRUDERBEITRAG, STUDENT_OR_PUPIL, UNTERSTUETZEND, +}; +use chrono::{Datelike, Local, NaiveDate}; use serde::Serialize; +use sqlx::SqlitePool; #[derive(Debug, Serialize)] pub struct Fee { @@ -56,3 +62,114 @@ impl Fee { } } } + +impl User { + pub async fn fee(&self, db: &SqlitePool) -> Option { + if !self.has_role(db, "Donau Linz").await + && !self.has_role(db, "Unterstützend").await + && !self.has_role(db, "Förderndes Mitglied").await + { + return None; + } + if self.deleted { + return None; + } + + let mut fee = Fee::new(); + + if let Some(family) = Family::find_by_opt_id(db, self.family_id).await { + for member in family.members(db).await { + fee.add_person(&member); + if member.has_role(db, "paid").await { + fee.paid(); + } + fee.merge(member.fee_without_families(db).await); + } + if family.amount_family_members(db).await > 2 { + fee.add("Familie 3+ Personen".into(), FAMILY_THREE_OR_MORE); + } else { + fee.add("Familie 2 Personen".into(), FAMILY_TWO); + } + } else { + fee.add_person(self); + if self.has_role(db, "paid").await { + fee.paid(); + } + fee.merge(self.fee_without_families(db).await); + } + + Some(fee) + } + + async fn fee_without_families(&self, db: &SqlitePool) -> Fee { + let mut fee = Fee::new(); + + if !self.has_role(db, "Donau Linz").await + && !self.has_role(db, "Unterstützend").await + && !self.has_role(db, "Förderndes Mitglied").await + { + return fee; + } + if self.has_role(db, "Rennrudern").await { + if self.has_role(db, "half-rennrudern").await { + fee.add("Rennruderbeitrag (1/2 Preis) ".into(), RENNRUDERBEITRAG / 2); + } else if !self.has_role(db, "renntrainer").await { + fee.add("Rennruderbeitrag".into(), RENNRUDERBEITRAG); + } + } + + let amount_boats = self.amount_boats(db).await; + if amount_boats > 0 { + fee.add( + format!("{}x Bootsplatz", amount_boats), + amount_boats * BOAT_STORAGE, + ); + } + + if let Some(member_since_date) = &self.member_since_date { + if let Ok(member_since_date) = NaiveDate::parse_from_str(member_since_date, "%Y-%m-%d") + { + if member_since_date.year() == Local::now().year() + && !self.has_role(db, "no-einschreibgebuehr").await + { + fee.add("Einschreibgebühr".into(), EINSCHREIBGEBUEHR); + } + } + } + + let halfprice = if let Some(member_since_date) = &self.member_since_date { + match NaiveDate::parse_from_str(member_since_date, "%Y-%m-%d") { + Ok(member_since_date) => { + let halfprice_startdate = + NaiveDate::from_ymd_opt(Local::now().year(), 7, 1).unwrap(); + member_since_date >= halfprice_startdate + } + Err(_) => false, + } + } else { + false + }; + + if self.has_role(db, "Unterstützend").await { + fee.add("Unterstützendes Mitglied".into(), UNTERSTUETZEND); + } else if self.has_role(db, "Förderndes Mitglied").await { + fee.add("Förderndes Mitglied".into(), FOERDERND); + } else if Family::find_by_opt_id(db, self.family_id).await.is_none() { + if self.has_role(db, "Student").await || self.has_role(db, "Schüler").await { + if halfprice { + fee.add("Schüler/Student (Halbpreis)".into(), STUDENT_OR_PUPIL / 2); + } else { + fee.add("Schüler/Student".into(), STUDENT_OR_PUPIL); + } + } else if self.has_role(db, "Ehrenmitglied").await { + fee.add("Ehrenmitglied".into(), 0); + } else if halfprice { + fee.add("Mitgliedsbeitrag (Halbpreis)".into(), REGULAR / 2); + } else { + fee.add("Mitgliedsbeitrag".into(), REGULAR); + } + } + + fee + } +} diff --git a/src/model/user/mod.rs b/src/model/user/mod.rs index b37879d..228f82e 100644 --- a/src/model/user/mod.rs +++ b/src/model/user/mod.rs @@ -26,14 +26,10 @@ use super::{ tripdetails::TripDetails, Day, }; -use crate::{ - tera::admin::user::UserEditForm, AMOUNT_DAYS_TO_SHOW_TRIPS_AHEAD, BOAT_STORAGE, - EINSCHREIBGEBUEHR, FAMILY_THREE_OR_MORE, FAMILY_TWO, FOERDERND, REGULAR, RENNRUDERBEITRAG, - SCHECKBUCH, STUDENT_OR_PUPIL, UNTERSTUETZEND, -}; -use fee::Fee; +use crate::{tera::admin::user::UserEditForm, AMOUNT_DAYS_TO_SHOW_TRIPS_AHEAD}; mod fee; +mod scheckbuch; #[derive(FromRow, Serialize, Deserialize, Clone, Debug, Eq, Hash, PartialEq)] pub struct User { @@ -114,8 +110,6 @@ impl User { if self.has_role(db, "Donau Linz").await { self.send_welcome_mail_full_member(db, mail, smtp_pw) .await?; - } else if self.has_role(db, "scheckbuch").await { - self.send_welcome_mail_scheckbuch(db, mail, smtp_pw).await?; } else if self.has_role(db, "schnupperant").await { self.send_welcome_mail_schnupper(db, mail, smtp_pw).await?; } else { @@ -174,78 +168,6 @@ ASKÖ Ruderverein Donau Linz", self.name), Ok(()) } - async fn send_welcome_mail_scheckbuch( - &self, - db: &SqlitePool, - mail: &str, - smtp_pw: &str, - ) -> Result<(), String> { - // 2 things to do: - // 1. Send mail to user - Mail::send_single( - db, - mail, - "ASKÖ Ruderverein Donau Linz | Dein Scheckbuch wartet auf Dich", - format!( -"Hallo {0}, - -herzlich willkommen beim ASKÖ Ruderverein Donau Linz! Wir freuen uns sehr, dass Du Dich entschieden hast, das Rudern bei uns auszuprobieren. Mit Deinem Scheckbuch kannst Du jetzt an fünf Ausfahrten teilnehmen und so diesen Sport in seiner vollen Vielfalt erleben. Falls du die {1} € noch nicht bezahlt hast, nimm diese bitte zur nächsten Ausfahrt mit (oder überweise sie auf unser Bankkonto [dieses findest du auf https://rudernlinz.at]). - -Für die Organisation unserer Ausfahrten nutzen wir app.rudernlinz.at. Logge Dich bitte mit Deinem Namen ('{0}', ohne Anführungszeichen) ein. Beim ersten Mal kannst Du das Passwortfeld leer lassen. Unter 'Geplante Ausfahrten' kannst Du Dich jederzeit für eine Ausfahrt anmelden. Wir bieten mindestens einmal pro Woche Ausfahrten an, sowohl für Anfänger als auch für Fortgeschrittene (A+F Rudern). Zusätzliche Ausfahrten werden von unseren Steuerleuten ausgeschrieben, öfters reinschauen kann sich also lohnen :-) - -Nach deinen 5 Ausfahrten würden wir uns freuen, dich als Mitglied in unserem Verein begrüßen zu dürfen. - -Wir freuen uns darauf, Dich bald am Wasser zu sehen und gemeinsam tolle Erfahrungen zu sammeln! - -Riemen- & Dollenbruch, -ASKÖ Ruderverein Donau Linz", self.name, SCHECKBUCH/100), - smtp_pw, - ).await?; - - // 2. Notify all coxes - Notification::create_for_steering_people( - db, - &format!( - "Liebe Steuerberechtigte, {} hat nun ein Scheckbuch. Wie immer, freuen wir uns wenn du uns beim A+F Rudern unterstützt oder selber Ausfahrten ausschreibst. Bitte beachte, dass Scheckbuch-Personen nur Ausfahrten sehen, bei denen 'Scheckbuch-Anmeldungen erlauben' ausgewählt wurde.", - self.name - ), - "Neues Scheckbuch", - None,None - ) - .await; - - Ok(()) - } - - async fn send_end_mail_scheckbuch( - &self, - db: &mut Transaction<'_, Sqlite>, - mail: &str, - smtp_pw: &str, - ) -> Result<(), String> { - Mail::send_single_tx( - db, - mail, - "ASKÖ Ruderverein Donau Linz | Deine Mitgliedschaft wartet auf Dich", - format!( -"Hallo {0}, - -herzlichen Glückwunsch---Du hast Deine fünf Scheckbuch-Ausfahrten erfolgreich absolviert! Wir hoffen, dass Du das Rudern bei uns genauso genossen hast wie wir es genossen haben, Dich auf dem Wasser zu begleiten. - -Wir würden uns sehr freuen, Dich als festes Mitglied in unserem Verein willkommen zu heißen! Als Mitglied stehen Dir dann alle unsere Ausfahrten offen, die von unseren Steuerleuten organisiert werden. Im Sommer erwarten Dich zusätzlich spannende Events: Wanderfahrten, Sternfahrten, Fetzenfahrt, .... Im Winter bieten wir Indoor-Ergo-Challenges an, bei denen Du Deine Fitness auf dem Ruderergometer unter Beweis stellen kannst. Alle Details zu diesen Aktionen erfährst Du, sobald Du Teil unseres Vereins bist! :-) - -Alle Informationen zu den Mitgliedsbeiträgen findest Du unter https://rudernlinz.at/unser-verein/gebuhren/ Falls Du Dich entscheidest, unserem Verein beizutreten, fülle bitte unser Beitrittsformular auf https://rudernlinz.at/unser-verein/downloads/ aus und sende es an info@rudernlinz.at. - -Wir freuen uns, Dich bald wieder auf dem Wasser zu sehen. - -Riemen- & Dollenbruch, -ASKÖ Ruderverein Donau Linz", self.name), - smtp_pw, - ).await?; - - Ok(()) - } - async fn send_welcome_mail_full_member( &self, db: &SqlitePool, @@ -297,115 +219,6 @@ ASKÖ Ruderverein Donau Linz", self.name), Ok(()) } - pub async fn fee(&self, db: &SqlitePool) -> Option { - if !self.has_role(db, "Donau Linz").await - && !self.has_role(db, "Unterstützend").await - && !self.has_role(db, "Förderndes Mitglied").await - { - return None; - } - if self.deleted { - return None; - } - - let mut fee = Fee::new(); - - if let Some(family) = Family::find_by_opt_id(db, self.family_id).await { - for member in family.members(db).await { - fee.add_person(&member); - if member.has_role(db, "paid").await { - fee.paid(); - } - fee.merge(member.fee_without_families(db).await); - } - if family.amount_family_members(db).await > 2 { - fee.add("Familie 3+ Personen".into(), FAMILY_THREE_OR_MORE); - } else { - fee.add("Familie 2 Personen".into(), FAMILY_TWO); - } - } else { - fee.add_person(self); - if self.has_role(db, "paid").await { - fee.paid(); - } - fee.merge(self.fee_without_families(db).await); - } - - Some(fee) - } - - async fn fee_without_families(&self, db: &SqlitePool) -> Fee { - let mut fee = Fee::new(); - - if !self.has_role(db, "Donau Linz").await - && !self.has_role(db, "Unterstützend").await - && !self.has_role(db, "Förderndes Mitglied").await - { - return fee; - } - if self.has_role(db, "Rennrudern").await { - if self.has_role(db, "half-rennrudern").await { - fee.add("Rennruderbeitrag (1/2 Preis) ".into(), RENNRUDERBEITRAG / 2); - } else if !self.has_role(db, "renntrainer").await { - fee.add("Rennruderbeitrag".into(), RENNRUDERBEITRAG); - } - } - - let amount_boats = self.amount_boats(db).await; - if amount_boats > 0 { - fee.add( - format!("{}x Bootsplatz", amount_boats), - amount_boats * BOAT_STORAGE, - ); - } - - if let Some(member_since_date) = &self.member_since_date { - if let Ok(member_since_date) = NaiveDate::parse_from_str(member_since_date, "%Y-%m-%d") - { - if member_since_date.year() == Local::now().year() - && !self.has_role(db, "no-einschreibgebuehr").await - { - fee.add("Einschreibgebühr".into(), EINSCHREIBGEBUEHR); - } - } - } - - let halfprice = if let Some(member_since_date) = &self.member_since_date { - if let Ok(member_since_date) = NaiveDate::parse_from_str(member_since_date, "%Y-%m-%d") - { - let halfprice_startdate = - NaiveDate::from_ymd_opt(Local::now().year(), 7, 1).unwrap(); - member_since_date >= halfprice_startdate - } else { - false - } - } else { - false - }; - - if self.has_role(db, "Unterstützend").await { - fee.add("Unterstützendes Mitglied".into(), UNTERSTUETZEND); - } else if self.has_role(db, "Förderndes Mitglied").await { - fee.add("Förderndes Mitglied".into(), FOERDERND); - } else if Family::find_by_opt_id(db, self.family_id).await.is_none() { - if self.has_role(db, "Student").await || self.has_role(db, "Schüler").await { - if halfprice { - fee.add("Schüler/Student (Halbpreis)".into(), STUDENT_OR_PUPIL / 2); - } else { - fee.add("Schüler/Student".into(), STUDENT_OR_PUPIL); - } - } else if self.has_role(db, "Ehrenmitglied").await { - fee.add("Ehrenmitglied".into(), 0); - } else if halfprice { - fee.add("Mitgliedsbeitrag (Halbpreis)".into(), REGULAR / 2); - } else { - fee.add("Mitgliedsbeitrag".into(), REGULAR); - } - } - - fee - } - pub async fn amount_boats(&self, db: &SqlitePool) -> i64 { sqlx::query!( "SELECT COUNT(*) as count FROM boat WHERE owner = ?", @@ -789,6 +602,35 @@ ORDER BY last_access DESC Ok(()) } + async fn send_end_mail_scheckbuch( + &self, + db: &mut Transaction<'_, Sqlite>, + mail: &str, + smtp_pw: &str, + ) -> Result<(), String> { + Mail::send_single_tx( + db, + mail, + "ASKÖ Ruderverein Donau Linz | Deine Mitgliedschaft wartet auf Dich", + format!( +"Hallo {0}, + +herzlichen Glückwunsch---Du hast Deine fünf Scheckbuch-Ausfahrten erfolgreich absolviert! Wir hoffen, dass Du das Rudern bei uns genauso genossen hast wie wir es genossen haben, Dich auf dem Wasser zu begleiten. + +Wir würden uns sehr freuen, Dich als festes Mitglied in unserem Verein willkommen zu heißen! Als Mitglied stehen Dir dann alle unsere Ausfahrten offen, die von unseren Steuerleuten organisiert werden. Im Sommer erwarten Dich zusätzlich spannende Events: Wanderfahrten, Sternfahrten, Fetzenfahrt, .... Im Winter bieten wir Indoor-Ergo-Challenges an, bei denen Du Deine Fitness auf dem Ruderergometer unter Beweis stellen kannst. Alle Details zu diesen Aktionen erfährst Du, sobald Du Teil unseres Vereins bist! :-) + +Alle Informationen zu den Mitgliedsbeiträgen findest Du unter https://rudernlinz.at/unser-verein/gebuhren/ Falls Du Dich entscheidest, unserem Verein beizutreten, fülle bitte unser Beitrittsformular auf https://rudernlinz.at/unser-verein/downloads/ aus und sende es an info@rudernlinz.at. + +Wir freuen uns, Dich bald wieder auf dem Wasser zu sehen. + +Riemen- & Dollenbruch, +ASKÖ Ruderverein Donau Linz", self.name), + smtp_pw, + ).await?; + + Ok(()) + } + pub async fn add_role_tx( &self, db: &mut Transaction<'_, Sqlite>, @@ -1106,6 +948,7 @@ impl<'r> FromRequest<'r> for User { } /// Creates a struct named $name. Allows to be created from a user, if one of the specified $roles are active for the user. +#[macro_export] macro_rules! special_user { ($name:ident, $($role:tt)*) => { #[derive(Debug)] diff --git a/src/model/user/scheckbuch.rs b/src/model/user/scheckbuch.rs new file mode 100644 index 0000000..033b6a3 --- /dev/null +++ b/src/model/user/scheckbuch.rs @@ -0,0 +1,84 @@ +use super::User; +use crate::model::user::LoginError; +use crate::{ + model::{mail::Mail, notification::Notification, role::Role}, + special_user, SCHECKBUCH, +}; +use rocket::async_trait; +use rocket::http::Status; +use rocket::request; +use rocket::request::FromRequest; +use rocket::request::Outcome; +use rocket::Request; +use sqlx::SqlitePool; +use std::ops::Deref; + +special_user!(ScheckbuchUser, +"scheckbuch"); + +impl ScheckbuchUser { + async fn from(user: User, db: &SqlitePool, mail: &str, smtp_pw: &str) -> Result<(), String> { + // TODO: see when/how to invoke this function (explicit `Neue Person hinzufügen` button? + // Button to transition existing users to scheckbuch? Automatically called when + // `scheckbuch` is newly selected as role? + if user.has_role(db, "scheckbuch").await { + return Err("User is already a scheckbuch".into()); + } + + // TODO: do we allow e.g. DonauLinz to scheckbuch? + + let scheckbuch = Role::find_by_name(db, "scheckbuch").await.unwrap(); + user.add_role(db, &scheckbuch).await.unwrap(); + + // TODO: remove all other `membership_type` roles + + let new_user = Self::new(db, user).await.unwrap(); + + new_user + .send_welcome_mail_to_user(db, mail, smtp_pw) + .await?; + new_user.notify_coxes_about_new_scheckbuch(db).await; + + Ok(()) + } + async fn send_welcome_mail_to_user( + &self, + db: &SqlitePool, + mail: &str, + smtp_pw: &str, + ) -> Result<(), String> { + Mail::send_single( + db, + mail, + "ASKÖ Ruderverein Donau Linz | Dein Scheckbuch wartet auf Dich", + format!( +"Hallo {0}, + +herzlich willkommen beim ASKÖ Ruderverein Donau Linz! Wir freuen uns sehr, dass Du Dich entschieden hast, das Rudern bei uns auszuprobieren. Mit Deinem Scheckbuch kannst Du jetzt an fünf Ausfahrten teilnehmen und so diesen Sport in seiner vollen Vielfalt erleben. Falls du die {1} € noch nicht bezahlt hast, nimm diese bitte zur nächsten Ausfahrt mit (oder überweise sie auf unser Bankkonto [dieses findest du auf https://rudernlinz.at]). + +Für die Organisation unserer Ausfahrten nutzen wir app.rudernlinz.at. Logge Dich bitte mit Deinem Namen ('{0}', ohne Anführungszeichen) ein. Beim ersten Mal kannst Du das Passwortfeld leer lassen. Unter 'Geplante Ausfahrten' kannst Du Dich jederzeit für eine Ausfahrt anmelden. Wir bieten mindestens einmal pro Woche Ausfahrten an, sowohl für Anfänger als auch für Fortgeschrittene (A+F Rudern). Zusätzliche Ausfahrten werden von unseren Steuerleuten ausgeschrieben, öfters reinschauen kann sich also lohnen :-) + +Nach deinen 5 Ausfahrten würden wir uns freuen, dich als Mitglied in unserem Verein begrüßen zu dürfen. + +Wir freuen uns darauf, Dich bald am Wasser zu sehen und gemeinsam tolle Erfahrungen zu sammeln! + +Riemen- & Dollenbruch, +ASKÖ Ruderverein Donau Linz", self.name, SCHECKBUCH/100), + smtp_pw, + ).await?; + + Ok(()) + } + + async fn notify_coxes_about_new_scheckbuch(&self, db: &SqlitePool) { + Notification::create_for_steering_people( + db, + &format!( + "Liebe Steuerberechtigte, {} hat nun ein Scheckbuch. Wie immer, freuen wir uns wenn du uns beim A+F Rudern unterstützt oder selber Ausfahrten ausschreibst. Bitte beachte, dass Scheckbuch-Personen nur Ausfahrten sehen, bei denen 'Scheckbuch-Anmeldungen erlauben' ausgewählt wurde.", + self.name + ), + "Neues Scheckbuch", + None,None + ) + .await; + } +} From 7604678d4a59a059c96da0e3e98669094292367f Mon Sep 17 00:00:00 2001 From: Philipp Hofer Date: Tue, 29 Apr 2025 21:00:50 +0200 Subject: [PATCH 2/2] make scheckbuch user behave as previously, but in own file --- src/model/event.rs | 2 +- src/model/notification.rs | 10 +++++----- src/model/trip.rs | 24 ++++++++++++------------ src/model/user/mod.rs | 9 ++++++--- src/model/user/scheckbuch.rs | 17 ++++++++++++----- src/model/usertrip.rs | 4 ++-- src/tera/admin/user.rs | 4 ++-- src/tera/log.rs | 4 ++-- 8 files changed, 42 insertions(+), 32 deletions(-) diff --git a/src/model/event.rs b/src/model/event.rs index 5ef81e4..699f5e7 100644 --- a/src/model/event.rs +++ b/src/model/event.rs @@ -552,7 +552,7 @@ mod test { let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap(); - let admin = EventUser::new(&pool, User::find_by_id(&pool, 1).await.unwrap()) + let admin = EventUser::new(&pool, &User::find_by_id(&pool, 1).await.unwrap()) .await .unwrap(); Event::create(&pool, &admin, "new-event".into(), 2, false, &trip_details).await; diff --git a/src/model/notification.rs b/src/model/notification.rs index 1c74a1a..db51693 100644 --- a/src/model/notification.rs +++ b/src/model/notification.rs @@ -256,7 +256,7 @@ mod test { let trip_details = TripDetails::find_by_id(&pool, tripdetails_id) .await .unwrap(); - let user = EventUser::new(&pool, User::find_by_id(&pool, 1).await.unwrap()) + let user = EventUser::new(&pool, &User::find_by_id(&pool, 1).await.unwrap()) .await .unwrap(); Event::create(&pool, &user, "new-event".into(), 2, false, &trip_details).await; @@ -269,7 +269,7 @@ mod test { UserTrip::create(&pool, &rower, &trip_details, None) .await .unwrap(); - let cox = SteeringUser::new(&pool, User::find_by_name(&pool, "cox").await.unwrap()) + let cox = SteeringUser::new(&pool, &User::find_by_name(&pool, "cox").await.unwrap()) .await .unwrap(); Trip::new_join(&pool, &cox, &event).await.unwrap(); @@ -284,7 +284,7 @@ mod test { is_locked: event.is_locked, trip_type_id: None, }; - event.update(&pool, &cancel_update).await; + event.update(&pool, &user, &cancel_update).await; // Rower received notification let notifications = Notification::for_user(&pool, &rower).await; @@ -314,12 +314,12 @@ mod test { is_locked: event.is_locked, trip_type_id: None, }; - event.update(&pool, &update).await; + event.update(&pool, &user, &update).await; assert!(Notification::for_user(&pool, &rower).await.is_empty()); assert!(Notification::for_user(&pool, &cox.user).await.is_empty()); // Cancel event again - event.update(&pool, &cancel_update).await; + event.update(&pool, &user, &cancel_update).await; // Rower is removed if notification is accepted assert!(event.is_rower_registered(&pool, &rower).await); diff --git a/src/model/trip.rs b/src/model/trip.rs index 98dd878..36c0773 100644 --- a/src/model/trip.rs +++ b/src/model/trip.rs @@ -532,7 +532,7 @@ mod test { let cox = SteeringUser::new( &pool, - User::find_by_name(&pool, "cox".into()).await.unwrap(), + &User::find_by_name(&pool, "cox".into()).await.unwrap(), ) .await .unwrap(); @@ -549,7 +549,7 @@ mod test { let pool = testdb!(); let cox = SteeringUser::new( &pool, - User::find_by_name(&pool, "cox".into()).await.unwrap(), + &User::find_by_name(&pool, "cox".into()).await.unwrap(), ) .await .unwrap(); @@ -558,7 +558,7 @@ mod test { let cox2 = SteeringUser::new( &pool, - User::find_by_name(&pool, "cox2".into()).await.unwrap(), + &User::find_by_name(&pool, "cox2".into()).await.unwrap(), ) .await .unwrap(); @@ -587,7 +587,7 @@ mod test { let cox = SteeringUser::new( &pool, - User::find_by_name(&pool, "cox2".into()).await.unwrap(), + &User::find_by_name(&pool, "cox2".into()).await.unwrap(), ) .await .unwrap(); @@ -603,7 +603,7 @@ mod test { let cox = SteeringUser::new( &pool, - User::find_by_name(&pool, "cox2".into()).await.unwrap(), + &User::find_by_name(&pool, "cox2".into()).await.unwrap(), ) .await .unwrap(); @@ -620,7 +620,7 @@ mod test { let cox = SteeringUser::new( &pool, - User::find_by_name(&pool, "cox".into()).await.unwrap(), + &User::find_by_name(&pool, "cox".into()).await.unwrap(), ) .await .unwrap(); @@ -648,7 +648,7 @@ mod test { let cox = SteeringUser::new( &pool, - User::find_by_name(&pool, "cox".into()).await.unwrap(), + &User::find_by_name(&pool, "cox".into()).await.unwrap(), ) .await .unwrap(); @@ -676,7 +676,7 @@ mod test { let cox = SteeringUser::new( &pool, - User::find_by_name(&pool, "cox2".into()).await.unwrap(), + &User::find_by_name(&pool, "cox2".into()).await.unwrap(), ) .await .unwrap(); @@ -701,7 +701,7 @@ mod test { let cox = SteeringUser::new( &pool, - User::find_by_name(&pool, "cox".into()).await.unwrap(), + &User::find_by_name(&pool, "cox".into()).await.unwrap(), ) .await .unwrap(); @@ -724,7 +724,7 @@ mod test { let cox = SteeringUser::new( &pool, - User::find_by_name(&pool, "cox".into()).await.unwrap(), + &User::find_by_name(&pool, "cox".into()).await.unwrap(), ) .await .unwrap(); @@ -742,7 +742,7 @@ mod test { let cox = SteeringUser::new( &pool, - User::find_by_name(&pool, "cox2".into()).await.unwrap(), + &User::find_by_name(&pool, "cox2".into()).await.unwrap(), ) .await .unwrap(); @@ -764,7 +764,7 @@ mod test { let cox = SteeringUser::new( &pool, - User::find_by_name(&pool, "cox".into()).await.unwrap(), + &User::find_by_name(&pool, "cox".into()).await.unwrap(), ) .await .unwrap(); diff --git a/src/model/user/mod.rs b/src/model/user/mod.rs index 228f82e..707143f 100644 --- a/src/model/user/mod.rs +++ b/src/model/user/mod.rs @@ -27,6 +27,7 @@ use super::{ Day, }; use crate::{tera::admin::user::UserEditForm, AMOUNT_DAYS_TO_SHOW_TRIPS_AHEAD}; +use scheckbuch::ScheckbuchUser; mod fee; mod scheckbuch; @@ -112,6 +113,8 @@ impl User { .await?; } else if self.has_role(db, "schnupperant").await { self.send_welcome_mail_schnupper(db, mail, smtp_pw).await?; + } else if let Some(scheckbuch) = ScheckbuchUser::new(db, &self).await { + scheckbuch.notify(db, mail, smtp_pw).await?; } else { return Err(format!( "Could not send welcome mail, because user {} is not in Donau Linz or scheckbuch or schnupperant group", @@ -259,7 +262,7 @@ ASKÖ Ruderverein Donau Linz", self.name), } pub async fn allowed_to_update_always_show_trip(&self, db: &SqlitePool) -> bool { - AllowedToUpdateTripToAlwaysBeShownUser::new(db, self.clone()) + AllowedToUpdateTripToAlwaysBeShownUser::new(db, &self) .await .is_some() } @@ -989,9 +992,9 @@ macro_rules! special_user { } impl $name { - pub async fn new(db: &SqlitePool, user: User) -> Option { + pub async fn new(db: &SqlitePool, user: &User) -> Option { if special_user!(@check_roles user, db, $($role)*) { - Some($name { user }) + Some($name { user: user.clone() }) } else { None } diff --git a/src/model/user/scheckbuch.rs b/src/model/user/scheckbuch.rs index 033b6a3..3fc04fe 100644 --- a/src/model/user/scheckbuch.rs +++ b/src/model/user/scheckbuch.rs @@ -30,16 +30,23 @@ impl ScheckbuchUser { user.add_role(db, &scheckbuch).await.unwrap(); // TODO: remove all other `membership_type` roles + let new_user = Self::new(db, &user).await.unwrap(); - let new_user = Self::new(db, user).await.unwrap(); + new_user.notify(db, mail, smtp_pw).await + } - new_user - .send_welcome_mail_to_user(db, mail, smtp_pw) - .await?; - new_user.notify_coxes_about_new_scheckbuch(db).await; + pub(crate) async fn notify( + &self, + db: &SqlitePool, + mail: &str, + smtp_pw: &str, + ) -> Result<(), String> { + self.send_welcome_mail_to_user(db, mail, smtp_pw).await?; + self.notify_coxes_about_new_scheckbuch(db).await; Ok(()) } + async fn send_welcome_mail_to_user( &self, db: &SqlitePool, diff --git a/src/model/usertrip.rs b/src/model/usertrip.rs index 9f14ba6..c58f078 100644 --- a/src/model/usertrip.rs +++ b/src/model/usertrip.rs @@ -197,7 +197,7 @@ impl UserTrip { let mut add_info = ""; if let Some(trip) = &trip_to_delete { let cox = User::find_by_id(db, trip.cox_id as i32).await.unwrap(); - trip.delete(db, &SteeringUser::new(db, cox).await.unwrap()) + trip.delete(db, &SteeringUser::new(db, &cox).await.unwrap()) .await .unwrap(); add_info = " Das war die letzte angemeldete Person. Nachdem nun alle Bescheid wissen, wird die Ausfahrt ab sofort nicht mehr angezeigt."; @@ -355,7 +355,7 @@ mod test { let cox = SteeringUser::new( &pool, - User::find_by_name(&pool, "cox".into()).await.unwrap(), + &User::find_by_name(&pool, "cox".into()).await.unwrap(), ) .await .unwrap(); diff --git a/src/tera/admin/user.rs b/src/tera/admin/user.rs index 192560b..fe4e607 100644 --- a/src/tera/admin/user.rs +++ b/src/tera/admin/user.rs @@ -60,7 +60,7 @@ async fn index( .collect(); let user: User = user.into_inner(); - let allowed_to_edit = ManageUserUser::new(db, user.clone()).await.is_some(); + let allowed_to_edit = ManageUserUser::new(db, &user).await.is_some(); let users: Vec = join_all(user_futures).await; @@ -94,7 +94,7 @@ async fn index_admin( let users: Vec = join_all(user_futures).await; let user: User = user.user; - let allowed_to_edit = ManageUserUser::new(db, user.clone()).await.is_some(); + let allowed_to_edit = ManageUserUser::new(db, &user).await.is_some(); let roles = Role::all(db).await; let families = Family::all_with_members(db).await; diff --git a/src/tera/log.rs b/src/tera/log.rs index 6269819..1f33e3a 100644 --- a/src/tera/log.rs +++ b/src/tera/log.rs @@ -296,7 +296,7 @@ async fn create_kiosk( create_logbook( db, data, - &DonauLinzUser::new(db, creator).await.unwrap(), + &DonauLinzUser::new(db, &creator).await.unwrap(), &config.smtp_pw, ) .await @@ -390,7 +390,7 @@ async fn home_kiosk( logbook_id, &DonauLinzUser::new( db, - User::find_by_id(db, logbook.shipmaster as i32) + &User::find_by_id(db, logbook.shipmaster as i32) .await .unwrap(), )