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 typing import Optional
from .insurance_ipt_data import IPT_RATES, IPT_RATES_HISTORY ← this capability’s own data, compiled from data/ipt-rates.json into the same file by fune build
from .insurance_ipt_types import IptBand, IptBreakdown
from .math_round_div import RoundingMode, 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 insurance_premium_tax(
amount: Money, includes_tax: bool, band: IptBand, on_date: str, mode: RoundingMode
) -> IptBreakdown:
"""Add UK Insurance Premium Tax to a net premium, or take it out of a gross one,
at the rate in force on the date the insurer receives the premium.
Only one figure is ever rounded - the tax when adding, the net when taking
out - and the other is the difference, so net + tax is always the gross.
Taking 12% off a gross premium is the classic error: the tax inside 112.00
is 12.00, not 13.44.
"""
if band not in ("standard", "higher"):
raise ValueError('unknown IPT band "%s": use standard or higher' % (band,))
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,))
rule = None
for r in IPT_RATES:
if r.band != band or on_date < r.valid_from:
continue
if r.valid_to is not None and on_date > r.valid_to:
continue
rule = r
if rule is None:
# A history=current build keeps only the rates in force; answering an
# older date with today's rate would be exactly the wrong answer.
if IPT_RATES_HISTORY != "full":
earliest: Optional[str] = None
for r in IPT_RATES:
if r.band == band and (earliest is None or r.valid_from < earliest):
earliest = r.valid_from
if earliest is not None and on_date < earliest:
raise ValueError(
"no IPT rule for %s on %s: this build was installed with history=%s, "
"so it only carries rates from %s. Reinstall with history=full for older premiums."
% (band, on_date, IPT_RATES_HISTORY, earliest)
)
raise ValueError("no IPT rule for %s on %s" % (band, on_date))
bp = rule.basis_points
if includes_tax:
gross = amount
net = money(round_div(amount.minor * 10000, 10000 + bp, mode), amount.currency)
tax = money(amount.minor - net.minor, amount.currency)
else:
net = amount
tax = money(round_div(amount.minor * bp, 10000, mode), amount.currency)
gross = money(amount.minor + tax.minor, amount.currency)
return IptBreakdown(net=net, tax=tax, gross=gross, basis_points=bp, band=band, valid_from=rule.valid_from)