Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import re
from .charity_gift_aid_data import BASIC_RATE, BASIC_RATE_HISTORY ← this capability’s own data, compiled from data/basic-rate.json into the same file by fune build
from .charity_gift_aid_types import GiftAid
from .math_round_div import round_div ← from math.round-div ^1.0.0 · built alongside by fune
from .money_amount import Money, money ← from money.amount ^1.0.0 · built alongside by fune
ISO_DATE = re.compile(r"[0-9]{4}-[0-9]{2}-[0-9]{2}")
def _basic_rate(on_date: str) -> int:
for row in BASIC_RATE:
if row.valid_from <= on_date and (row.valid_to is None or on_date <= row.valid_to):
return row.basis_points
# A history=current build carries only the rate in force; answering an old
# gift with today's rate would be a quiet wrong claim, so say why instead.
if BASIC_RATE_HISTORY != "full" and len(BASIC_RATE) > 0:
earliest = min(row.valid_from for row in BASIC_RATE)
if on_date < earliest:
raise ValueError(
"no Gift Aid basic rate on %s: this build was installed with history=%s, so it only carries rules from %s. "
"Reinstall with history=full for earlier tax years." % (on_date, BASIC_RATE_HISTORY, earliest)
)
raise ValueError("no Gift Aid basic rate on %s" % (on_date,))
def gift_aid(donation: Money, on_date: str) -> GiftAid:
"""The tax a charity reclaims on a Gift Aid donation. The donor is treated
as having given the gift after deducting basic rate tax (ITA 2007 s414), so
the charity reclaims donation x rate / (100% - rate): 25p per £1 at 20%.
It is always the UK basic rate, for Scottish and Welsh taxpayers too.
"""
if donation.currency != "GBP":
raise ValueError("Gift Aid is claimed in GBP, received %s" % (donation.currency,))
if donation.minor < 0:
raise ValueError("donation must not be negative, received %d" % (donation.minor,))
if not isinstance(on_date, str) or not ISO_DATE.fullmatch(on_date):
raise ValueError('onDate must be an ISO date (YYYY-MM-DD), received "%s"' % (on_date,))
rate = _basic_rate(on_date)
# Rounded down: a claim may never exceed the tax treated as deducted.
tax = round_div(donation.minor * rate, 10000 - rate, "down")
return GiftAid(
donation=money(donation.minor, "GBP"),
tax_reclaimable=money(tax, "GBP"),
gross=money(donation.minor + tax, "GBP"),
basic_rate_basis_points=rate,
)