Functional Weave
Code in Rust

finance.tax.vat-flat-rate@1.0.1

impl/python.py

2,568 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from typing import Optional

from .dates_add_days import add_days  ← from dates.add-days ^1.0.0 · built alongside by fune
from .dates_add_months import add_months  ← from dates.add-months ^1.0.0 · built alongside by fune
from .finance_tax_vat_flat_rate_data import FLAT_RATES, FLAT_RATES_HISTORY  ← this capability’s own data, compiled from data/flat-rates.json into the same file by fune build
from .finance_tax_vat_flat_rate_types import FlatRateVat
from .money_amount import Money, money  ← from money.amount ^1.0.0 · built alongside by fune
from .money_apply_rate import apply_rate  ← from money.apply-rate ^1.0.0 · built alongside by fune

_LIMITED_COST = "limited-cost-business"


def _rate_on(sector: str, on_date: str) -> int:
    rows = [r for r in FLAT_RATES if r.sector == sector]
    for row in rows:
        if on_date >= row.valid_from and (row.valid_to is None or on_date <= row.valid_to):
            return row.basis_points
    if FLAT_RATES_HISTORY != "full" and len(rows) > 0:
        earliest = min(r.valid_from for r in rows)
        if on_date < earliest:
            raise ValueError(
                "no flat rate for %s on %s: this build was installed with history=%s, so it only carries rates from %s. "
                "Reinstall with history=full for older periods." % (sector, on_date, FLAT_RATES_HISTORY, earliest)
            )
    raise ValueError("no flat rate for %s on %s" % (sector, on_date))


def flat_rate_vat(
    turnover: Money,
    sector: str,
    limited_cost_business: bool,
    registration_date: Optional[str],
    supply_date: str,
) -> FlatRateVat:
    """VAT due under the Flat Rate Scheme on a slice of VAT-inclusive turnover.

    The rate is the one in force on the supply date; the first-year reduction
    runs to the day before the first anniversary of registration.
    """
    if turnover.currency != "GBP":
        raise ValueError("the flat rate scheme is for GBP turnover, received %s" % (turnover.currency,))
    add_days(supply_date, 0)
    if sector == _LIMITED_COST or not any(r.sector == sector for r in FLAT_RATES):
        raise ValueError('unknown flat rate sector "%s"' % (sector,))
    base = _rate_on(_LIMITED_COST if limited_cost_business else sector, supply_date)

    reduced = False
    if registration_date is not None:
        if supply_date < add_days(registration_date, 0):
            raise ValueError(
                "supply date %s is before the VAT registration date %s" % (supply_date, registration_date)
            )
        reduced = supply_date < add_months(registration_date, 12)
    basis_points = max(base - 100, 0) if reduced else base
    return FlatRateVat(
        sector=sector,
        limited_cost_business=limited_cost_business,
        first_year_reduction=reduced,
        basis_points=basis_points,
        vat_due=money(apply_rate(turnover, basis_points, "half-up").minor, "GBP"),
    )