ZIP import / export now include inbox content

This commit is contained in:
Pierre HUBERT 2025-05-08 17:35:17 +02:00
parent 6e0d0fb48d
commit 55f2679d1a
3 changed files with 57 additions and 6 deletions

View File

@ -9,10 +9,12 @@ use crate::extractors::file_extractor::FileExtractor;
use crate::models::accounts::{Account, AccountID, AccountType}; use crate::models::accounts::{Account, AccountID, AccountType};
use crate::models::files; use crate::models::files;
use crate::models::files::FileID; 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::accounts_service::UpdateAccountQuery;
use crate::services::inbox_service::UpdateInboxEntryQuery;
use crate::services::movements_service::UpdateMovementQuery; 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 crate::utils::time_utils::{format_date, time};
use actix_files::NamedFile; use actix_files::NamedFile;
use actix_web::{HttpRequest, HttpResponse}; use actix_web::{HttpRequest, HttpResponse};
@ -31,6 +33,8 @@ pub enum BackupControllerError {
NonexistentAccountId(AccountID), NonexistentAccountId(AccountID),
#[error("The file with id {0:?} does not exists!")] #[error("The file with id {0:?} does not exists!")]
NonexistentFileId(FileID), NonexistentFileId(FileID),
#[error("The movement with id {0:?} does not exists!")]
NonexistentMovementId(MovementID),
} }
/// Generate export filename /// Generate export filename
@ -140,9 +144,13 @@ pub async fn zip_export(req: HttpRequest, auth: AuthExtractor) -> HttpResult {
constants::zip_export::MOVEMENTS_FILE, constants::zip_export::MOVEMENTS_FILE,
&movements_service::get_all_movements_user(auth.user_id()).await?, &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?; let files_list = files_service::get_all_files_user(auth.user_id()).await?;
zip_json(&mut zip, constants::zip_export::FILES_FILE, &files_list)?; zip_json(&mut zip, constants::zip_export::FILES_FILE, &files_list)?;
// TODO : inbox
// Process all files // Process all files
for file in files_list { for file in files_list {
@ -188,10 +196,12 @@ pub async fn zip_import(auth: AuthExtractor, file: FileExtractor) -> HttpResult
let new_accounts: Vec<Account> = unzip_json(&mut zip, constants::zip_export::ACCOUNTS_FILE)?; let new_accounts: Vec<Account> = unzip_json(&mut zip, constants::zip_export::ACCOUNTS_FILE)?;
let new_movements: Vec<Movement> = unzip_json(&mut zip, constants::zip_export::MOVEMENTS_FILE)?; let new_movements: Vec<Movement> = unzip_json(&mut zip, constants::zip_export::MOVEMENTS_FILE)?;
let new_inbox_entries: Vec<InboxEntry> =
unzip_json(&mut zip, constants::zip_export::INBOX_FILE)?;
let new_files: Vec<files::File> = unzip_json(&mut zip, constants::zip_export::FILES_FILE)?; let new_files: Vec<files::File> = unzip_json(&mut zip, constants::zip_export::FILES_FILE)?;
// TODO : inbox
// Delete all data // Delete all data
inbox_service::delete_all_user(auth.user_id()).await?;
accounts_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?; 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 // Create the movements
let mut movements_mapping = HashMap::new();
for movement in new_movements { for movement in new_movements {
movements_service::create(&UpdateMovementQuery { let created_movement = movements_service::create(&UpdateMovementQuery {
account_id: accounts_mapping account_id: accounts_mapping
.get(&movement.account_id()) .get(&movement.account_id())
.ok_or_else(|| BackupControllerError::NonexistentAccountId(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, checked: movement.checked,
}) })
.await?; .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()) Ok(HttpResponse::Accepted().finish())

View File

@ -3,7 +3,9 @@ use crate::models::files::FileID;
use crate::schema::*; use crate::schema::*;
use diesel::{Insertable, Queryable, QueryableByName}; 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); pub struct MovementID(pub i32);
/// Single movement information /// Single movement information

View File

@ -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()?)?; diesel::delete(inbox::dsl::inbox.filter(inbox::dsl::id.eq(id.0))).execute(&mut db()?)?;
Ok(()) 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(())
}