Functional Weave
Code in Rust

logistics.freight-rate@1.0.1

impl/python.py

4,541 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 List, Optional, Sequence

from .math_round_div import round_div  ← from math.round-div ^1.0.0 · built alongside by fune
from .money_add import add_money  ← from money.add ^1.0.0 · built alongside by fune
from .money_amount import Money, assert_same_currency, 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
from .money_compare import compare_money  ← from money.compare ^1.0.0 · built alongside by fune
from .logistics_freight_rate_types import FreightRate, FuelSurcharge, FreightQuote

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


def _whole(value: object) -> bool:
    return isinstance(value, int) and not isinstance(value, bool)


def _in_force(valid_from: str, valid_to: Optional[str], on_date: str) -> bool:
    return on_date >= valid_from and (valid_to is None or on_date <= valid_to)


def _round_up_to(grams: int, step: int) -> int:
    return round_div(grams, step, "up") * step


def _charge(rate: FreightRate, rated_grams: int) -> Money:
    """The break's charge at a weight: base plus the per-kilogram element, at least the minimum."""
    variable = round_div(rated_grams * rate.per_kg_minor, 1000, "half-up")
    freight = money(rate.base.minor + variable, rate.base.currency)
    if rate.minimum is not None and compare_money(freight, rate.minimum) < 0:
        return rate.minimum
    return freight


def freight_rate(
    rates: Sequence[FreightRate],
    fuel_surcharges: Sequence[FuelSurcharge],
    zone: str,
    chargeable_grams: int,
    ship_date: str,
) -> FreightQuote:
    """Freight for a consignment on a caller-supplied tariff: the zone's break
    covering the weight on the ship date, or a heavier break when that is
    cheaper, plus the fuel surcharge in force that day."""
    if not _whole(chargeable_grams) or chargeable_grams < 1:
        raise ValueError("chargeableGrams must be 1 or more, received %r" % (chargeable_grams,))
    if not isinstance(ship_date, str) or not _ISO_DATE.fullmatch(ship_date):
        raise ValueError('shipDate must be an ISO date (YYYY-MM-DD), received "%s"' % (ship_date,))

    candidates: List[FreightRate] = [
        r for r in rates if r.zone == zone and _in_force(r.valid_from, r.valid_to, ship_date)
    ]
    for rate in candidates:
        if not _whole(rate.step_grams) or rate.step_grams < 1:
            raise ValueError("stepGrams must be 1 or more, received %r" % (rate.step_grams,))
        if not _whole(rate.per_kg_minor) or rate.per_kg_minor < 0:
            raise ValueError("perKgMinor must not be negative, received %r" % (rate.per_kg_minor,))
        assert_same_currency(candidates[0].base, rate.base)

    covering = [
        r
        for r in candidates
        if chargeable_grams >= r.from_grams and (r.to_grams is None or chargeable_grams <= r.to_grams)
    ]
    if not covering:
        raise ValueError(
            'no freight rate for zone "%s" on %s covers %d g' % (zone, ship_date, chargeable_grams)
        )
    if len(covering) > 1:
        raise ValueError(
            'two freight rates for zone "%s" on %s cover %d g' % (zone, ship_date, chargeable_grams)
        )

    best = covering[0]
    best_grams = _round_up_to(chargeable_grams, best.step_grams)
    best_freight = _charge(best, best_grams)
    # Rates per kilogram fall as weight rises, so a heavier break charged at
    # its first weight can undercut the break the consignment falls in.
    for rate in candidates:
        if rate.from_grams <= chargeable_grams:
            continue
        grams = _round_up_to(rate.from_grams, rate.step_grams)
        freight = _charge(rate, grams)
        order = compare_money(freight, best_freight)
        if order < 0 or (order == 0 and grams < best_grams):
            best, best_grams, best_freight = rate, grams, freight

    basis_points = 0
    if len(fuel_surcharges) > 0:
        found: Optional[FuelSurcharge] = None
        for row in fuel_surcharges:
            if not _in_force(row.valid_from, row.valid_to, ship_date):
                continue
            if found is None or row.valid_from > found.valid_from:
                found = row
        # A table that stops short of the date has usually not been updated.
        if found is None:
            raise ValueError("no fuel surcharge in force on %s" % ship_date)
        basis_points = found.basis_points
    fuel_surcharge = apply_rate(best_freight, basis_points, "half-up")
    return FreightQuote(
        zone=zone,
        rated_grams=best_grams,
        break_from_grams=best.from_grams,
        freight=best_freight,
        fuel_surcharge_basis_points=basis_points,
        fuel_surcharge=fuel_surcharge,
        total=add_money(best_freight, fuel_surcharge),
    )