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 Sequence
from .hospitality_service_charge_types import BillLine, ServiceCharge
from .math_round_div import RoundingMode ← 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_apply_rate import apply_rate ← from money.apply-rate ^1.0.0 · built alongside by fune
from .money_sum import sum_money ← from money.sum ^1.0.0 · built alongside by fune
def service_charge(lines: Sequence[BillLine], basis_points: int, mode: RoundingMode) -> ServiceCharge:
"""A discretionary service charge on the eligible lines of a bill.
The rate is applied once, to the eligible total, and rounded once. Charging
each line and adding the pennies up drifts: three 3.33 lines at 12.5% are
0.42 each, 1.26 in all, where 12.5% of 9.99 is 1.25.
"""
if len(lines) == 0:
raise ValueError("a bill needs at least one line")
if isinstance(basis_points, bool) or not isinstance(basis_points, int) or basis_points < 0 or basis_points > 10000:
raise ValueError("basisPoints must be a whole number from 0 to 10000, received %s" % (basis_points,))
currency = lines[0].amount.currency
subtotal = sum_money([line.amount for line in lines], currency)
eligible_total = sum_money([line.amount for line in lines if line.eligible], currency)
if eligible_total.minor < 0:
raise ValueError(
"the eligible lines total %d, and a service charge cannot be negative" % (eligible_total.minor,)
)
charge = apply_rate(eligible_total, basis_points, mode)
return ServiceCharge(
eligible_total=eligible_total,
basis_points=basis_points,
charge=charge,
subtotal=subtotal,
total=add_money(subtotal, charge),
)