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, Sequence
from .math_round_div import 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
from .money_compare import compare_money ← from money.compare ^1.0.0 · built alongside by fune
from .retail_volumetric_weight import chargeable_weight ← from retail.volumetric-weight ^1.0.0 · built alongside by fune
from .retail_shipping_rate_types import ShippingBand, Parcel, ShippingQuote
_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 _chargeable_in(band: ShippingBand, parcel: Parcel) -> int:
if band.volumetric_divisor is None:
return round_div(parcel.actual_grams, band.round_up_to_grams, "up") * band.round_up_to_grams
return chargeable_weight(
parcel.length_mm,
parcel.width_mm,
parcel.height_mm,
parcel.actual_grams,
band.volumetric_divisor,
band.round_up_to_grams,
).chargeable_grams
def shipping_rate(
bands: Sequence[ShippingBand],
service: str,
zone: str,
parcel: Parcel,
basket_total: Money,
on_date: str,
) -> ShippingQuote:
"""The delivery charge for a parcel: the smallest band on the rate card in
force on the order date that takes it, free when the basket reaches the
band's threshold.
"""
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,))
for d in (parcel.length_mm, parcel.width_mm, parcel.height_mm):
if not _whole(d) or d < 1:
raise ValueError("dimensions must be 1 mm or more, received %r" % (d,))
if not _whole(parcel.actual_grams) or parcel.actual_grams < 0:
raise ValueError("actualGrams must not be negative, received %r" % (parcel.actual_grams,))
longest = max(parcel.length_mm, parcel.width_mm, parcel.height_mm)
best: Optional[ShippingBand] = None
best_grams = 0
for band in bands:
if band.service != service or band.zone != zone:
continue
if on_date < band.valid_from or (band.valid_to is not None and on_date > band.valid_to):
continue
if band.max_length_mm is not None and longest > band.max_length_mm:
continue
grams = _chargeable_in(band, parcel)
if grams > band.max_grams:
continue
if (
best is None
or band.max_grams < best.max_grams
or (band.max_grams == best.max_grams and compare_money(band.price, best.price) < 0)
):
best = band
best_grams = grams
if best is None:
raise ValueError(
'no shipping band for service "%s" to zone "%s" on %s fits this parcel' % (service, zone, on_date)
)
free = best.free_over is not None and compare_money(basket_total, best.free_over) >= 0
return ShippingQuote(
service=service,
zone=zone,
chargeable_grams=best_grams,
band_max_grams=best.max_grams,
standard_price=best.price,
price=money(0, best.price.currency) if free else best.price,
free=free,
)