finance.early-payment-discount@1.0.0
impl/typescript.ts
1,658 bytes · the TypeScript 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.
import { addDays } from "./dates_add_days.ts"; ← from dates.add-days ^1.0.0 · built alongside by fune
import { paymentDueDate } from "./finance_payment_terms_due_date.ts"; ← from finance.payment-terms-due-date ^1.0.0 · built alongside by fune
import { type PaymentTerms } from "./finance_payment_terms_due_date_types.ts";
import { subtractMoney } from "./money_add.ts"; ← from money.add ^1.0.0 · built alongside by fune
import { type Money, money } from "./money_amount.ts"; ← from money.amount ^1.0.0 · built alongside by fune
import { applyRate } from "./money_apply_rate.ts"; ← from money.apply-rate ^1.0.0 · built alongside by fune
import { type EarlyPaymentDiscount } from "./finance_early_payment_discount_types.ts";
/**
* The settlement discount open on `paymentDate`, 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.
*/
export function earlyPaymentDiscount(
invoiceTotal: Money,
invoiceDate: string,
terms: PaymentTerms,
paymentDate: string,
): EarlyPaymentDiscount {
if (invoiceTotal.minor < 0) {
throw new RangeError("invoice total must not be negative");
}
// Validates the terms, including a discount window that outlasts the due date.
const dueDate = paymentDueDate(invoiceDate, terms);
// Validates the payment date; ISO dates then compare as strings.
addDays(paymentDate, 0);
const offered = terms.discountBasisPoints > 0;
const discountDeadline = offered ? addDays(invoiceDate, terms.discountDays) : null;
const available = discountDeadline !== null && paymentDate <= discountDeadline;
const discount = available
? applyRate(invoiceTotal, terms.discountBasisPoints, "half-up")
: money(0, invoiceTotal.currency);
return {
available,
discount,
amountToPay: subtractMoney(invoiceTotal, discount),
discountDeadline,
dueDate,
};
}