(function(global) { 'use strict'; function fmt(n) { return '$' + Math.round(n).toLocaleString('en-US'); } const PRINT_LOGO = ``; function printInvoice() { const pricing = global.getPricingConfig(); var state = global.readFormState(); const q = global.SVSQuoteEngine.calculateQuote(state, pricing); const waived = document.getElementById('onboardingWaived')?.checked || false; const feeEl = document.getElementById('oneTimeFee'); const onboardingFee = waived ? 0 : (parseFloat(feeEl?.value) || Math.round(q.MRR / 2)); const waivedAmt = Math.round(q.MRR / 2); const quoteRef = document.getElementById('quoteRef')?.textContent || '—'; const quoteDate = document.getElementById('headerDate')?.textContent || '—'; const client = q.clientName || 'Client'; const repName = document.getElementById('repName')?.value || ''; const quoteNotes = document.getElementById('quoteNotes')?.value || ''; const termLabel = q.contractTerm === '12mo' ? '12-Month Contract — 3% off MRR' : q.contractTerm === '24mo' ? '24-Month Contract — 5% off MRR' : 'Month-to-Month'; // P2: Compute explicit validity date (30 days from now) const now = new Date(); const validUntil = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000); const validUntilStr = validUntil.toLocaleDateString('en-CA', { year: 'numeric', month: 'long', day: 'numeric' }); const rows = []; const row = (label, detail, amt, sub) => rows.push({ label, detail, amt, sub: !!sub }); if (q.users > 0) { const pkg = q.byol ? 'BYOL — Bring Your Own License' : 'M365 Premium Included (Identity, Email & Protection)'; row(`User Package — ${pkg}`, `${q.users} user${q.users !== 1 ? 's' : ''} × ${fmt(q.baseUserRate)}/mo`, fmt(q.userBase)); if (q.userExt > 0) row(`↳ Extended Hours (+${fmt(pricing.ADDON_EXT_HOURS)}/user)`, '', fmt(q.userExt), true); if (q.userPWM > 0) row(`↳ 1Password Business (+${fmt(pricing.ADDON_1PASSWORD)}/user)`, '', fmt(q.userPWM), true); if (q.userINKY > 0) row(`↳ INKY Pro Upgrade (+${fmt(pricing.ADDON_INKY)}/user)`, '', fmt(q.userINKY), true); if (q.userZT > 0) row(`↳ Zero Trust User (+${fmt(pricing.ADDON_ZERO_TRUST_USER)}/user)`, '', fmt(q.userZT), true); } if (q.endpoints > 0) { row('Endpoint Management', `${q.endpoints} endpoint${q.endpoints !== 1 ? 's' : ''} × ${fmt(pricing.RATE_ENDPOINT)}/mo`, fmt(q.endpointBase)); if (q.endpointUSB > 0) row(`↳ USB Blocking (+${fmt(pricing.ADDON_USB_BLOCKING)}/endpoint)`, '', fmt(q.endpointUSB), true); if (q.endpointBMB > 0) row(`↳ Bare Metal Backup (+${fmt(pricing.ADDON_BARE_METAL_BACKUP)}/endpoint)`, '', fmt(q.endpointBMB), true); } if (q.servers > 0) { row('Server Management', `${q.servers} server${q.servers !== 1 ? 's' : ''} × ${fmt(pricing.RATE_SERVER)}/mo`, fmt(q.serverBase)); } if (q.ztNetTotal > 0) { row('Zero Trust Networking — HaaS', '', fmt(q.ztNetTotal)); if (q.ztNetSeats > 0) row(`↳ ZT Seats (${q.ztSeats} × ${fmt(pricing.ZT_SEAT_RATE)}/mo)`, '', fmt(q.ztNetSeats), true); if (q.ztNetRouters > 0) row(`↳ HaaS Routers (${q.ztRouters} × ${fmt(pricing.ZT_ROUTER_RATE)}/mo)`, '', fmt(q.ztNetRouters), true); } if (q.voipTotal > 0) { const tier = { basic: 'Basic', standard: 'Standard', premium: 'Premium' }[q.voipTier] || 'Basic'; row(`VoIP / UCaaS — ${tier}`, `${q.voipSeats} seat${q.voipSeats !== 1 ? 's' : ''} × $${q.voipSeatRate}/mo`, fmt(q.voipSeatsAmt)); if (q.voipPhoneAmt > 0) row(`↳ Desk Phone HaaS (+${fmt(pricing.VOIP_PHONE_RATE)}/seat)`, '', fmt(q.voipPhoneAmt), true); if (q.voipFaxAmt > 0) row(`↳ Virtual Fax (+${fmt(pricing.VOIP_FAX_RATE)}/mo)`, '', fmt(q.voipFaxAmt), true); } if (q.adminWaived) { row('Site Admin Fee', `Tenant, network, documentation & vendor management (waived; normally ${fmt(q.adminFeeNet)}/mo)`, fmt(0)); } else { row('Site Admin Fee', 'Tenant, network, documentation & vendor management', fmt(q.adminFeeNet)); } row('↳ Base Site Admin', '', fmt(q.siteAdminBase), true); if (q.ztActive) row('↳ Zero Trust Supplement', '', fmt(pricing.ADMIN_FEE_ZT), true); if (q.addPWM && q.admin1PWM > 0) { row(`↳ 1Password Management (${Math.round(pricing.ADMIN_1PWM_PCT * 100)}%)`, '', fmt(q.admin1PWM), true); } const itemsHTML = rows.map(r => `