Functional Weave
Code in TypeScript

finance.early-payment-discount@1.0.0

impl/python.py

1,646 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.

from .dates_add_days import add_days  ← from dates.add-days ^1.0.0 · built alongside by fune
from .finance_early_payment_discount_types import EarlyPaymentDiscount
from .finance_payment_terms_due_date import payment_due_date  ← from finance.payment-terms-due-date ^1.0.0 · built alongside by fune
from .finance_payment_terms_due_date_types import PaymentTerms
from .money_add import subtract_money  ← from money.add ^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_apply_rate import apply_rate  ← from money.apply-rate ^1.0.0 · built alongside by fune


def early_payment_discount(
    invoice_total: Money, invoice_date: str, terms: PaymentTerms, payment_date: str
) -> EarlyPaymentDiscount:
    """The settlement discount open on ``payment_date``, and what is left to pay.

    The window is inclusive and counted in calendar days from the invoice date,
    so under 2/10 the tenth day after the invoice still earns the discount.
    """
    if invoice_total.minor < 0:
        raise ValueError("invoice total must not be negative")
    # Validates the terms, including a discount window that outlasts the due date.
    due_date = payment_due_date(invoice_date, terms)
    # Validates the payment date; ISO dates then compare as strings.
    add_days(payment_date, 0)

    offered = terms.discount_basis_points > 0
    deadline = add_days(invoice_date, terms.discount_days) if offered else None
    available = deadline is not None and payment_date <= deadline
    discount = (
        apply_rate(invoice_total, terms.discount_basis_points, "half-up")
        if available
        else money(0, invoice_total.currency)
    )
    return EarlyPaymentDiscount(
        available=available,
        discount=discount,
        amount_to_pay=subtract_money(invoice_total, discount),
        discount_deadline=deadline,
        due_date=due_date,
    )