Can export data to FinancesManager
This commit is contained in:
parent
b7d8bda735
commit
dadf959db2
89
moneymgr_backend/Cargo.lock
generated
89
moneymgr_backend/Cargo.lock
generated
@ -341,6 +341,21 @@ dependencies = [
|
|||||||
"alloc-no-stdlib",
|
"alloc-no-stdlib",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android-tzdata"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android_system_properties"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstream"
|
name = "anstream"
|
||||||
version = "0.6.18"
|
version = "0.6.18"
|
||||||
@ -623,6 +638,20 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.41"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
|
||||||
|
dependencies = [
|
||||||
|
"android-tzdata",
|
||||||
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
|
"num-traits",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cipher"
|
name = "cipher"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
@ -1610,6 +1639,30 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone"
|
||||||
|
version = "0.1.63"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
|
||||||
|
dependencies = [
|
||||||
|
"android_system_properties",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"iana-time-zone-haiku",
|
||||||
|
"js-sys",
|
||||||
|
"log",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone-haiku"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_collections"
|
name = "icu_collections"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@ -2093,6 +2146,7 @@ dependencies = [
|
|||||||
"actix-session",
|
"actix-session",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"diesel",
|
"diesel",
|
||||||
"diesel_migrations",
|
"diesel_migrations",
|
||||||
@ -3731,6 +3785,41 @@ dependencies = [
|
|||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.60.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca21a92a9cae9bf4ccae5cf8368dce0837100ddf6e6d57936749e85f152f6247"
|
||||||
|
dependencies = [
|
||||||
|
"windows-implement",
|
||||||
|
"windows-interface",
|
||||||
|
"windows-link",
|
||||||
|
"windows-result",
|
||||||
|
"windows-strings",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-implement"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-interface"
|
||||||
|
version = "0.59.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-link"
|
name = "windows-link"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -31,3 +31,4 @@ mime_guess = "2.0.5"
|
|||||||
rust-embed = { version = "8.6.0" }
|
rust-embed = { version = "8.6.0" }
|
||||||
sha2 = "0.10.8"
|
sha2 = "0.10.8"
|
||||||
httpdate = "1.0.3"
|
httpdate = "1.0.3"
|
||||||
|
chrono = "0.4.41"
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
use crate::controllers::HttpResult;
|
use crate::controllers::HttpResult;
|
||||||
use crate::converters::finances_manager_converter::FinancesManagerFile;
|
use crate::converters::finances_manager_converter::{
|
||||||
|
FinancesManagerAccount, FinancesManagerFile, FinancesManagerMovement,
|
||||||
|
};
|
||||||
use crate::extractors::auth_extractor::AuthExtractor;
|
use crate::extractors::auth_extractor::AuthExtractor;
|
||||||
use crate::extractors::file_extractor::FileExtractor;
|
use crate::extractors::file_extractor::FileExtractor;
|
||||||
use crate::models::accounts::AccountType;
|
use crate::models::accounts::AccountType;
|
||||||
use crate::services::accounts_service::UpdateAccountQuery;
|
use crate::services::accounts_service::UpdateAccountQuery;
|
||||||
use crate::services::movements_service::UpdateMovementQuery;
|
use crate::services::movements_service::UpdateMovementQuery;
|
||||||
use crate::services::{accounts_service, movements_service};
|
use crate::services::{accounts_service, movements_service};
|
||||||
|
use crate::utils::time_utils::{format_date, time};
|
||||||
use actix_web::HttpResponse;
|
use actix_web::HttpResponse;
|
||||||
|
|
||||||
/// Import data from a [FinancesManager](https://gitlab.com/pierre42100/cpp-financesmanager) file
|
/// Import data from a [FinancesManager](https://gitlab.com/pierre42100/cpp-financesmanager) file
|
||||||
pub async fn import_financesmanager(auth: AuthExtractor, file: FileExtractor) -> HttpResult {
|
pub async fn finances_manager_import(auth: AuthExtractor, file: FileExtractor) -> HttpResult {
|
||||||
let file = FinancesManagerFile::parse(&String::from_utf8_lossy(&file.buff))?;
|
let file = FinancesManagerFile::parse(&String::from_utf8_lossy(&file.buff))?;
|
||||||
|
|
||||||
// Create each account & push the movements independently
|
// Create each account & push the movements independently
|
||||||
@ -38,3 +41,38 @@ pub async fn import_financesmanager(auth: AuthExtractor, file: FileExtractor) ->
|
|||||||
|
|
||||||
Ok(HttpResponse::Accepted().finish())
|
Ok(HttpResponse::Accepted().finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Export data to a [FinancesManager](https://gitlab.com/pierre42100/cpp-financesmanager) file
|
||||||
|
pub async fn finances_manager_export(auth: AuthExtractor) -> HttpResult {
|
||||||
|
let accounts = accounts_service::get_list_user(auth.user_id()).await?;
|
||||||
|
|
||||||
|
let mut out = FinancesManagerFile { accounts: vec![] };
|
||||||
|
|
||||||
|
for account in accounts {
|
||||||
|
let movements = movements_service::get_list_account(account.id()).await?;
|
||||||
|
let mut file_account = FinancesManagerAccount {
|
||||||
|
name: account.name,
|
||||||
|
movements: Vec::with_capacity(movements.len()),
|
||||||
|
};
|
||||||
|
|
||||||
|
for movement in movements {
|
||||||
|
file_account.movements.push(FinancesManagerMovement {
|
||||||
|
label: movement.label,
|
||||||
|
time: movement.time as u64,
|
||||||
|
amount: movement.amount,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
out.accounts.push(file_account);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok()
|
||||||
|
.insert_header((
|
||||||
|
"Content-Disposition",
|
||||||
|
format!(
|
||||||
|
"attachment; filename=export_{}.finance",
|
||||||
|
format_date(time() as i64)?.replace('/', "-")
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.body(out.encode()))
|
||||||
|
}
|
||||||
|
@ -163,8 +163,12 @@ async fn main() -> std::io::Result<()> {
|
|||||||
)
|
)
|
||||||
// Backup controller
|
// Backup controller
|
||||||
.route(
|
.route(
|
||||||
"/api/backup/financesmanager/import",
|
"/api/backup/finances_manager/import",
|
||||||
web::post().to(backup_controller::import_financesmanager),
|
web::post().to(backup_controller::finances_manager_import),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/api/backup/finances_manager/export",
|
||||||
|
web::get().to(backup_controller::finances_manager_export),
|
||||||
)
|
)
|
||||||
// Static assets
|
// Static assets
|
||||||
.route("/", web::get().to(static_controller::root_index))
|
.route("/", web::get().to(static_controller::root_index))
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! # Time utilities
|
//! # Time utilities
|
||||||
|
|
||||||
|
use chrono::Datelike;
|
||||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
/// Get the current time since epoch
|
/// Get the current time since epoch
|
||||||
@ -19,3 +20,15 @@ pub fn unix_to_system_time(time: u64) -> SystemTime {
|
|||||||
pub fn unix_to_http_date(time: u64) -> String {
|
pub fn unix_to_http_date(time: u64) -> String {
|
||||||
httpdate::fmt_http_date(unix_to_system_time(time))
|
httpdate::fmt_http_date(unix_to_system_time(time))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Format given UNIX time in a simple format
|
||||||
|
pub fn format_date(time: i64) -> anyhow::Result<String> {
|
||||||
|
let date = chrono::DateTime::from_timestamp(time, 0).ok_or(anyhow::anyhow!("invalid date"))?;
|
||||||
|
|
||||||
|
Ok(format!(
|
||||||
|
"{:0>2}/{:0>2}/{}",
|
||||||
|
date.day(),
|
||||||
|
date.month(),
|
||||||
|
date.year()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user