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:
58
src/main.rs
58
src/main.rs
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user