mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 04:20:55 +00:00
37 lines
1.3 KiB
TypeScript
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 };
|
|
}
|