mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 09:50:01 +00:00
Checks: align Print Checks page with Check Setup generator
PrintChecksPage was still using the old generator (utils/checkPdfGenerator + check_layouts), so it had the same bugs as Bill Approvals (wrong return address, missing vendor address, ignored x/y offsets). Route it through lib/checkPdf.generateCheckPDF using the accounting company (return address), check_settings (layout/offsets/field positions/signature/MICR), the selected bank account (routing/account), and vendor address as payee. DB side effects unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,8 @@ import { Checkbox } from "@/components/ui/checkbox";
|
|||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
||||||
import { downloadChecksPdf, type CheckData } from "@/utils/checkPdfGenerator";
|
import { generateCheckPDF, type CheckData } from "@/pages/accounting/lib/checkPdf";
|
||||||
|
import { accounting } from "@/lib/accountingClient";
|
||||||
|
|
||||||
interface BankAccount {
|
interface BankAccount {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -89,12 +90,21 @@ export default function PrintChecksPage() {
|
|||||||
const selectedChecks = checks.filter((c) => selected.has(c.id));
|
const selectedChecks = checks.filter((c) => selected.has(c.id));
|
||||||
let nextNum = selectedBank.next_check_number;
|
let nextNum = selectedBank.next_check_number;
|
||||||
|
|
||||||
// Load layout for this bank's association (optional)
|
// Load accounting company (return address) per association + the bank
|
||||||
const { data: layoutRow } = await supabase
|
// association's Check Setup settings, so output matches the Check Setup sample.
|
||||||
.from("check_layouts")
|
const assocIdsInvolved = Array.from(new Set(
|
||||||
.select("*")
|
selectedChecks.map((c) => c.association_id).concat(selectedBank.association_id).filter(Boolean)
|
||||||
.eq("association_id", selectedBank.association_id)
|
));
|
||||||
.maybeSingle();
|
const { data: companiesData } = await accounting
|
||||||
|
.from("companies").select("id, association_id, name, address").in("association_id", assocIdsInvolved);
|
||||||
|
const companyByAssoc: Record<string, any> = {};
|
||||||
|
(companiesData || []).forEach((c: any) => { companyByAssoc[c.association_id] = c; });
|
||||||
|
const bankCompany = companyByAssoc[selectedBank.association_id] || null;
|
||||||
|
let settings: any = {};
|
||||||
|
if (bankCompany) {
|
||||||
|
const { data: settingsRow } = await accounting.from("check_settings").select("*").eq("company_id", bankCompany.id).maybeSingle();
|
||||||
|
settings = settingsRow || {};
|
||||||
|
}
|
||||||
|
|
||||||
if (includeMicr && (!selectedBank.routing_number || !selectedBank.account_number)) {
|
if (includeMicr && (!selectedBank.routing_number || !selectedBank.account_number)) {
|
||||||
toast({ title: "Missing routing/account number", description: "Add them on the bank account before printing MICR.", variant: "destructive" });
|
toast({ title: "Missing routing/account number", description: "Add them on the bank account before printing MICR.", variant: "destructive" });
|
||||||
@@ -186,19 +196,30 @@ export default function PrintChecksPage() {
|
|||||||
) || matches[0] || null;
|
) || matches[0] || null;
|
||||||
const payeeAddress = vendorMatch?.address || null;
|
const payeeAddress = vendorMatch?.address || null;
|
||||||
|
|
||||||
|
const grpCompany = companyByAssoc[first.association_id] || bankCompany || null;
|
||||||
|
const checkDateDisplay = new Date((first.check_date || today) + "T00:00:00").toLocaleDateString("en-US", { month: "2-digit", day: "2-digit", year: "numeric" });
|
||||||
printable.push({
|
printable.push({
|
||||||
check_number: checkNum,
|
companyName: grpCompany?.name || first.associations?.name || "",
|
||||||
check_date: first.check_date || today,
|
companyAddress: grpCompany?.address || undefined,
|
||||||
|
bankName: selectedBank.bank_name || undefined,
|
||||||
|
bankAddress: settings.bank_address || undefined,
|
||||||
|
routingNumber: includeMicr ? (selectedBank.routing_number || undefined) : undefined,
|
||||||
|
accountNumber: includeMicr ? (selectedBank.account_number || undefined) : undefined,
|
||||||
|
fractionalRouting: settings.fractional_routing || undefined,
|
||||||
|
checkNumber: Number(checkNum) || 0,
|
||||||
|
date: checkDateDisplay,
|
||||||
payee: first.payee,
|
payee: first.payee,
|
||||||
payee_address: payeeAddress,
|
payeeAddress: payeeAddress || undefined,
|
||||||
amount: total,
|
amount: total,
|
||||||
memo,
|
memo: memo || undefined,
|
||||||
line_items: lineItems.length > 1 ? lineItems : null,
|
lineItems: lineItems.length > 1
|
||||||
bank_account_name: selectedBank.account_name,
|
? lineItems.map((li) => ({
|
||||||
bank_routing_number: selectedBank.routing_number,
|
description: [li.invoice_number ? `Inv #${li.invoice_number}` : null, li.description].filter(Boolean).join(" — ") || "Payment",
|
||||||
bank_account_number: selectedBank.account_number,
|
amount: Number(li.amount) || 0,
|
||||||
association_name: first.associations?.name,
|
}))
|
||||||
layout: (layoutRow as any) || null,
|
: undefined,
|
||||||
|
printSignature: !!settings.print_signature,
|
||||||
|
signatureDataUrl: settings.signature_url || undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mark every source check as printed under this combined check number
|
// Mark every source check as printed under this combined check number
|
||||||
@@ -222,8 +243,25 @@ export default function PrintChecksPage() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate & download the PDF (one page per group/check)
|
// Generate & download the PDF (one page per group/check) — same generator as Check Setup
|
||||||
await downloadChecksPdf(printable, `checks-${today}.pdf`, { includeMicr });
|
const opts: any = {
|
||||||
|
style: settings.default_style || "voucher",
|
||||||
|
position: settings.default_position || "top",
|
||||||
|
fontSize: settings.font_size || "medium",
|
||||||
|
offsetX: Number(settings.offset_x ?? 0),
|
||||||
|
offsetY: Number(settings.offset_y ?? 0),
|
||||||
|
micrOffsetY: Number(settings.micr_offset_y ?? 0),
|
||||||
|
micrGap1: Number(settings.micr_gap_1 ?? 1),
|
||||||
|
micrGap2: Number(settings.micr_gap_2 ?? 1),
|
||||||
|
fieldPositions: { ...(settings.field_positions || {}), ...(includeMicr ? {} : { micr: { hidden: true } }) },
|
||||||
|
};
|
||||||
|
const dataUrl = generateCheckPDF(printable, opts);
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.href = dataUrl;
|
||||||
|
a.download = `checks-${today}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
|
||||||
// Persist: mark printed, save check numbers + bank account, advance next_check_number
|
// Persist: mark printed, save check numbers + bank account, advance next_check_number
|
||||||
for (const u of sourceUpdates) {
|
for (const u of sourceUpdates) {
|
||||||
|
|||||||
Reference in New Issue
Block a user