from .math_round_div import RoundingMode, round_div from .money_amount import Money, money def apply_rate(amount: Money, basis_points: int, mode: RoundingMode = "half-up") -> Money: """Apply a rate given in basis points (10000 = 100%). Rates are integers, never floats, so VAT, discounts, interest and commission all stay in exact arithmetic right up to the single rounding step the caller asked for. """ if isinstance(basis_points, bool) or not isinstance(basis_points, int): raise TypeError("basis_points must be an integer, received %r" % (basis_points,)) return money(round_div(amount.minor * basis_points, 10000, mode), amount.currency) def apply_rate_complement(amount: Money, basis_points: int, mode: RoundingMode = "half-up") -> Money: """The complement: what is left after the rate is taken off.""" return money(amount.minor - apply_rate(amount, basis_points, mode).minor, amount.currency)