rowt/src/model/notification.rs
philipp 64f3596132
All checks were successful
CI/CD Pipeline / test (push) Successful in 9m35s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
remove notificatoin about canceled trip if cancelation has been canceled
2024-05-21 20:43:05 +02:00

168 lines
4.9 KiB
Rust

use std::ops::DerefMut;
use chrono::NaiveDateTime;
use regex::Regex;
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
use super::{role::Role, user::User};
#[derive(FromRow, Debug, Serialize, Deserialize)]
pub struct Notification {
pub id: i64,
pub user_id: i64,
pub message: String,
pub read_at: Option<NaiveDateTime>,
pub created_at: NaiveDateTime,
pub category: String,
pub link: Option<String>,
pub action_after_reading: Option<String>,
}
impl Notification {
pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option<Self> {
sqlx::query_as!(Self, "SELECT * FROM notification WHERE id like ?", id)
.fetch_one(db)
.await
.ok()
}
pub async fn create_with_tx(
db: &mut Transaction<'_, Sqlite>,
user: &User,
message: &str,
category: &str,
link: Option<&str>,
action_after_reading: Option<&str>,
) {
sqlx::query!(
"INSERT INTO notification(user_id, message, category, link, action_after_reading) VALUES (?, ?, ?, ?, ?)",
user.id,
message,
category,
link,
action_after_reading
)
.execute(db.deref_mut())
.await
.unwrap();
}
pub async fn create(
db: &SqlitePool,
user: &User,
message: &str,
category: &str,
link: Option<&str>,
action_after_reading: Option<&str>,
) {
let mut tx = db.begin().await.unwrap();
Self::create_with_tx(&mut tx, user, message, category, link, action_after_reading).await;
tx.commit().await.unwrap();
}
pub async fn create_for_role_tx(
db: &mut Transaction<'_, Sqlite>,
role: &Role,
message: &str,
category: &str,
link: Option<&str>,
action_after_reading: Option<&str>,
) {
let users = User::all_with_role_tx(db, role).await;
for user in users {
Self::create_with_tx(db, &user, message, category, link, action_after_reading).await;
}
}
pub async fn create_for_role(
db: &SqlitePool,
role: &Role,
message: &str,
category: &str,
link: Option<&str>,
action_after_reading: Option<&str>,
) {
let mut tx = db.begin().await.unwrap();
Self::create_for_role_tx(&mut tx, role, message, category, link, action_after_reading)
.await;
tx.commit().await.unwrap();
}
pub async fn for_user(db: &SqlitePool, user: &User) -> Vec<Self> {
let rows = sqlx::query!(
"
SELECT id, user_id, message, read_at, datetime(created_at, 'localtime') as created_at, category, link, action_after_reading FROM notification
WHERE
user_id = ?
AND (
read_at IS NULL
OR read_at >= datetime('now', '-14 days')
)
AND created_at is not NULL
ORDER BY read_at DESC, created_at DESC;
",
user.id
)
.fetch_all(db)
.await
.unwrap();
rows.into_iter()
.map(|rec| Notification {
id: rec.id,
user_id: rec.user_id,
message: rec.message,
read_at: rec.read_at,
created_at: NaiveDateTime::parse_from_str(
&rec.created_at.unwrap(),
"%Y-%m-%d %H:%M:%S",
)
.unwrap(),
category: rec.category,
link: rec.link,
action_after_reading: rec.action_after_reading,
})
.collect()
}
pub async fn mark_read(self, db: &SqlitePool) {
sqlx::query!(
"UPDATE notification SET read_at=CURRENT_TIMESTAMP WHERE id=?",
self.id
)
.execute(db)
.await
.unwrap();
if let Some(action) = self.action_after_reading.as_ref() {
// User read notification about cancelled trip/event
let re = Regex::new(r"^remove_user_trip_with_trip_details_id:(\d+)$").unwrap();
if let Some(caps) = re.captures(action) {
if let Some(matched) = caps.get(1) {
if let Ok(number) = matched.as_str().parse::<i32>() {
let _ = sqlx::query!(
"DELETE FROM user_trip WHERE user_id = ? AND trip_details_id = ?",
self.user_id,
number
)
.execute(db)
.await
.unwrap();
}
}
}
}
}
pub(crate) async fn delete_by_action(db: &sqlx::Pool<Sqlite>, action: &str) {
sqlx::query!(
"DELETE FROM notification WHERE action_after_reading=? and read_at = null",
action
)
.execute(db)
.await
.unwrap();
}
}