allow to change type between members

This commit is contained in:
Philipp Hofer 2025-05-03 16:46:40 +02:00
parent 8dc55a7aad
commit 46981c3311
3 changed files with 214 additions and 3 deletions

View File

@ -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(())
}
}

View File

@ -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;

View File

@ -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/<id>/change-membertype", data = "<data>")]
async fn change_membertype(
db: &State<SqlitePool>,
admin: ManageUserUser,
data: Form<ChangeMembertypeForm>,
id: i32,
) -> Flash<Redirect> {
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<Route> {
routes![
index,
@ -962,5 +1009,6 @@ pub fn routes() -> Vec<Route> {
remove_role,
//
scheckbook_to_regular,
change_membertype,
]
}