Functional Weave
Code in Python

legal.court-fee@1.0.2

impl/python.py

2,295 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.

import re
from typing import Optional

from .legal_court_fee_data import ISSUE_FEES, ISSUE_FEES_HISTORY  ← this capability’s own data, compiled from data/issue-fees.json into the same file by fune build
from .legal_court_fee_types import FilingChannel
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

_ISO_DATE = re.compile(r"[0-9]{4}-[0-9]{2}-[0-9]{2}")


def court_fee(claim: Money, channel: FilingChannel, on_date: str) -> Money:
    """The fee to issue a money claim, from the bands in force on the issue date."""
    if claim.currency != "GBP":
        raise ValueError("court fees are set for claims in GBP, received %s" % (claim.currency,))
    if claim.minor <= 0:
        raise ValueError("claim must be greater than zero")
    if channel not in ("paper", "online"):
        raise ValueError('unknown filing channel "%s": expected paper or online' % (channel,))
    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,))
    in_force = 0
    earliest: Optional[str] = None
    for row in ISSUE_FEES:
        if row.channel != channel:
            continue
        if earliest is None or row.valid_from < earliest:
            earliest = row.valid_from
        if on_date < row.valid_from or (row.valid_to is not None and on_date > row.valid_to):
            continue
        in_force += 1
        if claim.minor <= row.over_minor or (row.up_to_minor is not None and claim.minor > row.up_to_minor):
            continue
        if row.fee_minor is not None:
            return money(row.fee_minor, "GBP")
        # gov.uk: "round down the result to the nearest 1 pence".
        return apply_rate(claim, row.basis_points, "down")
    if in_force > 0:
        raise ValueError(
            "a claim of %s pence cannot be issued %s on %s: online claims are limited to GBP 100,000" % (claim.minor, channel, on_date)
        )
    if ISSUE_FEES_HISTORY != "full" and earliest is not None and on_date < earliest:
        raise ValueError(
            "no %s court fee on %s: this build was installed with history=%s, so it only carries fees from %s. "
            "Reinstall with history=full for older claims." % (channel, on_date, ISSUE_FEES_HISTORY, earliest)
        )
    raise ValueError("no %s court fee in force on %s" % (channel, on_date))