Files
2026-07-12 10:17:17 -04:00

2.8 KiB
Raw Permalink Blame History

Quote PDF Generation (quote-tab-manager.js)

Entry Points

Two user actions, both in quote-tab-manager.js:

  • downloadPdf() (line ~3696): creates download link, triggers save as Quote_XXX_CustomerName.pdf
  • printQuote() (line ~3670): opens PDF blob in new window, triggers window.print()

Both call generateQuotePDF() — the only difference is what happens with the returned blob.

Button Wiring

ensureDownloadPdfBtnListener() (line ~706):

  1. Looks for buttons with IDs download-pdf-btn or generate-pdf-btn
  2. Falls back to scanning all buttons for text/classes containing "pdf" or "download"
  3. If still nothing found, dynamically creates a PDF button via createPdfButton()

generateQuotePDF() Structure

Location: quote-tab-manager.js line ~3727

  1. Dynamically imports jsPDF from CDN: https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js
  2. Accesses via window.jspdf.jsPDF
  3. Validates customer name + services exist
  4. Builds PDF with these sections:

Header (two-column layout)

  • Left column: "SERVICE PROVIDER" label, business name/address/phone, service advisor
  • Right column: "CUSTOMER INFORMATION" label, name/vehicle/RO#/mileage/VIN/date
  • Bold separator line between header and content

Personalized Message

  • Uses appSettings.headerMessage template with {customerName} and {vehicleInfo} placeholders
  • Split to fit content width

Services Section

  • Split into "SERVICES APPROVED" and "POSTPONED SERVICES" if mixed decisions exist
  • Each service: green "✓ CUSTOMER APPROVED" or red "✗ CUSTOMER DECLINED" badge
  • Service name: bold, 10px (reduced from 12px)
  • Price: right-aligned
  • Priority header (if prioritized): [CRITICAL], [SAFETY], [RECOMMENDED], [MAINTENANCE], [OPTIONAL]
  • Recommendation level text
  • Service explanation (split to fit width)
  • Parts/aftermarket notes
  • Light gray separator between services

Pricing Summary (totals box)

  • Subtle #f8f8f8 rounded-rect background box with #dcdcdc border
  • 45% width from right margin
  • Line items (9px, labels in gray #646464): Subtotal, Approved (green), Discount (green with sign), Shop charge, Tax
  • Separator: 0.5px #b4b4b4 line
  • TOTAL: bold 10px
  • Row spacing: 8px throughout

Shop Charge Note

  • Positioned at boxBottomY + 10 — must stay after the box's visual boundary
  • 8px font, gray, prefixed with *
  • Light gray separator line
  • Centered appSettings.footerMessage and appSettings.quoteFooterNote
  • Page numbers: "Page X of Y" at bottom right

Key Design Choice

technicianNotes are deliberately excluded from PDFs — they're internal AI context notes, not customer-facing.

Invoice PDF (repair-orders.js)

Separate from quotes. printInvoice() at line ~1340 in repair-orders.js calls generateInvoicePDF() which also uses jsPDF but with a different layout.