Files
edr-platform/apps/edr-freight-api/src/modules/billing/invoice-settlement.util.ts
2026-06-30 11:58:28 +00:00

37 lines
1.3 KiB
TypeScript

/**
* Shared payment/settlement math for invoices. Both the global
* `BillingService.recordPayment` and the warehouse fee invoice flow apply a
* payment the same way — accumulate `paidAmount`, derive the outstanding
* `balanceAmount`, and decide whether the invoice is now fully settled. Keeping
* it here means the two flows can never drift on rounding or the
* partial-vs-full threshold.
*/
/** Round to 2 decimals, avoiding binary float drift. */
export const round2 = (n: number): number => Math.round(n * 100) / 100;
export interface SettlementResult {
/** New cumulative amount paid. */
paidAmount: number;
/** Remaining balance (0 once fully paid). */
balanceAmount: number;
/** True once the balance reaches zero. */
fullyPaid: boolean;
}
/**
* Apply a single payment of `amount` to an invoice with `totalAmount` already
* carrying `currentPaid`. Caller is responsible for validating `amount > 0` and
* the invoice being in a payable state.
*/
export function applySettlement(
totalAmount: number,
currentPaid: number,
amount: number,
): SettlementResult {
const total = Number(totalAmount);
const paidAmount = round2(Number(currentPaid) + Number(amount));
const balanceAmount = Math.max(0, round2(total - paidAmount));
return { paidAmount, balanceAmount, fullyPaid: paidAmount >= total };
}