Merge pull request 'reflect new fee structure' (#1029) from new-fee-structure into main
Reviewed-on: #1029
This commit was merged in pull request #1029.
	This commit is contained in:
		| @@ -23,6 +23,9 @@ pub(crate) const UNTERSTUETZEND: i64 = 2500; | ||||
| pub(crate) const FOERDERND: i64 = 8500; | ||||
| pub(crate) const SCHECKBUCH: i64 = 3000; | ||||
| pub(crate) const EINSCHREIBGEBUEHR: i64 = 3000; | ||||
| pub(crate) const DUAL_MEMBERSHIP: i64 = 18000; | ||||
| pub(crate) const TRIAL_ROWING: i64 = 12000; | ||||
| pub(crate) const TRIAL_ROWING_REDUCED: i64 = 6000; | ||||
|  | ||||
| #[derive(Debug, Clone, PartialEq, Eq)] | ||||
| pub struct NonEmptyString(String); | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| use std::{error::Error, fs}; | ||||
|  | ||||
| use lettre::{ | ||||
|     Address, Message, SmtpTransport, Transport, | ||||
|     message::{Attachment, MultiPart, SinglePart, header::ContentType}, | ||||
|     message::{header::ContentType, Attachment, MultiPart, SinglePart}, | ||||
|     transport::smtp::authentication::Credentials, | ||||
|     Address, Message, SmtpTransport, Transport, | ||||
| }; | ||||
| use sqlx::{Sqlite, SqlitePool, Transaction}; | ||||
|  | ||||
| @@ -161,6 +161,11 @@ impl Mail { | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if user.has_role(db, "schnupperant").await { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if !user.has_role(db, "paid").await || test.is_some() { | ||||
|                 let mut is_family = false; | ||||
|                 let mut send_to = String::new(); | ||||
| @@ -273,6 +278,11 @@ Der Vorstand"); | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if user.has_role(db, "schnupperant").await { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if let Some(fee) = user.fee(db).await { | ||||
|                 if !fee.paid || test.is_some() { | ||||
|                     let mut is_family = false; | ||||
|   | ||||
| @@ -519,6 +519,15 @@ impl User { | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     pub(crate) async fn remove_membership_pdf(&self, db: &SqlitePool, updated_by: &ManageUserUser) { | ||||
|         sqlx::query!( | ||||
|             "UPDATE user SET membership_pdf = null where id = ?", | ||||
|             self.id | ||||
|         ) | ||||
|         .execute(db) | ||||
|         .await | ||||
|         .unwrap(); //Okay, because we can only create a User of a valid id | ||||
|     } | ||||
|     pub(crate) async fn add_membership_pdf( | ||||
|         &self, | ||||
|         db: &SqlitePool, | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| use super::User; | ||||
| use crate::{ | ||||
|     BOAT_STORAGE, EINSCHREIBGEBUEHR, FAMILY_THREE_OR_MORE, FAMILY_TWO, FOERDERND, REGULAR, | ||||
|     RENNRUDERBEITRAG, STUDENT_OR_PUPIL, UNTERSTUETZEND, model::family::Family, | ||||
|     model::family::Family, BOAT_STORAGE, DUAL_MEMBERSHIP, EINSCHREIBGEBUEHR, FAMILY_THREE_OR_MORE, | ||||
|     FAMILY_TWO, FOERDERND, REGULAR, RENNRUDERBEITRAG, STUDENT_OR_PUPIL, TRIAL_ROWING, | ||||
|     TRIAL_ROWING_REDUCED, UNTERSTUETZEND, | ||||
| }; | ||||
| use chrono::{Datelike, Local, NaiveDate}; | ||||
| use serde::Serialize; | ||||
| @@ -68,6 +69,7 @@ impl User { | ||||
|         if !self.has_role(db, "Donau Linz").await | ||||
|             && !self.has_role(db, "Unterstützend").await | ||||
|             && !self.has_role(db, "Förderndes Mitglied").await | ||||
|             && !self.has_role(db, "schnupperant").await | ||||
|         { | ||||
|             return None; | ||||
|         } | ||||
| @@ -107,6 +109,7 @@ impl User { | ||||
|         if !self.has_role(db, "Donau Linz").await | ||||
|             && !self.has_role(db, "Unterstützend").await | ||||
|             && !self.has_role(db, "Förderndes Mitglied").await | ||||
|             && !self.has_role(db, "schnupperant").await | ||||
|         { | ||||
|             return fee; | ||||
|         } | ||||
| @@ -126,13 +129,16 @@ impl User { | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         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 | ||||
|         if !self.has_role(db, "schnupperant").await { | ||||
|             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") | ||||
|                 { | ||||
|                     fee.add("Einschreibgebühr".into(), EINSCHREIBGEBUEHR); | ||||
|                     if member_since_date.year() == Local::now().year() | ||||
|                         && !self.has_role(db, "no-einschreibgebuehr").await | ||||
|                     { | ||||
|                         fee.add("Einschreibgebühr".into(), EINSCHREIBGEBUEHR); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -150,7 +156,13 @@ impl User { | ||||
|             false | ||||
|         }; | ||||
|  | ||||
|         if self.has_role(db, "Unterstützend").await { | ||||
|         if self.has_role(db, "schnupperant").await { | ||||
|             if self.has_role(db, "Student").await || self.has_role(db, "Schüler").await { | ||||
|                 fee.add("Schnupperkurs (reduziert)".into(), TRIAL_ROWING_REDUCED); | ||||
|             } else { | ||||
|                 fee.add("Schnupperkurs".into(), TRIAL_ROWING); | ||||
|             } | ||||
|         } else 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); | ||||
| @@ -163,6 +175,18 @@ impl User { | ||||
|                 } | ||||
|             } else if self.has_role(db, "Ehrenmitglied").await { | ||||
|                 fee.add("Ehrenmitglied".into(), 0); | ||||
|             } else if self.has_role(db, "dual_membership").await { | ||||
|                 if halfprice { | ||||
|                     fee.add( | ||||
|                         "Doppelmitgliedschaft mit anderem österr. Ruderverein (Halbpreis)".into(), | ||||
|                         DUAL_MEMBERSHIP / 2, | ||||
|                     ); | ||||
|                 } else { | ||||
|                     fee.add( | ||||
|                         "Doppelmitgliedschaft mit anderem österr. Ruderverein".into(), | ||||
|                         DUAL_MEMBERSHIP, | ||||
|                     ); | ||||
|                 } | ||||
|             } else if halfprice { | ||||
|                 fee.add("Mitgliedsbeitrag (Halbpreis)".into(), REGULAR / 2); | ||||
|             } else { | ||||
| @@ -170,6 +194,19 @@ impl User { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if !self.has_role(db, "schnupperant").await | ||||
|             && self.has_role(db, "participated_schnupperkurs").await | ||||
|         { | ||||
|             if self.has_role(db, "Student").await || self.has_role(db, "Schüler").await { | ||||
|                 fee.add( | ||||
|                     "Anrechnung reduzierter Schnupperkurs".into(), | ||||
|                     -TRIAL_ROWING_REDUCED, | ||||
|                 ); | ||||
|             } else { | ||||
|                 fee.add("Anrechnung Schnupperkurs".into(), -TRIAL_ROWING); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         fee | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| use super::{ManageUserUser, User}; | ||||
| use crate::{ | ||||
|     NonEmptyString, | ||||
|     model::{activity::ActivityBuilder, mail::Mail, notification::Notification, role::Role}, | ||||
|     special_user, | ||||
|     special_user, NonEmptyString, | ||||
| }; | ||||
| use chrono::NaiveDate; | ||||
| use rocket::{async_trait, fs::TempFile, tokio::io::AsyncReadExt}; | ||||
| @@ -93,6 +92,8 @@ Beim nächsten Treffen im Verein, erinnere jemand vom Vorstand (https://rudernli | ||||
|  | ||||
| Damit du dich noch mehr verbunden fühlst (:-)), haben wir im Bootshaus ein WLAN für Vereinsmitglieder 'ASKÖ Ruderverein Donau Linz' eingerichtet. Das Passwort dafür lautet 'donau1921' (ohne Anführungszeichen). Bitte gib das Passwort an keine vereinsfremden Personen weiter. | ||||
|  | ||||
| Falls du deinen Mitgliedsbeitrag noch nicht bezahlt hast, erledige dies bitte demnächst. Den genauen Betrag und einen QR Code, den du mit deiner Bankapp scannen kannst findest du unter https://app.rudernlinz.at/planned | ||||
|  | ||||
| Wir freuen uns darauf, dich bald am Wasser zu sehen und gemeinsam tolle Erfahrungen zu sammeln! | ||||
|  | ||||
| Riemen- & Dollenbruch | ||||
|   | ||||
| @@ -4,9 +4,9 @@ use super::scheckbuch::ScheckbuchUser; | ||||
| use super::schnupperinterest::SchnupperInterestUser; | ||||
| use super::unterstuetzend::UnterstuetzendUser; | ||||
| use super::{ManageUserUser, User}; | ||||
| use crate::NonEmptyString; | ||||
| use crate::model::activity::ActivityBuilder; | ||||
| use crate::model::role::Role; | ||||
| use crate::NonEmptyString; | ||||
| use crate::{ | ||||
|     model::{mail::Mail, notification::Notification}, | ||||
|     special_user, | ||||
| @@ -65,20 +65,32 @@ impl SchnupperantUser { | ||||
|         .await?; | ||||
|  | ||||
|         // Change roles | ||||
|         let regular = Role::find_by_name(db, "Donau Linz").await.unwrap(); | ||||
|         let paid = Role::find_by_name(db, "paid").await.unwrap(); | ||||
|         if self.user.remove_role(db, changed_by, &paid).await.is_err() { | ||||
|             self.remove_membership_pdf(db, changed_by).await; | ||||
|             return Err("Kann noch kein normales Mitglied werden, da die Schnupperkurs-Gebühr noch nicht bezahlt wurde.".into()); | ||||
|         } | ||||
|         let scheckbook = Role::find_by_name(db, "schnupperant").await.unwrap(); | ||||
|         self.user.remove_role(db, changed_by, &scheckbook).await?; | ||||
|  | ||||
|         let regular = Role::find_by_name(db, "Donau Linz").await.unwrap(); | ||||
|         self.user.add_role(db, changed_by, ®ular).await?; | ||||
|  | ||||
|         let participated_schnupperkurs = Role::find_by_name(db, "participated_schnupperkurs") | ||||
|             .await | ||||
|             .unwrap(); | ||||
|         self.user | ||||
|             .add_role(db, changed_by, &participated_schnupperkurs) | ||||
|             .await?; | ||||
|  | ||||
|         // Notify | ||||
|         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, {} nahm an unserem Schnupperkurs teil und ist nun seit {} ein neues reguläres Mitglied. 🎉", | ||||
|                 self.name, | ||||
|                 self.member_since_date.clone().unwrap() | ||||
|                 "Liebe Steuerberechtigte, {} nahm an unserem Schnupperkurs teil und ist nun seit {member_since} ein neues reguläres Mitglied. 🎉", | ||||
|                 self.name | ||||
|             ), | ||||
|             "Neues Vereinsmitglied", | ||||
|             None, | ||||
| @@ -203,6 +215,11 @@ impl SchnupperantUser { | ||||
|         .await?; | ||||
|  | ||||
|         // Change roles | ||||
|         let paid = Role::find_by_name(db, "paid").await.unwrap(); | ||||
|         if self.user.remove_role(db, changed_by, &paid).await.is_err() { | ||||
|             self.remove_membership_pdf(db, changed_by).await; | ||||
|             return Err("Kann noch kein normales Mitglied werden, da die Schnupperkurs-Gebühr noch nicht bezahlt wurde.".into()); | ||||
|         } | ||||
|         let unterstuetzend = Role::find_by_name(db, "Unterstützend").await.unwrap(); | ||||
|         let scheckbook = Role::find_by_name(db, "schnupperant").await.unwrap(); | ||||
|         self.user.remove_role(db, changed_by, &scheckbook).await?; | ||||
| @@ -267,6 +284,11 @@ impl SchnupperantUser { | ||||
|         .await?; | ||||
|  | ||||
|         // Change roles | ||||
|         let paid = Role::find_by_name(db, "paid").await.unwrap(); | ||||
|         if self.user.remove_role(db, changed_by, &paid).await.is_err() { | ||||
|             self.remove_membership_pdf(db, changed_by).await; | ||||
|             return Err("Kann noch kein normales Mitglied werden, da die Schnupperkurs-Gebühr noch nicht bezahlt wurde.".into()); | ||||
|         } | ||||
|         let unterstuetzend = Role::find_by_name(db, "Förderndes Mitglied").await.unwrap(); | ||||
|         let scheckbook = Role::find_by_name(db, "schnupperant").await.unwrap(); | ||||
|         self.user.remove_role(db, changed_by, &scheckbook).await?; | ||||
| @@ -307,7 +329,7 @@ impl SchnupperantUser { | ||||
|  | ||||
|     // TODO: make private | ||||
|     pub(crate) async fn notify(&self, db: &SqlitePool, smtp_pw: &str) -> Result<(), String> { | ||||
|         self.notify_coxes_about_new_scheckbuch(db).await; | ||||
|         self.notify_coxes_about_new_schnupperant(db).await; | ||||
|         self.send_welcome_mail_to_user(db, smtp_pw).await?; | ||||
|  | ||||
|         ActivityBuilder::new(&format!( | ||||
| @@ -335,19 +357,27 @@ impl SchnupperantUser { | ||||
|             mail, | ||||
|             "ASKÖ Ruderverein Donau Linz | Anmeldung Schnupperkurs", | ||||
|             format!( | ||||
| "Hallo {0}, | ||||
|                 "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. | ||||
| es freut uns sehr, dich bei unserem Schnupperkurs willkommen heißen zu dürfen. | ||||
|  | ||||
| Bitte überweise die {1} € auf unser Bankkonto (IBAN: AT58 2032 0321 0072 9256) und gib beim Verwendungszweck 'Schnupperkurs {0}' an. | ||||
|  | ||||
| Detaillierte Informationen folgen noch, du wirst sie ein paar Tage vor dem Termin bekommen (wenn das Wetter/Wasserstand/... abschätzbar ist). | ||||
|  | ||||
| Riemen- & Dollenbruch, | ||||
| ASKÖ Ruderverein Donau Linz", self.name), | ||||
| ASKÖ Ruderverein Donau Linz", | ||||
|                 self.name, | ||||
|                 self.fee(db).await.unwrap().sum_in_cents/100 | ||||
|             ), | ||||
|             smtp_pw, | ||||
|         ).await?; | ||||
|         ) | ||||
|         .await?; | ||||
|  | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     async fn notify_coxes_about_new_scheckbuch(&self, db: &SqlitePool) { | ||||
|     async fn notify_coxes_about_new_schnupperant(&self, db: &SqlitePool) { | ||||
|         if let Some(role) = Role::find_by_name(db, "schnupper-betreuer").await { | ||||
|             Notification::create_for_role( | ||||
|                 db, | ||||
|   | ||||
| @@ -5,44 +5,5 @@ INSERT INTO user(name) VALUES('Philipp'); | ||||
| INSERT INTO "user_role" (user_id, role_id) VALUES((SELECT id from user where name = 'Philipp'),(SELECT id FROM role where name = 'Donau Linz')); | ||||
|  | ||||
|  | ||||
| -- Step 1: Create a new table without the 'notes' column | ||||
| CREATE TABLE "user_new" ( | ||||
|     "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, | ||||
|     "name" text NOT NULL UNIQUE, | ||||
|     "pw" text,  | ||||
|     "deleted" boolean NOT NULL DEFAULT FALSE, | ||||
|     "last_access" DATETIME, | ||||
|     "dob" text, | ||||
|     "weight" text, | ||||
|     "sex" text, | ||||
|     "dirty_thirty" text, | ||||
|     "dirty_dozen" text, | ||||
|     "member_since_date" text, | ||||
|     "birthdate" text, | ||||
|     "mail" text, | ||||
|     "nickname" text, | ||||
|     "phone" text, | ||||
|     "address" text, | ||||
|     "family_id" INTEGER REFERENCES family(id), | ||||
|     "membership_pdf" BLOB, | ||||
|     "user_token" TEXT NOT NULL DEFAULT (lower(hex(randomblob(16)))) | ||||
| ); | ||||
|  | ||||
| -- Step 2: Copy data from the old table to the new one (excluding 'notes') | ||||
| INSERT INTO user_new ( | ||||
|     id, name, pw, deleted, last_access, dob, weight, sex,  | ||||
|     dirty_thirty, dirty_dozen, member_since_date, birthdate,  | ||||
|     mail, nickname, phone, address, family_id, membership_pdf, user_token | ||||
| ) | ||||
| SELECT  | ||||
|     id, name, pw, deleted, last_access, dob, weight, sex,  | ||||
|     dirty_thirty, dirty_dozen, member_since_date, birthdate,  | ||||
|     mail, nickname, phone, address, family_id, membership_pdf, user_token | ||||
| FROM user; | ||||
|  | ||||
| -- Step 3: Drop the old table | ||||
| DROP TABLE user; | ||||
|  | ||||
| -- Step 4: Rename the new table to the original name | ||||
| ALTER TABLE user_new RENAME TO user; | ||||
|  | ||||
| insert into role(name, cluster, formatted_name) values('dual_membership', 'financial', 'Doppelmitgliedschaft mit anderem österr. Ruderverein'); | ||||
| insert into role(name, hide_in_lists) values('participated_schnupperkurs', true); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user