mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 01:40:01 +00:00
Checks: print PDF now uses Check Setup settings (matches the sample)
Bulk "Print Checks" was rendering via a separate generator (utils/checkPdfGenerator + check_layouts), so the printed PDF ignored the accounting Check Setup: wrong return address (generic company vs association name + mailing address), missing vendor address, and ignored x/y field-position offsets. Route the print through the same generator as the working sample (lib/checkPdf.generateCheckPDF) fed by the accounting company (return address), check_settings (style/offsets/field_positions/signature/MICR gaps), the chosen bank account (routing/account), and the vendor address as payee. DB side effects (checks, transactions, bill paid status, check numbering) unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,8 @@ import { supabase } from "@/integrations/supabase/client";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { useAuth } from "@/contexts/AuthContext";
|
||||
import { UserCheck, Plus, Search, Eye, Upload, X, ArrowUpDown, Edit, Trash2, MoreHorizontal, AlertTriangle, Loader2, Bell, Printer, Sparkles, Download } from "lucide-react";
|
||||
import { downloadChecksPdf, type CheckData } from "@/utils/checkPdfGenerator";
|
||||
import { generateCheckPDF, type CheckData } from "@/pages/accounting/lib/checkPdf";
|
||||
import { accounting } from "@/lib/accountingClient";
|
||||
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -697,13 +698,19 @@ export default function BillApprovalsPage({ boardAssociationIds }: { boardAssoci
|
||||
try {
|
||||
const { data: userData } = await supabase.auth.getUser();
|
||||
|
||||
// Load per-association check layouts (optional)
|
||||
const { data: layoutsData } = await supabase
|
||||
.from("check_layouts")
|
||||
.select("*")
|
||||
.in("association_id", assocIds);
|
||||
const layoutsByAssoc: Record<string, any> = {};
|
||||
(layoutsData || []).forEach((l: any) => { layoutsByAssoc[l.association_id] = l; });
|
||||
// Load the accounting company (return address = association name + mailing
|
||||
// address) and the saved Check Setup settings per association, so printed
|
||||
// checks match the Check Setup sample exactly.
|
||||
const { data: companiesData } = await accounting
|
||||
.from("companies").select("id, association_id, name, address").in("association_id", assocIds);
|
||||
const companyByAssoc: Record<string, any> = {};
|
||||
(companiesData || []).forEach((c: any) => { companyByAssoc[c.association_id] = c; });
|
||||
const companyIds = (companiesData || []).map((c: any) => c.id);
|
||||
const settingsByCompany: Record<string, any> = {};
|
||||
if (companyIds.length) {
|
||||
const { data: settingsData } = await accounting.from("check_settings").select("*").in("company_id", companyIds);
|
||||
(settingsData || []).forEach((s: any) => { settingsByCompany[s.company_id] = s; });
|
||||
}
|
||||
|
||||
let totalPrinted = 0;
|
||||
let totalReprinted = 0;
|
||||
@@ -717,7 +724,10 @@ export default function BillApprovalsPage({ boardAssociationIds }: { boardAssoci
|
||||
const billStatusUpdates: Array<{ billId: string; checkId: string; checkNumber: string }> = [];
|
||||
const txInserts: any[] = [];
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
const todayDisplay = new Date(today + "T00:00:00").toLocaleDateString("en-US", { month: "2-digit", day: "2-digit", year: "numeric" });
|
||||
const assocName = associations.find((a: any) => a.id === assocId)?.name || "";
|
||||
const company = companyByAssoc[assocId] || null;
|
||||
const settings: any = company ? (settingsByCompany[company.id] || {}) : {};
|
||||
|
||||
// Group bills by payee (vendor) when combining is enabled.
|
||||
// Otherwise treat each bill as its own group.
|
||||
@@ -845,18 +855,27 @@ export default function BillApprovalsPage({ boardAssociationIds }: { boardAssoci
|
||||
}
|
||||
|
||||
checkDataList.push({
|
||||
check_number: checkNumber,
|
||||
check_date: today,
|
||||
companyName: company?.name || assocName || "",
|
||||
companyAddress: company?.address || undefined,
|
||||
bankName: bank.bank_name || undefined,
|
||||
bankAddress: settings.bank_address || undefined,
|
||||
routingNumber: printIncludeMicr ? (bank.routing_number || undefined) : undefined,
|
||||
accountNumber: printIncludeMicr ? (bank.account_number || undefined) : undefined,
|
||||
fractionalRouting: settings.fractional_routing || undefined,
|
||||
checkNumber: Number(checkNumber) || 0,
|
||||
date: todayDisplay,
|
||||
payee,
|
||||
payee_address: payeeAddress,
|
||||
payeeAddress: payeeAddress || undefined,
|
||||
amount: totalAmount,
|
||||
memo,
|
||||
line_items: lineItems.length > 1 ? lineItems : null,
|
||||
bank_account_name: bank.account_name,
|
||||
bank_routing_number: bank.routing_number,
|
||||
bank_account_number: bank.account_number,
|
||||
association_name: assocName,
|
||||
layout: (layoutsByAssoc[assocId] as any) || null,
|
||||
memo: memo || undefined,
|
||||
lineItems: lineItems.length > 1
|
||||
? lineItems.map((li: any) => ({
|
||||
description: [li.invoice_number ? `Inv #${li.invoice_number}` : null, li.description].filter(Boolean).join(" — ") || "Payment",
|
||||
amount: Number(li.amount) || 0,
|
||||
}))
|
||||
: undefined,
|
||||
printSignature: !!settings.print_signature,
|
||||
signatureDataUrl: settings.signature_url || undefined,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -882,7 +901,24 @@ export default function BillApprovalsPage({ boardAssociationIds }: { boardAssoci
|
||||
}
|
||||
|
||||
const safeName = (assocName || "association").replace(/[^a-z0-9-_]+/gi, "_");
|
||||
await downloadChecksPdf(checkDataList, `checks-${safeName}-${today}.pdf`, { includeMicr: printIncludeMicr });
|
||||
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 || {}), ...(printIncludeMicr ? {} : { micr: { hidden: true } }) },
|
||||
};
|
||||
const dataUrl = generateCheckPDF(checkDataList, opts);
|
||||
const a = document.createElement("a");
|
||||
a.href = dataUrl;
|
||||
a.download = `checks-${safeName}-${today}.pdf`;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
}
|
||||
|
||||
const parts: string[] = [];
|
||||
|
||||
Reference in New Issue
Block a user