allow to create users
This commit is contained in:
parent
ebbb4fe3da
commit
d9e86bf43b
@ -8,7 +8,7 @@ use rot::rest;
|
|||||||
use rot::tera;
|
use rot::tera;
|
||||||
use rot::{scheduled, tera::Config};
|
use rot::{scheduled, tera::Config};
|
||||||
|
|
||||||
use sqlx::{pool::PoolOptions, sqlite::SqliteConnectOptions, ConnectOptions};
|
use sqlx::{ConnectOptions, pool::PoolOptions, sqlite::SqliteConnectOptions};
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
@ -2,8 +2,8 @@ use std::ops::DerefMut;
|
|||||||
|
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rocket::serde::{Deserialize, Serialize};
|
|
||||||
use rocket::FromForm;
|
use rocket::FromForm;
|
||||||
|
use rocket::serde::{Deserialize, Serialize};
|
||||||
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
|
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
|
||||||
|
|
||||||
use crate::model::boathouse::Boathouse;
|
use crate::model::boathouse::Boathouse;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::model::{boat::Boat, user::User};
|
use crate::model::{boat::Boat, user::User};
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use rocket::serde::{Deserialize, Serialize};
|
|
||||||
use rocket::FromForm;
|
use rocket::FromForm;
|
||||||
|
use rocket::serde::{Deserialize, Serialize};
|
||||||
use sqlx::{FromRow, SqlitePool};
|
use sqlx::{FromRow, SqlitePool};
|
||||||
|
|
||||||
use super::log::Log;
|
use super::log::Log;
|
||||||
|
@ -2,8 +2,8 @@ use std::io::Write;
|
|||||||
|
|
||||||
use chrono::{Duration, NaiveDate, NaiveTime};
|
use chrono::{Duration, NaiveDate, NaiveTime};
|
||||||
use ics::{
|
use ics::{
|
||||||
properties::{DtEnd, DtStart, Summary},
|
|
||||||
ICalendar,
|
ICalendar,
|
||||||
|
properties::{DtEnd, DtStart, Summary},
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use sqlx::{FromRow, Row, SqlitePool};
|
use sqlx::{FromRow, Row, SqlitePool};
|
||||||
@ -578,6 +578,11 @@ mod test {
|
|||||||
|
|
||||||
let today = Local::now().date_naive().format("%Y%m%d").to_string();
|
let today = Local::now().date_naive().format("%Y%m%d").to_string();
|
||||||
let actual = Event::get_ics_feed(&pool).await;
|
let actual = Event::get_ics_feed(&pool).await;
|
||||||
assert_eq!(format!("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:ics-rs\r\nBEGIN:VEVENT\r\nUID:event-1@rudernlinz.at\r\nDTSTAMP:19900101T180000\r\nDTSTART:{today}T100000\r\nDTEND:{today}T130000\r\nSUMMARY:test-planned-event \r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"), actual);
|
assert_eq!(
|
||||||
|
format!(
|
||||||
|
"BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:ics-rs\r\nBEGIN:VEVENT\r\nUID:event-1@rudernlinz.at\r\nDTSTAMP:19900101T180000\r\nDTSTART:{today}T100000\r\nDTEND:{today}T130000\r\nSUMMARY:test-planned-event \r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"
|
||||||
|
),
|
||||||
|
actual
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use sqlx::{sqlite::SqliteQueryResult, FromRow, Sqlite, SqlitePool, Transaction};
|
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction, sqlite::SqliteQueryResult};
|
||||||
|
|
||||||
use super::user::User;
|
use super::user::User;
|
||||||
|
|
||||||
|
@ -823,7 +823,13 @@ ORDER BY departure DESC
|
|||||||
if difference > Duration::hours(1) {
|
if difference > Duration::hours(1) {
|
||||||
let vorstand = Role::find_by_name(db, "Vorstand").await.unwrap();
|
let vorstand = Role::find_by_name(db, "Vorstand").await.unwrap();
|
||||||
let logbook = LogbookWithBoatAndRowers::from(db, self.clone()).await;
|
let logbook = LogbookWithBoatAndRowers::from(db, self.clone()).await;
|
||||||
let mut msg = format!("{} hat folgenden Logbuch-Eintrag jetzt gelöscht, welcher bereits vor über einer Stunde begonnen wurde: Schiffsführer: {}, Steuerperson: {}, Abfahrt: {}", user.name, logbook.steering_user.name, logbook.steering_user.name, logbook.logbook.departure.format("%Y-%m-%d %H:%M"));
|
let mut msg = format!(
|
||||||
|
"{} hat folgenden Logbuch-Eintrag jetzt gelöscht, welcher bereits vor über einer Stunde begonnen wurde: Schiffsführer: {}, Steuerperson: {}, Abfahrt: {}",
|
||||||
|
user.name,
|
||||||
|
logbook.steering_user.name,
|
||||||
|
logbook.steering_user.name,
|
||||||
|
logbook.logbook.departure.format("%Y-%m-%d %H:%M")
|
||||||
|
);
|
||||||
if let Some(destination) = logbook.logbook.destination {
|
if let Some(destination) = logbook.logbook.destination {
|
||||||
msg.push_str(&format!(", Ziel: {}", destination));
|
msg.push_str(&format!(", Ziel: {}", destination));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use std::{error::Error, fs};
|
use std::{error::Error, fs};
|
||||||
|
|
||||||
use lettre::{
|
use lettre::{
|
||||||
message::{header::ContentType, Attachment, MultiPart, SinglePart},
|
|
||||||
transport::smtp::authentication::Credentials,
|
|
||||||
Address, Message, SmtpTransport, Transport,
|
Address, Message, SmtpTransport, Transport,
|
||||||
|
message::{Attachment, MultiPart, SinglePart, header::ContentType},
|
||||||
|
transport::smtp::authentication::Credentials,
|
||||||
};
|
};
|
||||||
use sqlx::{Sqlite, SqlitePool, Transaction};
|
use sqlx::{Sqlite, SqlitePool, Transaction};
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use ics::{components::Property, ICalendar};
|
use ics::{ICalendar, components::Property};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::model::{event::Event, trip::Trip, user::User};
|
use crate::model::{event::Event, trip::Trip, user::User};
|
||||||
|
@ -567,9 +567,11 @@ mod test {
|
|||||||
|
|
||||||
let last_notification = &Notification::for_user(&pool, &cox).await[0];
|
let last_notification = &Notification::for_user(&pool, &cox).await[0];
|
||||||
|
|
||||||
assert!(last_notification
|
assert!(
|
||||||
|
last_notification
|
||||||
.message
|
.message
|
||||||
.starts_with("cox2 hat eine Ausfahrt zur selben Zeit"));
|
.starts_with("cox2 hat eine Ausfahrt zur selben Zeit")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[sqlx::test]
|
#[sqlx::test]
|
||||||
|
@ -20,7 +20,7 @@ impl User {
|
|||||||
let note = note.trim();
|
let note = note.trim();
|
||||||
|
|
||||||
ActivityBuilder::new(&format!("({updated_by}) {note}"))
|
ActivityBuilder::new(&format!("({updated_by}) {note}"))
|
||||||
.relevant_for_user(&user)
|
.relevant_for_user(user)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -48,7 +48,9 @@ impl User {
|
|||||||
|
|
||||||
let msg = match &self.mail {
|
let msg = match &self.mail {
|
||||||
Some(old_mail) => {
|
Some(old_mail) => {
|
||||||
format!("{updated_by} hat die Mail-Adresse von {self} von {old_mail} auf {new_mail} geändert.")
|
format!(
|
||||||
|
"{updated_by} hat die Mail-Adresse von {self} von {old_mail} auf {new_mail} geändert."
|
||||||
|
)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
format!("{updated_by} eine neue Mail-Adresse für {self} hinzugefügt: {new_mail}")
|
format!("{updated_by} eine neue Mail-Adresse für {self} hinzugefügt: {new_mail}")
|
||||||
@ -87,9 +89,15 @@ impl User {
|
|||||||
query.execute(db).await.unwrap(); //Okay, because we can only create a User of a valid id
|
query.execute(db).await.unwrap(); //Okay, because we can only create a User of a valid id
|
||||||
|
|
||||||
let msg = match &self.phone {
|
let msg = match &self.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) if new_phone.is_empty() => format!(
|
||||||
Some(old_phone) => format!("{updated_by} hat die Telefonnummer von {self} von {old_phone} auf {new_phone} geändert."),
|
"{updated_by} hat die Telefonnummer von {self} entfernt (alte Nummer: {old_phone})"
|
||||||
None => format!("{updated_by} hat eine neue Telefonnummer für {self} hinzugefügt: {new_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}"
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
ActivityBuilder::new(&msg)
|
ActivityBuilder::new(&msg)
|
||||||
@ -107,7 +115,7 @@ impl User {
|
|||||||
let new_address = new_address.trim();
|
let new_address = new_address.trim();
|
||||||
|
|
||||||
let query = if new_address.is_empty() {
|
let query = if new_address.is_empty() {
|
||||||
if !self.address.is_none() {
|
if self.address.is_none() {
|
||||||
return; // nothing to do
|
return; // nothing to do
|
||||||
}
|
}
|
||||||
sqlx::query!("UPDATE user SET address = NULL where id = ?", self.id)
|
sqlx::query!("UPDATE user SET address = NULL where id = ?", self.id)
|
||||||
@ -126,9 +134,13 @@ impl User {
|
|||||||
query.execute(db).await.unwrap(); //Okay, because we can only create a User of a valid id
|
query.execute(db).await.unwrap(); //Okay, because we can only create a User of a valid id
|
||||||
|
|
||||||
let msg = match &self.address {
|
let msg = match &self.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) if new_address.is_empty() => format!(
|
||||||
Some(old_address) => format!("{updated_by} hat die Adresse von {self} von {old_address} auf {new_address} geändert."),
|
"{updated_by} hat die Adresse von {self} entfernt (alte Adresse: {old_address})"
|
||||||
None => format!("{updated_by} hat eine Adresse für {self} hinzugefügt: {new_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}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
ActivityBuilder::new(&msg)
|
ActivityBuilder::new(&msg)
|
||||||
@ -157,9 +169,15 @@ impl User {
|
|||||||
query.execute(db).await.unwrap(); //Okay, because we can only create a User of a valid id
|
query.execute(db).await.unwrap(); //Okay, because we can only create a User of a valid id
|
||||||
|
|
||||||
let msg = match &self.nickname {
|
let msg = match &self.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) if new_nickname.is_empty() => format!(
|
||||||
Some(old_nickname) => format!("{updated_by} hat den Spitznamen von {self} von {old_nickname} auf {new_nickname} geändert."),
|
"{updated_by} hat den Sitznamen von {self} entfernt (alter Spitzname: {old_nickname})"
|
||||||
None => format!("{updated_by} hat einen neuen Spitznamen für {self} hinzugefügt: {new_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}"
|
||||||
|
),
|
||||||
};
|
};
|
||||||
ActivityBuilder::new(&msg)
|
ActivityBuilder::new(&msg)
|
||||||
.relevant_for_user(self)
|
.relevant_for_user(self)
|
||||||
@ -185,8 +203,12 @@ impl User {
|
|||||||
.unwrap(); //Okay, because we can only create a User of a valid id
|
.unwrap(); //Okay, because we can only create a User of a valid id
|
||||||
|
|
||||||
let msg = match &self.member_since_date {
|
let msg = match &self.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."),
|
Some(old_member_since_date) => format!(
|
||||||
None => format!("{updated_by} hat ein neues Beitrittsdatum für {self} hinzugefügt: {new_member_since_date}")
|
"{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}"
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
ActivityBuilder::new(&msg)
|
ActivityBuilder::new(&msg)
|
||||||
@ -211,8 +233,12 @@ impl User {
|
|||||||
.unwrap(); //Okay, because we can only create a User of a valid id
|
.unwrap(); //Okay, because we can only create a User of a valid id
|
||||||
|
|
||||||
let msg = match &self.birthdate {
|
let msg = match &self.birthdate {
|
||||||
Some(old_birthdate) => format!("{updated_by} hat das Geburtsdatum von {self} von {old_birthdate} auf {new_birthdate} geändert."),
|
Some(old_birthdate) => format!(
|
||||||
None => format!("{updated_by} hat ein Geburtsdatum für {self} hinzugefügt: {new_birthdate}")
|
"{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}")
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ActivityBuilder::new(&msg)
|
ActivityBuilder::new(&msg)
|
||||||
@ -272,7 +298,7 @@ impl User {
|
|||||||
let bootsfuehrer = Role::find_by_name(db, "Bootsführer").await.unwrap();
|
let bootsfuehrer = Role::find_by_name(db, "Bootsführer").await.unwrap();
|
||||||
|
|
||||||
match (old_skill, skill) {
|
match (old_skill, skill) {
|
||||||
(old, new) if old == None && new == Some(cox.clone()) => {
|
(None, new) if new == Some(cox.clone()) => {
|
||||||
self.add_role(db, updated_by, &cox).await?;
|
self.add_role(db, updated_by, &cox).await?;
|
||||||
Notification::create_for_role(
|
Notification::create_for_role(
|
||||||
db,
|
db,
|
||||||
@ -309,7 +335,7 @@ impl User {
|
|||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
(old, new) if new == None => {
|
(old, None) => {
|
||||||
if let Some(old) = old {
|
if let Some(old) = old {
|
||||||
self.remove_role(db, updated_by, &old).await?;
|
self.remove_role(db, updated_by, &old).await?;
|
||||||
let vorstand = Role::find_by_name(db, "Vorstand").await.unwrap();
|
let vorstand = Role::find_by_name(db, "Vorstand").await.unwrap();
|
||||||
@ -360,7 +386,7 @@ impl User {
|
|||||||
ActivityBuilder::new(&format!(
|
ActivityBuilder::new(&format!(
|
||||||
"{updated_by} hat die Ermäßigung von {self} von {old} auf {new} geändert"
|
"{updated_by} hat die Ermäßigung von {self} von {old} auf {new} geändert"
|
||||||
))
|
))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -374,7 +400,9 @@ impl User {
|
|||||||
role: &Role,
|
role: &Role,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
if !self.has_role(db, &role.name).await {
|
if !self.has_role(db, &role.name).await {
|
||||||
return Err(format!("Kann Rolle {role} von User {self} nicht entfernen, da der User die Rolle gar nicht hat"));
|
return Err(format!(
|
||||||
|
"Kann Rolle {role} von User {self} nicht entfernen, da der User die Rolle gar nicht hat"
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
@ -389,7 +417,7 @@ impl User {
|
|||||||
ActivityBuilder::new(&format!(
|
ActivityBuilder::new(&format!(
|
||||||
"{updated_by} hat die Rolle {role} von {self} entfernt."
|
"{updated_by} hat die Rolle {role} von {self} entfernt."
|
||||||
))
|
))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -415,7 +443,7 @@ impl User {
|
|||||||
ActivityBuilder::new(&format!(
|
ActivityBuilder::new(&format!(
|
||||||
"{updated_by} hat den Bezahlstatus von {self} auf 'nicht bezahlt' gesetzt."
|
"{updated_by} hat den Bezahlstatus von {self} auf 'nicht bezahlt' gesetzt."
|
||||||
))
|
))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -438,7 +466,7 @@ impl User {
|
|||||||
ActivityBuilder::new(&format!(
|
ActivityBuilder::new(&format!(
|
||||||
"{updated_by} hat den Bezahlstatus von {self} auf 'bezahlt' gesetzt."
|
"{updated_by} hat den Bezahlstatus von {self} auf 'bezahlt' gesetzt."
|
||||||
))
|
))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -450,7 +478,9 @@ impl User {
|
|||||||
role: &Role,
|
role: &Role,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
if self.has_role(db, &role.name).await {
|
if self.has_role(db, &role.name).await {
|
||||||
return Err(format!("Kann Rolle {role} von User {self} nicht hinzufügen, da der User die Rolle schon hat"));
|
return Err(format!(
|
||||||
|
"Kann Rolle {role} von User {self} nicht hinzufügen, da der User die Rolle schon hat"
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
@ -473,7 +503,7 @@ impl User {
|
|||||||
ActivityBuilder::new(&format!(
|
ActivityBuilder::new(&format!(
|
||||||
"{updated_by} hat die Rolle '{role}' dem Benutzer {self} hinzugefügt."
|
"{updated_by} hat die Rolle '{role}' dem Benutzer {self} hinzugefügt."
|
||||||
))
|
))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -491,7 +521,7 @@ impl User {
|
|||||||
return Err(format!("User {self} hat bereits eine Beitrittserklärung."));
|
return Err(format!("User {self} hat bereits eine Beitrittserklärung."));
|
||||||
}
|
}
|
||||||
if membership_pdf.len() == 0 {
|
if membership_pdf.len() == 0 {
|
||||||
return Err(format!("Keine Beitrittserklärung mitgeschickt."));
|
return Err("Keine Beitrittserklärung mitgeschickt.".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut stream = membership_pdf.open().await.unwrap();
|
let mut stream = membership_pdf.open().await.unwrap();
|
||||||
@ -509,7 +539,7 @@ impl User {
|
|||||||
ActivityBuilder::new(&format!(
|
ActivityBuilder::new(&format!(
|
||||||
"{updated_by} hat die Mitgliedserklärung (PDF) für user {self} hinzugefügt."
|
"{updated_by} hat die Mitgliedserklärung (PDF) für user {self} hinzugefügt."
|
||||||
))
|
))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::User;
|
use super::User;
|
||||||
use crate::{
|
use crate::{
|
||||||
model::family::Family, BOAT_STORAGE, EINSCHREIBGEBUEHR, FAMILY_THREE_OR_MORE, FAMILY_TWO,
|
BOAT_STORAGE, EINSCHREIBGEBUEHR, FAMILY_THREE_OR_MORE, FAMILY_TWO, FOERDERND, REGULAR,
|
||||||
FOERDERND, REGULAR, RENNRUDERBEITRAG, STUDENT_OR_PUPIL, UNTERSTUETZEND,
|
RENNRUDERBEITRAG, STUDENT_OR_PUPIL, UNTERSTUETZEND, model::family::Family,
|
||||||
};
|
};
|
||||||
use chrono::{Datelike, Local, NaiveDate};
|
use chrono::{Datelike, Local, NaiveDate};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
use super::User;
|
use super::{regular::ClubMember, ManageUserUser, User};
|
||||||
use crate::{
|
use crate::{
|
||||||
model::{activity::ActivityBuilder, mail::Mail},
|
model::{activity::ActivityBuilder, mail::Mail, notification::Notification, role::Role},
|
||||||
special_user,
|
special_user, NonEmptyString,
|
||||||
};
|
};
|
||||||
use rocket::async_trait;
|
use chrono::NaiveDate;
|
||||||
|
use rocket::{async_trait, fs::TempFile};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
special_user!(FoerderndUser, +"Förderndes Mitglied");
|
special_user!(FoerderndUser, +"Förderndes Mitglied");
|
||||||
|
|
||||||
|
impl ClubMember for FoerderndUser {}
|
||||||
|
|
||||||
impl FoerderndUser {
|
impl FoerderndUser {
|
||||||
pub(crate) async fn send_welcome_mail_to_user(
|
pub(crate) async fn send_welcome_mail_to_user(
|
||||||
&self,
|
&self,
|
||||||
@ -41,10 +44,57 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
ActivityBuilder::new(&format!(
|
ActivityBuilder::new(&format!(
|
||||||
"User {self} hat die Info-Mail bzgl. neues förderndes Mitglied (Handbuch und WLAN Infos) an {mail} gesendet bekommen"
|
"User {self} hat die Info-Mail bzgl. neues förderndes Mitglied (Handbuch und WLAN Infos) an {mail} gesendet bekommen"
|
||||||
))
|
))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn create(
|
||||||
|
db: &SqlitePool,
|
||||||
|
created_by: &ManageUserUser,
|
||||||
|
smtp_pw: &str,
|
||||||
|
name: NonEmptyString,
|
||||||
|
mail: &str,
|
||||||
|
financial: Option<Role>,
|
||||||
|
birthdate: &NaiveDate,
|
||||||
|
member_since: &NaiveDate,
|
||||||
|
phone: NonEmptyString,
|
||||||
|
address: NonEmptyString,
|
||||||
|
membership_pdf: &TempFile<'_>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let role = Role::find_by_name(db, "Förderndes Mitglied").await.unwrap();
|
||||||
|
let user = Self::create_member(
|
||||||
|
db,
|
||||||
|
created_by,
|
||||||
|
&role,
|
||||||
|
name,
|
||||||
|
mail,
|
||||||
|
financial,
|
||||||
|
birthdate,
|
||||||
|
member_since,
|
||||||
|
phone,
|
||||||
|
address,
|
||||||
|
membership_pdf,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let user = Self::new(db, &user).await.unwrap();
|
||||||
|
user.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, es gibt ein neues förderndes Mitglied: {user}"),
|
||||||
|
"Neues unterstützendes Vereinsmitglied",
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,19 +36,19 @@ impl Member {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_club_member(&self) -> bool {
|
pub(crate) fn is_club_member(&self) -> bool {
|
||||||
match self {
|
matches!(
|
||||||
Member::Regular(_) | Member::Foerdernd(_) | Member::Unterstuetzend(_) => true,
|
self,
|
||||||
_ => false,
|
Member::Regular(_) | Member::Foerdernd(_) | Member::Unterstuetzend(_)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
pub(crate) fn supposed_to_pay(&self) -> bool {
|
pub(crate) fn supposed_to_pay(&self) -> bool {
|
||||||
match self {
|
matches!(
|
||||||
|
self,
|
||||||
Member::Schnupperant(_)
|
Member::Schnupperant(_)
|
||||||
| Member::Scheckbuch(_)
|
| Member::Scheckbuch(_)
|
||||||
| Member::Regular(_)
|
| Member::Regular(_)
|
||||||
| Member::Foerdernd(_)
|
| Member::Foerdernd(_)
|
||||||
| Member::Unterstuetzend(_) => true,
|
| Member::Unterstuetzend(_)
|
||||||
_ => false,
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -458,7 +458,7 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
smtp_pw,
|
smtp_pw,
|
||||||
).await?;
|
).await?;
|
||||||
|
|
||||||
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;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -541,7 +541,7 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
|
|
||||||
// TODO: add responsible person
|
// TODO: add responsible person
|
||||||
ActivityBuilder::new(&format!("Passwort von User {self} wurde zurückgesetzt."))
|
ActivityBuilder::new(&format!("Passwort von User {self} wurde zurückgesetzt."))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -555,7 +555,7 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
ActivityBuilder::new(&format!(
|
ActivityBuilder::new(&format!(
|
||||||
"Passwort von User {self} wurde erfolgreich geändert."
|
"Passwort von User {self} wurde erfolgreich geändert."
|
||||||
))
|
))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -578,7 +578,7 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
.await
|
.await
|
||||||
.unwrap(); //Okay, because we can only create a User of a valid id
|
.unwrap(); //Okay, because we can only create a User of a valid id
|
||||||
ActivityBuilder::new(&format!("User {self} hat sich eingeloggt."))
|
ActivityBuilder::new(&format!("User {self} hat sich eingeloggt."))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -589,7 +589,7 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
.await
|
.await
|
||||||
.unwrap(); //Okay, because we can only create a User of a valid id
|
.unwrap(); //Okay, because we can only create a User of a valid id
|
||||||
ActivityBuilder::new(&format!("User {self} wurde gelöscht."))
|
ActivityBuilder::new(&format!("User {self} wurde gelöscht."))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -684,7 +684,7 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
)
|
)
|
||||||
.await;
|
.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"))
|
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)
|
.relevant_for_user(self)
|
||||||
.save_tx(db)
|
.save_tx(db)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -702,7 +702,7 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
ActivityBuilder::new(&format!("{self} hat nun bereits die {amount_trips}. seiner 5 Scheckbuchausfahrten absolviert. Vorstand wurde via Notification informiert."))
|
ActivityBuilder::new(&format!("{self} hat nun bereits die {amount_trips}. seiner 5 Scheckbuchausfahrten absolviert. Vorstand wurde via Notification informiert."))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save_tx(db)
|
.save_tx(db)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -727,7 +727,7 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
ActivityBuilder::new(&format!(
|
ActivityBuilder::new(&format!(
|
||||||
"{self} hat das heurige Fahrtenabzeichen geschafft! Der Vorstand + {self} wurde via Notification informiert."
|
"{self} hat das heurige Fahrtenabzeichen geschafft! Der Vorstand + {self} wurde via Notification informiert."
|
||||||
))
|
))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save_tx(db)
|
.save_tx(db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -749,7 +749,7 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
ActivityBuilder::new(&format!("{self} hat den Äquatorpreis in {level} geschafft! Der Vorstand + {self} wurde via Notification informiert."))
|
ActivityBuilder::new(&format!("{self} hat den Äquatorpreis in {level} geschafft! Der Vorstand + {self} wurde via Notification informiert."))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save_tx(db)
|
.save_tx(db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -812,7 +812,7 @@ macro_rules! special_user {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<'r> rocket::request::FromRequest<'r> for $name {
|
impl<'r> rocket::request::FromRequest<'r> for $name {
|
||||||
type Error = crate::model::user::LoginError;
|
type Error = $crate::model::user::LoginError;
|
||||||
async fn from_request(req: &'r rocket::request::Request<'_>) -> rocket::request::Outcome<Self, Self::Error> {
|
async fn from_request(req: &'r rocket::request::Request<'_>) -> rocket::request::Outcome<Self, Self::Error> {
|
||||||
let db = req.rocket().state::<SqlitePool>().unwrap();
|
let db = req.rocket().state::<SqlitePool>().unwrap();
|
||||||
match User::from_request(req).await {
|
match User::from_request(req).await {
|
||||||
|
@ -1,13 +1,66 @@
|
|||||||
use super::User;
|
use super::{ManageUserUser, User};
|
||||||
use crate::{
|
use crate::{
|
||||||
model::{activity::ActivityBuilder, mail::Mail},
|
model::{activity::ActivityBuilder, mail::Mail, notification::Notification, role::Role},
|
||||||
special_user,
|
special_user, NonEmptyString,
|
||||||
};
|
};
|
||||||
use rocket::async_trait;
|
use chrono::NaiveDate;
|
||||||
|
use rocket::{async_trait, fs::TempFile, tokio::io::AsyncReadExt};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
special_user!(RegularUser, +"Donau Linz");
|
special_user!(RegularUser, +"Donau Linz");
|
||||||
|
|
||||||
|
pub trait ClubMember {
|
||||||
|
async fn create_member(
|
||||||
|
db: &SqlitePool,
|
||||||
|
created_by: &ManageUserUser,
|
||||||
|
role: &Role,
|
||||||
|
name: NonEmptyString,
|
||||||
|
mail: &str,
|
||||||
|
financial: Option<Role>,
|
||||||
|
birthdate: &NaiveDate,
|
||||||
|
member_since: &NaiveDate,
|
||||||
|
phone: NonEmptyString,
|
||||||
|
address: NonEmptyString,
|
||||||
|
membership_pdf: &TempFile<'_>,
|
||||||
|
) -> Result<User, String> {
|
||||||
|
if membership_pdf.len() == 0 {
|
||||||
|
return Err("Keine Beitrittserklärung mitgeschickt.".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut stream = membership_pdf.open().await.unwrap();
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
stream.read_to_end(&mut buffer).await.unwrap();
|
||||||
|
|
||||||
|
let name = name.as_str();
|
||||||
|
let phone = phone.as_str();
|
||||||
|
let address = address.as_str();
|
||||||
|
|
||||||
|
sqlx::query!(
|
||||||
|
"INSERT INTO user(name, member_since_date, birthdate, mail, phone, address, membership_pdf)
|
||||||
|
VALUES (?,?,?,?,?,?,?)",
|
||||||
|
name, member_since, birthdate, mail, phone, address,buffer
|
||||||
|
)
|
||||||
|
.execute(db)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let user = User::find_by_name(db, name).await.unwrap();
|
||||||
|
user.change_financial(db, created_by, financial).await?;
|
||||||
|
user.add_role(db, created_by, role).await?;
|
||||||
|
|
||||||
|
ActivityBuilder::new(&format!(
|
||||||
|
"{created_by} hat Mitglied {user} mit der Rolle {role} angelegt."
|
||||||
|
))
|
||||||
|
.relevant_for_user(&user)
|
||||||
|
.save(db)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClubMember for RegularUser {}
|
||||||
|
|
||||||
impl RegularUser {
|
impl RegularUser {
|
||||||
pub(crate) async fn send_welcome_mail_to_user(
|
pub(crate) async fn send_welcome_mail_to_user(
|
||||||
&self,
|
&self,
|
||||||
@ -47,10 +100,54 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
).await?;
|
).await?;
|
||||||
|
|
||||||
ActivityBuilder::new(&format!("Willkommensmail für {self} wurde an {mail} verschickt (Handbuch, Signal-Gruppe, App-Info, Fingerprint, WLAN)."))
|
ActivityBuilder::new(&format!("Willkommensmail für {self} wurde an {mail} verschickt (Handbuch, Signal-Gruppe, App-Info, Fingerprint, WLAN)."))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn create(
|
||||||
|
db: &SqlitePool,
|
||||||
|
created_by: &ManageUserUser,
|
||||||
|
smtp_pw: &str,
|
||||||
|
name: NonEmptyString,
|
||||||
|
mail: &str,
|
||||||
|
financial: Option<Role>,
|
||||||
|
birthdate: &NaiveDate,
|
||||||
|
member_since: &NaiveDate,
|
||||||
|
phone: NonEmptyString,
|
||||||
|
address: NonEmptyString,
|
||||||
|
membership_pdf: &TempFile<'_>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let role = Role::find_by_name(db, "Donau Linz").await.unwrap();
|
||||||
|
let user = Self::create_member(
|
||||||
|
db,
|
||||||
|
created_by,
|
||||||
|
&role,
|
||||||
|
name,
|
||||||
|
mail,
|
||||||
|
financial,
|
||||||
|
birthdate,
|
||||||
|
member_since,
|
||||||
|
phone,
|
||||||
|
address,
|
||||||
|
membership_pdf,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let user = Self::new(db, &user).await.unwrap();
|
||||||
|
user.send_welcome_mail_to_user(db, smtp_pw).await?;
|
||||||
|
|
||||||
|
Notification::create_for_steering_people(
|
||||||
|
db,
|
||||||
|
&format!("Liebe Steuerberechtigte, es gibt ein neues Mitglied: {user} 🎉"),
|
||||||
|
"Neues Vereinsmitglied",
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ impl ScheckbuchUser {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
ActivityBuilder::new(&format!(
|
ActivityBuilder::new(&format!(
|
||||||
"{changed_by} hat den Scheckbuch-User {self} auf ein reguläres Mitglied upgegraded!"
|
"{changed_by} hat den Scheckbuch-User {self} auf ein reguläres Mitglied upgegraded! Die Steuerpersonen wurden via Notification informiert."
|
||||||
))
|
))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(&self)
|
||||||
.save(db)
|
.save(db)
|
||||||
@ -214,7 +214,7 @@ impl ScheckbuchUser {
|
|||||||
ActivityBuilder::new(&format!(
|
ActivityBuilder::new(&format!(
|
||||||
"{self} hat eine Info-Mail bekommen (Erklärung Scheckbuch, Ruderapp) und alle Steuerberechtigten wurden informiert."
|
"{self} hat eine Info-Mail bekommen (Erklärung Scheckbuch, Ruderapp) und alle Steuerberechtigten wurden informiert."
|
||||||
))
|
))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -233,7 +233,7 @@ impl ScheckbuchUser {
|
|||||||
};
|
};
|
||||||
Mail::send_single(
|
Mail::send_single(
|
||||||
db,
|
db,
|
||||||
&mail,
|
mail,
|
||||||
"ASKÖ Ruderverein Donau Linz | Dein Scheckbuch wartet auf Dich",
|
"ASKÖ Ruderverein Donau Linz | Dein Scheckbuch wartet auf Dich",
|
||||||
format!(
|
format!(
|
||||||
"Hallo {0},
|
"Hallo {0},
|
||||||
@ -266,4 +266,38 @@ ASKÖ Ruderverein Donau Linz", self.name, SCHECKBUCH/100),
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn create(
|
||||||
|
db: &SqlitePool,
|
||||||
|
created_by: &ManageUserUser,
|
||||||
|
smtp_pw: &str,
|
||||||
|
name: NonEmptyString,
|
||||||
|
mail: &str,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let role = Role::find_by_name(db, "scheckbuch").await.unwrap();
|
||||||
|
|
||||||
|
let name = name.as_str();
|
||||||
|
sqlx::query!(
|
||||||
|
"INSERT INTO user(name, mail)
|
||||||
|
VALUES (?,?)",
|
||||||
|
name,
|
||||||
|
mail
|
||||||
|
)
|
||||||
|
.execute(db)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let user = User::find_by_name(db, name).await.unwrap();
|
||||||
|
user.add_role(db, created_by, &role).await?;
|
||||||
|
|
||||||
|
let user = Self::new(db, &user).await.unwrap();
|
||||||
|
user.notify(db, smtp_pw).await?;
|
||||||
|
|
||||||
|
ActivityBuilder::new(&format!("{created_by} hat Scheckbuch {user} angelegt."))
|
||||||
|
.relevant_for_user(&user)
|
||||||
|
.save(db)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ impl SchnupperantUser {
|
|||||||
self.user.add_role(db, changed_by, &scheckbook).await?;
|
self.user.add_role(db, changed_by, &scheckbook).await?;
|
||||||
|
|
||||||
if let Some(no_einschreibgebuehr) = Role::find_by_name(db, "no-einschreibgebuehr").await {
|
if let Some(no_einschreibgebuehr) = Role::find_by_name(db, "no-einschreibgebuehr").await {
|
||||||
self.add_role(db, &changed_by, &no_einschreibgebuehr)
|
self.add_role(db, changed_by, &no_einschreibgebuehr)
|
||||||
.await
|
.await
|
||||||
.expect("role doesn't have a group");
|
.expect("role doesn't have a group");
|
||||||
}
|
}
|
||||||
@ -208,7 +208,7 @@ impl SchnupperantUser {
|
|||||||
self.user.remove_role(db, changed_by, &scheckbook).await?;
|
self.user.remove_role(db, changed_by, &scheckbook).await?;
|
||||||
self.user.add_role(db, changed_by, &unterstuetzend).await?;
|
self.user.add_role(db, changed_by, &unterstuetzend).await?;
|
||||||
if let Some(no_einschreibgebuehr) = Role::find_by_name(db, "no-einschreibgebuehr").await {
|
if let Some(no_einschreibgebuehr) = Role::find_by_name(db, "no-einschreibgebuehr").await {
|
||||||
self.add_role(db, &changed_by, &no_einschreibgebuehr)
|
self.add_role(db, changed_by, &no_einschreibgebuehr)
|
||||||
.await
|
.await
|
||||||
.expect("role doesn't have a group");
|
.expect("role doesn't have a group");
|
||||||
}
|
}
|
||||||
@ -272,7 +272,7 @@ impl SchnupperantUser {
|
|||||||
self.user.remove_role(db, changed_by, &scheckbook).await?;
|
self.user.remove_role(db, changed_by, &scheckbook).await?;
|
||||||
self.user.add_role(db, changed_by, &unterstuetzend).await?;
|
self.user.add_role(db, changed_by, &unterstuetzend).await?;
|
||||||
if let Some(no_einschreibgebuehr) = Role::find_by_name(db, "no-einschreibgebuehr").await {
|
if let Some(no_einschreibgebuehr) = Role::find_by_name(db, "no-einschreibgebuehr").await {
|
||||||
self.add_role(db, &changed_by, &no_einschreibgebuehr)
|
self.add_role(db, changed_by, &no_einschreibgebuehr)
|
||||||
.await
|
.await
|
||||||
.expect("role doesn't have a group");
|
.expect("role doesn't have a group");
|
||||||
}
|
}
|
||||||
@ -313,7 +313,7 @@ impl SchnupperantUser {
|
|||||||
ActivityBuilder::new(&format!(
|
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."
|
"{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)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -332,7 +332,7 @@ impl SchnupperantUser {
|
|||||||
};
|
};
|
||||||
Mail::send_single(
|
Mail::send_single(
|
||||||
db,
|
db,
|
||||||
&mail,
|
mail,
|
||||||
"ASKÖ Ruderverein Donau Linz | Anmeldung Schnupperkurs",
|
"ASKÖ Ruderverein Donau Linz | Anmeldung Schnupperkurs",
|
||||||
format!(
|
format!(
|
||||||
"Hallo {0},
|
"Hallo {0},
|
||||||
@ -363,4 +363,40 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn create(
|
||||||
|
db: &SqlitePool,
|
||||||
|
created_by: &ManageUserUser,
|
||||||
|
smtp_pw: &str,
|
||||||
|
name: NonEmptyString,
|
||||||
|
mail: &str,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let role = Role::find_by_name(db, "schnupperant").await.unwrap();
|
||||||
|
|
||||||
|
let name = name.as_str();
|
||||||
|
sqlx::query!(
|
||||||
|
"INSERT INTO user(name, mail)
|
||||||
|
VALUES (?,?)",
|
||||||
|
name,
|
||||||
|
mail
|
||||||
|
)
|
||||||
|
.execute(db)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let user = User::find_by_name(db, name).await.unwrap();
|
||||||
|
user.add_role(db, created_by, &role).await?;
|
||||||
|
|
||||||
|
let user = Self::new(db, &user).await.unwrap();
|
||||||
|
user.notify(db, smtp_pw).await?;
|
||||||
|
|
||||||
|
ActivityBuilder::new(&format!(
|
||||||
|
"{created_by} hat {user} zur fixen Schnupperkurs-Anmeldung hinzugefügt."
|
||||||
|
))
|
||||||
|
.relevant_for_user(&user)
|
||||||
|
.save(db)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ use super::schnupperant::SchnupperantUser;
|
|||||||
use super::{ManageUserUser, User};
|
use super::{ManageUserUser, User};
|
||||||
use crate::model::activity::ActivityBuilder;
|
use crate::model::activity::ActivityBuilder;
|
||||||
use crate::model::role::Role;
|
use crate::model::role::Role;
|
||||||
|
use crate::NonEmptyString;
|
||||||
use crate::{model::notification::Notification, special_user};
|
use crate::{model::notification::Notification, special_user};
|
||||||
use rocket::async_trait;
|
use rocket::async_trait;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
@ -98,7 +99,7 @@ impl SchnupperInterestUser {
|
|||||||
ActivityBuilder::new(&format!(
|
ActivityBuilder::new(&format!(
|
||||||
"Der Schnupperbetreuer hat eine Info via Notification bekommen, dass {self} Interesse an einen Schnupperkurs hat."
|
"Der Schnupperbetreuer hat eine Info via Notification bekommen, dass {self} Interesse an einen Schnupperkurs hat."
|
||||||
))
|
))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -121,4 +122,41 @@ impl SchnupperInterestUser {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn create(
|
||||||
|
db: &SqlitePool,
|
||||||
|
created_by: &ManageUserUser,
|
||||||
|
name: NonEmptyString,
|
||||||
|
mail: &str,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let role = Role::find_by_name(db, "schnupper-interessierte")
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let name = name.as_str();
|
||||||
|
sqlx::query!(
|
||||||
|
"INSERT INTO user(name, mail)
|
||||||
|
VALUES (?,?)",
|
||||||
|
name,
|
||||||
|
mail
|
||||||
|
)
|
||||||
|
.execute(db)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let user = User::find_by_name(db, name).await.unwrap();
|
||||||
|
user.add_role(db, created_by, &role).await?;
|
||||||
|
|
||||||
|
let user = Self::new(db, &user).await.unwrap();
|
||||||
|
user.notify(db).await?;
|
||||||
|
|
||||||
|
ActivityBuilder::new(&format!(
|
||||||
|
"{created_by} hat Schnupper-Interessierten {user} angelegt."
|
||||||
|
))
|
||||||
|
.relevant_for_user(&user)
|
||||||
|
.save(db)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
use super::User;
|
use super::{regular::ClubMember, ManageUserUser, User};
|
||||||
use crate::{
|
use crate::{
|
||||||
model::{activity::ActivityBuilder, mail::Mail},
|
model::{activity::ActivityBuilder, mail::Mail, notification::Notification, role::Role},
|
||||||
special_user,
|
special_user, NonEmptyString,
|
||||||
};
|
};
|
||||||
use rocket::async_trait;
|
use chrono::NaiveDate;
|
||||||
|
use rocket::{async_trait, fs::TempFile};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
special_user!(UnterstuetzendUser, +"Unterstützend");
|
special_user!(UnterstuetzendUser, +"Unterstützend");
|
||||||
|
|
||||||
|
impl ClubMember for UnterstuetzendUser {}
|
||||||
|
|
||||||
impl UnterstuetzendUser {
|
impl UnterstuetzendUser {
|
||||||
pub(crate) async fn send_welcome_mail_to_user(
|
pub(crate) async fn send_welcome_mail_to_user(
|
||||||
&self,
|
&self,
|
||||||
@ -41,10 +44,57 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
ActivityBuilder::new(&format!(
|
ActivityBuilder::new(&format!(
|
||||||
"{self} hat eine Mail an {mail} bekommen, mit Infos dass er/sie nun ein unterstützendes Mitglied ist (Handbuch, WLAN)."
|
"{self} hat eine Mail an {mail} bekommen, mit Infos dass er/sie nun ein unterstützendes Mitglied ist (Handbuch, WLAN)."
|
||||||
))
|
))
|
||||||
.relevant_for_user(&self)
|
.relevant_for_user(self)
|
||||||
.save(db)
|
.save(db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn create(
|
||||||
|
db: &SqlitePool,
|
||||||
|
created_by: &ManageUserUser,
|
||||||
|
smtp_pw: &str,
|
||||||
|
name: NonEmptyString,
|
||||||
|
mail: &str,
|
||||||
|
financial: Option<Role>,
|
||||||
|
birthdate: &NaiveDate,
|
||||||
|
member_since: &NaiveDate,
|
||||||
|
phone: NonEmptyString,
|
||||||
|
address: NonEmptyString,
|
||||||
|
membership_pdf: &TempFile<'_>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let role = Role::find_by_name(db, "Unterstützend").await.unwrap();
|
||||||
|
let user = Self::create_member(
|
||||||
|
db,
|
||||||
|
created_by,
|
||||||
|
&role,
|
||||||
|
name,
|
||||||
|
mail,
|
||||||
|
financial,
|
||||||
|
birthdate,
|
||||||
|
member_since,
|
||||||
|
phone,
|
||||||
|
address,
|
||||||
|
membership_pdf,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let user = Self::new(db, &user).await.unwrap();
|
||||||
|
user.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, es gibt ein neues unterstützendes Mitglied: {user}"),
|
||||||
|
"Neues unterstützendes Vereinsmitglied",
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use rocket::{form::Form, post, routes, Build, FromForm, Rocket, State};
|
use rocket::{Build, FromForm, Rocket, State, form::Form, post, routes};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
|
@ -96,7 +96,9 @@ struct DailyWeather {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fetch(api_key: &str) -> Result<Data, String> {
|
fn fetch(api_key: &str) -> Result<Data, String> {
|
||||||
let url = format!("https://api.openweathermap.org/data/3.0/onecall?lat=48.31970&lon=14.29451&units=metric&exclude=current,minutely,hourly,alert&appid={api_key}");
|
let url = format!(
|
||||||
|
"https://api.openweathermap.org/data/3.0/onecall?lat=48.31970&lon=14.29451&units=metric&exclude=current,minutely,hourly,alert&appid={api_key}"
|
||||||
|
);
|
||||||
|
|
||||||
match ureq::get(&url).call() {
|
match ureq::get(&url).call() {
|
||||||
Ok(mut response) => {
|
Ok(mut response) => {
|
||||||
|
@ -5,13 +5,14 @@ use crate::model::{
|
|||||||
user::{User, UserWithDetails, VorstandUser},
|
user::{User, UserWithDetails, VorstandUser},
|
||||||
};
|
};
|
||||||
use rocket::{
|
use rocket::{
|
||||||
|
Route, State,
|
||||||
form::Form,
|
form::Form,
|
||||||
get, post,
|
get, post,
|
||||||
request::FlashMessage,
|
request::FlashMessage,
|
||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes, Route, State,
|
routes,
|
||||||
};
|
};
|
||||||
use rocket_dyn_templates::{tera::Context, Template};
|
use rocket_dyn_templates::{Template, tera::Context};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
#[get("/boat")]
|
#[get("/boat")]
|
||||||
@ -245,9 +246,11 @@ mod test {
|
|||||||
|
|
||||||
let rocket = rocket::build().manage(db.clone());
|
let rocket = rocket::build().manage(db.clone());
|
||||||
let rocket = crate::tera::config(rocket);
|
let rocket = crate::tera::config(rocket);
|
||||||
assert!(Boat::find_by_name(&db, "completely-new-boat".into())
|
assert!(
|
||||||
|
Boat::find_by_name(&db, "completely-new-boat".into())
|
||||||
.await
|
.await
|
||||||
.is_none());
|
.is_none()
|
||||||
|
);
|
||||||
|
|
||||||
let client = Client::tracked(rocket).await.unwrap();
|
let client = Client::tracked(rocket).await.unwrap();
|
||||||
let login = client
|
let login = client
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use rocket::{
|
use rocket::{
|
||||||
|
FromForm, Route, State,
|
||||||
form::Form,
|
form::Form,
|
||||||
get, post, put,
|
get, post, put,
|
||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes, FromForm, Route, State,
|
routes,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use rocket::form::Form;
|
use rocket::form::Form;
|
||||||
use rocket::fs::TempFile;
|
use rocket::fs::TempFile;
|
||||||
use rocket::response::{Flash, Redirect};
|
use rocket::response::{Flash, Redirect};
|
||||||
use rocket::{get, request::FlashMessage, routes, Route, State};
|
use rocket::{FromForm, post};
|
||||||
use rocket::{post, FromForm};
|
use rocket::{Route, State, get, request::FlashMessage, routes};
|
||||||
use rocket_dyn_templates::{tera::Context, Template};
|
use rocket_dyn_templates::{Template, tera::Context};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::model::log::Log;
|
use crate::model::log::Log;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use csv::ReaderBuilder;
|
use csv::ReaderBuilder;
|
||||||
use rocket::{form::Form, get, post, routes, FromForm, Route, State};
|
use rocket::{FromForm, Route, State, form::Form, get, post, routes};
|
||||||
use rocket_dyn_templates::{context, Template};
|
use rocket_dyn_templates::{Template, context};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -6,13 +6,14 @@ use crate::model::{
|
|||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rocket::{
|
use rocket::{
|
||||||
|
FromForm, Route, State,
|
||||||
form::Form,
|
form::Form,
|
||||||
get, post,
|
get, post,
|
||||||
request::FlashMessage,
|
request::FlashMessage,
|
||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes, FromForm, Route, State,
|
routes,
|
||||||
};
|
};
|
||||||
use rocket_dyn_templates::{tera::Context, Template};
|
use rocket_dyn_templates::{Template, tera::Context};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
#[get("/notification")]
|
#[get("/notification")]
|
||||||
|
@ -3,8 +3,8 @@ use crate::model::{
|
|||||||
user::{SchnupperBetreuerUser, User, UserWithDetails},
|
user::{SchnupperBetreuerUser, User, UserWithDetails},
|
||||||
};
|
};
|
||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
use rocket::{get, request::FlashMessage, routes, Route, State};
|
use rocket::{Route, State, get, request::FlashMessage, routes};
|
||||||
use rocket_dyn_templates::{tera::Context, Template};
|
use rocket_dyn_templates::{Template, tera::Context};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
#[get("/schnupper")]
|
#[get("/schnupper")]
|
||||||
|
@ -4,11 +4,13 @@ use crate::{
|
|||||||
family::Family,
|
family::Family,
|
||||||
log::Log,
|
log::Log,
|
||||||
logbook::Logbook,
|
logbook::Logbook,
|
||||||
|
mail::valid_mails,
|
||||||
role::Role,
|
role::Role,
|
||||||
user::{
|
user::{
|
||||||
clubmember::ClubMemberUser, member::Member, scheckbuch::ScheckbuchUser,
|
clubmember::ClubMemberUser, foerdernd::FoerderndUser, member::Member,
|
||||||
schnupperant::SchnupperantUser, schnupperinterest::SchnupperInterestUser, AdminUser,
|
regular::RegularUser, scheckbuch::ScheckbuchUser, schnupperant::SchnupperantUser,
|
||||||
AllowedToEditPaymentStatusUser, ManageUserUser, User, UserWithDetails,
|
schnupperinterest::SchnupperInterestUser, unterstuetzend::UnterstuetzendUser,
|
||||||
|
AdminUser, AllowedToEditPaymentStatusUser, ManageUserUser, User, UserWithDetails,
|
||||||
UserWithMembershipPdf, UserWithRolesAndMembershipPdf, VorstandUser,
|
UserWithMembershipPdf, UserWithRolesAndMembershipPdf, VorstandUser,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -64,6 +66,7 @@ async fn index(
|
|||||||
let allowed_to_edit = ManageUserUser::new(db, &user).await.is_some();
|
let allowed_to_edit = ManageUserUser::new(db, &user).await.is_some();
|
||||||
|
|
||||||
let users: Vec<UserWithRolesAndMembershipPdf> = join_all(user_futures).await;
|
let users: Vec<UserWithRolesAndMembershipPdf> = join_all(user_futures).await;
|
||||||
|
let financial = Role::all_cluster(db, "financial").await;
|
||||||
|
|
||||||
let roles = Role::all(db).await;
|
let roles = Role::all(db).await;
|
||||||
let families = Family::all_with_members(db).await;
|
let families = Family::all_with_members(db).await;
|
||||||
@ -75,6 +78,7 @@ async fn index(
|
|||||||
context.insert("allowed_to_edit", &allowed_to_edit);
|
context.insert("allowed_to_edit", &allowed_to_edit);
|
||||||
context.insert("users", &users);
|
context.insert("users", &users);
|
||||||
context.insert("roles", &roles);
|
context.insert("roles", &roles);
|
||||||
|
context.insert("financial", &financial);
|
||||||
context.insert("families", &families);
|
context.insert("families", &families);
|
||||||
context.insert("loggedin_user", &UserWithDetails::from_user(user, db).await);
|
context.insert("loggedin_user", &UserWithDetails::from_user(user, db).await);
|
||||||
|
|
||||||
@ -95,6 +99,7 @@ async fn index_admin(
|
|||||||
let users: Vec<UserWithRolesAndMembershipPdf> = join_all(user_futures).await;
|
let users: Vec<UserWithRolesAndMembershipPdf> = join_all(user_futures).await;
|
||||||
|
|
||||||
let user: User = user.user;
|
let user: User = user.user;
|
||||||
|
let financial = Role::all_cluster(db, "financial").await;
|
||||||
let allowed_to_edit = ManageUserUser::new(db, &user).await.is_some();
|
let allowed_to_edit = ManageUserUser::new(db, &user).await.is_some();
|
||||||
|
|
||||||
let roles = Role::all(db).await;
|
let roles = Role::all(db).await;
|
||||||
@ -107,6 +112,7 @@ async fn index_admin(
|
|||||||
context.insert("allowed_to_edit", &allowed_to_edit);
|
context.insert("allowed_to_edit", &allowed_to_edit);
|
||||||
context.insert("users", &users);
|
context.insert("users", &users);
|
||||||
context.insert("roles", &roles);
|
context.insert("roles", &roles);
|
||||||
|
context.insert("financial", &financial);
|
||||||
context.insert("families", &families);
|
context.insert("families", &families);
|
||||||
context.insert("loggedin_user", &UserWithDetails::from_user(user, db).await);
|
context.insert("loggedin_user", &UserWithDetails::from_user(user, db).await);
|
||||||
|
|
||||||
@ -463,13 +469,13 @@ async fn change_skill(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let skill = if &data.skill_id == "" {
|
let skill = if data.skill_id.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let Ok(skill_id) = data.skill_id.parse() else {
|
let Ok(skill_id) = data.skill_id.parse() else {
|
||||||
return Flash::error(
|
return Flash::error(
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
Redirect::to(format!("/admin/user/{id}")),
|
||||||
format!("Skill_id is not a number"),
|
"Skill_id is not a number",
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
Role::find_by_id(db, skill_id).await
|
Role::find_by_id(db, skill_id).await
|
||||||
@ -503,13 +509,13 @@ async fn change_financial(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let financial = if &data.financial_id == "" {
|
let financial = if data.financial_id.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let Ok(financial_id) = data.financial_id.parse() else {
|
let Ok(financial_id) = data.financial_id.parse() else {
|
||||||
return Flash::error(
|
return Flash::error(
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
Redirect::to(format!("/admin/user/{id}")),
|
||||||
format!("Finacial_id is not a number"),
|
"Finacial_id is not a number",
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
Role::find_by_id(db, financial_id).await
|
Role::find_by_id(db, financial_id).await
|
||||||
@ -899,7 +905,7 @@ async fn schnupperant_to_regular(
|
|||||||
return Flash::error(
|
return Flash::error(
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
Redirect::to(format!("/admin/user/{id}")),
|
||||||
"Membertype gibts ned",
|
"Membertype gibts ned",
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1018,7 +1024,7 @@ async fn scheckbook_to_regular(
|
|||||||
return Flash::error(
|
return Flash::error(
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
Redirect::to(format!("/admin/user/{id}")),
|
||||||
"Membertype gibts ned",
|
"Membertype gibts ned",
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1050,7 +1056,7 @@ async fn change_membertype(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(user) = ClubMemberUser::new(&db, &user).await else {
|
let Some(user) = ClubMemberUser::new(db, &user).await else {
|
||||||
return Flash::error(
|
return Flash::error(
|
||||||
Redirect::to("/admin/user"),
|
Redirect::to("/admin/user"),
|
||||||
format!("User {user} ist kein Vereinsmitglied"),
|
format!("User {user} ist kein Vereinsmitglied"),
|
||||||
@ -1063,9 +1069,9 @@ async fn change_membertype(
|
|||||||
"foerdernd" => user.move_to_foerdernd(db, &admin).await,
|
"foerdernd" => user.move_to_foerdernd(db, &admin).await,
|
||||||
_ => {
|
_ => {
|
||||||
return Flash::error(
|
return Flash::error(
|
||||||
Redirect::to(format!("/admin/user/{{ id }}")),
|
Redirect::to(format!("/admin/user/{id}")),
|
||||||
format!("Membertype gibt's ned"),
|
"Membertype gibt's ned",
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1092,7 +1098,7 @@ async fn schnupperant_to_scheckbook(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(user) = SchnupperantUser::new(&db, &user).await else {
|
let Some(user) = SchnupperantUser::new(db, &user).await else {
|
||||||
return Flash::error(
|
return Flash::error(
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
Redirect::to(format!("/admin/user/{id}")),
|
||||||
format!("User {user} ist kein Schnupperant"),
|
format!("User {user} ist kein Schnupperant"),
|
||||||
@ -1122,7 +1128,7 @@ async fn schnupperinterest_to_schnupperant(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(user) = SchnupperInterestUser::new(&db, &user).await else {
|
let Some(user) = SchnupperInterestUser::new(db, &user).await else {
|
||||||
return Flash::error(
|
return Flash::error(
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
Redirect::to(format!("/admin/user/{id}")),
|
||||||
format!("User {user} ist kein Schnupperinteressierter"),
|
format!("User {user} ist kein Schnupperinteressierter"),
|
||||||
@ -1151,7 +1157,7 @@ async fn schnupperant_to_schnupperinterest(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(user) = SchnupperantUser::new(&db, &user).await else {
|
let Some(user) = SchnupperantUser::new(db, &user).await else {
|
||||||
return Flash::error(
|
return Flash::error(
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
Redirect::to(format!("/admin/user/{id}")),
|
||||||
format!("User {user} ist kein Schnupperant"),
|
format!("User {user} ist kein Schnupperant"),
|
||||||
@ -1180,7 +1186,7 @@ async fn schnupperinterest_to_scheckbuch(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(user) = SchnupperInterestUser::new(&db, &user).await else {
|
let Some(user) = SchnupperInterestUser::new(db, &user).await else {
|
||||||
return Flash::error(
|
return Flash::error(
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
Redirect::to(format!("/admin/user/{id}")),
|
||||||
format!("User {user} ist kein Schnupperinteressierter"),
|
format!("User {user} ist kein Schnupperinteressierter"),
|
||||||
@ -1196,19 +1202,236 @@ async fn schnupperinterest_to_scheckbuch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(FromForm, Debug)]
|
||||||
|
pub struct AddClubMemberForm<'a> {
|
||||||
|
name: String,
|
||||||
|
mail: String,
|
||||||
|
financial_id: String,
|
||||||
|
membertype: String,
|
||||||
|
member_since: String,
|
||||||
|
birthdate: String,
|
||||||
|
phone: String,
|
||||||
|
address: String,
|
||||||
|
membership_pdf: TempFile<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/user/new/clubmember", data = "<data>")]
|
||||||
|
async fn add_club_member(
|
||||||
|
db: &State<SqlitePool>,
|
||||||
|
data: Form<AddClubMemberForm<'_>>,
|
||||||
|
admin: ManageUserUser,
|
||||||
|
config: &State<Config>,
|
||||||
|
) -> Flash<Redirect> {
|
||||||
|
if !valid_mails(&data.mail) {
|
||||||
|
return Flash::error(
|
||||||
|
Redirect::to("/admin/user"),
|
||||||
|
format!(
|
||||||
|
"{} ist kein gültiges Format für eine Mailadresse",
|
||||||
|
&data.mail
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let financial = if data.financial_id.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let Ok(financial_id) = data.financial_id.parse() else {
|
||||||
|
return Flash::error(Redirect::to("/admin/user"), "Finacial_id is not a number");
|
||||||
|
};
|
||||||
|
Role::find_by_id(db, financial_id).await
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(birthdate) = NaiveDate::parse_from_str(&data.birthdate, "%Y-%m-%d") else {
|
||||||
|
return Flash::error(
|
||||||
|
Redirect::to("/admin/user/"),
|
||||||
|
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("/admin/user"),
|
||||||
|
format!(
|
||||||
|
"Beitrittsdatum {} ist nicht im YYYY-MM-DD Format",
|
||||||
|
&data.birthdate
|
||||||
|
),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(phone) = data.phone.clone().try_into() else {
|
||||||
|
return Flash::error(
|
||||||
|
Redirect::to("/admin/user"),
|
||||||
|
"Vereinsmitglied braucht eine Telefonnummer",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
let Ok(address) = data.address.clone().try_into() else {
|
||||||
|
return Flash::error(
|
||||||
|
Redirect::to("/admin/user"),
|
||||||
|
"Vereinsmitglied braucht eine Adresse",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
let Ok(name) = data.name.clone().try_into() else {
|
||||||
|
return Flash::error(
|
||||||
|
Redirect::to("/admin/user"),
|
||||||
|
"Vereinsmitglied braucht einen Namen",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
let response = match &*data.membertype {
|
||||||
|
"regular" => {
|
||||||
|
RegularUser::create(
|
||||||
|
db,
|
||||||
|
&admin,
|
||||||
|
&config.smtp_pw,
|
||||||
|
name,
|
||||||
|
&data.mail,
|
||||||
|
financial,
|
||||||
|
&birthdate,
|
||||||
|
&member_since,
|
||||||
|
phone,
|
||||||
|
address,
|
||||||
|
&data.membership_pdf,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
"unterstuetzend" => {
|
||||||
|
UnterstuetzendUser::create(
|
||||||
|
db,
|
||||||
|
&admin,
|
||||||
|
&config.smtp_pw,
|
||||||
|
name,
|
||||||
|
&data.mail,
|
||||||
|
financial,
|
||||||
|
&birthdate,
|
||||||
|
&member_since,
|
||||||
|
phone,
|
||||||
|
address,
|
||||||
|
&data.membership_pdf,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
"foerdernd" => {
|
||||||
|
FoerderndUser::create(
|
||||||
|
db,
|
||||||
|
&admin,
|
||||||
|
&config.smtp_pw,
|
||||||
|
name,
|
||||||
|
&data.mail,
|
||||||
|
financial,
|
||||||
|
&birthdate,
|
||||||
|
&member_since,
|
||||||
|
phone,
|
||||||
|
address,
|
||||||
|
&data.membership_pdf,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
_ => return Flash::error(Redirect::to("/admin/user"), "Membertype gibts ned"),
|
||||||
|
};
|
||||||
|
|
||||||
|
match response {
|
||||||
|
Ok(_) => Flash::success(Redirect::to("/admin/user"), "Mitglied erfolgreich erstellt"),
|
||||||
|
Err(e) => Flash::error(Redirect::to("/admin/user"), e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(FromForm, Debug)]
|
||||||
|
pub struct AddScheckbuchForm {
|
||||||
|
name: String,
|
||||||
|
mail: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/user/new/scheckbuch", data = "<data>")]
|
||||||
|
async fn add_scheckbuch(
|
||||||
|
db: &State<SqlitePool>,
|
||||||
|
data: Form<AddScheckbuchForm>,
|
||||||
|
admin: ManageUserUser,
|
||||||
|
config: &State<Config>,
|
||||||
|
) -> Flash<Redirect> {
|
||||||
|
if !valid_mails(&data.mail) {
|
||||||
|
return Flash::error(
|
||||||
|
Redirect::to("/admin/user"),
|
||||||
|
format!(
|
||||||
|
"{} ist kein gültiges Format für eine Mailadresse",
|
||||||
|
&data.mail
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let Ok(name) = data.name.clone().try_into() else {
|
||||||
|
return Flash::error(
|
||||||
|
Redirect::to("/admin/user"),
|
||||||
|
"Scheckbuch braucht einen Namen",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
match ScheckbuchUser::create(db, &admin, &config.smtp_pw, name, &data.mail).await {
|
||||||
|
Ok(_) => Flash::success(
|
||||||
|
Redirect::to("/admin/user"),
|
||||||
|
"Scheckbuch erfolgreich erstellt",
|
||||||
|
),
|
||||||
|
Err(e) => Flash::error(Redirect::to("/admin/user"), e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(FromForm, Debug)]
|
||||||
|
pub struct AddSchnupperForm {
|
||||||
|
name: String,
|
||||||
|
mail: String,
|
||||||
|
schnupper_type: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/user/new/schnupper", data = "<data>")]
|
||||||
|
async fn add_schnupper(
|
||||||
|
db: &State<SqlitePool>,
|
||||||
|
data: Form<AddSchnupperForm>,
|
||||||
|
admin: ManageUserUser,
|
||||||
|
config: &State<Config>,
|
||||||
|
) -> Flash<Redirect> {
|
||||||
|
if !valid_mails(&data.mail) {
|
||||||
|
return Flash::error(
|
||||||
|
Redirect::to("/admin/user"),
|
||||||
|
format!(
|
||||||
|
"{} ist kein gültiges Format für eine Mailadresse",
|
||||||
|
&data.mail
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let Ok(name) = data.name.clone().try_into() else {
|
||||||
|
return Flash::error(
|
||||||
|
Redirect::to("/admin/user"),
|
||||||
|
"Schnupperer braucht einen Namen",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
let response = match &*data.schnupper_type {
|
||||||
|
"schnupperInterested" => SchnupperInterestUser::create(db, &admin, name, &data.mail).await,
|
||||||
|
"schnupperant" => {
|
||||||
|
SchnupperantUser::create(db, &admin, &config.smtp_pw, name, &data.mail).await
|
||||||
|
}
|
||||||
|
_ => return Flash::error(Redirect::to("/admin/user"), "Schnuppertyp gibts ned"),
|
||||||
|
};
|
||||||
|
match response {
|
||||||
|
Ok(_) => Flash::success(
|
||||||
|
Redirect::to("/admin/user"),
|
||||||
|
"Schnupperer erfolgreich erstellt",
|
||||||
|
),
|
||||||
|
Err(e) => Flash::error(Redirect::to("/admin/user"), e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
routes![
|
routes![
|
||||||
index,
|
index,
|
||||||
index_admin,
|
index_admin,
|
||||||
view,
|
view,
|
||||||
resetpw,
|
resetpw,
|
||||||
//create_scheckbuch,
|
|
||||||
delete,
|
delete,
|
||||||
fees,
|
fees,
|
||||||
fees_paid,
|
fees_paid,
|
||||||
scheckbuch,
|
scheckbuch,
|
||||||
download_membership_pdf,
|
download_membership_pdf,
|
||||||
//
|
// Updates
|
||||||
update_mail,
|
update_mail,
|
||||||
update_phone,
|
update_phone,
|
||||||
update_nickname,
|
update_nickname,
|
||||||
@ -1222,7 +1445,7 @@ pub fn routes() -> Vec<Route> {
|
|||||||
add_role,
|
add_role,
|
||||||
add_note,
|
add_note,
|
||||||
remove_role,
|
remove_role,
|
||||||
//
|
// Moves
|
||||||
scheckbook_to_regular,
|
scheckbook_to_regular,
|
||||||
schnupperant_to_regular,
|
schnupperant_to_regular,
|
||||||
schnupperant_to_scheckbook,
|
schnupperant_to_scheckbook,
|
||||||
@ -1230,5 +1453,9 @@ pub fn routes() -> Vec<Route> {
|
|||||||
schnupperant_to_schnupperinterest,
|
schnupperant_to_schnupperinterest,
|
||||||
schnupperinterest_to_scheckbuch,
|
schnupperinterest_to_scheckbuch,
|
||||||
change_membertype,
|
change_membertype,
|
||||||
|
// Add
|
||||||
|
add_club_member,
|
||||||
|
add_scheckbuch,
|
||||||
|
add_schnupper,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use rocket::{
|
use rocket::{
|
||||||
|
FromForm, Request, Route, State,
|
||||||
form::Form,
|
form::Form,
|
||||||
get,
|
get,
|
||||||
http::{Cookie, CookieJar},
|
http::{Cookie, CookieJar},
|
||||||
@ -8,9 +9,8 @@ use rocket::{
|
|||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes,
|
routes,
|
||||||
time::{Duration, OffsetDateTime},
|
time::{Duration, OffsetDateTime},
|
||||||
FromForm, Request, Route, State,
|
|
||||||
};
|
};
|
||||||
use rocket_dyn_templates::{context, tera, Template};
|
use rocket_dyn_templates::{Template, context, tera};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::model::{
|
use crate::model::{
|
||||||
@ -73,7 +73,10 @@ async fn login(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Flash::error(Redirect::to("/auth"), "Falscher Benutzername/Passwort. Du bist Vereinsmitglied und der Login klappt nicht? Kontaktiere unseren Schriftführer oder schreibe eine Mail an info@rudernlinz.at!");
|
return Flash::error(
|
||||||
|
Redirect::to("/auth"),
|
||||||
|
"Falscher Benutzername/Passwort. Du bist Vereinsmitglied und der Login klappt nicht? Kontaktiere unseren Schriftführer oder schreibe eine Mail an info@rudernlinz.at!",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@ use crate::model::{
|
|||||||
role::Role,
|
role::Role,
|
||||||
user::{User, UserWithDetails, VorstandUser},
|
user::{User, UserWithDetails, VorstandUser},
|
||||||
};
|
};
|
||||||
use rocket::{get, request::FlashMessage, routes, Route, State};
|
use rocket::{Route, State, get, request::FlashMessage, routes};
|
||||||
use rocket_dyn_templates::{tera::Context, Template};
|
use rocket_dyn_templates::{Template, tera::Context};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
#[get("/achievement")]
|
#[get("/achievement")]
|
||||||
|
@ -4,13 +4,14 @@ use crate::model::{
|
|||||||
user::{AdminUser, UserWithDetails, VorstandUser},
|
user::{AdminUser, UserWithDetails, VorstandUser},
|
||||||
};
|
};
|
||||||
use rocket::{
|
use rocket::{
|
||||||
|
FromForm, Route, State,
|
||||||
form::Form,
|
form::Form,
|
||||||
get, post,
|
get, post,
|
||||||
request::FlashMessage,
|
request::FlashMessage,
|
||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes, FromForm, Route, State,
|
routes,
|
||||||
};
|
};
|
||||||
use rocket_dyn_templates::{tera::Context, Template};
|
use rocket_dyn_templates::{Template, tera::Context};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
#[get("/boathouse")]
|
#[get("/boathouse")]
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use rocket::{
|
use rocket::{
|
||||||
|
FromForm, Route, State,
|
||||||
form::Form,
|
form::Form,
|
||||||
get, post,
|
get, post,
|
||||||
request::FlashMessage,
|
request::FlashMessage,
|
||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes, FromForm, Route, State,
|
routes,
|
||||||
};
|
};
|
||||||
use rocket_dyn_templates::Template;
|
use rocket_dyn_templates::Template;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use rocket::{
|
use rocket::{
|
||||||
|
FromForm, Route, State,
|
||||||
form::Form,
|
form::Form,
|
||||||
get, post,
|
get, post,
|
||||||
request::FlashMessage,
|
request::FlashMessage,
|
||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes, FromForm, Route, State,
|
routes,
|
||||||
};
|
};
|
||||||
use rocket_dyn_templates::Template;
|
use rocket_dyn_templates::Template;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use rocket::{
|
use rocket::{
|
||||||
|
FromForm, Route, State,
|
||||||
form::Form,
|
form::Form,
|
||||||
get, post,
|
get, post,
|
||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes, FromForm, Route, State,
|
routes,
|
||||||
};
|
};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
@ -137,9 +138,10 @@ async fn join(db: &State<SqlitePool>, planned_event_id: i64, cox: SteeringUser)
|
|||||||
.await;
|
.await;
|
||||||
Flash::success(Redirect::to("/planned"), "Danke für's helfen!")
|
Flash::success(Redirect::to("/planned"), "Danke für's helfen!")
|
||||||
}
|
}
|
||||||
Err(CoxHelpError::CanceledEvent) => {
|
Err(CoxHelpError::CanceledEvent) => Flash::error(
|
||||||
Flash::error(Redirect::to("/planned"), "Die Ausfahrt wurde leider abgesagt...")
|
Redirect::to("/planned"),
|
||||||
}
|
"Die Ausfahrt wurde leider abgesagt...",
|
||||||
|
),
|
||||||
Err(CoxHelpError::AlreadyRegisteredAsCox) => {
|
Err(CoxHelpError::AlreadyRegisteredAsCox) => {
|
||||||
Flash::error(Redirect::to("/planned"), "Du hilfst bereits aus!")
|
Flash::error(Redirect::to("/planned"), "Du hilfst bereits aus!")
|
||||||
}
|
}
|
||||||
@ -147,9 +149,10 @@ async fn join(db: &State<SqlitePool>, planned_event_id: i64, cox: SteeringUser)
|
|||||||
Redirect::to("/planned"),
|
Redirect::to("/planned"),
|
||||||
"Du hast dich bereits als Ruderer angemeldet!",
|
"Du hast dich bereits als Ruderer angemeldet!",
|
||||||
),
|
),
|
||||||
Err(CoxHelpError::DetailsLocked) => {
|
Err(CoxHelpError::DetailsLocked) => Flash::error(
|
||||||
Flash::error(Redirect::to("/planned"), "Die Bootseinteilung wurde bereits gemacht. Wenn du noch steuern möchtest, frag bitte bei einer bereits angemeldeten Steuerperson nach, ob das noch möglich ist.")
|
Redirect::to("/planned"),
|
||||||
}
|
"Die Bootseinteilung wurde bereits gemacht. Wenn du noch steuern möchtest, frag bitte bei einer bereits angemeldeten Steuerperson nach, ob das noch möglich ist.",
|
||||||
|
),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Flash::error(Redirect::to("/planned"), "Event gibt's nicht")
|
Flash::error(Redirect::to("/planned"), "Event gibt's nicht")
|
||||||
@ -197,9 +200,10 @@ async fn remove(
|
|||||||
|
|
||||||
Flash::success(Redirect::to("/planned"), "Erfolgreich abgemeldet!")
|
Flash::success(Redirect::to("/planned"), "Erfolgreich abgemeldet!")
|
||||||
}
|
}
|
||||||
Err(TripHelpDeleteError::DetailsLocked) => {
|
Err(TripHelpDeleteError::DetailsLocked) => Flash::error(
|
||||||
Flash::error(Redirect::to("/planned"), "Die Bootseinteilung wurde bereits gemacht. Wenn du doch nicht steuern kannst, melde dich bitte unbedingt schnellstmöglich bei einer anderen Steuerperson!")
|
Redirect::to("/planned"),
|
||||||
}
|
"Die Bootseinteilung wurde bereits gemacht. Wenn du doch nicht steuern kannst, melde dich bitte unbedingt schnellstmöglich bei einer anderen Steuerperson!",
|
||||||
|
),
|
||||||
Err(TripHelpDeleteError::CoxNotHelping) => {
|
Err(TripHelpDeleteError::CoxNotHelping) => {
|
||||||
Flash::error(Redirect::to("/planned"), "Steuermann hilft nicht aus...")
|
Flash::error(Redirect::to("/planned"), "Steuermann hilft nicht aus...")
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ use std::env;
|
|||||||
|
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use rocket::{
|
use rocket::{
|
||||||
|
FromForm, Route, State,
|
||||||
form::Form,
|
form::Form,
|
||||||
fs::TempFile,
|
fs::TempFile,
|
||||||
get,
|
get,
|
||||||
@ -9,9 +10,9 @@ use rocket::{
|
|||||||
post,
|
post,
|
||||||
request::FlashMessage,
|
request::FlashMessage,
|
||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes, FromForm, Route, State,
|
routes,
|
||||||
};
|
};
|
||||||
use rocket_dyn_templates::{context, Template};
|
use rocket_dyn_templates::{Template, context};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
use tera::Context;
|
use tera::Context;
|
||||||
|
142
src/tera/log.rs
142
src/tera/log.rs
@ -1,6 +1,7 @@
|
|||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
|
|
||||||
use rocket::{
|
use rocket::{
|
||||||
|
Request, Route, State,
|
||||||
form::Form,
|
form::Form,
|
||||||
get,
|
get,
|
||||||
http::{Cookie, CookieJar},
|
http::{Cookie, CookieJar},
|
||||||
@ -9,9 +10,8 @@ use rocket::{
|
|||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes,
|
routes,
|
||||||
time::{Duration, OffsetDateTime},
|
time::{Duration, OffsetDateTime},
|
||||||
Request, Route, State,
|
|
||||||
};
|
};
|
||||||
use rocket_dyn_templates::{context, Template};
|
use rocket_dyn_templates::{Template, context};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
use tera::Context;
|
use tera::Context;
|
||||||
|
|
||||||
@ -215,31 +215,77 @@ async fn create_logbook(
|
|||||||
user: &DonauLinzUser,
|
user: &DonauLinzUser,
|
||||||
smtp_pw: &str,
|
smtp_pw: &str,
|
||||||
) -> Flash<Redirect> {
|
) -> Flash<Redirect> {
|
||||||
match Logbook::create(
|
match Logbook::create(db, data.into_inner(), user, smtp_pw).await {
|
||||||
db,
|
Ok(msg) => Flash::success(
|
||||||
data.into_inner(),
|
Redirect::to("/log"),
|
||||||
user, smtp_pw
|
format!("Ausfahrt erfolgreich hinzugefügt{msg}"),
|
||||||
)
|
),
|
||||||
.await
|
Err(LogbookCreateError::BoatAlreadyOnWater) => {
|
||||||
{
|
Flash::error(Redirect::to("/log"), "Boot schon am Wasser")
|
||||||
Ok(msg) => Flash::success(Redirect::to("/log"), format!("Ausfahrt erfolgreich hinzugefügt{msg}")),
|
}
|
||||||
Err(LogbookCreateError::BoatAlreadyOnWater) => Flash::error(Redirect::to("/log"), "Boot schon am Wasser"),
|
Err(LogbookCreateError::RowerAlreadyOnWater(rower)) => Flash::error(
|
||||||
Err(LogbookCreateError::RowerAlreadyOnWater(rower)) => Flash::error(Redirect::to("/log"), format!("Ruderer {} schon am Wasser", rower.name)),
|
Redirect::to("/log"),
|
||||||
|
format!("Ruderer {} schon am Wasser", rower.name),
|
||||||
|
),
|
||||||
Err(LogbookCreateError::BoatLocked) => Flash::error(Redirect::to("/log"), "Boot gesperrt"),
|
Err(LogbookCreateError::BoatLocked) => Flash::error(Redirect::to("/log"), "Boot gesperrt"),
|
||||||
Err(LogbookCreateError::BoatNotFound) => Flash::error(Redirect::to("/log"), "Boot gibt's ned"),
|
Err(LogbookCreateError::BoatNotFound) => {
|
||||||
Err(LogbookCreateError::TooManyRowers(expected, actual)) => Flash::error(Redirect::to("/log"), format!("Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)")),
|
Flash::error(Redirect::to("/log"), "Boot gibt's ned")
|
||||||
Err(LogbookCreateError::RowerCreateError(rower, e)) => Flash::error(Redirect::to("/log"), format!("Fehler bei Ruderer {rower}: {e}")),
|
}
|
||||||
Err(LogbookCreateError::ArrivalNotAfterDeparture) => Flash::error(Redirect::to("/log"), "Ankunftszeit kann nicht vor der Abfahrtszeit sein"),
|
Err(LogbookCreateError::TooManyRowers(expected, actual)) => Flash::error(
|
||||||
Err(LogbookCreateError::UserNotAllowedToUseBoat) => Flash::error(Redirect::to("/log"), "Schiffsführer darf dieses Boot nicht verwenden"),
|
Redirect::to("/log"),
|
||||||
Err(LogbookCreateError::SteeringPersonNotInRowers) => Flash::error(Redirect::to("/log"), "Steuerperson nicht in Liste der Ruderer!"),
|
format!(
|
||||||
Err(LogbookCreateError::ShipmasterNotInRowers) => Flash::error(Redirect::to("/log"), "Schiffsführer nicht in Liste der Ruderer!"),
|
"Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)"
|
||||||
Err(LogbookCreateError::NotYourEntry) => Flash::error(Redirect::to("/log"), "Nicht deine Ausfahrt!"),
|
),
|
||||||
Err(LogbookCreateError::ArrivalSetButNotRemainingTwo) => Flash::error(Redirect::to("/log"), "Ankunftszeit gesetzt aber nicht Distanz + Strecke"),
|
),
|
||||||
Err(LogbookCreateError::OnlyAllowedToEndTripsEndingToday) => Flash::error(Redirect::to("/log"), "Nur Ausfahrten, die in der letzten Woche enden dürfen eingetragen werden. Für einen Nachtrag schreibe alle Daten an den Vorstand (info@rudernlinz.at)."),
|
Err(LogbookCreateError::RowerCreateError(rower, e)) => Flash::error(
|
||||||
Err(LogbookCreateError::CantChangeHandoperatableStatusForThisBoat) => Flash::error(Redirect::to("/log"), "Handsteuer-Status dieses Boots kann nicht verändert werden."),
|
Redirect::to("/log"),
|
||||||
Err(LogbookCreateError::TooFast(km, min)) => Flash::error(Redirect::to("/log"), format!("KM zu groß für die eingegebene Dauer ({km} km in {min} Minuten). Bitte überprüfe deine Start- und Endzeit und versuche es erneut.")),
|
format!("Fehler bei Ruderer {rower}: {e}"),
|
||||||
Err(LogbookCreateError::AlreadyFinalized) => Flash::error(Redirect::to("/log"), "Logbucheintrag wurde bereits abgeschlossen."),
|
),
|
||||||
Err(LogbookCreateError::ExternalSteeringPersonMustSteerOrShipmaster) => Flash::error(Redirect::to("/log"), "Wenn du eine 'Externe Steuerperson' hinzufügst, muss diese steuern oder Schiffsführer sein!"),
|
Err(LogbookCreateError::ArrivalNotAfterDeparture) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
"Ankunftszeit kann nicht vor der Abfahrtszeit sein",
|
||||||
|
),
|
||||||
|
Err(LogbookCreateError::UserNotAllowedToUseBoat) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
"Schiffsführer darf dieses Boot nicht verwenden",
|
||||||
|
),
|
||||||
|
Err(LogbookCreateError::SteeringPersonNotInRowers) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
"Steuerperson nicht in Liste der Ruderer!",
|
||||||
|
),
|
||||||
|
Err(LogbookCreateError::ShipmasterNotInRowers) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
"Schiffsführer nicht in Liste der Ruderer!",
|
||||||
|
),
|
||||||
|
Err(LogbookCreateError::NotYourEntry) => {
|
||||||
|
Flash::error(Redirect::to("/log"), "Nicht deine Ausfahrt!")
|
||||||
|
}
|
||||||
|
Err(LogbookCreateError::ArrivalSetButNotRemainingTwo) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
"Ankunftszeit gesetzt aber nicht Distanz + Strecke",
|
||||||
|
),
|
||||||
|
Err(LogbookCreateError::OnlyAllowedToEndTripsEndingToday) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
"Nur Ausfahrten, die in der letzten Woche enden dürfen eingetragen werden. Für einen Nachtrag schreibe alle Daten an den Vorstand (info@rudernlinz.at).",
|
||||||
|
),
|
||||||
|
Err(LogbookCreateError::CantChangeHandoperatableStatusForThisBoat) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
"Handsteuer-Status dieses Boots kann nicht verändert werden.",
|
||||||
|
),
|
||||||
|
Err(LogbookCreateError::TooFast(km, min)) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
format!(
|
||||||
|
"KM zu groß für die eingegebene Dauer ({km} km in {min} Minuten). Bitte überprüfe deine Start- und Endzeit und versuche es erneut."
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Err(LogbookCreateError::AlreadyFinalized) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
"Logbucheintrag wurde bereits abgeschlossen.",
|
||||||
|
),
|
||||||
|
Err(LogbookCreateError::ExternalSteeringPersonMustSteerOrShipmaster) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
"Wenn du eine 'Externe Steuerperson' hinzufügst, muss diese steuern oder Schiffsführer sein!",
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +358,13 @@ async fn update(
|
|||||||
let data = data.into_inner();
|
let data = data.into_inner();
|
||||||
|
|
||||||
let Some(logbook) = Logbook::find_by_id(db, data.id).await else {
|
let Some(logbook) = Logbook::find_by_id(db, data.id).await else {
|
||||||
return Flash::error(Redirect::to("/log"), format!("Logbucheintrag kann nicht bearbeitet werden, da es einen Logbuch-Eintrag mit ID={} nicht gibt", data.id));
|
return Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
format!(
|
||||||
|
"Logbucheintrag kann nicht bearbeitet werden, da es einen Logbuch-Eintrag mit ID={} nicht gibt",
|
||||||
|
data.id
|
||||||
|
),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
match logbook.update(db, data.clone(), &user.user).await {
|
match logbook.update(db, data.clone(), &user.user).await {
|
||||||
@ -355,12 +407,34 @@ async fn home_logbook(
|
|||||||
|
|
||||||
match logbook.home(db, user, data.into_inner(), smtp_pw).await {
|
match logbook.home(db, user, data.into_inner(), smtp_pw).await {
|
||||||
Ok(_) => Flash::success(Redirect::to("/log"), "Ausfahrt korrekt eingetragen"),
|
Ok(_) => Flash::success(Redirect::to("/log"), "Ausfahrt korrekt eingetragen"),
|
||||||
Err(LogbookUpdateError::TooManyRowers(expected, actual)) => Flash::error(Redirect::to("/log"), format!("Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)")),
|
Err(LogbookUpdateError::TooManyRowers(expected, actual)) => Flash::error(
|
||||||
Err(LogbookUpdateError::OnlyAllowedToEndTripsEndingToday) => Flash::error(Redirect::to("/log"), "Nur Ausfahrten, die heute enden dürfen eingetragen werden. Für einen Nachtrag schreibe alle Daten dem Vorstand an info@rudernlinz.at."),
|
Redirect::to("/log"),
|
||||||
Err(LogbookUpdateError::TooFast(km, min)) => Flash::error(Redirect::to("/log"), format!("KM zu groß für die eingegebene Dauer ({km} km in {min} Minuten). Bitte überprüfe deine Start- und Endzeit und versuche es erneut.")),
|
format!(
|
||||||
Err(LogbookUpdateError::AlreadyFinalized) => Flash::error(Redirect::to("/log"), "Logbucheintrag wurde bereits abgeschlossen."),
|
"Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)"
|
||||||
Err(LogbookUpdateError::ExternalSteeringPersonMustSteerOrShipmaster) => Flash::error(Redirect::to("/log"), "Wenn du eine 'Externe Steuerperson' hinzufügst, muss diese steuern oder Schiffsführer sein!"),
|
),
|
||||||
Err(LogbookUpdateError::BoatAlreadyOnWater) => Flash::error(Redirect::to("/log"), "Das Boot war in diesem Zeitraum schon am Wasser. Bitte überprüfe das Datum und die Zeit."),
|
),
|
||||||
|
Err(LogbookUpdateError::OnlyAllowedToEndTripsEndingToday) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
"Nur Ausfahrten, die heute enden dürfen eingetragen werden. Für einen Nachtrag schreibe alle Daten dem Vorstand an info@rudernlinz.at.",
|
||||||
|
),
|
||||||
|
Err(LogbookUpdateError::TooFast(km, min)) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
format!(
|
||||||
|
"KM zu groß für die eingegebene Dauer ({km} km in {min} Minuten). Bitte überprüfe deine Start- und Endzeit und versuche es erneut."
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Err(LogbookUpdateError::AlreadyFinalized) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
"Logbucheintrag wurde bereits abgeschlossen.",
|
||||||
|
),
|
||||||
|
Err(LogbookUpdateError::ExternalSteeringPersonMustSteerOrShipmaster) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
"Wenn du eine 'Externe Steuerperson' hinzufügst, muss diese steuern oder Schiffsführer sein!",
|
||||||
|
),
|
||||||
|
Err(LogbookUpdateError::BoatAlreadyOnWater) => Flash::error(
|
||||||
|
Redirect::to("/log"),
|
||||||
|
"Das Boot war in diesem Zeitraum schon am Wasser. Bitte überprüfe das Datum und die Zeit.",
|
||||||
|
),
|
||||||
Err(e) => Flash::error(
|
Err(e) => Flash::error(
|
||||||
Redirect::to("/log"),
|
Redirect::to("/log"),
|
||||||
format!("Eintrag {logbook_id} konnte nicht abgesendet werden (Fehler: {e:?})!"),
|
format!("Eintrag {logbook_id} konnte nicht abgesendet werden (Fehler: {e:?})!"),
|
||||||
@ -508,7 +582,7 @@ mod test {
|
|||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::model::logbook::Logbook;
|
use crate::model::logbook::Logbook;
|
||||||
use crate::tera::{log::Boat, User};
|
use crate::tera::{User, log::Boat};
|
||||||
use crate::testdb;
|
use crate::testdb;
|
||||||
|
|
||||||
#[sqlx::test]
|
#[sqlx::test]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use rocket::{get, http::ContentType, routes, Route, State};
|
use rocket::{Route, State, get, http::ContentType, routes};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::model::{event::Event, personal::cal::get_personal_cal, user::User};
|
use crate::model::{event::Event, personal::cal::get_personal_cal, user::User};
|
||||||
|
@ -2,7 +2,7 @@ use std::{fs::OpenOptions, io::Write};
|
|||||||
|
|
||||||
use chrono::{Datelike, Local};
|
use chrono::{Datelike, Local};
|
||||||
use rocket::{
|
use rocket::{
|
||||||
catch, catchers,
|
Build, Data, FromForm, Request, Rocket, State, catch, catchers,
|
||||||
fairing::{AdHoc, Fairing, Info, Kind},
|
fairing::{AdHoc, Fairing, Info, Kind},
|
||||||
form::Form,
|
form::Form,
|
||||||
fs::FileServer,
|
fs::FileServer,
|
||||||
@ -13,7 +13,6 @@ use rocket::{
|
|||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes,
|
routes,
|
||||||
time::{Duration, OffsetDateTime},
|
time::{Duration, OffsetDateTime},
|
||||||
Build, Data, FromForm, Request, Rocket, State,
|
|
||||||
};
|
};
|
||||||
use rocket_dyn_templates::Template;
|
use rocket_dyn_templates::Template;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
@ -21,6 +20,7 @@ use sqlx::SqlitePool;
|
|||||||
use tera::Context;
|
use tera::Context;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
SCHECKBUCH,
|
||||||
model::{
|
model::{
|
||||||
logbook::Logbook,
|
logbook::Logbook,
|
||||||
notification::Notification,
|
notification::Notification,
|
||||||
@ -28,7 +28,6 @@ use crate::{
|
|||||||
role::Role,
|
role::Role,
|
||||||
user::{User, UserWithDetails},
|
user::{User, UserWithDetails},
|
||||||
},
|
},
|
||||||
SCHECKBUCH,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) mod admin;
|
pub(crate) mod admin;
|
||||||
@ -202,7 +201,10 @@ async fn blogpost_unpublished(
|
|||||||
|
|
||||||
#[catch(403)] //forbidden
|
#[catch(403)] //forbidden
|
||||||
fn forbidden_error() -> Flash<Redirect> {
|
fn forbidden_error() -> Flash<Redirect> {
|
||||||
Flash::error(Redirect::to("/"), "Keine Berechtigung für diese Aktion. Wenn du der Meinung bist, dass du das machen darfst, melde dich bitte bei it@rudernlinz.at.")
|
Flash::error(
|
||||||
|
Redirect::to("/"),
|
||||||
|
"Keine Berechtigung für diese Aktion. Wenn du der Meinung bist, dass du das machen darfst, melde dich bitte bei it@rudernlinz.at.",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Usage {}
|
struct Usage {}
|
||||||
@ -328,11 +330,13 @@ mod test {
|
|||||||
|
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
|
||||||
assert!(response
|
assert!(
|
||||||
|
response
|
||||||
.into_string()
|
.into_string()
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.contains("Ruderassistent"));
|
.contains("Ruderassistent")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[sqlx::test]
|
#[sqlx::test]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use rocket::{
|
use rocket::{
|
||||||
get,
|
Route, State, get,
|
||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes, Route, State,
|
routes,
|
||||||
};
|
};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
use rocket::{
|
use rocket::{
|
||||||
get,
|
Route, State, get,
|
||||||
request::FlashMessage,
|
request::FlashMessage,
|
||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes, Route, State,
|
routes,
|
||||||
};
|
};
|
||||||
use rocket_dyn_templates::Template;
|
use rocket_dyn_templates::Template;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
use tera::Context;
|
use tera::Context;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
AMOUNT_DAYS_TO_SHOW_TRIPS_AHEAD,
|
||||||
model::{
|
model::{
|
||||||
log::Log,
|
log::Log,
|
||||||
tripdetails::TripDetails,
|
tripdetails::TripDetails,
|
||||||
@ -16,7 +17,6 @@ use crate::{
|
|||||||
user::{AllowedForPlannedTripsUser, User, UserWithDetails},
|
user::{AllowedForPlannedTripsUser, User, UserWithDetails},
|
||||||
usertrip::{UserTrip, UserTripDeleteError, UserTripError},
|
usertrip::{UserTrip, UserTripDeleteError, UserTripError},
|
||||||
},
|
},
|
||||||
AMOUNT_DAYS_TO_SHOW_TRIPS_AHEAD,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
@ -88,7 +88,8 @@ async fn join(
|
|||||||
"User {} registered the guest '{}' for trip_details.id={}",
|
"User {} registered the guest '{}' for trip_details.id={}",
|
||||||
user.name, registered_user, trip_details_id
|
user.name, registered_user, trip_details_id
|
||||||
),
|
),
|
||||||
).await;
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
Flash::success(Redirect::to("/planned"), "Erfolgreich angemeldet!")
|
Flash::success(Redirect::to("/planned"), "Erfolgreich angemeldet!")
|
||||||
}
|
}
|
||||||
@ -98,9 +99,10 @@ async fn join(
|
|||||||
Err(UserTripError::AlreadyRegistered) => {
|
Err(UserTripError::AlreadyRegistered) => {
|
||||||
Flash::error(Redirect::to("/planned"), "Du nimmst bereits teil!")
|
Flash::error(Redirect::to("/planned"), "Du nimmst bereits teil!")
|
||||||
}
|
}
|
||||||
Err(UserTripError::AlreadyRegisteredAsCox) => {
|
Err(UserTripError::AlreadyRegisteredAsCox) => Flash::error(
|
||||||
Flash::error(Redirect::to("/planned"), "Du hilfst bereits als Steuerperson aus!")
|
Redirect::to("/planned"),
|
||||||
}
|
"Du hilfst bereits als Steuerperson aus!",
|
||||||
|
),
|
||||||
Err(UserTripError::CantRegisterAtOwnEvent) => Flash::error(
|
Err(UserTripError::CantRegisterAtOwnEvent) => Flash::error(
|
||||||
Redirect::to("/planned"),
|
Redirect::to("/planned"),
|
||||||
"Du kannst bei einer selbst ausgeschriebenen Fahrt nicht mitrudern ;)",
|
"Du kannst bei einer selbst ausgeschriebenen Fahrt nicht mitrudern ;)",
|
||||||
@ -160,7 +162,10 @@ async fn remove_guest(
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
Flash::error(Redirect::to("/planned"), "Die Bootseinteilung wurde bereits gemacht. Wenn du doch nicht mitrudern kannst, melde dich bitte unbedingt schnellstmöglich bei einer angemeldeten Steuerperson!")
|
Flash::error(
|
||||||
|
Redirect::to("/planned"),
|
||||||
|
"Die Bootseinteilung wurde bereits gemacht. Wenn du doch nicht mitrudern kannst, melde dich bitte unbedingt schnellstmöglich bei einer angemeldeten Steuerperson!",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Err(UserTripDeleteError::GuestNotParticipating) => {
|
Err(UserTripDeleteError::GuestNotParticipating) => {
|
||||||
Flash::error(Redirect::to("/planned"), "Gast nicht angemeldet.")
|
Flash::error(Redirect::to("/planned"), "Gast nicht angemeldet.")
|
||||||
@ -211,7 +216,10 @@ async fn remove(
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
Flash::error(Redirect::to("/planned"), "Das Boot ist bereits eingeteilt. Bitte kontaktiere den Schiffsführer (Nummern siehe Signalgruppe) falls du dich doch abmelden willst.")
|
Flash::error(
|
||||||
|
Redirect::to("/planned"),
|
||||||
|
"Das Boot ist bereits eingeteilt. Bitte kontaktiere den Schiffsführer (Nummern siehe Signalgruppe) falls du dich doch abmelden willst.",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Err(UserTripDeleteError::NotVisibleToUser) => {
|
Err(UserTripDeleteError::NotVisibleToUser) => {
|
||||||
Log::create(
|
Log::create(
|
||||||
@ -223,7 +231,10 @@ async fn remove(
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
Flash::error(Redirect::to("/planned"), "Abmeldung nicht möglich, da du dieses Event eigentlich gar nicht sehen solltest...")
|
Flash::error(
|
||||||
|
Redirect::to("/planned"),
|
||||||
|
"Abmeldung nicht möglich, da du dieses Event eigentlich gar nicht sehen solltest...",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
panic!("Not possible to be here");
|
panic!("Not possible to be here");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use rocket::{get, routes, Route, State};
|
use rocket::{Route, State, get, routes};
|
||||||
use rocket_dyn_templates::{context, Template};
|
use rocket_dyn_templates::{Template, context};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::model::{
|
use crate::model::{
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use rocket::{
|
use rocket::{
|
||||||
|
FromForm, Route, State,
|
||||||
form::Form,
|
form::Form,
|
||||||
get, post,
|
get, post,
|
||||||
request::FlashMessage,
|
request::FlashMessage,
|
||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes, FromForm, Route, State,
|
routes,
|
||||||
};
|
};
|
||||||
use rocket_dyn_templates::Template;
|
use rocket_dyn_templates::Template;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
@ -8,26 +8,66 @@
|
|||||||
<summary class="px-3 cursor-pointer text-md font-bold text-primary-950 dark:text-white">
|
<summary class="px-3 cursor-pointer text-md font-bold text-primary-950 dark:text-white">
|
||||||
Neue Person hinzufügen
|
Neue Person hinzufügen
|
||||||
</summary>
|
</summary>
|
||||||
<form action="/admin/user/new"
|
<details class="mt-5 bg-gray-200 dark:bg-primary-600 p-3 rounded-md">
|
||||||
onsubmit="return confirm('Willst du wirklich einen neuen Benutzer anlegen?');"
|
<summary class="px-3 cursor-pointer text-md font-bold text-primary-950 dark:text-white">Vereinsmitglied</summary>
|
||||||
|
<form action="/admin/user/new/clubmember"
|
||||||
method="post"
|
method="post"
|
||||||
class="flex mt-4 rounded-md sm:flex items-end justify-between">
|
enctype="multipart/form-data"
|
||||||
<div class="w-full">
|
class="grid gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label for="name" class="sr-only">Name</label>
|
<label for="membertype" class="text-sm text-gray-600 dark:text-gray-100">Mitgliedstyp</label>
|
||||||
<input type="text"
|
<select name="membertype" id="membertype" class="input rounded-md ">
|
||||||
name="name"
|
<option selected="" value="regular">Reguläres Vereinsmitglied</option>
|
||||||
class="input rounded-md w-100"
|
<option value="unterstuetzend">Unterstützendes Vereinsmitglied</option>
|
||||||
placeholder="Name" />
|
<option value="foerdernd">Förderndes Vereinsmitglied</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{ macros::input(label='Name', name='name', type="text", required=true) }}
|
||||||
<div class="text-right ml-3">
|
{{ macros::input(label='Mailadresse', name='mail', type="email", required=true) }}
|
||||||
<input value="Hinzufügen"
|
{{ macros::select(label="Finanzielles", data=financial, name='financial_id', display=['name'], default="Keine Ermäßigung") }}
|
||||||
|
{{ macros::input(label='Mitglied seit', name='member_since', type="date", value=now() | date(), required=true) }}
|
||||||
|
{{ macros::input(label='Geburtsdatum', name='birthdate', type="date", required=true) }}
|
||||||
|
{{ macros::input(label='Telefonnummer', name='phone', type="text", required=true) }}
|
||||||
|
{{ macros::input(label='Adresse', name='address', type="text", required=true) }}
|
||||||
|
{{ macros::input(label='Beitrittserklärung', name='membership_pdf', type="file", accept='application/pdf', required=true) }}
|
||||||
|
<input value="Neues Vereinsmitglied anlegen"
|
||||||
type="submit"
|
type="submit"
|
||||||
class="w-28 mt-2 sm:mt-0 rounded-md bg-primary-500 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer" />
|
class="btn btn-primary" />
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</details>
|
</details>
|
||||||
|
<details class="mt-5 bg-gray-200 dark:bg-primary-600 p-3 rounded-md">
|
||||||
|
<summary class="px-3 cursor-pointer text-md font-bold text-primary-950 dark:text-white">Scheckbuch</summary>
|
||||||
|
<form action="/admin/user/new/scheckbuch"
|
||||||
|
method="post"
|
||||||
|
enctype="multipart/form-data"
|
||||||
|
class="grid gap-3">
|
||||||
|
{{ macros::input(label='Name', name='name', type="text", required=true) }}
|
||||||
|
{{ macros::input(label='Mailadresse', name='mail', type="email", required=true) }}
|
||||||
|
<input value="Neues Scheckbuch anlegen"
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-primary" />
|
||||||
|
</form>
|
||||||
|
</details>
|
||||||
|
<details class="mt-5 bg-gray-200 dark:bg-primary-600 p-3 rounded-md">
|
||||||
|
<summary class="px-3 cursor-pointer text-md font-bold text-primary-950 dark:text-white">Schnupperkurs</summary>
|
||||||
|
<form action="/admin/user/new/schnupper"
|
||||||
|
method="post"
|
||||||
|
enctype="multipart/form-data"
|
||||||
|
class="grid gap-3">
|
||||||
|
<div>
|
||||||
|
<label for="schnupper_type" class="text-sm text-gray-600 dark:text-gray-100">Typ</label>
|
||||||
|
<select name="schnupper_type" id="schnupper_type" class="input rounded-md ">
|
||||||
|
<option value="schnupperInterested">Interessiert am Schnupperkurs</option>
|
||||||
|
<option value="schnupperant">Fixe Schnupperkurs-Anmeldung</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{{ macros::input(label='Name', name='name', type="text", required=true) }}
|
||||||
|
{{ macros::input(label='Mailadresse', name='mail', type="email", required=true) }}
|
||||||
|
{{ macros::select(label="Finanzielles", data=financial, name='financial_id', display=['name'], default="Keine Ermäßigung") }}
|
||||||
|
<input value="Hinzufügen" type="submit" class="btn btn-primary" />
|
||||||
|
</form>
|
||||||
|
</details>
|
||||||
|
</details>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<!-- START filterBar -->
|
<!-- START filterBar -->
|
||||||
<div class="search-wrapper flex">
|
<div class="search-wrapper flex">
|
||||||
|
@ -175,19 +175,27 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<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? Seine restlichen Scheckbuch-Ausfahrten entfallen damit...');">
|
||||||
|
{% include "includes/delete-icon" %}
|
||||||
|
Daten löschen
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% elif "SchnupperInterest" in member %}
|
{% elif "SchnupperInterest" in member %}
|
||||||
{% if allowed_to_edit %}
|
{% if allowed_to_edit %}
|
||||||
<div class="grid pt-3">
|
|
||||||
<a href="/admin/user/{{ user.id }}/schnupperinterest-to-scheckbuch"
|
|
||||||
class="btn btn-dark"
|
|
||||||
onclick="return confirm('Willst du \'{{ user.name }}\' wirklich auf ein Scheckbuch umwandeln?');">In Scheckbuch umwandeln</a>
|
|
||||||
</div>
|
|
||||||
<div class="grid pt-3">
|
<div class="grid pt-3">
|
||||||
<a href="/admin/user/{{ user.id }}/schnupperinterest-to-schnupperant"
|
<a href="/admin/user/{{ user.id }}/schnupperinterest-to-schnupperant"
|
||||||
class="btn btn-dark"
|
class="btn btn-dark"
|
||||||
onclick="return confirm('Hat sich \'{{ user.name }}\' wirklich zum Kurs angemeldet?');">Zum Schnupperkurs angemeldet</a>
|
onclick="return confirm('Hat sich \'{{ user.name }}\' wirklich zum Kurs angemeldet?');">Zum Schnupperkurs angemeldet</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grid pt-3">
|
||||||
|
<a href="/admin/user/{{ user.id }}/schnupperinterest-to-scheckbuch"
|
||||||
|
class="btn btn-dark"
|
||||||
|
onclick="return confirm('Willst du \'{{ user.name }}\' wirklich auf ein Scheckbuch umwandeln?');">In Scheckbuch umwandeln</a>
|
||||||
|
</div>
|
||||||
<div class="grid pt-3">
|
<div class="grid pt-3">
|
||||||
<a href="/admin/user/{{ user.id }}/delete"
|
<a href="/admin/user/{{ user.id }}/delete"
|
||||||
class="btn btn-alert"
|
class="btn btn-alert"
|
||||||
@ -272,14 +280,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
<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? Seine restlichen Scheckbuch-Ausfahrten entfallen damit...');">
|
|
||||||
{% include "includes/delete-icon" %}
|
|
||||||
Daten löschen
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user