Add basic Excel export
This commit is contained in:
10
moneymgr_backend/Cargo.lock
generated
10
moneymgr_backend/Cargo.lock
generated
@ -2282,6 +2282,7 @@ dependencies = [
|
||||
"rand 0.9.0",
|
||||
"rust-embed",
|
||||
"rust-s3",
|
||||
"rust_xlsxwriter",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
@ -2990,6 +2991,15 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust_xlsxwriter"
|
||||
version = "0.86.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34ab327483e6b6fc521b7e303691c14bf3624a68e0cb4c2b9f9c5d692e07f637"
|
||||
dependencies = [
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.24"
|
||||
|
@ -34,4 +34,5 @@ sha2 = "0.10.8"
|
||||
httpdate = "1.0.3"
|
||||
chrono = "0.4.41"
|
||||
tempfile = "3.19.1"
|
||||
zip = "2.6.1"
|
||||
zip = "2.6.1"
|
||||
rust_xlsxwriter = "0.86.1"
|
@ -16,6 +16,7 @@ use crate::services::{accounts_service, files_service, movements_service};
|
||||
use crate::utils::time_utils::{format_date, time};
|
||||
use actix_files::NamedFile;
|
||||
use actix_web::{HttpRequest, HttpResponse};
|
||||
use rust_xlsxwriter::{Color, Format, Workbook};
|
||||
use serde::Serialize;
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::collections::HashMap;
|
||||
@ -257,3 +258,48 @@ pub async fn zip_import(auth: AuthExtractor, file: FileExtractor) -> HttpResult
|
||||
|
||||
Ok(HttpResponse::Accepted().finish())
|
||||
}
|
||||
|
||||
/// Export all movement to XSLX
|
||||
pub async fn xslx_export(auth: AuthExtractor) -> HttpResult {
|
||||
let mut workbook = Workbook::new();
|
||||
|
||||
for account in accounts_service::get_list_user(auth.user_id()).await? {
|
||||
let worksheet = workbook.add_worksheet();
|
||||
worksheet.set_name(account.name.to_string())?;
|
||||
|
||||
// Configure columns
|
||||
let header_format = Format::new()
|
||||
.set_bold()
|
||||
.set_background_color(Color::Black)
|
||||
.set_foreground_color(Color::White);
|
||||
|
||||
worksheet.set_column_width(0, 15)?;
|
||||
worksheet.set_column_width(1, 70)?;
|
||||
worksheet.set_column_width(2, 15)?;
|
||||
|
||||
// Write headers
|
||||
worksheet.write_with_format(0, 0, "Date", &header_format)?;
|
||||
worksheet.write_with_format(0, 1, "Label", &header_format)?;
|
||||
worksheet.write_with_format(0, 2, "Amount", &header_format)?;
|
||||
|
||||
// Write movements
|
||||
let mut movements = movements_service::get_list_account(account.id()).await?;
|
||||
movements.sort_by(|a, b| a.time.to_string().cmp(&b.time.to_string()));
|
||||
for (idx, movement) in movements.iter().enumerate() {
|
||||
worksheet.write(idx as u32 + 1, 0, format_date(movement.time)?)?;
|
||||
worksheet.write(idx as u32 + 1, 1, &movement.label)?;
|
||||
worksheet.write(idx as u32 + 1, 2, movement.amount)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Save final Excel Document
|
||||
let raw_excel = workbook.save_to_buffer()?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/vnd.ms-excel")
|
||||
.insert_header((
|
||||
"Content-Disposition",
|
||||
format!("attachment; filename={}", export_filename("xslx")),
|
||||
))
|
||||
.body(raw_excel))
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ pub enum HttpFailure {
|
||||
StdIoError(#[from] std::io::Error),
|
||||
#[error("an error occurred while performing backup/recovery operation: {0}")]
|
||||
BackupControllerError(#[from] BackupControllerError),
|
||||
#[error("an error while encoding Excel document: {0}")]
|
||||
XslxError(#[from] rust_xlsxwriter::XlsxError),
|
||||
}
|
||||
|
||||
impl ResponseError for HttpFailure {
|
||||
|
@ -178,6 +178,10 @@ async fn main() -> std::io::Result<()> {
|
||||
"/api/backup/zip/import",
|
||||
web::post().to(backup_controller::zip_import),
|
||||
)
|
||||
.route(
|
||||
"/api/backup/xslx/export",
|
||||
web::get().to(backup_controller::xslx_export),
|
||||
)
|
||||
// Static assets
|
||||
.route("/", web::get().to(static_controller::root_index))
|
||||
.route(
|
||||
|
Reference in New Issue
Block a user