diff --git a/src/model/activity.rs b/src/model/activity.rs index 33e0939..a6676d6 100644 --- a/src/model/activity.rs +++ b/src/model/activity.rs @@ -14,6 +14,37 @@ pub struct Activity { pub keep_until: Option, } +pub struct ActivityBuilder { + text: String, + relevant_for: String, + keep_until: Option, +} + +impl ActivityBuilder { + pub fn new(text: &str) -> Self { + Self { + text: text.into(), + relevant_for: String::new(), + keep_until: None, + } + } + + pub fn relevant_for_user(self, user: &User) -> Self { + Self { + relevant_for: format!("{}user-{};", self.relevant_for, user.id), + ..self + } + } + + pub async fn save(self, db: &SqlitePool) { + Activity::create(db, &self.text, &self.relevant_for, self.keep_until).await; + } + + pub async fn save_tx(self, db: &mut Transaction<'_, Sqlite>) { + Activity::create_with_tx(db, &self.text, &self.relevant_for, self.keep_until).await; + } +} + impl Activity { pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option { sqlx::query_as!( @@ -25,7 +56,7 @@ impl Activity { .await .ok() } - pub async fn create_with_tx( + pub(super) async fn create_with_tx( db: &mut Transaction<'_, Sqlite>, text: &str, relevant_for: &str, @@ -42,7 +73,7 @@ impl Activity { .unwrap(); } - pub async fn create( + pub(super) async fn create( db: &SqlitePool, text: &str, relevant_for: &str, diff --git a/src/model/mail.rs b/src/model/mail.rs index 746889f..bbb6253 100644 --- a/src/model/mail.rs +++ b/src/model/mail.rs @@ -9,7 +9,7 @@ use sqlx::{Sqlite, SqlitePool, Transaction}; use crate::tera::admin::mail::MailToSend; -use super::{family::Family, log::Log, role::Role, user::User}; +use super::{activity::ActivityBuilder, family::Family, log::Log, role::Role, user::User}; pub struct Mail {} @@ -253,6 +253,12 @@ Der Vorstand"); // Send the email mailer.send(&email).unwrap(); + ActivityBuilder::new(&format!( + "{user} hat die Info-Mail bzgl. Gebühren gesendet bekommen." + )) + .relevant_for_user(&user) + .save(db) + .await; } } } @@ -369,6 +375,12 @@ Der Vorstand"); // Send the email mailer.send(&email).unwrap(); + ActivityBuilder::new(&format!( + "{user} hat die Mahn-Mail bzgl. Gebühren gesendet bekommen." + )) + .relevant_for_user(&user) + .save(db) + .await; } } } diff --git a/src/model/user/basic.rs b/src/model/user/basic.rs index ea3bf10..1dd4bcc 100644 --- a/src/model/user/basic.rs +++ b/src/model/user/basic.rs @@ -2,7 +2,7 @@ use super::{AllowedToEditPaymentStatusUser, ManageUserUser, User}; use crate::model::{ - activity::Activity, family::Family, log::Log, mail::valid_mails, notification::Notification, + activity::ActivityBuilder, family::Family, mail::valid_mails, notification::Notification, role::Role, }; use chrono::NaiveDate; @@ -19,13 +19,10 @@ impl User { ) -> Result<(), String> { let note = note.trim(); - Activity::create( - db, - &format!("({updated_by}) {note}"), - &format!("user-{};", user.id), - None, - ) - .await; + ActivityBuilder::new(&format!("({updated_by}) {note}")) + .relevant_for_user(&user) + .save(db) + .await; Ok(()) } @@ -50,12 +47,18 @@ impl User { .unwrap(); //Okay, because we can only create a User of a valid id let msg = match &self.mail { - Some(old_mail) => format!( - "{updated_by} has changed the mail address of {self} from {old_mail} to {new_mail}" - ), - None => format!("{updated_by} has added a mail address for {self}: {new_mail}"), + Some(old_mail) => { + format!("{updated_by} hat die Mail-Adresse von {self} von {old_mail} auf {new_mail} geändert.") + } + None => { + format!("{updated_by} eine neue Mail-Adresse für {self} hinzugefügt: {new_mail}") + } }; - Log::create(db, msg).await; + + ActivityBuilder::new(&msg) + .relevant_for_user(self) + .save(db) + .await; Ok(()) } @@ -84,11 +87,15 @@ impl User { query.execute(db).await.unwrap(); //Okay, because we can only create a User of a valid id let msg = match &self.phone { - Some(old_phone) if new_phone.is_empty() => format!("{updated_by} has removed the phone number of {self} (old number: {old_phone})"), - Some(old_phone) => format!("{updated_by} has changed the phone number of {self} from {old_phone} to {new_phone}"), - None => format!("{updated_by} has added a phone number for {self}: {new_phone}") + Some(old_phone) if new_phone.is_empty() => format!("{updated_by} hat die Telefonnummer von {self} entfernt (alte Nummer: {old_phone})"), + Some(old_phone) => format!("{updated_by} hat die Telefonnummer von {self} von {old_phone} auf {new_phone} geändert."), + None => format!("{updated_by} hat eine neue Telefonnummer für {self} hinzugefügt: {new_phone}") }; - Log::create(db, msg).await; + + ActivityBuilder::new(&msg) + .relevant_for_user(self) + .save(db) + .await; } pub(crate) async fn update_address( @@ -119,11 +126,15 @@ impl User { query.execute(db).await.unwrap(); //Okay, because we can only create a User of a valid id let msg = match &self.address { - Some(old_address) if new_address.is_empty() => format!("{updated_by} has removed the address of {self} (old address: {old_address})"), - Some(old_address) => format!("{updated_by} has changed the address of {self} from {old_address} to {new_address}"), - None => format!("{updated_by} has added an address for {self}: {new_address}") + Some(old_address) if new_address.is_empty() => format!("{updated_by} hat die Adresse von {self} entfernt (alte Adresse: {old_address})"), + Some(old_address) => format!("{updated_by} hat die Adresse von {self} von {old_address} auf {new_address} geändert."), + None => format!("{updated_by} hat eine Adresse für {self} hinzugefügt: {new_address}") }; - Log::create(db, msg).await; + + ActivityBuilder::new(&msg) + .relevant_for_user(self) + .save(db) + .await; } pub(crate) async fn update_nickname( @@ -146,11 +157,14 @@ impl User { query.execute(db).await.unwrap(); //Okay, because we can only create a User of a valid id let msg = match &self.nickname { - Some(old_nickname) if new_nickname.is_empty() => format!("{updated_by} has removed the nickname of {self} (old nickname: {old_nickname})"), - Some(old_nickname) => format!("{updated_by} has changed the nickname of {self} from {old_nickname} to {new_nickname}"), - None => format!("{updated_by} has added a nickname for {self}: {new_nickname}") + Some(old_nickname) if new_nickname.is_empty() => format!("{updated_by} hat den Sitznamen von {self} entfernt (alter Spitzname: {old_nickname})"), + Some(old_nickname) => format!("{updated_by} hat den Spitznamen von {self} von {old_nickname} auf {new_nickname} geändert."), + None => format!("{updated_by} hat einen neuen Spitznamen für {self} hinzugefügt: {new_nickname}") }; - Log::create(db, msg).await; + ActivityBuilder::new(&msg) + .relevant_for_user(self) + .save(db) + .await; Ok(()) } @@ -171,10 +185,14 @@ impl User { .unwrap(); //Okay, because we can only create a User of a valid id let msg = match &self.member_since_date { - Some(old_member_since_date) => format!("{updated_by} has changed the member_since date of {self} from {old_member_since_date} to {new_member_since_date}"), - None => format!("{updated_by} has added a member_since_date for {self}: {new_member_since_date}") + Some(old_member_since_date) => format!("{updated_by} hat das Beitrittsdatum von {self} von {old_member_since_date} auf {new_member_since_date} geändert."), + None => format!("{updated_by} hat ein neues Beitrittsdatum für {self} hinzugefügt: {new_member_since_date}") }; - Log::create(db, msg).await; + + ActivityBuilder::new(&msg) + .relevant_for_user(self) + .save(db) + .await; } pub(crate) async fn update_birthdate( @@ -193,10 +211,14 @@ impl User { .unwrap(); //Okay, because we can only create a User of a valid id let msg = match &self.birthdate{ - Some(old_birthdate) => format!("{updated_by} has changed the birthdate of {self} from {old_birthdate} to {new_birthdate}"), - None => format!("{updated_by} has added a birthdate for {self}: {new_birthdate}") + Some(old_birthdate) => format!("{updated_by} hat das Geburtsdatum von {self} von {old_birthdate} auf {new_birthdate} geändert."), + None => format!("{updated_by} hat ein Geburtsdatum für {self} hinzugefügt: {new_birthdate}") }; - Log::create(db, msg).await; + + ActivityBuilder::new(&msg) + .relevant_for_user(self) + .save(db) + .await; } pub(crate) async fn update_family( @@ -215,20 +237,26 @@ impl User { .execute(db) .await .unwrap(); + ActivityBuilder::new(&format!( + "{updated_by} hat {self} zu einer Familie hinzugefügt." + )) + .relevant_for_user(self) + .save(db) + .await; } else { sqlx::query!("UPDATE user SET family_id = NULL where id = ?", self.id) .execute(db) .await .unwrap(); + ActivityBuilder::new(&format!( + "{updated_by} hat die Familienzugehörigkeit von {self} gelöscht." + )) + .relevant_for_user(self) + .save(db) + .await; }; Family::clean_families_without_members(db).await; - - Log::create( - db, - format!("{updated_by} hat die Familie von {self} aktualisiert."), - ) - .await; } pub(crate) async fn change_skill( @@ -257,6 +285,10 @@ impl User { None, ) .await; + ActivityBuilder::new(&format!("{updated_by} hat {self} zur Steuerperson gemacht")) + .relevant_for_user(self) + .save(db) + .await; } (old, new) if old == Some(cox.clone()) && new == Some(bootsfuehrer.clone()) => { self.remove_role(db, updated_by, &cox).await?; @@ -272,6 +304,10 @@ impl User { None, ) .await; + ActivityBuilder::new(&format!("{updated_by} hat {self} zum Bootsführer gemacht")) + .relevant_for_user(self) + .save(db) + .await; } (old, new) if new == None => { if let Some(old) = old { @@ -286,6 +322,10 @@ impl User { None, ) .await; + ActivityBuilder::new(&format!("{updated_by} hat {self} zum normalen Mitlgied gemacht (keine Steuerperson/Schiffsführer mehr)")) + .relevant_for_user(self) + .save(db) + .await; } } (old, new) => return Err(format!("Not allowed to change from {old:?} to {new:?}")), @@ -317,12 +357,11 @@ impl User { new.push_str("Keine Ermäßigung"); } - Activity::create( - db, - &format!("({updated_by}) Ermäßigung von {self} von {old} auf {new} geändert"), - &format!("user-{};", self.id), - None, - ) + ActivityBuilder::new(&format!( + "{updated_by} hat die Ermäßigung von {self} von {old} auf {new} geändert" + )) + .relevant_for_user(&self) + .save(db) .await; Ok(()) @@ -347,10 +386,11 @@ impl User { .await .unwrap(); - Log::create( - db, - format!("{updated_by} has removed role {role} from user {self}"), - ) + ActivityBuilder::new(&format!( + "{updated_by} hat die Rolle {role} von {self} entfernt." + )) + .relevant_for_user(&self) + .save(db) .await; Ok(()) @@ -372,10 +412,11 @@ impl User { .await .unwrap(); - Log::create( - db, - format!("{updated_by} has set that user {self} has NOT paid the fee (yet)"), - ) + ActivityBuilder::new(&format!( + "{updated_by} hat den Bezahlstatus von {self} auf 'nicht bezahlt' gesetzt." + )) + .relevant_for_user(&self) + .save(db) .await; } pub(crate) async fn has_paid( @@ -394,10 +435,11 @@ impl User { .await .expect("paid role has no group"); - Log::create( - db, - format!("{updated_by} has set that user {self} has paid the fee (yet)"), - ) + ActivityBuilder::new(&format!( + "{updated_by} hat den Bezahlstatus von {self} auf 'bezahlt' gesetzt." + )) + .relevant_for_user(&self) + .save(db) .await; } @@ -427,10 +469,11 @@ impl User { ) })?; - Log::create( - db, - format!("{updated_by} has added role {role} to user {self}"), - ) + ActivityBuilder::new(&format!( + "{updated_by} hat die Rolle '{role}' dem Benutzer {self} hinzugefügt." + )) + .relevant_for_user(&self) + .save(db) .await; Ok(()) @@ -461,10 +504,11 @@ impl User { .await .unwrap(); //Okay, because we can only create a User of a valid id - Log::create( - db, - format!("{updated_by} has added the membership pdf for user {self}"), - ) + ActivityBuilder::new(&format!( + "{updated_by} hat die Mitgliedserklärung (PDF) für user {self} hinzugefügt." + )) + .relevant_for_user(&self) + .save(db) .await; Ok(()) diff --git a/src/model/user/clubmember.rs b/src/model/user/clubmember.rs index 4219754..6d54c91 100644 --- a/src/model/user/clubmember.rs +++ b/src/model/user/clubmember.rs @@ -1,6 +1,8 @@ use super::User; use crate::{ - model::{log::Log, notification::Notification, role::Role, user::ManageUserUser}, + model::{ + activity::ActivityBuilder, notification::Notification, role::Role, user::ManageUserUser, + }, special_user, }; use rocket::async_trait; @@ -81,10 +83,11 @@ impl ClubMemberUser { ) .await; - Log::create( - db, - format!("{modified_by} has moved user {self} to regular membership."), - ) + ActivityBuilder::new(&format!( + "{modified_by} hat den User {self} zu einem regulären hochgestuft." + )) + .relevant_for_user(&self) + .save(db) .await; Ok(()) @@ -116,10 +119,11 @@ impl ClubMemberUser { .await; } - Log::create( - db, - format!("{modified_by} has moved user {self} to unterstützend membership."), - ) + ActivityBuilder::new(&format!( + "{modified_by} hat den User {self} zu einem unterstützenden Mitglied gemacht." + )) + .relevant_for_user(&self) + .save(db) .await; Ok(()) @@ -151,10 +155,11 @@ impl ClubMemberUser { .await; } - Log::create( - db, - format!("{modified_by} has moved user {self} to fördernd membership."), - ) + ActivityBuilder::new(&format!( + "{modified_by} hat den User {self} zu ein förderndes Mitglied gemacht." + )) + .relevant_for_user(&self) + .save(db) .await; Ok(()) diff --git a/src/model/user/foerdernd.rs b/src/model/user/foerdernd.rs index 215fbf6..6c257c5 100644 --- a/src/model/user/foerdernd.rs +++ b/src/model/user/foerdernd.rs @@ -1,5 +1,8 @@ use super::User; -use crate::{model::mail::Mail, special_user}; +use crate::{ + model::{activity::ActivityBuilder, mail::Mail}, + special_user, +}; use rocket::async_trait; use sqlx::SqlitePool; @@ -35,6 +38,13 @@ ASKÖ Ruderverein Donau Linz", self.name), smtp_pw, ).await?; + ActivityBuilder::new(&format!( + "User {self} hat die Info-Mail bzgl. neues förderndes Mitglied (Handbuch und WLAN Infos) an {mail} gesendet bekommen" + )) + .relevant_for_user(&self) + .save(db) + .await; + Ok(()) } } diff --git a/src/model/user/mod.rs b/src/model/user/mod.rs index 80b1af2..8d5f54d 100644 --- a/src/model/user/mod.rs +++ b/src/model/user/mod.rs @@ -13,6 +13,7 @@ use rocket::{ use serde::{Deserialize, Serialize}; use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; +use super::activity::ActivityBuilder; use super::{ log::Log, logbook::Logbook, @@ -112,74 +113,6 @@ impl User { self.has_role_tx(db, "cox").await || self.has_role_tx(db, "Bootsführer").await } - pub async fn send_welcome_email(&self, db: &SqlitePool, smtp_pw: &str) -> Result<(), String> { - let Some(mail) = &self.mail else { - return Err(format!( - "Could not send welcome mail, because user {} has no email address", - self.name - )); - }; - - 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, smtp_pw).await?; - } else { - return Err(format!( - "Could not send welcome mail, because user {} is not in Donau Linz or scheckbuch or schnupperant group", - self.name - )); - } - - Log::create( - db, - format!("Willkommensemail wurde an {} versandt", self.name), - ) - .await; - - Ok(()) - } - - async fn send_welcome_mail_schnupper( - &self, - db: &SqlitePool, - mail: &str, - smtp_pw: &str, - ) -> Result<(), String> { - // 2 things to do: - // 1. Send mail to user - Mail::send_single( - db, - mail, - "Schnupperrudern beim ASKÖ Ruderverein Donau Linz", - format!( -"Hallo {0}, - -es freut uns sehr, dich bei unserem Schnupperkurs willkommen heißen zu dürfen. Detaillierte Informationen folgen noch, ich werde sie dir ein paar Tage vor dem Termin zusenden. - -Riemen- & Dollenbruch, -ASKÖ Ruderverein Donau Linz", self.name), - smtp_pw, - ).await?; - - // 2. Notify all coxes - let coxes = Role::find_by_name(db, "schnupper-betreuer").await.unwrap(); - Notification::create_for_role( - db, - &coxes, - &format!( - "Liebe Schnupper-Betreuer, {} nimmt am Schnupperkurs teil.", - self.name - ), - "Neue(r) Schnupperteilnehmer:in ", - None, - None, - ) - .await; - - Ok(()) - } - pub async fn amount_boats(&self, db: &SqlitePool) -> i64 { sqlx::query!( "SELECT COUNT(*) as count FROM boat WHERE owner = ?", @@ -275,6 +208,7 @@ AND r.cluster = 'financial'; .await .unwrap() } + pub async fn skill(&self, db: &SqlitePool) -> Option { sqlx::query_as!( Role, @@ -485,22 +419,6 @@ ORDER BY last_access DESC .unwrap() } - pub async fn create(db: &SqlitePool, name: &str) -> bool { - let name = name.trim(); - sqlx::query!("INSERT INTO USER(name) VALUES (?)", name) - .execute(db) - .await - .is_ok() - } - - pub async fn create_with_mail(db: &SqlitePool, name: &str, mail: &str) -> bool { - let name = name.trim(); - sqlx::query!("INSERT INTO USER(name, mail) VALUES (?, ?)", name, mail) - .execute(db) - .await - .is_ok() - } - pub async fn update_ergo(&self, db: &SqlitePool, dob: i32, weight: i64, sex: &str) { sqlx::query!( "UPDATE user SET dob = ?, weight = ?, sex = ? where id = ?", @@ -540,29 +458,7 @@ ASKÖ Ruderverein Donau Linz", self.name), smtp_pw, ).await?; - Ok(()) - } - - pub async fn add_role_tx( - &self, - db: &mut Transaction<'_, Sqlite>, - role: &Role, - ) -> Result<(), String> { - sqlx::query!( - "INSERT INTO user_role(user_id, role_id) VALUES (?, ?)", - self.id, - role.id - ) - .execute(db.deref_mut()) - .await - .map_err(|_| { - format!( - "User already has a role in the cluster '{}'", - role.cluster - .clone() - .expect("db trigger can't activate on empty string") - ) - })?; + ActivityBuilder::new(&format!("User {self} hat eine Mail bekommen, dass seine 5 Ausfahrten mit der heutigen Ausfahrt aufgebraucht sind, und dass der nächste Schritt eine Vereinsmitgliedschaft wäre (inkl. Links zu Beitrittserklärung + Info, dass sie an info@ geschickt werden soll.")).relevant_for_user(&self).save_tx(db).await; Ok(()) } @@ -609,10 +505,11 @@ ASKÖ Ruderverein Donau Linz", self.name), }; if user.deleted { - Log::create( - db, - format!("User ({name}) already deleted (tried to login)."), - ) + ActivityBuilder::new(&format!( + "User {user} wollte sich einloggen, klappte jedoch nicht weil er gelöscht wurde." + )) + .relevant_for_user(&user) + .save(db) .await; return Err(LoginError::InvalidAuthenticationCombo); //User existed sometime ago; has //been deleted @@ -623,7 +520,12 @@ ASKÖ Ruderverein Donau Linz", self.name), if password_hash == user_pw { return Ok(user); } - Log::create(db, format!("User {name} supplied the wrong PW")).await; + ActivityBuilder::new(&format!( + "User {user} wollte sich einloggen, hat jedoch das falsche Passwort angegeben." + )) + .relevant_for_user(&user) + .save(db) + .await; Err(LoginError::InvalidAuthenticationCombo) } else { info!("User {name} has no PW set"); @@ -636,6 +538,12 @@ ASKÖ Ruderverein Donau Linz", self.name), .execute(db) .await .unwrap(); //Okay, because we can only create a User of a valid id + + // TODO: add responsible person + ActivityBuilder::new(&format!("Passwort von User {self} wurde zurückgesetzt.")) + .relevant_for_user(&self) + .save(db) + .await; } pub async fn update_pw(&self, db: &SqlitePool, pw: &str) { @@ -644,6 +552,12 @@ ASKÖ Ruderverein Donau Linz", self.name), .execute(db) .await .unwrap(); //Okay, because we can only create a User of a valid id + ActivityBuilder::new(&format!( + "Passwort von User {self} wurde erfolgreich geändert." + )) + .relevant_for_user(&self) + .save(db) + .await; } fn get_hashed_pw(pw: &str) -> String { @@ -663,6 +577,10 @@ ASKÖ Ruderverein Donau Linz", self.name), .execute(db) .await .unwrap(); //Okay, because we can only create a User of a valid id + ActivityBuilder::new(&format!("User {self} hat sich eingeloggt.")) + .relevant_for_user(&self) + .save(db) + .await; } pub async fn delete(&self, db: &SqlitePool) { @@ -670,6 +588,10 @@ ASKÖ Ruderverein Donau Linz", self.name), .execute(db) .await .unwrap(); //Okay, because we can only create a User of a valid id + ActivityBuilder::new(&format!("User {self} wurde gelöscht.")) + .relevant_for_user(&self) + .save(db) + .await; } pub async fn get_days(&self, db: &SqlitePool) -> Vec { @@ -761,6 +683,10 @@ ASKÖ Ruderverein Donau Linz", self.name), None,None ) .await; + ActivityBuilder::new(&format!("5 Scheckbuchausfahrten von {self} wurden mit der heutigen Ausfahrt aufgebraucht. Info-Mail wurde an {self} geschickt + alle Steuerberechtigten informiert, dass wir pot. ein neues Mitglied haben")) + .relevant_for_user(&self) + .save_tx(db) + .await; } a if a > 5 => { let board = Role::find_by_name_tx(db, "Vorstand").await.unwrap(); @@ -775,6 +701,10 @@ ASKÖ Ruderverein Donau Linz", self.name), None,None ) .await; + ActivityBuilder::new(&format!("{self} hat nun bereits die {amount_trips}. seiner 5 Scheckbuchausfahrten absolviert. Vorstand wurde via Notification informiert.")) + .relevant_for_user(&self) + .save_tx(db) + .await; } _ => {} } @@ -794,6 +724,12 @@ ASKÖ Ruderverein Donau Linz", self.name), None,None ) .await; + ActivityBuilder::new(&format!( + "{self} hat das heurige Fahrtenabzeichen geschafft! Der Vorstand + {self} wurde via Notification informiert." + )) + .relevant_for_user(&self) + .save_tx(db) + .await; Notification::create_with_tx(db, self, "Mit deiner letzten Ausfahrt hast du nun alle Anforderungen für das heurige Fahrtenzeichen erfüllt. Gratuliere! 🎉", "Fahrtenabzeichen geschafft", None, None).await; } @@ -812,6 +748,10 @@ ASKÖ Ruderverein Donau Linz", self.name), None,None ) .await; + ActivityBuilder::new(&format!("{self} hat den Äquatorpreis in {level} geschafft! Der Vorstand + {self} wurde via Notification informiert.")) + .relevant_for_user(&self) + .save_tx(db) + .await; Notification::create_with_tx(db, self, &format!("Mit deiner letzten Ausfahrt erfüllst du nun alle Anforderungen für den Äquatorpreis in {level}. Gratuliere! 🎉"), "Äquatorpreis", None, None).await; } @@ -1031,20 +971,6 @@ mod test { assert_eq!(res.len(), 4); } - #[sqlx::test] - fn test_succ_create() { - let pool = testdb!(); - - assert_eq!(User::create(&pool, "new-user-name".into()).await, true); - } - - #[sqlx::test] - fn test_duplicate_name_create() { - let pool = testdb!(); - - assert_eq!(User::create(&pool, "admin".into()).await, false); - } - #[sqlx::test] fn succ_login_with_test_db() { let pool = testdb!(); diff --git a/src/model/user/regular.rs b/src/model/user/regular.rs index cd7fdce..2611434 100644 --- a/src/model/user/regular.rs +++ b/src/model/user/regular.rs @@ -1,5 +1,8 @@ use super::User; -use crate::{model::mail::Mail, special_user}; +use crate::{ + model::{activity::ActivityBuilder, mail::Mail}, + special_user, +}; use rocket::async_trait; use sqlx::SqlitePool; @@ -43,6 +46,11 @@ ASKÖ Ruderverein Donau Linz", self.name), smtp_pw, ).await?; + ActivityBuilder::new(&format!("Willkommensmail für {self} wurde an {mail} verschickt (Handbuch, Signal-Gruppe, App-Info, Fingerprint, WLAN).")) + .relevant_for_user(&self) + .save(db) + .await; + Ok(()) } } diff --git a/src/model/user/scheckbuch.rs b/src/model/user/scheckbuch.rs index cc038ec..5006383 100644 --- a/src/model/user/scheckbuch.rs +++ b/src/model/user/scheckbuch.rs @@ -2,6 +2,7 @@ use super::foerdernd::FoerderndUser; use super::regular::RegularUser; use super::unterstuetzend::UnterstuetzendUser; use super::{ManageUserUser, User}; +use crate::model::activity::ActivityBuilder; use crate::model::role::Role; use crate::NonEmptyString; use crate::{ @@ -83,6 +84,13 @@ impl ScheckbuchUser { ) .await; + ActivityBuilder::new(&format!( + "{changed_by} hat den Scheckbuch-User {self} auf ein reguläres Mitglied upgegraded!" + )) + .relevant_for_user(&self) + .save(db) + .await; + Ok(()) } @@ -134,6 +142,10 @@ impl ScheckbuchUser { ) .await; } + ActivityBuilder::new(&format!("{changed_by} hat den Scheckbuch-User {self} auf ein unterstützendes Mitglied upgegraded!")) + .relevant_for_user(&self) + .save(db) + .await; Ok(()) } @@ -184,6 +196,12 @@ impl ScheckbuchUser { ) .await; } + ActivityBuilder::new(&format!( + "{changed_by} hat den Scheckbuch-User {self} auf ein förderndes Mitglied upgegraded!" + )) + .relevant_for_user(&self) + .save(db) + .await; Ok(()) } @@ -193,6 +211,13 @@ impl ScheckbuchUser { self.notify_coxes_about_new_scheckbuch(db).await; self.send_welcome_mail_to_user(db, smtp_pw).await?; + ActivityBuilder::new(&format!( + "{self} hat eine Info-Mail bekommen (Erklärung Scheckbuch, Ruderapp) und alle Steuerberechtigten wurden informiert." + )) + .relevant_for_user(&self) + .save(db) + .await; + Ok(()) } diff --git a/src/model/user/schnupperant.rs b/src/model/user/schnupperant.rs index 6ff87b1..f486a66 100644 --- a/src/model/user/schnupperant.rs +++ b/src/model/user/schnupperant.rs @@ -1,8 +1,10 @@ use super::foerdernd::FoerderndUser; use super::regular::RegularUser; use super::scheckbuch::ScheckbuchUser; +use super::schnupperinterest::SchnupperInterestUser; use super::unterstuetzend::UnterstuetzendUser; use super::{ManageUserUser, User}; +use crate::model::activity::ActivityBuilder; use crate::model::role::Role; use crate::NonEmptyString; use crate::{ @@ -84,6 +86,13 @@ impl SchnupperantUser { ) .await; + ActivityBuilder::new(&format!( + "{changed_by} hat den Schnupperant {self} auf ein reguläres Mitglied upgegraded!" + )) + .relevant_for_user(&self) + .save(db) + .await; + Ok(()) } @@ -105,7 +114,7 @@ impl SchnupperantUser { } let scheckbook = ScheckbuchUser::new(db, &self.user).await.unwrap(); - scheckbook.send_welcome_mail_to_user(db, smtp_pw).await?; + scheckbook.notify(db, smtp_pw).await?; Notification::create_for_steering_people( db, @@ -118,6 +127,13 @@ impl SchnupperantUser { ) .await; + ActivityBuilder::new(&format!( + "{changed_by} hat dem ehemaligen Schnupperant {self} nun ein Scheckbuch gegeben" + )) + .relevant_for_user(&self) + .save(db) + .await; + Ok(()) } @@ -135,6 +151,9 @@ impl SchnupperantUser { .add_role(db, changed_by, &schnupperinterest) .await?; + let schnupperinterest = SchnupperInterestUser::new(db, &self.user).await.unwrap(); + schnupperinterest.notify(db).await?; + if let Some(role) = Role::find_by_name(db, "schnupper-betreuer").await { Notification::create_for_role( db, @@ -150,6 +169,13 @@ impl SchnupperantUser { .await; } + ActivityBuilder::new(&format!( + "{changed_by} hat dem eigentlichen Schnupperanten {self} wieder auf die 'Interessierten'-Liste zurückgegeben." + )) + .relevant_for_user(&self) + .save(db) + .await; + Ok(()) } @@ -207,6 +233,13 @@ impl SchnupperantUser { .await; } + ActivityBuilder::new(&format!( + "{changed_by} hat den Schnupperant {self} auf ein unterstützendes Mitglied upgegraded!" + )) + .relevant_for_user(&self) + .save(db) + .await; + Ok(()) } @@ -262,6 +295,13 @@ impl SchnupperantUser { .await; } + ActivityBuilder::new(&format!( + "{changed_by} hat den Schnupperant {self} auf ein förderndes Mitglied upgegraded!" + )) + .relevant_for_user(&self) + .save(db) + .await; + Ok(()) } @@ -270,6 +310,13 @@ impl SchnupperantUser { self.notify_coxes_about_new_scheckbuch(db).await; self.send_welcome_mail_to_user(db, smtp_pw).await?; + ActivityBuilder::new(&format!( + "{self} hat eine Mail bekommen (Inhalt: wir freuen uns auf ihn + senden detailliertere Infos später zu) und die Schnupperbetreuer wurden via Notification informiert." + )) + .relevant_for_user(&self) + .save(db) + .await; + Ok(()) } diff --git a/src/model/user/schnupperinterest.rs b/src/model/user/schnupperinterest.rs index 3fb07d1..cfafe91 100644 --- a/src/model/user/schnupperinterest.rs +++ b/src/model/user/schnupperinterest.rs @@ -1,6 +1,7 @@ use super::scheckbuch::ScheckbuchUser; use super::schnupperant::SchnupperantUser; use super::{ManageUserUser, User}; +use crate::model::activity::ActivityBuilder; use crate::model::role::Role; use crate::{model::notification::Notification, special_user}; use rocket::async_trait; @@ -25,7 +26,7 @@ impl SchnupperInterestUser { self.user.add_role(db, changed_by, &scheckbook).await?; let scheckbook = ScheckbuchUser::new(db, &self.user).await.unwrap(); - scheckbook.send_welcome_mail_to_user(db, smtp_pw).await?; + scheckbook.notify(db, smtp_pw).await?; Notification::create_for_steering_people( db, @@ -39,6 +40,13 @@ impl SchnupperInterestUser { ) .await; + ActivityBuilder::new(&format!( + "Der Schnupperinteressierte {self} hat sich (ohne Schnupperkurs) doch gleich direkt für ein Scheckbuch entschieden. {changed_by} hat dieses eingerichtet." + )) + .relevant_for_user(&self) + .save(db) + .await; + Ok(()) } @@ -74,6 +82,12 @@ impl SchnupperInterestUser { ) .await; } + ActivityBuilder::new(&format!( + "Der Schnupperinteressierte {self} hat sich zum Schnupperkurs angemeldet." + )) + .relevant_for_user(&self) + .save(db) + .await; Ok(()) } @@ -81,6 +95,13 @@ impl SchnupperInterestUser { pub(crate) async fn notify(&self, db: &SqlitePool) -> Result<(), String> { self.notify_schnupperbetreuer_about_new_interest(db).await; + ActivityBuilder::new(&format!( + "Der Schnupperbetreuer hat eine Info via Notification bekommen, dass {self} Interesse an einen Schnupperkurs hat." + )) + .relevant_for_user(&self) + .save(db) + .await; + Ok(()) } diff --git a/src/model/user/unterstuetzend.rs b/src/model/user/unterstuetzend.rs index b417371..552d9aa 100644 --- a/src/model/user/unterstuetzend.rs +++ b/src/model/user/unterstuetzend.rs @@ -1,5 +1,8 @@ use super::User; -use crate::{model::mail::Mail, special_user}; +use crate::{ + model::{activity::ActivityBuilder, mail::Mail}, + special_user, +}; use rocket::async_trait; use sqlx::SqlitePool; @@ -35,6 +38,13 @@ ASKÖ Ruderverein Donau Linz", self.name), smtp_pw, ).await?; + ActivityBuilder::new(&format!( + "{self} hat eine Mail an {mail} bekommen, mit Infos dass er/sie nun ein unterstützendes Mitglied ist (Handbuch, WLAN)." + )) + .relevant_for_user(&self) + .save(db) + .await; + Ok(()) } } diff --git a/src/tera/admin/user.rs b/src/tera/admin/user.rs index 5b298be..d093b59 100644 --- a/src/tera/admin/user.rs +++ b/src/tera/admin/user.rs @@ -254,26 +254,6 @@ async fn fees_paid( ) } -#[get("/user//send-welcome-mail")] -async fn send_welcome_mail( - db: &State, - _admin: ManageUserUser, - config: &State, - user: i32, -) -> Flash { - let Some(user) = User::find_by_id(db, user).await else { - return Flash::error(Redirect::to("/admin/user"), "User does not exist"); - }; - - match user.send_welcome_email(db, &config.smtp_pw).await { - Ok(()) => Flash::success( - Redirect::to("/admin/user"), - format!("Willkommens-Email wurde an {} versandt.", user.name), - ), - Err(e) => Flash::error(Redirect::to("/admin/user"), e), - } -} - #[get("/user//reset-pw")] async fn resetpw(db: &State, admin: ManageUserUser, user: i32) -> Flash { let user = User::find_by_id(db, user).await; @@ -760,32 +740,6 @@ async fn download_membership_pdf( (ContentType::PDF, user.membership_pdf.unwrap()) } -#[derive(FromForm, Debug)] -struct UserAddForm<'r> { - name: &'r str, -} - -#[post("/user/new", data = "")] -async fn create( - db: &State, - data: Form>, - admin: ManageUserUser, -) -> Flash { - if User::create(db, data.name).await { - Log::create( - db, - format!("{} created new user: {data:?}", admin.user.name), - ) - .await; - Flash::success(Redirect::to("/admin/user"), "Successfully created user") - } else { - Flash::error( - Redirect::to("/admin/user"), - format!("User {} already exists", data.name), - ) - } -} - //#[derive(FromForm, Debug)] //struct UserAddScheckbuchForm<'r> { // name: &'r str, @@ -1248,14 +1202,12 @@ pub fn routes() -> Vec { index_admin, view, resetpw, - create, //create_scheckbuch, delete, fees, fees_paid, scheckbuch, download_membership_pdf, - send_welcome_mail, // update_mail, update_phone,