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 Optional
from .charity_donation_matching_types import DonationMatch, MatchLimit
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
def _check(name: str, currency: str, amount: Money) -> None:
if amount.currency != currency:
raise ValueError("currency mismatch: %s and %s" % (amount.currency, currency))
if amount.minor < 0:
raise ValueError("%s must not be negative, received %d" % (name, amount.minor))
def donation_match(
donation: Money,
ratio_basis_points: int,
donor_cap: Optional[Money],
donor_matched_so_far: Money,
programme_cap: Optional[Money],
programme_matched_so_far: Money,
) -> DonationMatch:
"""An employer's matched-giving contribution. The ratio is applied first
and rounded down; then the match is held to whatever room is left under
the donor's cap and the programme's budget, never below zero.
"""
currency = donation.currency
_check("donation", currency, donation)
if isinstance(ratio_basis_points, bool) or not isinstance(ratio_basis_points, int) or ratio_basis_points < 0:
raise ValueError("ratioBasisPoints must be a non-negative integer, received %s" % (ratio_basis_points,))
if donor_cap is not None:
_check("donorCap", currency, donor_cap)
_check("donorMatchedSoFar", currency, donor_matched_so_far)
if programme_cap is not None:
_check("programmeCap", currency, programme_cap)
_check("programmeMatchedSoFar", currency, programme_matched_so_far)
uncapped = apply_rate(donation, ratio_basis_points, "down").minor
matched = uncapped
capped_by: MatchLimit = "none"
if donor_cap is not None:
room = max(0, donor_cap.minor - donor_matched_so_far.minor)
if room < matched:
matched = room
capped_by = "donor"
if programme_cap is not None:
room = max(0, programme_cap.minor - programme_matched_so_far.minor)
if room < matched:
matched = room
capped_by = "programme"
return DonationMatch(matched=money(matched, currency), uncapped=money(uncapped, currency), capped_by=capped_by)