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

70 lines
2.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 `*`
### Footer
- 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.