from .charity_payroll_giving_types import PayrollGiving from .money_amount import Money, money from .payroll_income_tax import income_tax from .payroll_tax_period_types import PayFrequency def payroll_giving( tax_code: str, frequency: PayFrequency, period: int, pay: Money, donation: Money, previous_pay_to_date: Money, previous_tax_to_date: Money, pay_date: str, ) -> PayrollGiving: """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. """ if donation.currency != "GBP": raise ValueError("payroll amounts must be in GBP, received %s for donation" % (donation.currency,)) if donation.minor < 0: raise ValueError("donation must not be negative, received %d" % (donation.minor,)) if donation.minor > pay.minor: raise ValueError("donation of %d is more than pay of %d" % (donation.minor, pay.minor)) taxable_pay = money(pay.minor - donation.minor, "GBP") without = income_tax(tax_code, frequency, period, pay, previous_pay_to_date, previous_tax_to_date, pay_date).tax.minor with_giving = income_tax( tax_code, frequency, period, taxable_pay, previous_pay_to_date, previous_tax_to_date, pay_date ).tax.minor return PayrollGiving( taxable_pay=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"), )