Accept CSV file path as command line argument

Output is now written to the same directory as the input file.
This commit is contained in:
2026-03-23 10:41:54 +01:00
parent 623cf12a1c
commit 1929b3ed49

View File

@@ -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<dyn std::error::Error>> {
let data_dir = Path::new("input");
let output_dir = Path::new("output");
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
eprintln!("Usage: {} <csv-file>", 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<Batch> = 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<String> = 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<dyn std::error::Error>> {
.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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
}
println!(
"\nGenerated {} customer invoices in output/",
customer_count
"\nGenerated {} customer invoices in {:?}",
customer_count, output_dir
);
Ok(())