use crate::connections::db_connection::db; use crate::controllers::server_controller::ServerConstraints; use crate::models::files::FileID; use crate::models::inbox::{InboxEntry, InboxEntryID, NewInboxEntry}; use crate::models::movements::MovementID; use crate::models::users::UserID; use crate::schema::inbox; use crate::services::{accounts_service, files_service, movements_service}; use crate::utils::time_utils::time; use diesel::prelude::*; #[derive(serde::Deserialize)] pub struct UpdateInboxEntryQuery { pub file_id: FileID, pub movement_id: Option, pub time: u64, pub label: Option, pub amount: Option, } impl UpdateInboxEntryQuery { pub async fn check_error(&self, user_id: UserID) -> anyhow::Result> { let constraints = ServerConstraints::default(); // Check inbox entry label if let Some(label) = &self.label { if !constraints.inbox_entry_label.check_str(label) { return Ok(Some("Invalid inbox entry label length!")); } } // Check the referenced movement if let Some(movement_id) = self.movement_id { let Ok(movement) = movements_service::get_by_id(movement_id).await else { return Ok(Some("Movement not found")); }; let account = accounts_service::get_by_id(movement.account_id()).await?; if account.user_id() != user_id { return Ok(Some("The account does not own this movement!")); } } // Check the file let Ok(file) = files_service::get_file_with_id(self.file_id) else { return Ok(Some("The account does not own this file!")); }; if file.user_id() != user_id { return Ok(Some("The user does not own the referenced file!")); } Ok(None) } } /// Create a new inbox entry pub async fn create(user_id: UserID, query: &UpdateInboxEntryQuery) -> anyhow::Result { let new_entry = NewInboxEntry { time: query.time as i64, label: query.label.as_deref(), file_id: query.file_id.0, user_id: user_id.0, amount: query.amount, time_create: time() as i64, time_update: time() as i64, movement_id: None, }; let res: InboxEntry = diesel::insert_into(inbox::table) .values(&new_entry) .get_result(&mut db()?)?; update(res.id(), query).await?; Ok(res) } /// Update a inbox entry pub async fn update(id: InboxEntryID, q: &UpdateInboxEntryQuery) -> anyhow::Result<()> { diesel::update(inbox::dsl::inbox.filter(inbox::dsl::id.eq(id.0))) .set(( inbox::dsl::time_update.eq(time() as i64), inbox::dsl::movement_id.eq(q.movement_id.map(|m| m.0)), inbox::dsl::time.eq(q.time as i64), inbox::dsl::label.eq(&q.label), inbox::dsl::file_id.eq(&q.file_id.0), inbox::dsl::amount.eq(q.amount), )) .execute(&mut db()?)?; Ok(()) } /// Get the full list of inbox entries of a user pub async fn get_list_user(user_id: UserID) -> anyhow::Result> { Ok(inbox::table .filter(inbox::dsl::user_id.eq(user_id.0)) .get_results(&mut db()?)?) } /// Get a single inbox entry by its ID pub async fn get_by_id(entry_id: InboxEntryID) -> anyhow::Result { Ok(inbox::table .filter(inbox::dsl::id.eq(entry_id.0)) .get_result(&mut db()?)?) }