Changes
Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
co-authored by
renee-png
parent
d05d33dd7f
commit
c0035b2dc8
+54
-4
@@ -1,13 +1,13 @@
|
||||
// Priority order for payment allocation: Bank → Interest → Late → Legal → Admin → Violations → Assessments
|
||||
export const BUCKETS = ["bank", "interest", "late", "legal", "admin", "viol", "assess"] as const;
|
||||
// Priority order for payment allocation: Bank → Interest → Late → Admin → Legal → Violations → Assessments
|
||||
export const BUCKETS = ["bank", "interest", "late", "admin", "legal", "viol", "assess"] as const;
|
||||
export type Bucket = (typeof BUCKETS)[number];
|
||||
|
||||
export const BUCKET_LABEL: Record<Bucket, string> = {
|
||||
bank: "Bank Fees",
|
||||
interest: "Interest",
|
||||
late: "Late Fees",
|
||||
legal: "Legal Fees",
|
||||
admin: "Admin Fees",
|
||||
legal: "Legal Fees",
|
||||
viol: "Violations",
|
||||
assess: "Assessments",
|
||||
};
|
||||
@@ -16,8 +16,8 @@ export const BUCKET_SHORT: Record<Bucket, string> = {
|
||||
bank: "Bank",
|
||||
interest: "Int",
|
||||
late: "Late",
|
||||
legal: "Legal",
|
||||
admin: "Admin",
|
||||
legal: "Legal",
|
||||
viol: "Viol",
|
||||
assess: "Assess",
|
||||
};
|
||||
@@ -93,3 +93,53 @@ export function withRunningBalance(entries: LedgerEntry[], opening = 0) {
|
||||
return { ...e, runningBalance: bal };
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* For each row, compute:
|
||||
* - runningBalance (overall)
|
||||
* - allocations: Record<Bucket, number> — how much of THIS row's payment was
|
||||
* applied to each bucket (in priority order). Empty / zero for non-payment rows.
|
||||
* - bucketBalancesAfter: per-bucket remaining balance after this row.
|
||||
*/
|
||||
export function withAllocations(entries: LedgerEntry[], opening = 0) {
|
||||
const bal: Record<Bucket, number> = {
|
||||
bank: 0, interest: 0, late: 0, admin: 0, legal: 0, viol: 0, assess: 0,
|
||||
};
|
||||
bal.assess += opening;
|
||||
let running = opening;
|
||||
|
||||
return entries.map((e) => {
|
||||
// First add this row's charges
|
||||
BUCKETS.forEach((b) => { bal[b] += num((e as any)[b]); });
|
||||
running += rowCharges(e);
|
||||
|
||||
// Then allocate this row's payment in priority order
|
||||
const allocations: Record<Bucket, number> = {
|
||||
bank: 0, interest: 0, late: 0, admin: 0, legal: 0, viol: 0, assess: 0,
|
||||
};
|
||||
let pay = num(e.payment);
|
||||
if (pay > 0) {
|
||||
for (const b of BUCKETS) {
|
||||
if (pay <= 0) break;
|
||||
if (bal[b] <= 0) continue;
|
||||
const take = Math.min(bal[b], pay);
|
||||
bal[b] -= take;
|
||||
allocations[b] += take;
|
||||
pay -= take;
|
||||
}
|
||||
// leftover overpayment → reduce assess (creates credit)
|
||||
if (pay > 0) {
|
||||
bal.assess -= pay;
|
||||
allocations.assess += pay;
|
||||
}
|
||||
running -= num(e.payment);
|
||||
}
|
||||
|
||||
return {
|
||||
...e,
|
||||
runningBalance: running,
|
||||
allocations,
|
||||
bucketBalancesAfter: { ...bal },
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user