Add PDF generation for invoices
- Generate both HTML and PDF versions of each customer invoice - PDFs use printpdf with HTML rendering for consistent styling - Same layout and formatting as HTML output
This commit is contained in:
62
src/main.rs
62
src/main.rs
@@ -6,6 +6,7 @@ use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
mod invoice_generator;
|
||||
mod pdf;
|
||||
|
||||
use invoice_generator::{group_by_customer, read_csv_file, Customer};
|
||||
|
||||
@@ -14,43 +15,43 @@ fn fmt(v: f64) -> String {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ProductSummary {
|
||||
name: String,
|
||||
volume: String,
|
||||
amount: String,
|
||||
avg_price: String,
|
||||
pub struct ProductSummary {
|
||||
pub name: String,
|
||||
pub volume: String,
|
||||
pub amount: String,
|
||||
pub avg_price: String,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Summary {
|
||||
total_volume: String,
|
||||
grand_total: String,
|
||||
products: Vec<ProductSummary>,
|
||||
pub struct Summary {
|
||||
pub total_volume: String,
|
||||
pub grand_total: String,
|
||||
pub products: Vec<ProductSummary>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct CardData {
|
||||
card_number: String,
|
||||
transactions: Vec<FormattedTransaction>,
|
||||
total_amount: String,
|
||||
total_volume: String,
|
||||
pub struct CardData {
|
||||
pub card_number: String,
|
||||
pub transactions: Vec<FormattedTransaction>,
|
||||
pub total_amount: String,
|
||||
pub total_volume: String,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct FormattedTransaction {
|
||||
date: String,
|
||||
quality_name: String,
|
||||
price: String,
|
||||
volume: String,
|
||||
amount: String,
|
||||
receipt: String,
|
||||
pub struct FormattedTransaction {
|
||||
pub date: String,
|
||||
pub quality_name: String,
|
||||
pub price: String,
|
||||
pub volume: String,
|
||||
pub amount: String,
|
||||
pub receipt: String,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct PreparedCustomer {
|
||||
customer_number: String,
|
||||
cards: Vec<CardData>,
|
||||
summary: Summary,
|
||||
pub struct PreparedCustomer {
|
||||
pub customer_number: String,
|
||||
pub cards: Vec<CardData>,
|
||||
pub summary: Summary,
|
||||
}
|
||||
|
||||
impl PreparedCustomer {
|
||||
@@ -212,7 +213,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
for (customer_num, customer) in customers {
|
||||
let prepared = PreparedCustomer::from_customer(customer);
|
||||
let customer_html = CustomerTemplate {
|
||||
customer: prepared,
|
||||
customer: prepared.clone(),
|
||||
period: period.clone(),
|
||||
generated_date: generated_date.clone(),
|
||||
}
|
||||
@@ -221,6 +222,15 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let filename = format!("customer_{}.html", customer_num);
|
||||
fs::write(output_dir.join(&filename), customer_html)?;
|
||||
println!("Genererade {}", filename);
|
||||
|
||||
let pdf_filename = format!("customer_{}.pdf", customer_num);
|
||||
pdf::generate_customer_pdf(
|
||||
&prepared,
|
||||
&period,
|
||||
&generated_date,
|
||||
&output_dir.join(&pdf_filename),
|
||||
)?;
|
||||
println!("Genererade {}", pdf_filename);
|
||||
}
|
||||
|
||||
println!(
|
||||
|
||||
Reference in New Issue
Block a user