Compare commits
8 Commits
main
...
f6eac7b32f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6eac7b32f | ||
| b2157a31c5 | |||
| bfb3ae4b6e | |||
| 88a3e5f2d0 | |||
| 32c250536d | |||
| b9d0e2a2dc | |||
| b597898bdf | |||
| e90555214a |
1621
Cargo.lock
generated
1621
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -23,11 +23,11 @@ tera = { version = "1.20", features = ["date-locale"], optional = true}
|
|||||||
ics = "0.5"
|
ics = "0.5"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
lettre = "0.11"
|
lettre = "0.11"
|
||||||
csv = "1.3"
|
csv = "1.4"
|
||||||
itertools = "0.14"
|
itertools = "0.14"
|
||||||
job_scheduler_ng = "2.2"
|
job_scheduler_ng = "2.4"
|
||||||
ureq = { version = "3.0", features = ["json"] }
|
ureq = { version = "3.2", features = ["json"] }
|
||||||
regex = "1.11"
|
regex = "1.12"
|
||||||
urlencoding = "2.1"
|
urlencoding = "2.1"
|
||||||
|
|
||||||
[target.'cfg(not(windows))'.dependencies]
|
[target.'cfg(not(windows))'.dependencies]
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ pub(crate) enum Member {
|
|||||||
Regular(User),
|
Regular(User),
|
||||||
Foerdernd(User),
|
Foerdernd(User),
|
||||||
Unterstuetzend(User),
|
Unterstuetzend(User),
|
||||||
NoMembership(User),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Member {
|
impl Member {
|
||||||
@@ -32,7 +31,7 @@ impl Member {
|
|||||||
} else if user.has_role(db, "Unterstützend").await {
|
} else if user.has_role(db, "Unterstützend").await {
|
||||||
Self::Unterstuetzend(user)
|
Self::Unterstuetzend(user)
|
||||||
} else {
|
} else {
|
||||||
Self::NoMembership(user)
|
panic!("User {user} has no membership_type!!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ mod fee;
|
|||||||
pub(crate) mod foerdernd;
|
pub(crate) mod foerdernd;
|
||||||
pub(crate) mod member;
|
pub(crate) mod member;
|
||||||
pub mod merge;
|
pub mod merge;
|
||||||
pub(crate) mod nomembership;
|
|
||||||
pub(crate) mod regular;
|
pub(crate) mod regular;
|
||||||
pub(crate) mod scheckbuch;
|
pub(crate) mod scheckbuch;
|
||||||
pub(crate) mod schnupperant;
|
pub(crate) mod schnupperant;
|
||||||
|
|||||||
@@ -1,233 +0,0 @@
|
|||||||
use super::foerdernd::FoerderndUser;
|
|
||||||
use super::regular::RegularUser;
|
|
||||||
use super::scheckbuch::ScheckbuchUser;
|
|
||||||
use super::unterstuetzend::UnterstuetzendUser;
|
|
||||||
use super::{ManageUserUser, User};
|
|
||||||
use crate::NonEmptyString;
|
|
||||||
use crate::model::activity::ActivityBuilder;
|
|
||||||
use crate::model::role::Role;
|
|
||||||
use crate::model::notification::Notification;
|
|
||||||
use chrono::NaiveDate;
|
|
||||||
use rocket::fs::TempFile;
|
|
||||||
use sqlx::SqlitePool;
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
pub(crate) struct NoMembershipUser {
|
|
||||||
pub(crate) user: User,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for NoMembershipUser {
|
|
||||||
type Target = User;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.user
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for NoMembershipUser {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{}", self.user.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NoMembershipUser {
|
|
||||||
pub(crate) async fn new(db: &SqlitePool, user: &User) -> Option<Self> {
|
|
||||||
if ScheckbuchUser::new(db, user).await.is_some() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
if user.has_role(db, "schnupper-interessierte").await {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
if user.has_role(db, "schnupperant").await {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
if user.has_role(db, "Donau Linz").await {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
if user.has_role(db, "Förderndes Mitglied").await {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
if user.has_role(db, "Unterstützend").await {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(Self { user: user.clone() })
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn set_data_for_clubmember(
|
|
||||||
&self,
|
|
||||||
db: &SqlitePool,
|
|
||||||
changed_by: &ManageUserUser,
|
|
||||||
member_since: &NaiveDate,
|
|
||||||
birthdate: &NaiveDate,
|
|
||||||
phone: NonEmptyString,
|
|
||||||
address: NonEmptyString,
|
|
||||||
membership_pdf: &TempFile<'_>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
self.user.update_birthdate(db, changed_by, birthdate).await;
|
|
||||||
self.user
|
|
||||||
.update_member_since(db, changed_by, member_since)
|
|
||||||
.await;
|
|
||||||
self.user.update_phone(db, changed_by, &phone).await;
|
|
||||||
self.user.update_address(db, changed_by, &address).await;
|
|
||||||
self.user
|
|
||||||
.add_membership_pdf(db, changed_by, membership_pdf)
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn convert_to_regular_user(
|
|
||||||
self,
|
|
||||||
db: &SqlitePool,
|
|
||||||
smtp_pw: &str,
|
|
||||||
changed_by: &ManageUserUser,
|
|
||||||
member_since: &NaiveDate,
|
|
||||||
birthdate: &NaiveDate,
|
|
||||||
phone: NonEmptyString,
|
|
||||||
address: NonEmptyString,
|
|
||||||
membership_pdf: &TempFile<'_>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
self.set_data_for_clubmember(
|
|
||||||
db,
|
|
||||||
changed_by,
|
|
||||||
member_since,
|
|
||||||
birthdate,
|
|
||||||
phone,
|
|
||||||
address,
|
|
||||||
membership_pdf,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let regular = Role::find_by_name(db, "Donau Linz").await.unwrap();
|
|
||||||
self.user.add_role(db, changed_by, ®ular).await?;
|
|
||||||
|
|
||||||
let regular = RegularUser::new(db, &self.user).await.unwrap();
|
|
||||||
regular.send_welcome_mail_to_user(db, smtp_pw).await?;
|
|
||||||
Notification::create_for_steering_people(
|
|
||||||
db,
|
|
||||||
&format!(
|
|
||||||
"Liebe Steuerberechtigte, {} hatte keinen Mitgliedsstatus und ist nun seit {} ein neues reguläres Mitglied. 🎉",
|
|
||||||
self.name,
|
|
||||||
member_since
|
|
||||||
),
|
|
||||||
"Neues Vereinsmitglied",
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
ActivityBuilder::new(&format!(
|
|
||||||
"{changed_by} hat den User ohne Mitgliedsstatus {self} auf ein reguläres Mitglied upgegraded! Die Steuerpersonen wurden via Notification informiert."
|
|
||||||
))
|
|
||||||
.user(&self)
|
|
||||||
.save(db)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn convert_to_unterstuetzend_user(
|
|
||||||
self,
|
|
||||||
db: &SqlitePool,
|
|
||||||
smtp_pw: &str,
|
|
||||||
changed_by: &ManageUserUser,
|
|
||||||
member_since: &NaiveDate,
|
|
||||||
birthdate: &NaiveDate,
|
|
||||||
phone: NonEmptyString,
|
|
||||||
address: NonEmptyString,
|
|
||||||
membership_pdf: &TempFile<'_>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
self.set_data_for_clubmember(
|
|
||||||
db,
|
|
||||||
changed_by,
|
|
||||||
member_since,
|
|
||||||
birthdate,
|
|
||||||
phone,
|
|
||||||
address,
|
|
||||||
membership_pdf,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let unterstuetzend = Role::find_by_name(db, "Unterstützend").await.unwrap();
|
|
||||||
self.user.add_role(db, changed_by, &unterstuetzend).await?;
|
|
||||||
|
|
||||||
let unterstuetzend = UnterstuetzendUser::new(db, &self.user).await.unwrap();
|
|
||||||
unterstuetzend
|
|
||||||
.send_welcome_mail_to_user(db, smtp_pw)
|
|
||||||
.await?;
|
|
||||||
if let Some(vorstand) = Role::find_by_name(db, "vorstand").await {
|
|
||||||
Notification::create_for_role(
|
|
||||||
db,
|
|
||||||
&vorstand,
|
|
||||||
&format!(
|
|
||||||
"Lieber Vorstand, {} hatte keinen Mitgliedsstatus und ist nun seit {} ein neues unterstützendes Mitglied.",
|
|
||||||
self.name,
|
|
||||||
member_since
|
|
||||||
),
|
|
||||||
"Neues unterstützendes Vereinsmitglied",
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
ActivityBuilder::new(&format!(
|
|
||||||
"{changed_by} hat den User ohne Mitgliedsstatus {self} auf ein unterstützendes Mitglied upgegraded!"
|
|
||||||
))
|
|
||||||
.user(&self)
|
|
||||||
.save(db)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn convert_to_foerdernd_user(
|
|
||||||
self,
|
|
||||||
db: &SqlitePool,
|
|
||||||
smtp_pw: &str,
|
|
||||||
changed_by: &ManageUserUser,
|
|
||||||
member_since: &NaiveDate,
|
|
||||||
birthdate: &NaiveDate,
|
|
||||||
phone: NonEmptyString,
|
|
||||||
address: NonEmptyString,
|
|
||||||
membership_pdf: &TempFile<'_>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
self.set_data_for_clubmember(
|
|
||||||
db,
|
|
||||||
changed_by,
|
|
||||||
member_since,
|
|
||||||
birthdate,
|
|
||||||
phone,
|
|
||||||
address,
|
|
||||||
membership_pdf,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let foerdernd = Role::find_by_name(db, "Förderndes Mitglied").await.unwrap();
|
|
||||||
self.user.add_role(db, changed_by, &foerdernd).await?;
|
|
||||||
|
|
||||||
let foerdernd = FoerderndUser::new(db, &self.user).await.unwrap();
|
|
||||||
foerdernd.send_welcome_mail_to_user(db, smtp_pw).await?;
|
|
||||||
if let Some(vorstand) = Role::find_by_name(db, "vorstand").await {
|
|
||||||
Notification::create_for_role(
|
|
||||||
db,
|
|
||||||
&vorstand,
|
|
||||||
&format!(
|
|
||||||
"Lieber Vorstand, {} hatte keinen Mitgliedsstatus und ist nun seit {} ein neues förderndes Mitglied.",
|
|
||||||
self.name,
|
|
||||||
member_since
|
|
||||||
),
|
|
||||||
"Neues förderndes Vereinsmitglied",
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
ActivityBuilder::new(&format!(
|
|
||||||
"{changed_by} hat den User ohne Mitgliedsstatus {self} auf ein förderndes Mitglied upgegraded!"
|
|
||||||
))
|
|
||||||
.user(&self)
|
|
||||||
.save(db)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,9 +8,8 @@ use crate::{
|
|||||||
role::Role,
|
role::Role,
|
||||||
user::{
|
user::{
|
||||||
clubmember::ClubMemberUser, foerdernd::FoerderndUser, member::Member,
|
clubmember::ClubMemberUser, foerdernd::FoerderndUser, member::Member,
|
||||||
nomembership::NoMembershipUser, regular::RegularUser, scheckbuch::ScheckbuchUser,
|
regular::RegularUser, scheckbuch::ScheckbuchUser, schnupperant::SchnupperantUser,
|
||||||
schnupperant::SchnupperantUser, schnupperinterest::SchnupperInterestUser,
|
schnupperinterest::SchnupperInterestUser, unterstuetzend::UnterstuetzendUser,
|
||||||
unterstuetzend::UnterstuetzendUser,
|
|
||||||
AdminUser, AllowedToEditPaymentStatusUser, ManageUserUser, User, UserWithDetails,
|
AdminUser, AllowedToEditPaymentStatusUser, ManageUserUser, User, UserWithDetails,
|
||||||
UserWithMembershipPdf, UserWithRolesAndMembershipPdf, VorstandUser,
|
UserWithMembershipPdf, UserWithRolesAndMembershipPdf, VorstandUser,
|
||||||
},
|
},
|
||||||
@@ -1142,115 +1141,6 @@ async fn scheckbook_to_regular(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/user/<id>/nomembership-to-regular", data = "<data>")]
|
|
||||||
async fn nomembership_to_regular(
|
|
||||||
db: &State<SqlitePool>,
|
|
||||||
data: Form<ScheckToRegularForm<'_>>,
|
|
||||||
admin: ManageUserUser,
|
|
||||||
config: &State<Config>,
|
|
||||||
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 Ok(birthdate) = NaiveDate::parse_from_str(&data.birthdate, "%Y-%m-%d") else {
|
|
||||||
return Flash::error(
|
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
|
||||||
format!(
|
|
||||||
"Geburtsdatum {} ist nicht im YYYY-MM-DD Format",
|
|
||||||
&data.birthdate
|
|
||||||
),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
let Ok(member_since) = NaiveDate::parse_from_str(&data.member_since, "%Y-%m-%d") else {
|
|
||||||
return Flash::error(
|
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
|
||||||
format!(
|
|
||||||
"Beitrittsdatum {} ist nicht im YYYY-MM-DD Format",
|
|
||||||
&data.birthdate
|
|
||||||
),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(user) = NoMembershipUser::new(db, &user).await else {
|
|
||||||
return Flash::error(
|
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
|
||||||
"User hat keinen fehlenden Mitgliedsstatus",
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
let Ok(phone) = data.phone.clone().try_into() else {
|
|
||||||
return Flash::error(
|
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
|
||||||
"Vereinsmitglied braucht eine Telefonnummer",
|
|
||||||
);
|
|
||||||
};
|
|
||||||
let Ok(address) = data.address.clone().try_into() else {
|
|
||||||
return Flash::error(
|
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
|
||||||
"Vereinsmitglied braucht eine Adresse",
|
|
||||||
);
|
|
||||||
};
|
|
||||||
let response = match &*data.membertype {
|
|
||||||
"regular" => {
|
|
||||||
user.convert_to_regular_user(
|
|
||||||
db,
|
|
||||||
&config.smtp_pw,
|
|
||||||
&admin,
|
|
||||||
&member_since,
|
|
||||||
&birthdate,
|
|
||||||
phone,
|
|
||||||
address,
|
|
||||||
&data.membership_pdf,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
"unterstuetzend" => {
|
|
||||||
user.convert_to_unterstuetzend_user(
|
|
||||||
db,
|
|
||||||
&config.smtp_pw,
|
|
||||||
&admin,
|
|
||||||
&member_since,
|
|
||||||
&birthdate,
|
|
||||||
phone,
|
|
||||||
address,
|
|
||||||
&data.membership_pdf,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
"foerdernd" => {
|
|
||||||
user.convert_to_foerdernd_user(
|
|
||||||
db,
|
|
||||||
&config.smtp_pw,
|
|
||||||
&admin,
|
|
||||||
&member_since,
|
|
||||||
&birthdate,
|
|
||||||
phone,
|
|
||||||
address,
|
|
||||||
&data.membership_pdf,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Flash::error(
|
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
|
||||||
"Membertype gibts 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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromForm, Debug)]
|
#[derive(FromForm, Debug)]
|
||||||
pub struct ChangeMembertypeForm {
|
pub struct ChangeMembertypeForm {
|
||||||
membertype: String,
|
membertype: String,
|
||||||
@@ -1664,7 +1554,6 @@ pub fn routes() -> Vec<Route> {
|
|||||||
remove_role,
|
remove_role,
|
||||||
// Moves
|
// Moves
|
||||||
scheckbook_to_regular,
|
scheckbook_to_regular,
|
||||||
nomembership_to_regular,
|
|
||||||
schnupperant_to_regular,
|
schnupperant_to_regular,
|
||||||
schnupperant_to_scheckbook,
|
schnupperant_to_scheckbook,
|
||||||
schnupperinterest_to_schnupperant,
|
schnupperinterest_to_schnupperant,
|
||||||
|
|||||||
@@ -73,8 +73,6 @@
|
|||||||
Förderndes Vereinsmitglied
|
Förderndes Vereinsmitglied
|
||||||
{% elif "Unterstuetzend" in member %}
|
{% elif "Unterstuetzend" in member %}
|
||||||
Unterstützendes Vereinsmitglied
|
Unterstützendes Vereinsmitglied
|
||||||
{% elif "NoMembership" in member %}
|
|
||||||
⚠️ Kein Mitgliedsstatus!
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</small>
|
</small>
|
||||||
</h2>
|
</h2>
|
||||||
@@ -230,19 +228,8 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% elif "NoMembership" in member %}
|
|
||||||
{% if allowed_to_edit %}
|
|
||||||
<div class="grid pt-3">
|
|
||||||
<a href="/admin/user/{{ user.id }}/delete"
|
|
||||||
class="btn btn-alert"
|
|
||||||
onclick="return confirm('Willst du die Daten von {{ user.name }} wirklich löschen?');">
|
|
||||||
{% include "includes/delete-icon" %}
|
|
||||||
Daten löschen
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% if "Scheckbuch" in member or "Schnupperant" in member %}
|
||||||
{% if "Scheckbuch" in member or "Schnupperant" in member or "NoMembership" in member %}
|
|
||||||
{% if allowed_to_edit %}
|
{% if allowed_to_edit %}
|
||||||
<div class="grid gap-3 pb-3 mt-3">
|
<div class="grid gap-3 pb-3 mt-3">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
@@ -270,8 +257,6 @@
|
|||||||
{% set action = "scheckbook-to-regular" %}
|
{% set action = "scheckbook-to-regular" %}
|
||||||
{% elif "Schnupperant" in member %}
|
{% elif "Schnupperant" in member %}
|
||||||
{% set action = "schnupperant-to-regular" %}
|
{% set action = "schnupperant-to-regular" %}
|
||||||
{% elif "NoMembership" in member %}
|
|
||||||
{% set action = "nomembership-to-regular" %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<form action="/admin/user/{{ user.id }}/{{ action }}"
|
<form action="/admin/user/{{ user.id }}/{{ action }}"
|
||||||
method="post"
|
method="post"
|
||||||
|
|||||||
Reference in New Issue
Block a user