use std::ops::DerefMut; use chrono::NaiveDateTime; 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, pub created_at: NaiveDateTime, pub category: String, pub link: Option, } impl Notification { pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option { 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>, ) { sqlx::query!( "INSERT INTO notification(user_id, message, category, link) VALUES (?, ?, ?, ?)", user.id, message, category, link ) .execute(db.deref_mut()) .await .unwrap(); } pub async fn create( db: &SqlitePool, user: &User, message: &str, category: &str, link: Option<&str>, ) { let mut tx = db.begin().await.unwrap(); Self::create_with_tx(&mut tx, user, message, category, link).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>, ) { let users = User::all_with_role_tx(db, role).await; for user in users { Self::create_with_tx(db, &user, message, category, link).await; } } pub async fn for_user(db: &SqlitePool, user: &User) -> Vec { let rows = sqlx::query!( " SELECT id, user_id, message, read_at, datetime(created_at, 'localtime') as created_at, category, link 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(); println!("{rows:#?}"); 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, }) .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(); } }