From 1929b3ed4916cd888edf2608fd932e57bcecf417 Mon Sep 17 00:00:00 2001 From: Jakob Date: Mon, 23 Mar 2026 10:41:54 +0100 Subject: [PATCH] Accept CSV file path as command line argument Output is now written to the same directory as the input file. --- src/main.rs | 64 +++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/src/main.rs b/src/main.rs index e6e8e8f..ed5c3b2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,12 @@ use askama::Template; use chrono::Utc; +use std::env; use std::fs; use std::path::Path; mod invoice_generator; -use invoice_generator::{group_by_customer, read_csv_file, Batch, Customer}; +use invoice_generator::{group_by_customer, read_csv_file, Customer}; fn fmt(v: f64) -> String { format!("{:.2}", v) @@ -101,40 +102,35 @@ struct CustomerTemplate { } fn main() -> Result<(), Box> { - let data_dir = Path::new("input"); - let output_dir = Path::new("output"); + let args: Vec = env::args().collect(); + + if args.len() != 2 { + eprintln!("Usage: {} ", args[0]); + std::process::exit(1); + } + + let input_path = Path::new(&args[1]); + + if !input_path.exists() { + eprintln!("Error: File not found: {:?}", input_path); + std::process::exit(1); + } + + let output_dir = input_path.parent().unwrap_or(Path::new(".")); if !output_dir.exists() { fs::create_dir_all(output_dir)?; } - let mut batches: Vec = Vec::new(); + let batch = read_csv_file(input_path)?; + println!( + "Loaded {} transactions from {}", + batch.transactions.len(), + batch.filename + ); - for entry in fs::read_dir(data_dir)? { - let entry = entry?; - let path = entry.path(); - if path.extension().and_then(|s| s.to_str()) == Some("csv") { - match read_csv_file(&path) { - Ok(batch) => { - println!( - "Loaded {} transactions from {}", - batch.transactions.len(), - batch.filename - ); - batches.push(batch); - } - Err(e) => { - eprintln!("Error reading {:?}: {}", path, e); - } - } - } - } - - batches.sort_by(|a, b| a.filename.cmp(&b.filename)); - - let batch_filenames: Vec = batches.iter().map(|b| b.filename.clone()).collect(); - - let customers = group_by_customer(&batches); + let batch_filename = batch.filename.clone(); + let customers = group_by_customer(&[batch]); let index_customers: Vec<(String, usize)> = customers .iter() @@ -142,8 +138,8 @@ fn main() -> Result<(), Box> { .collect(); let html = IndexTemplate { - customers: index_customers, - batches: batch_filenames.clone(), + customers: index_customers.clone(), + batches: vec![batch_filename.clone()], } .render() .unwrap(); @@ -156,7 +152,7 @@ fn main() -> Result<(), Box> { let prepared = PreparedCustomer::from_customer(customer); let customer_html = CustomerTemplate { customer: prepared, - batches: batch_filenames.clone(), + batches: vec![batch_filename.clone()], generated_date: generated_date.clone(), } .render() @@ -167,8 +163,8 @@ fn main() -> Result<(), Box> { } println!( - "\nGenerated {} customer invoices in output/", - customer_count + "\nGenerated {} customer invoices in {:?}", + customer_count, output_dir ); Ok(())