use super::funejson::Value; use super::money_amount::{money, money_from_value, money_to_value, Money}; use super::payroll_income_tax::income_tax; /// Payroll Giving (ITEPA 2003 s713): the donation is deducted from pay before /// PAYE is worked out, so the relief is whatever PAYE the lower pay saves, by /// the same tax table routines the payroll uses. PAYE rounds taxable pay down /// to whole pounds, so a 50p donation can save nothing. /// /// # Panics /// Panics on a non-GBP or negative donation, a donation above pay, and /// anything payroll.income-tax refuses. pub fn payroll_giving( tax_code: &str, frequency: &str, period: i64, pay: &Money, donation: &Money, previous_pay_to_date: &Money, previous_tax_to_date: &Money, pay_date: &str, ) -> PayrollGiving { if donation.currency != "GBP" { panic!("payroll amounts must be in GBP, received {} for donation", donation.currency); } if donation.minor < 0 { panic!("donation must not be negative, received {}", donation.minor); } if donation.minor > pay.minor { panic!("donation of {} is more than pay of {}", donation.minor, pay.minor); } let taxable_pay = money(pay.minor - donation.minor, "GBP"); let without = income_tax(tax_code, frequency, period, pay, previous_pay_to_date, previous_tax_to_date, pay_date).tax.minor; let with_giving = income_tax(tax_code, frequency, period, &taxable_pay, previous_pay_to_date, previous_tax_to_date, pay_date).tax.minor; PayrollGiving { taxable_pay, tax_without_giving: money(without, "GBP"), tax_with_giving: money(with_giving, "GBP"), tax_saved: money(without - with_giving, "GBP"), net_cost: money(donation.minor - (without - with_giving), "GBP"), } } pub fn payroll_giving_to_value(g: &PayrollGiving) -> Value { Value::obj(vec![ ("taxablePay", money_to_value(&g.taxable_pay)), ("taxWithoutGiving", money_to_value(&g.tax_without_giving)), ("taxWithGiving", money_to_value(&g.tax_with_giving)), ("taxSaved", money_to_value(&g.tax_saved)), ("netCost", money_to_value(&g.net_cost)), ]) } pub fn fune_vector(args: &[Value]) -> Value { if let Value::Float(_) = args[2] { panic!("period {} is not a tax period for {} pay", args[2].as_f64(), args[1].as_str()); } payroll_giving_to_value(&payroll_giving( args[0].as_str(), args[1].as_str(), args[2].as_i64(), &money_from_value(&args[3]), &money_from_value(&args[4]), &money_from_value(&args[5]), &money_from_value(&args[6]), args[7].as_str(), )) }