Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-04-26 08:54:45 +00:00
co-authored by renee-png
parent 852e9a8215
commit c4efc305f2
+61
View File
@@ -786,6 +786,67 @@ export function CollectionDetail({
},
});
// ── Amounts Due Breakdown (below the ledger) ──
// Group entries by bucket → account label → subtotal
const subAccountTotals: Record<string, Record<string, number>> = {};
BUCKETS.forEach((b) => (subAccountTotals[b] = {}));
entries.forEach((e: any) => {
const acctLabel = (e.account && String(e.account).trim()) || "—";
BUCKETS.forEach((b) => {
const v = num(e[b]);
if (v) {
subAccountTotals[b][acctLabel] = (subAccountTotals[b][acctLabel] || 0) + v;
}
});
});
const breakdownBody: any[] = [];
const DISPLAY_ORDER: Array<typeof BUCKETS[number]> = [
"assess", "late", "admin", "legal", "viol", "interest", "bank",
];
DISPLAY_ORDER.forEach((b) => {
const bucketTotal = Math.max(0, computed[b] ?? 0);
const label =
b === "interest"
? `Interest @ ${(effectiveRate || 0).toFixed(2)}%`
: BUCKET_LABEL[b];
breakdownBody.push([
{ content: label, styles: { fontStyle: "bold", fillColor: [245, 245, 245] } },
{ content: formatCurrency(bucketTotal), styles: { halign: "right", fontStyle: "bold", fillColor: [245, 245, 245] } },
]);
const subs = subAccountTotals[b];
const subKeys = Object.keys(subs);
if (subKeys.length > 0) {
subKeys
.sort((a, z) => subs[z] - subs[a])
.forEach((sk) => {
breakdownBody.push([
{ content: ` ${sk}`, styles: { textColor: 90 } },
{ content: formatCurrency(subs[sk]), styles: { halign: "right", textColor: 90 } },
]);
});
}
});
breakdownBody.push([
{ content: "TOTAL DUE", styles: { fontStyle: "bold", fillColor: [20, 20, 20], textColor: 255 } },
{ content: formatCurrency(Math.max(0, computed.total)), styles: { halign: "right", fontStyle: "bold", fillColor: [20, 20, 20], textColor: 255 } },
]);
const ledgerEndY = (doc as any).lastAutoTable?.finalY ?? txStartY;
autoTable(doc, {
startY: ledgerEndY + 20,
margin: { left: margin, right: pageWidth / 2 + 20 },
head: [["Amounts Due Breakdown", "Amount"]],
body: breakdownBody,
styles: { fontSize: 9, cellPadding: 4 },
headStyles: { fillColor: [20, 20, 20], textColor: 255, fontStyle: "bold" },
columnStyles: {
0: { cellWidth: "auto" },
1: { halign: "right", cellWidth: 90 },
},
theme: "grid",
});
doc.save(`${name}.pdf`);
toast.success("PDF exported");
};