from typing import Optional from .dates_add_days import add_days from .dates_add_months import add_months from .finance_tax_vat_flat_rate_data import FLAT_RATES, FLAT_RATES_HISTORY from .finance_tax_vat_flat_rate_types import FlatRateVat from .money_amount import Money, money from .money_apply_rate import apply_rate _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"), )