From 55f2679d1aa9b0b674054bd6c1b8894cfe252bbf Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Thu, 8 May 2025 17:35:17 +0200 Subject: [PATCH] ZIP import / export now include inbox content --- .../src/controllers/backup_controller.rs | 51 +++++++++++++++++-- moneymgr_backend/src/models/movements.rs | 4 +- .../src/services/inbox_service.rs | 8 +++ 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/moneymgr_backend/src/controllers/backup_controller.rs b/moneymgr_backend/src/controllers/backup_controller.rs index 0a212be..4b35db3 100644 --- a/moneymgr_backend/src/controllers/backup_controller.rs +++ b/moneymgr_backend/src/controllers/backup_controller.rs @@ -9,10 +9,12 @@ use crate::extractors::file_extractor::FileExtractor; use crate::models::accounts::{Account, AccountID, AccountType}; use crate::models::files; use crate::models::files::FileID; -use crate::models::movements::Movement; +use crate::models::inbox::InboxEntry; +use crate::models::movements::{Movement, MovementID}; use crate::services::accounts_service::UpdateAccountQuery; +use crate::services::inbox_service::UpdateInboxEntryQuery; use crate::services::movements_service::UpdateMovementQuery; -use crate::services::{accounts_service, files_service, movements_service}; +use crate::services::{accounts_service, files_service, inbox_service, movements_service}; use crate::utils::time_utils::{format_date, time}; use actix_files::NamedFile; use actix_web::{HttpRequest, HttpResponse}; @@ -31,6 +33,8 @@ pub enum BackupControllerError { NonexistentAccountId(AccountID), #[error("The file with id {0:?} does not exists!")] NonexistentFileId(FileID), + #[error("The movement with id {0:?} does not exists!")] + NonexistentMovementId(MovementID), } /// Generate export filename @@ -140,9 +144,13 @@ pub async fn zip_export(req: HttpRequest, auth: AuthExtractor) -> HttpResult { constants::zip_export::MOVEMENTS_FILE, &movements_service::get_all_movements_user(auth.user_id()).await?, )?; + zip_json( + &mut zip, + constants::zip_export::INBOX_FILE, + &inbox_service::get_list_user(auth.user_id()).await?, + )?; let files_list = files_service::get_all_files_user(auth.user_id()).await?; zip_json(&mut zip, constants::zip_export::FILES_FILE, &files_list)?; - // TODO : inbox // Process all files for file in files_list { @@ -188,10 +196,12 @@ pub async fn zip_import(auth: AuthExtractor, file: FileExtractor) -> HttpResult let new_accounts: Vec = unzip_json(&mut zip, constants::zip_export::ACCOUNTS_FILE)?; let new_movements: Vec = unzip_json(&mut zip, constants::zip_export::MOVEMENTS_FILE)?; + let new_inbox_entries: Vec = + unzip_json(&mut zip, constants::zip_export::INBOX_FILE)?; let new_files: Vec = unzip_json(&mut zip, constants::zip_export::FILES_FILE)?; - // TODO : inbox // Delete all data + inbox_service::delete_all_user(auth.user_id()).await?; accounts_service::delete_all_user(auth.user_id()).await?; files_service::delete_all_user(auth.user_id()).await?; @@ -233,8 +243,9 @@ pub async fn zip_import(auth: AuthExtractor, file: FileExtractor) -> HttpResult } // Create the movements + let mut movements_mapping = HashMap::new(); for movement in new_movements { - movements_service::create(&UpdateMovementQuery { + let created_movement = movements_service::create(&UpdateMovementQuery { account_id: accounts_mapping .get(&movement.account_id()) .ok_or_else(|| BackupControllerError::NonexistentAccountId(movement.account_id()))? @@ -254,6 +265,36 @@ pub async fn zip_import(auth: AuthExtractor, file: FileExtractor) -> HttpResult checked: movement.checked, }) .await?; + + movements_mapping.insert(movement.id(), created_movement); + } + + // Create the inbox entries + for inbox_entry in new_inbox_entries { + inbox_service::create( + auth.user_id(), + &UpdateInboxEntryQuery { + file_id: files_mapping + .get(&inbox_entry.file_id()) + .ok_or(BackupControllerError::NonexistentFileId( + inbox_entry.file_id(), + ))? + .id(), + movement_id: inbox_entry + .movement_id() + .map(|mov_id| { + movements_mapping + .get(&mov_id) + .ok_or(BackupControllerError::NonexistentMovementId(mov_id)) + }) + .transpose()? + .map(|f| f.id()), + time: inbox_entry.time as u64, + label: inbox_entry.label, + amount: inbox_entry.amount, + }, + ) + .await?; } Ok(HttpResponse::Accepted().finish()) diff --git a/moneymgr_backend/src/models/movements.rs b/moneymgr_backend/src/models/movements.rs index 0422416..78d35df 100644 --- a/moneymgr_backend/src/models/movements.rs +++ b/moneymgr_backend/src/models/movements.rs @@ -3,7 +3,9 @@ use crate::models::files::FileID; use crate::schema::*; use diesel::{Insertable, Queryable, QueryableByName}; -#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq)] +#[derive( + Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord, +)] pub struct MovementID(pub i32); /// Single movement information diff --git a/moneymgr_backend/src/services/inbox_service.rs b/moneymgr_backend/src/services/inbox_service.rs index 35a1512..fac4515 100644 --- a/moneymgr_backend/src/services/inbox_service.rs +++ b/moneymgr_backend/src/services/inbox_service.rs @@ -111,3 +111,11 @@ pub async fn delete(id: InboxEntryID) -> anyhow::Result<()> { diesel::delete(inbox::dsl::inbox.filter(inbox::dsl::id.eq(id.0))).execute(&mut db()?)?; Ok(()) } + +/// Delete all the inbox entries of a user +pub async fn delete_all_user(user: UserID) -> anyhow::Result<()> { + for inbox_entry in get_list_user(user).await? { + delete(inbox_entry.id()).await?; + } + Ok(()) +}