start with activity + fix tests
This commit is contained in:
parent
d50501b362
commit
e360c4f06b
@ -225,6 +225,15 @@ CREATE TABLE IF NOT EXISTS "distance" (
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "activity" (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
text TEXT NOT NULL,
|
||||
relevant_for TEXT NOT NULL, -- e.g. user_id=123;trip_id=456
|
||||
keep_until DATETIME
|
||||
);
|
||||
|
||||
|
||||
CREATE TRIGGER IF NOT EXISTS prevent_multiple_roles_same_cluster
|
||||
BEFORE INSERT ON user_role
|
||||
BEGIN
|
||||
|
54
src/model/activity.rs
Normal file
54
src/model/activity.rs
Normal file
@ -0,0 +1,54 @@
|
||||
use std::ops::DerefMut;
|
||||
|
||||
use chrono::NaiveDateTime;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
|
||||
|
||||
#[derive(FromRow, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct Activity {
|
||||
pub id: i64,
|
||||
pub created_at: NaiveDateTime,
|
||||
pub text: String,
|
||||
pub relevant_for: String,
|
||||
pub keep_until: Option<NaiveDateTime>,
|
||||
}
|
||||
|
||||
impl Activity {
|
||||
pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option<Self> {
|
||||
sqlx::query_as!(
|
||||
Self,
|
||||
"SELECT id, created_at, text, relevant_for, keep_until FROM activity WHERE id like ?",
|
||||
id
|
||||
)
|
||||
.fetch_one(db)
|
||||
.await
|
||||
.ok()
|
||||
}
|
||||
pub async fn create_with_tx(
|
||||
db: &mut Transaction<'_, Sqlite>,
|
||||
text: &str,
|
||||
relevant_for: &str,
|
||||
keep_until: Option<NaiveDateTime>,
|
||||
) {
|
||||
sqlx::query!(
|
||||
"INSERT INTO activity(text, relevant_for, keep_until) VALUES (?, ?, ?)",
|
||||
text,
|
||||
relevant_for,
|
||||
keep_until
|
||||
)
|
||||
.execute(db.deref_mut())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub async fn create(
|
||||
db: &SqlitePool,
|
||||
text: &str,
|
||||
relevant_for: &str,
|
||||
keep_until: Option<NaiveDateTime>,
|
||||
) {
|
||||
let mut tx = db.begin().await.unwrap();
|
||||
Self::create_with_tx(&mut tx, text, relevant_for, keep_until).await;
|
||||
tx.commit().await.unwrap();
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ use self::{
|
||||
use boatreservation::{BoatReservation, BoatReservationWithDetails};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub mod activity;
|
||||
pub mod boat;
|
||||
pub mod boatdamage;
|
||||
pub mod boathouse;
|
||||
|
@ -1,12 +1,25 @@
|
||||
// TODO: put back in `src/model/user/mod.rs` once that is cleaned up
|
||||
|
||||
use super::{AllowedToEditPaymentStatusUser, ManageUserUser, User};
|
||||
use crate::model::{family::Family, log::Log, mail::valid_mails, role::Role};
|
||||
use crate::model::{activity::Activity, family::Family, log::Log, mail::valid_mails, role::Role};
|
||||
use chrono::NaiveDate;
|
||||
use rocket::{fs::TempFile, tokio::io::AsyncReadExt};
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
impl User {
|
||||
pub(crate) async fn add_note(
|
||||
&self,
|
||||
db: &SqlitePool,
|
||||
updated_by: &ManageUserUser,
|
||||
note: &str,
|
||||
) -> Result<(), String> {
|
||||
let note = note.trim();
|
||||
|
||||
Activity::create(db, note, "relevant_for", None).await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn update_mail(
|
||||
&self,
|
||||
db: &SqlitePool,
|
||||
|
@ -951,9 +951,7 @@ impl UserWithMembershipPdf {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{tera::admin::user::UserEditForm, testdb};
|
||||
use crate::testdb;
|
||||
|
||||
use super::User;
|
||||
use sqlx::SqlitePool;
|
||||
@ -1014,38 +1012,6 @@ mod test {
|
||||
assert_eq!(User::create(&pool, "admin".into()).await, false);
|
||||
}
|
||||
|
||||
#[sqlx::test]
|
||||
fn test_update() {
|
||||
let pool = testdb!();
|
||||
|
||||
let user = User::find_by_id(&pool, 1).await.unwrap();
|
||||
user.update(
|
||||
&pool,
|
||||
UserEditForm {
|
||||
id: 1,
|
||||
dob: None,
|
||||
weight: None,
|
||||
sex: Some("m".into()),
|
||||
roles: HashMap::new(),
|
||||
member_since_date: None,
|
||||
birthdate: None,
|
||||
mail: None,
|
||||
nickname: None,
|
||||
notes: None,
|
||||
phone: None,
|
||||
address: None,
|
||||
family_id: None,
|
||||
membership_pdf: None,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let user = User::find_by_id(&pool, 1).await.unwrap();
|
||||
|
||||
assert_eq!(user.sex, Some("m".into()));
|
||||
}
|
||||
|
||||
#[sqlx::test]
|
||||
fn succ_login_with_test_db() {
|
||||
let pool = testdb!();
|
||||
|
@ -327,6 +327,34 @@ async fn update_mail(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromForm, Debug)]
|
||||
pub struct AddNoteForm {
|
||||
note: String,
|
||||
}
|
||||
|
||||
#[post("/user/<id>/add-note", data = "<data>")]
|
||||
async fn add_note(
|
||||
db: &State<SqlitePool>,
|
||||
data: Form<AddNoteForm>,
|
||||
admin: ManageUserUser,
|
||||
id: i32,
|
||||
) -> Flash<Redirect> {
|
||||
let Some(user) = User::find_by_id(db, id).await else {
|
||||
return Flash::error(
|
||||
Redirect::to("/admin/user"),
|
||||
format!("User with ID {} does not exist!", id),
|
||||
);
|
||||
};
|
||||
|
||||
match user.add_note(db, &admin, &data.note).await {
|
||||
Ok(_) => Flash::success(
|
||||
Redirect::to(format!("/admin/user/{}", user.id)),
|
||||
"Notiz hinzugefügt",
|
||||
),
|
||||
Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", user.id)), e),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromForm, Debug)]
|
||||
pub struct PhoneUpdateForm {
|
||||
phone: String,
|
||||
@ -1147,6 +1175,7 @@ pub fn routes() -> Vec<Route> {
|
||||
update_family,
|
||||
add_membership_pdf,
|
||||
add_role,
|
||||
add_note,
|
||||
remove_role,
|
||||
//
|
||||
scheckbook_to_regular,
|
||||
|
@ -25,3 +25,11 @@ UPDATE role SET desc='Es können Logbucheinträge im Nachhinein hinzugefügt wer
|
||||
UPDATE role SET desc='Erlaubt den Login auf der Wordpress-Website um zB Artikel zu schreiben.' WHERE name='allow_website_login';
|
||||
UPDATE role SET desc='Muss nur den halben Rennruderbeitrag bezahlen (da zB erst in der 2. Jahreshälfte dazugestoßen wurde)' WHERE name='half-rennrudern';
|
||||
UPDATE role SET desc='Muss keinen Rennruderbeitrag bezahlen, obwohl man in Rennruder-Gruppe ist.' WHERE name='renntrainer';
|
||||
|
||||
CREATE TABLE activity (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
text TEXT NOT NULL,
|
||||
relevant_for TEXT NOT NULL, -- e.g. user_id=123;trip_id=456
|
||||
keep_until DATETIME -- OPTIONAL field
|
||||
);
|
||||
|
@ -31,6 +31,11 @@
|
||||
<form action="/admin/user/{{ user.id }}/change-nickname" method="post">
|
||||
{{ macros::inputgroup(label='Spitzname', name='nickname', type="text", value=user.nickname, readonly=not allowed_to_edit) }}
|
||||
</form>
|
||||
{% if allowed_to_edit %}
|
||||
<form action="/admin/user/{{ user.id }}/new-note" method="post">
|
||||
{{ macros::inputgroup(label='Neue Notiz', name='note', type="text") }}
|
||||
</form>
|
||||
{% endif %}
|
||||
<span>Notizen: to be replaced with activity :-)</span>
|
||||
{% if user.pw and allowed_to_edit %}
|
||||
<div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user