diff --git a/src/model/user/clubmember.rs b/src/model/user/clubmember.rs new file mode 100644 index 0000000..1fb461e --- /dev/null +++ b/src/model/user/clubmember.rs @@ -0,0 +1,162 @@ +use super::User; +use crate::{ + model::{log::Log, notification::Notification, role::Role, user::ManageUserUser}, + special_user, +}; +use rocket::async_trait; +use sqlx::SqlitePool; + +special_user!(ClubMemberUser, +"Donau Linz", +"Förderndes Mitglied", +"Unterstützend"); + +impl ClubMemberUser { + async fn add_membership_role(&self, db: &SqlitePool, role: &Role) { + sqlx::query!( + "INSERT INTO user_role(user_id, role_id) VALUES (?, ?)", + self.id, + role.id + ) + .execute(db) + .await + .unwrap(); + } + + async fn remove_membership_role(&self, db: &SqlitePool) { + let role = Role::find_by_name(db, "Förderndes Mitglied").await.unwrap(); + sqlx::query!( + "DELETE FROM user_role WHERE user_id = ? and role_id = ?", + self.id, + role.id + ) + .execute(db) + .await + .unwrap(); + + let role = Role::find_by_name(db, "Unterstützend").await.unwrap(); + sqlx::query!( + "DELETE FROM user_role WHERE user_id = ? and role_id = ?", + self.id, + role.id + ) + .execute(db) + .await + .unwrap(); + + let role = Role::find_by_name(db, "Donau Linz").await.unwrap(); + sqlx::query!( + "DELETE FROM user_role WHERE user_id = ? and role_id = ?", + self.id, + role.id + ) + .execute(db) + .await + .unwrap(); + } + async fn new_membership_role(&self, db: &SqlitePool, role: &str) -> Result<(), String> { + let role = Role::find_by_name(db, role).await.unwrap(); + self.remove_membership_role(db).await; + self.add_membership_role(db, &role).await; + Ok(()) + } + + pub(crate) async fn move_to_regular( + self, + db: &SqlitePool, + modified_by: &ManageUserUser, + ) -> Result<(), String> { + if self.has_role(db, "Donau Linz").await { + return Err(format!("User {self} ist bereits reguläres Mitglied.")); + } + + self.new_membership_role(db, "Donau Linz").await?; + + Notification::create_for_steering_people( + db, + &format!( + "Liebe Steuerberechtigte, {} war unterstützendes/förderndes Mitglied und ist nun ein neues reguläres Mitglied. 🎉", + self.name, + ), + "Neues Vereinsmitglied", + None, + None, + ) + .await; + + Log::create( + db, + format!("{modified_by} has moved user {self} to regular membership."), + ) + .await; + + Ok(()) + } + + pub(crate) async fn move_to_unterstuetzend( + self, + db: &SqlitePool, + modified_by: &ManageUserUser, + ) -> Result<(), String> { + if self.has_role(db, "Unterstützend").await { + return Err(format!("User {self} ist bereits unterstützendes Mitglied.")); + } + + self.new_membership_role(db, "Unterstützend").await?; + + if let Some(vorstand) = Role::find_by_name(db, "vorstand").await { + Notification::create_for_role( + db, + &vorstand, + &format!( + "Lieber Vorstnad, {} war aktives/förderndes Mitglied und ist nun ein unterstützendes Mitglied.", + self.name, + ), + "Neues unterstützendes Vereinsmitglied", + None, + None, + ) + .await; + } + + Log::create( + db, + format!("{modified_by} has moved user {self} to unterstützend membership."), + ) + .await; + + Ok(()) + } + + pub(crate) async fn move_to_foerdernd( + self, + db: &SqlitePool, + modified_by: &ManageUserUser, + ) -> Result<(), String> { + if self.has_role(db, "Förderndes Mitglied").await { + return Err(format!("User {self} ist bereits förderndes Mitglied.")); + } + + self.new_membership_role(db, "Förderndes Mitglied").await?; + + if let Some(vorstand) = Role::find_by_name(db, "vorstand").await { + Notification::create_for_role( + db, + &vorstand, + &format!( + "Lieber Vorstnad, {} war aktives/unterstützendes Mitglied und ist nun ein förderndes Mitglied.", + self.name, + ), + "Neues förderndes Vereinsmitglied", + None, + None, + ) + .await; + } + + Log::create( + db, + format!("{modified_by} has moved user {self} to fördernd membership."), + ) + .await; + + Ok(()) + } +} diff --git a/src/model/user/mod.rs b/src/model/user/mod.rs index 46a3443..a7dcb1f 100644 --- a/src/model/user/mod.rs +++ b/src/model/user/mod.rs @@ -30,6 +30,7 @@ use crate::{tera::admin::user::UserEditForm, AMOUNT_DAYS_TO_SHOW_TRIPS_AHEAD}; use scheckbuch::ScheckbuchUser; mod basic; +pub(crate) mod clubmember; mod fee; pub(crate) mod foerdernd; pub(crate) mod member; diff --git a/src/tera/admin/user.rs b/src/tera/admin/user.rs index 2a8b88b..77e5695 100644 --- a/src/tera/admin/user.rs +++ b/src/tera/admin/user.rs @@ -7,9 +7,9 @@ use crate::{ logbook::Logbook, role::Role, user::{ - member::Member, scheckbuch::ScheckbuchUser, AdminUser, AllowedToEditPaymentStatusUser, - ManageUserUser, User, UserWithDetails, UserWithMembershipPdf, - UserWithRolesAndMembershipPdf, VorstandUser, + clubmember::ClubMemberUser, member::Member, scheckbuch::ScheckbuchUser, AdminUser, + AllowedToEditPaymentStatusUser, ManageUserUser, User, UserWithDetails, + UserWithMembershipPdf, UserWithRolesAndMembershipPdf, VorstandUser, }, }, tera::Config, @@ -933,6 +933,53 @@ async fn scheckbook_to_regular( } } +#[derive(FromForm, Debug)] +pub struct ChangeMembertypeForm { + membertype: String, +} + +#[post("/user//change-membertype", data = "")] +async fn change_membertype( + db: &State, + admin: ManageUserUser, + data: Form, + id: i32, +) -> Flash { + let Some(user) = User::find_by_id(db, id).await else { + return Flash::error( + Redirect::to("/admin/user"), + format!("User with ID {} does not exist!", id), + ); + }; + + let Some(user) = ClubMemberUser::new(&db, &user).await else { + return Flash::error( + Redirect::to("/admin/user"), + format!("User {user} ist kein Vereinsmitglied"), + ); + }; + + let response = match &*data.membertype { + "regular" => user.move_to_regular(db, &admin).await, + "unterstuetzend" => user.move_to_unterstuetzend(db, &admin).await, + "foerdernd" => user.move_to_foerdernd(db, &admin).await, + _ => { + return Flash::error( + Redirect::to("/admin/user"), + format!("Membertype gibt's ned"), + ) + } + }; + + match response { + Ok(_) => Flash::success( + Redirect::to(format!("/admin/user/{}", id)), + "Mitgliedstyp umgewandelt und Infos versendet", + ), + Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", id)), e), + } +} + pub fn routes() -> Vec { routes![ index, @@ -962,5 +1009,6 @@ pub fn routes() -> Vec { remove_role, // scheckbook_to_regular, + change_membertype, ] }