///|
/// Tax rules express how normalized accounts contribute to a tax base.
pub(all) enum TaxTreatment {
TaxableRevenue
DeductibleExpense
Exempt
} derive(Debug, Eq)
///|
pub struct TaxRule {
account : String
treatment : TaxTreatment
} derive(Debug, Eq)
///|
pub fn TaxRule::new(account : String, treatment : TaxTreatment) -> TaxRule {
{ account, treatment }
}
///|
pub struct TaxSummary {
period : String
revenue : Amount
deductions : Amount
base : Amount
rate : Int
tax : Amount
} derive(Debug, Eq)
///|
pub fn tax_summary(
entries : Array[Entry],
period : String,
rules : Array[TaxRule],
rate~ : Int,
) -> TaxSummary {
let mut revenue = 0
let mut deductions = 0
for entry in entries {
if entry.period != period {
continue
}
match find_tax_rule(rules, entry.account) {
Some(rule) =>
match rule.treatment {
TaxableRevenue => revenue += entry.credit - entry.debit
DeductibleExpense => deductions += entry.debit - entry.credit
Exempt => ()
}
None => ()
}
}
let base = if revenue > deductions { revenue - deductions } else { 0 }
{ period, revenue, deductions, base, rate, tax: base * rate / 100 }
}
///|
fn find_tax_rule(rules : Array[TaxRule], account : String) -> TaxRule? {
for rule in rules {
if rule.account == account {
return Some(rule)
}
}
None
}
///|
pub fn tax_amount(base : Amount, rate : Int) -> Amount {
if base <= 0 || rate <= 0 {
0
} else {
base * rate / 100
}
}