Add summary section with product breakdown

- Show total volume, total amount, and average price per product
- Include grand total row
- Products sorted alphabetically
This commit is contained in:
2026-03-23 10:57:35 +01:00
parent 809f5d2a58
commit 4119ad7059
2 changed files with 121 additions and 3 deletions

View File

@@ -1,5 +1,6 @@
use askama::Template;
use chrono::Utc;
use std::collections::HashMap;
use std::env;
use std::fs;
use std::path::Path;
@@ -12,6 +13,21 @@ fn fmt(v: f64) -> String {
format!("{:.2}", v)
}
#[derive(Clone)]
struct ProductSummary {
name: String,
volume: String,
amount: String,
avg_price: String,
}
#[derive(Clone)]
struct Summary {
total_volume: String,
grand_total: String,
products: Vec<ProductSummary>,
}
#[derive(Clone)]
struct CardData {
card_number: String,
@@ -34,7 +50,7 @@ struct FormattedTransaction {
struct PreparedCustomer {
customer_number: String,
cards: Vec<CardData>,
grand_total: String,
summary: Summary,
}
impl PreparedCustomer {
@@ -78,10 +94,48 @@ impl PreparedCustomer {
.map(|c| c.total_amount.parse::<f64>().unwrap())
.sum();
let mut product_totals: HashMap<String, (f64, f64)> = HashMap::new();
for card in &cards {
for tx in &card.transactions {
let volume: f64 = tx.volume.parse().unwrap();
let amount: f64 = tx.amount.parse().unwrap();
let entry = product_totals
.entry(tx.quality_name.clone())
.or_insert((0.0, 0.0));
entry.0 += volume;
entry.1 += amount;
}
}
let mut products: Vec<ProductSummary> = product_totals
.into_iter()
.map(|(name, (volume, amount))| {
let avg_price = if volume > 0.0 { amount / volume } else { 0.0 };
ProductSummary {
name,
volume: fmt(volume),
amount: fmt(amount),
avg_price: fmt(avg_price),
}
})
.collect();
products.sort_by(|a, b| a.name.cmp(&b.name));
let total_volume: f64 = products
.iter()
.map(|p| p.volume.parse::<f64>().unwrap())
.sum();
let summary = Summary {
total_volume: fmt(total_volume),
grand_total: fmt(grand_total),
products,
};
PreparedCustomer {
customer_number: customer.customer_number,
cards,
grand_total: fmt(grand_total),
summary,
}
}
}