ledger_utils/
monthly_report.rs

1use crate::balance::Balance;
2use crate::Ledger;
3use chrono::Datelike;
4
5#[derive(Debug, Clone)]
6pub struct MonthlyBalance {
7    pub year: i32,
8    pub month: u32,
9    pub monthly_change: Balance,
10    pub total: Balance,
11}
12
13impl MonthlyBalance {
14    pub fn new(year: i32, month: u32) -> MonthlyBalance {
15        MonthlyBalance {
16            year,
17            month,
18            monthly_change: Balance::new(),
19            total: Balance::new(),
20        }
21    }
22}
23
24#[derive(Debug, Clone)]
25pub struct MonthlyReport {
26    pub monthly_balances: Vec<MonthlyBalance>,
27}
28
29impl Default for MonthlyReport {
30    fn default() -> Self {
31        Self::new()
32    }
33}
34
35impl MonthlyReport {
36    pub fn new() -> MonthlyReport {
37        MonthlyReport {
38            monthly_balances: Vec::new(),
39        }
40    }
41}
42
43impl<'a> From<&'a Ledger> for MonthlyReport {
44    fn from(ledger: &'a Ledger) -> Self {
45        let mut report = MonthlyReport::new();
46
47        let mut current_year = 0;
48        let mut current_month = 0;
49        let mut current_monthly_balance: Option<MonthlyBalance> = None;
50        let mut monthly_balance = Balance::new();
51        let mut total_balance = Balance::new();
52
53        for transaction in &ledger.transactions {
54            if transaction.date.year() != current_year || transaction.date.month() != current_month
55            {
56                // begin new month
57
58                if let Some(mut b) = current_monthly_balance.take() {
59                    b.monthly_change = monthly_balance.clone();
60                    b.total = total_balance.clone();
61                    report.monthly_balances.push(b);
62                }
63
64                current_year = transaction.date.year();
65                current_month = transaction.date.month();
66                monthly_balance = Balance::new();
67
68                current_monthly_balance = Some(MonthlyBalance::new(current_year, current_month));
69            }
70
71            monthly_balance.update_with_transaction(transaction);
72            total_balance.update_with_transaction(transaction);
73        }
74
75        if let Some(mut b) = current_monthly_balance.take() {
76            b.monthly_change = monthly_balance.clone();
77            b.total = total_balance.clone();
78            report.monthly_balances.push(b);
79        }
80
81        report
82    }
83}