Euro 0
Euro 1
Euro 2
Euro 3
Euro 4
Euro 5
Euro 6
▾
Anno prima immatricolazione
2026
2025
2024
2023
2022
2021
2020
2019
▾
Tipo di carrozzeria
Seleziona tipo
Berlina
SUV / Crossover
Station Wagon
Monovolume
Coupé
Cabrio
City Car
Furgone / Van
▾
Tassa annuale stimata attuale
—
Totale su 9 anni—
Costo manutenzione 9 anni · 135.000 km
9 anni / 135.000 kmTotale
Totale su 9 anni · 135.000 km—
2Vuoi finanziare l'acquisto?
TAN (Tasso Annuo Nominale)
TAN 8,9% fissoiDato indicativo per la simulazione. Non costituisce offerta di finanziamento né impegno da parte dell'azienda.
Capitale da finanziare
€
Durata
36 mesi
48 mesi
60 mesi
72 mesi
84 mesi
▾
Anticipo versato
iQuando versi un anticipo, quei soldi smettono di lavorare per te. In questa simulazione consideriamo quanto avresti potuto ottenere lasciandoli investiti in modo prudente al 2% annuo per 9 anni.
€
Rendimento a cui rinunci—
Rata mensile
€—
al mese per —
TAN 8,9% fisso——
Prezzo auto
—
Bollo 9 anni
—
Interessi finanziamento
—
Costo reale anticipo
—
Manutenzione 9 anni
—
Costo totale stimato di possesso
€—
in 9 anni · 135.000 km
Costo mensile di possessoPrezzo + bollo + manutenzione su 9 anni, ÷ 108 mesi
€—
(function loadPdfLib(cb){
var s=document.createElement('script');
s.src='https://cdn.jsdelivr.net/npm/pdf-lib@1.17.1/dist/pdf-lib.min.js';
s.onload=cb; document.head.appendChild(s);
})(function(){
const MODELLI = {
'Citroën': ['C3', 'C3 Aircross', 'C5 Aircross'],
'Dacia': ['Sandero', 'Duster', 'Bigster'],
'Fiat': ['Pandina', 'Grande Panda', 'Tipo'],
'Ford': ['Puma', 'Puma Gen-E', 'Kuga'],
'Kia': ['Sportage', 'Stonic', 'Niro'],
'MG': ['MG ZS', 'MG HS', 'MG3'],
'Omoda': ['Omoda 5', 'Omoda 5 SHS-H', 'Omoda 7'],
'Jaecoo': ['Jaecoo 5 SHS-H', 'Jaecoo 7 SHS-H', 'Jaecoo 7 SHS-P', 'Jaecoo 8 SHS-P'],
'Opel': ['Corsa', 'Mokka', 'Frontera'],
'Peugeot': ['208', '2008', '3008'],
'Renault': ['Clio', 'Captur', 'Austral'],
'Toyota': ['Yaris', 'Yaris Cross', 'C-HR'],
'Volkswagen': ['T-Cross', 'T-Roc', 'Tiguan']
};
const CONTATTI = {
'Massimo Rossomandi': '333 140 9319',
'Iacopo Sorano': '377 393 1561',
'Nadesh Van Schaik': '377 394 4681',
'Lada Lanevska': '377 305 1577',
'Alessia Proto': '377 344 3599',
'Massimiliano Marzano': '333 140 9582',
'Giada Coccato': '377 374 2211',
'Valentina Leonetti': '377 392 5136'
};
(() => {
'use strict';
const ANNI = 9;
const TAN = 0.089;
const TASSO_DEPOSITO = 0.02;
const ANNO_CORRENTE = new Date().getFullYear();
let durata = 36;
let finanziamentoAttivo = true;
let lastCapitale = 0;
let lastRata = 0;
let lastTotFinanziato = 0;
const REGIONI = {
standard: { nome: 'Regione non selezionata' },
lombardia: { nome: 'Lombardia' },
piemonte: { nome: 'Piemonte' },
toscana: { nome: 'Toscana' },
emilia: { nome: 'Emilia-Romagna' },
veneto: { nome: 'Veneto' },
lazio: { nome: 'Lazio' }
};
const MANUTENZIONE = {
benzina: [
{ nome:'Tagliandi', costo:350, tip:'Ogni anno o circa ogni 15.000 km.', interventi: km => km===10000?9:Math.max(1,Math.floor((km*ANNI)/15000)) },
{ nome:'Gomme', costo:500, tip:'Sostituzione media ogni 30.000 km.', interventi: km => km===10000?2:(km===15000||km===20000?3:Math.max(1,Math.floor((km*ANNI)/30000))) },
{ nome:'Pastiglie freno', costo:180, tip:'Dipende dal tipo di percorso.', interventi: km => km===10000?2:(km===15000?3:(km===20000?5:Math.max(1,Math.floor((km*ANNI)/30000)))) },
{ nome:'Dischi freno', costo:220, tip:'Durata indicativa 50.000-60.000 km.', interventi: km => Math.max(1,Math.floor((km*ANNI)/60000)) },
{ nome:'Batteria 12V', costo:200, tip:'Durata media 4-5 anni.', interventi: () => 2 },
{ nome:'Tergicristalli', costo:40, tip:'Sostituzione ogni 2-3 anni.', interventi: () => Math.max(1,Math.floor(ANNI/3)) },
{ nome:'Revisioni', costo:90, tip:'Al 4° anno, poi ogni 2 anni.', interventi: () => contaRevisioni() },
{ nome:'Interventi straordinari', costo:1500, tip:'Voce prudenziale per imprevisti ordinari.', interventi: km => (km*ANNI>=150000?2:1) }
],
diesel: [
{ nome:'Tagliandi', costo:350, tip:'Mediamente più onerosi rispetto a benzina.', interventi: km => km===10000?9:Math.max(1,Math.floor((km*ANNI)/15000)) },
{ nome:'Gomme', costo:500, tip:'Valore medio indicativo.', interventi: km => km===10000?2:(km===15000||km===20000?3:Math.max(1,Math.floor((km*ANNI)/30000))) },
{ nome:'Pastiglie freno', costo:180, tip:'Consumo variabile.', interventi: km => km===10000?2:(km===15000?3:(km===20000?5:Math.max(1,Math.floor((km*ANNI)/32000)))) },
{ nome:'Dischi freno', costo:220, tip:'Durata media 50.000-60.000 km.', interventi: km => Math.max(1,Math.floor((km*ANNI)/60000)) },
{ nome:'Batteria 12V', costo:200, tip:'Durata media 4-5 anni.', interventi: () => 2 },
{ nome:'Tergicristalli', costo:40, tip:'Sostituzione ogni 2-3 anni.', interventi: () => Math.max(1,Math.floor(ANNI/3)) },
{ nome:'Revisioni', costo:90, tip:'Al 4° anno, poi ogni 2 anni.', interventi: () => contaRevisioni() },
{ nome:'Interventi straordinari', costo:1800, tip:'Voce prudenziale anche per componenti tipiche dei diesel.', interventi: km => (km*ANNI>=150000?2:1) }
],
ibrido: [
{ nome:'Tagliandi', costo:350, tip:'Valore medio indicativo per mild/full hybrid.', interventi: km => km===10000?9:Math.max(1,Math.floor((km*ANNI)/15000)) },
{ nome:'Gomme', costo:500, tip:'Dipende da peso e misura.', interventi: km => km===10000?2:(km===15000||km===20000?3:Math.max(1,Math.floor((km*ANNI)/30000))) },
{ nome:'Pastiglie freno', costo:180, tip:'Spesso più longeve grazie alla frenata rigenerativa.', interventi: km => km===10000?2:(km===15000?3:(km===20000?5:Math.max(1,Math.floor((km*ANNI)/40000)))) },
{ nome:'Dischi freno', costo:220, tip:'Usura spesso inferiore, ma variabile.', interventi: km => Math.max(1,Math.floor((km*ANNI)/70000)) },
{ nome:'Batteria 12V', costo:200, tip:'Voce separata dalla batteria di trazione.', interventi: () => 2 },
{ nome:'Tergicristalli', costo:40, tip:'Sostituzione ogni 2-3 anni.', interventi: () => Math.max(1,Math.floor(ANNI/3)) },
{ nome:'Revisioni', costo:90, tip:'Al 4° anno, poi ogni 2 anni.', interventi: () => contaRevisioni() },
{ nome:'Interventi straordinari', costo:1300, tip:'Voce prudenziale per imprevisti ordinari.', interventi: km => (km*ANNI>=150000?2:1) }
],
phev: [
{ nome:'Tagliandi', costo:350, tip:'Valore medio indicativo per sistemi ibridi plug-in.', interventi: km => km===10000?9:Math.max(1,Math.floor((km*ANNI)/15000)) },
{ nome:'Gomme', costo:500, tip:'Peso spesso superiore alla media.', interventi: km => km===10000?2:(km===15000||km===20000?3:Math.max(1,Math.floor((km*ANNI)/30000))) },
{ nome:'Pastiglie freno', costo:180, tip:'La rigenerazione può ridurne l\'usura.', interventi: km => km===10000?2:(km===15000?3:(km===20000?5:Math.max(1,Math.floor((km*ANNI)/40000)))) },
{ nome:'Dischi freno', costo:240, tip:'Usura variabile in base all\'utilizzo.', interventi: km => Math.max(1,Math.floor((km*ANNI)/70000)) },
{ nome:'Batteria 12V', costo:200, tip:'Voce separata dalla batteria di trazione.', interventi: () => 2 },
{ nome:'Tergicristalli', costo:40, tip:'Sostituzione ogni 2-3 anni.', interventi: () => Math.max(1,Math.floor(ANNI/3)) },
{ nome:'Revisioni', costo:90, tip:'Al 4° anno, poi ogni 2 anni.', interventi: () => contaRevisioni() },
{ nome:'Interventi straordinari', costo:1450, tip:'Voce prudenziale per gestione meccanica più complessa.', interventi: km => (km*ANNI>=150000?2:1) }
],
elettrico: [
{ nome:'Controlli periodici', costo:350, tip:'Controlli ordinari mediamente inferiori.', interventi: km => km===10000?9:Math.max(1,Math.floor((km*ANNI)/20000)) },
{ nome:'Gomme', costo:500, tip:'Peso e coppia immediata possono aumentare l\'usura.', interventi: km => km===10000?2:(km===15000||km===20000?3:Math.max(1,Math.floor((km*ANNI)/28000))) },
{ nome:'Pastiglie freno', costo:180, tip:'Spesso durano di più grazie alla rigenerazione.', interventi: km => km===10000?2:(km===15000?3:(km===20000?5:Math.max(1,Math.floor((km*ANNI)/50000)))) },
{ nome:'Dischi freno', costo:220, tip:'Usura spesso inferiore ma non nulla.', interventi: km => Math.max(1,Math.floor((km*ANNI)/80000)) },
{ nome:'Batteria 12V', costo:200, tip:'Da non confondere con la batteria di trazione.', interventi: () => 2 },
{ nome:'Tergicristalli', costo:40, tip:'Sostituzione ogni 2-3 anni.', interventi: () => Math.max(1,Math.floor(ANNI/3)) },
{ nome:'Revisioni', costo:90, tip:'Al 4° anno, poi ogni 2 anni.', interventi: () => contaRevisioni() },
{ nome:'Interventi straordinari', costo:900, tip:'Voce prudenziale per assetto e sospensioni.', interventi: km => (km*ANNI>=180000?2:1) }
],
'gpl-metano': [
{ nome:'Tagliandi', costo:350, tip:'Valore medio indicativo per GPL o metano.', interventi: km => km===10000?9:Math.max(1,Math.floor((km*ANNI)/15000)) },
{ nome:'Gomme', costo:500, tip:'Sostituzione media ogni 30.000 km.', interventi: km => km===10000?2:(km===15000||km===20000?3:Math.max(1,Math.floor((km*ANNI)/30000))) },
{ nome:'Pastiglie freno', costo:180, tip:'Dipende dal tipo di percorso.', interventi: km => km===10000?2:(km===15000?3:(km===20000?5:Math.max(1,Math.floor((km*ANNI)/30000)))) },
{ nome:'Dischi freno', costo:220, tip:'Durata indicativa 50.000-60.000 km.', interventi: km => Math.max(1,Math.floor((km*ANNI)/60000)) },
{ nome:'Batteria 12V', costo:200, tip:'Durata media 4-5 anni.', interventi: () => 2 },
{ nome:'Tergicristalli', costo:40, tip:'Sostituzione ogni 2-3 anni.', interventi: () => Math.max(1,Math.floor(ANNI/3)) },
{ nome:'Revisioni', costo:90, tip:'Al 4° anno, poi ogni 2 anni.', interventi: () => contaRevisioni() },
{ nome:'Interventi straordinari', costo:1500, tip:'Voce prudenziale per imprevisti ordinari.', interventi: km => (km*ANNI>=150000?2:1) }
]
};
const $ = id => document.getElementById(id);
const euro = (num, digits = 2) => Number(num || 0).toLocaleString('it-IT', { minimumFractionDigits: digits, maximumFractionDigits: digits });
const euroNoSym = num => `€ ${euro(num, 0)}`;
const euroInput = num => `${Math.round(Number(num || 0))}`;
const setText = (id, value) => { const el = $(id); if (el) el.textContent = value; };
const valueNum = (id, fallback = 0) => {
const el = $(id);
const val = parseFloat(el ? el.value : '');
return Number.isFinite(val) ? val : fallback;
};
const prezzo = () => valueNum('prezzo-auto', 0);
const kmAnnui = () => valueNum('km-annui', 15000);
const kmTotali = () => kmAnnui() * ANNI;
const kw = () => valueNum('kw', 0);
const regione = () => $('regione-bollo') ? $('regione-bollo').value : 'standard';
const alimentazione = () => $('alimentazione') ? $('alimentazione').value : 'benzina';
const classeEuro = () => $('classe-euro') ? $('classe-euro').value : '6';
const annoImm = () => valueNum('anno-imm', ANNO_CORRENTE);
const capitale = () => valueNum('capitale', 0);
const anticipo = () => valueNum('anticipo', 0);
const marcaAuto = () => { const el = $('marca-auto'); return el ? el.value.trim() : ''; };
const modelloAuto = () => { const el = $('modello-auto'); return el ? el.value.trim() : ''; };
const venditore = () => { const el = $('venditore-sel'); return el ? el.value.trim() : ''; };
const bolloCompilato = () => kw() > 0 && regione() !== 'standard';
function contaRevisioni() {
let c = 0;
for (let a = 1; a = 4 && (a - 4) % 2 === 0) c++;
}
return c;
}
function labelAlim(alim) {
const m = {
benzina:'Benzina',
diesel:'Diesel',
ibrido:'Ibrido mild/full',
phev:'Ibrido plug-in',
elettrico:'Elettrico',
'gpl-metano':'GPL/Metano'
};
return m[alim] || 'Veicolo';
}
function bolloLombardiaBase(kwVal) {
if (!kwVal || kwVal <= 0) return 0;
return kwVal <= 100 ? kwVal * 2.58 : (100 * 2.58) + ((kwVal - 100) * 3.87);
}
function bolloPiemonteBase(kwVal) {
if (!kwVal || kwVal <= 0) return 0;
if (kwVal <= 53) return kwVal * 2.58;
if (kwVal <= 100) return kwVal * 2.73;
if (kwVal <= 130) return kwVal * 2.79;
return kwVal * 4.18;
}
function bolloToscanaBase(kwVal) {
if (!kwVal || kwVal <= 0) return 0;
return kwVal <= 100 ? kwVal * 2.71 : (100 * 2.71) + ((kwVal - 100) * 4.26);
}
function bolloEmiliaBase(kwVal) {
if (!kwVal || kwVal <= 0) return 0;
return kwVal <= 100 ? kwVal * 2.84 : (100 * 2.84) + ((kwVal - 100) * 4.26);
}
function bolloVenetoBase(kwVal) {
if (!kwVal || kwVal <= 0) return 0;
return kwVal <= 100 ? kwVal * 2.84 : (100 * 2.84) + ((kwVal - 100) * 4.26);
}
function bolloLazioBase(kwVal) {
if (!kwVal || kwVal <= 0) return 0;
return kwVal <= 100 ? kwVal * 2.84 : (100 * 2.84) + ((kwVal - 100) * 4.26);
}
function bolloBase(kwVal, reg) {
if (!kwVal || kwVal = 20) return 0;
if (eta >= 15) return 0.15;
if (eta >= 10) return 0.30;
if (eta >= 5) return 0.60;
return 1;
}
function superbolloAnnuo(kwVal, anno, refYear = ANNO_CORRENTE) {
if (!kwVal || kwVal <= 185) return 0;
return (kwVal - 185) * 20 * coeffSuperbollo(refYear, anno);
}
function bolloPostEsenzioneElettrico(reg, kwVal) {
if (!kwVal || kwVal <= 0) return 0;
const t = { toscana: 2.71, emilia: 2.84, lazio: 2.84, veneto: 2.84 };
return t[reg] ? kwVal * t[reg] * 0.25 : 0;
}
function stimaCo2Grezza(alim, kwVal) {
if (!kwVal || kwVal kwVal = 2026 && kwVal <= 100;
if (!usaStima) return { usaStima: false, attiva: false, co2Stimata, anniAgevolati: 0 };
const anniAgevolati = co2Stimata <= 60 ? 5 : co2Stimata 0 && eta < anniAgevolati, co2Stimata, anniAgevolati };
}
function bolloAnnuoNetto(alim, reg, anno, kwVal, refYear) {
if (!kwVal || kwVal <= 0) return 0;
const eta = Math.max(0, refYear - anno);
if (alim === 'elettrico') {
if (reg === 'lombardia' || reg === 'piemonte') return 0;
if (['toscana','emilia','lazio','veneto'].includes(reg)) return eta < 5 ? 0 : bolloPostEsenzioneElettrico(reg, kwVal);
return bolloBase(kwVal, reg);
}
if (reg === 'lombardia' && (alim === 'ibrido' || alim === 'phev')) {
const baseIbrida = kwVal * 2.58;
const agev = getAgevolazioneLombardiaStimata(alim, anno, kwVal, refYear);
return agev.attiva ? baseIbrida * 0.5 : baseIbrida;
}
return bolloBase(kwVal, reg);
}
function getBolloOrdinarioSenzaSgravi(alim, reg, kwVal) {
if (!kwVal || kwVal <= 0) return 0;
if (reg === 'lombardia' && (alim === 'ibrido' || alim === 'phev')) return kwVal * 2.58;
return bolloBase(kwVal, reg);
}
function getDettaglioSgravo(alim, reg, anno, kwVal, refYear = ANNO_CORRENTE) {
if (!kwVal || kwVal <= 0) {
return { attivo: false, annuoOrdinario: 0, annuoAgevolato: 0, sgravoAnnuale: 0, descrizione: '', corrispondeA: '' };
}
const annuoOrdinario = getBolloOrdinarioSenzaSgravi(alim, reg, kwVal);
const annuoAgevolato = bolloAnnuoNetto(alim, reg, anno, kwVal, refYear);
const sgravoAnnuale = Math.max(0, annuoOrdinario - annuoAgevolato);
if (sgravoAnnuale <= 0.01) {
return { attivo: false, annuoOrdinario, annuoAgevolato, sgravoAnnuale: 0, descrizione: '', corrispondeA: '' };
}
let descrizione = 'Agevolazione regionale applicata';
let corrispondeA = '';
if (alim === 'elettrico' && (reg === 'lombardia' || reg === 'piemonte')) {
descrizione = 'Esenzione permanente del bollo per veicoli elettrici';
corrispondeA = `Differenza tra bollo ordinario (€ ${euro(annuoOrdinario, 2)}) e importo dovuto (€ ${euro(annuoAgevolato, 2)}).`;
} else if (alim === 'elettrico' && ['toscana','emilia','lazio','veneto'].includes(reg)) {
const eta = Math.max(0, refYear - anno);
descrizione = eta < 5 ? 'Esenzione dei primi 5 anni per veicoli elettrici' : 'Riduzione dopo il periodo di esenzione dei veicoli elettrici';
corrispondeA = `Riduzione rispetto al bollo ordinario regionale (€ ${euro(annuoOrdinario, 2)}).`;
} else if (reg === 'lombardia' && (alim === 'ibrido' || alim === 'phev')) {
const agev = getAgevolazioneLombardiaStimata(alim, anno, kwVal, refYear);
if (agev.usaStima && agev.co2Stimata !== null) {
descrizione = `Riduzione stimata in base a CO2 grezza (${agev.co2Stimata} g/km)`;
corrispondeA = `Sconto rispetto alla tariffa ordinaria regionale: bollo ordinario € ${euro(annuoOrdinario, 2)}, bollo agevolato € ${euro(annuoAgevolato, 2)}.`;
} else {
descrizione = 'Riduzione regionale applicata';
corrispondeA = 'Sconto rispetto al bollo ordinario regionale.';
}
} else {
corrispondeA = 'Differenza rispetto al bollo ordinario regionale.';
}
return { attivo: true, annuoOrdinario, annuoAgevolato, sgravoAnnuale, descrizione, corrispondeA };
}
function getRegolaBollo(reg, alim, anno, kwVal) {
const regName = (REGIONI[reg] || REGIONI.standard).nome;
if (!kwVal || kwVal <= 0) {
return {
annuoPieno:0, annuoBase:0, superbolloAnnuale:0, totaleBase:0, superbolloTotale:0, totale:0,
tone:'tipo-orange', message:'Inserisci i kW per una stima del bollo.', approx:false,
co2Stimata:null, sgravoAttivo:false, sgravoAnnuale:0, sgravoTotale:0,
sgravoDescrizione:'', sgravoCorrispondeA:'', annuoOrdinarioSenzaSgravi:0
};
}
let totaleBase = 0, totaleSuper = 0, totaleSgravo = 0;
for (let i = 0; i 0 || totaleSuper > 0) {
tone = 'tipo-red';
parts.push('Superbollo stimato incluso oltre 185 kW, con riduzione progressiva in base all\'età del veicolo.');
}
return {
annuoPieno,
annuoBase,
superbolloAnnuale: annuoSuper,
totaleBase,
superbolloTotale: totaleSuper,
totale: totaleBase + totaleSuper,
tone,
message: parts.join(' '),
approx: agevLombardia.usaStima,
co2Stimata: agevLombardia.co2Stimata,
sgravoAttivo: dettaglioSgravo.attivo,
sgravoAnnuale: dettaglioSgravo.sgravoAnnuale,
sgravoTotale: totaleSgravo,
sgravoDescrizione: dettaglioSgravo.descrizione,
sgravoCorrispondeA: dettaglioSgravo.corrispondeA,
annuoOrdinarioSenzaSgravi: dettaglioSgravo.annuoOrdinario
};
}
function getVoci() {
return MANUTENZIONE[alimentazione()] || MANUTENZIONE.benzina;
}
function costoOpp(imp) {
return !imp || imp <= 0 ? 0 : Math.round(imp * (Math.pow(1 + TASSO_DEPOSITO, ANNI) - 1));
}
function valoreFuturo(imp) {
return !imp || imp <= 0 ? 0 : Math.round(imp * Math.pow(1 + TASSO_DEPOSITO, ANNI));
}
function snapshotFinanziamentoCorrente() {
if (!finanziamentoAttivo) return { finOn:false, capFinanziato:0, rataVal:0, totRimborsato:0, interessi:0 };
const cap = Math.max(0, capitale());
if (cap p && p > 0) {
ant = p;
note.push('Anticipo riportato al prezzo auto.');
}
const manuale = capEl.dataset.manuale === '1' && !forceAuto;
const maxCap = Math.max(0, p - ant);
if (!manuale) {
cap = maxCap;
} else if (cap > maxCap) {
cap = maxCap;
note.push('Capitale ridotto per non superare il prezzo auto al netto dell\'anticipo.');
}
antEl.value = ant > 0 ? euroInput(ant) : '';
capEl.value = cap > 0 ? euroInput(cap) : '';
if (!finanziamentoAttivo) {
setFinInfo('');
return;
}
const residuoContanti = Math.max(0, p - ant - cap);
if (manuale && p > 0 && residuoContanti > 0) {
note.push(`Restano ${euroNoSym(residuoContanti)} da coprire fuori finanziamento.`);
}
if (!manuale && p > 0) {
note.push(`Capitale sincronizzato automaticamente: prezzo auto ${euroNoSym(p)} − anticipo ${euroNoSym(ant)} = ${euroNoSym(cap)}.`);
}
setFinInfo(note.join(' '));
}
function getSimData() {
const p = prezzo();
const bolloAbilitato = bolloCompilato();
const bolloDet = bolloAbilitato ? getRegolaBollo(regione(), alimentazione(), annoImm(), kw()) : null;
const totBollo = bolloDet ? bolloDet.totale : 0;
const km = kmAnnui();
const voci = getVoci();
const manDet = voci.map(v => ({
nome:v.nome,
costo:v.costo,
interventi:v.interventi(km),
totale:v.costo*v.interventi(km)
}));
const manTot = manDet.reduce((s, v) => s + v.totale, 0);
const fin = snapshotFinanziamentoCorrente();
const anticipoVal = anticipo();
const rendimentoPersoAnticipo = finanziamentoAttivo ? costoOpp(anticipoVal) : 0;
const valFuturoAnticipo = finanziamentoAttivo ? valoreFuturo(anticipoVal) : 0;
let interessiNonMaturati = 0;
if (finanziamentoAttivo && anticipoVal > 0 && durata > 0) {
const r = TAN / 12, n = durata;
const rataAnticipo = r === 0 ? anticipoVal / n : anticipoVal * (r * Math.pow(1+r,n)) / (Math.pow(1+r,n) - 1);
interessiNonMaturati = Math.max(0, rataAnticipo * n - anticipoVal);
}
const totale = p + totBollo + manTot + fin.interessi + rendimentoPersoAnticipo;
return {
p,
bolloDet,
totBollo,
bolloAbilitato,
manDet,
manTot,
finOn:fin.finOn,
capFinanziato:fin.capFinanziato,
rataVal:fin.rataVal,
totRimborsato:fin.totRimborsato,
interessi:fin.interessi,
anticipoVal,
costoAnticipo:rendimentoPersoAnticipo,
rendimentoPersoAnticipo,
valFuturoAnticipo,
interessiNonMaturati,
totale,
mensile:totale/(ANNI*12),
km,
kmTot:kmTotali(),
alimLabel:labelAlim(alimentazione()),
durataVal:durata,
regNome:(REGIONI[regione()]||REGIONI.standard).nome,
kwVal:kw(),
euroVal:classeEuro(),
annoImmVal:annoImm(),
marcaVal:marcaAuto(),
modelloVal:modelloAuto()
};
}
async function generaPDF() {
const btn = $('pdfbtn');
btn.disabled = true;
btn.textContent = 'Generazione PDF…';
try {
refreshAll();
const data = getSimData();
const { PDFDocument, rgb, StandardFonts } = PDFLib;
const templateUrl = 'https://rossomandi.com/wp-content/uploads/2026/04/rossomandi.com-cambia-prospettiva-3-cambia-prospettiva-3.pdf';
const response = await fetch(templateUrl, { cache: 'no-store' });
if (!response.ok) {
throw new Error(`Download template fallito: HTTP ${response.status}`);
}
const templateBytes = await response.arrayBuffer();
const templateDoc = await PDFDocument.load(templateBytes);
const pdfDoc = await PDFDocument.create();
const helveticaBold = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
const helvetica = await pdfDoc.embedFont(StandardFonts.Helvetica);
const [templatePage] = await pdfDoc.copyPages(templateDoc, [0]);
pdfDoc.addPage(templatePage);
const page = pdfDoc.getPages()[0];
const { width, height } = page.getSize();
const nero = rgb(0.07, 0.07, 0.07);
const rosso = rgb(0.78, 0.16, 0.17);
const grigio = rgb(0.25, 0.25, 0.25);
const grigioR = rgb(0.92, 0.92, 0.92);
const bianco = rgb(1, 1, 1);
const scuro = rgb(0.12, 0.12, 0.12);
const ML = 48;
const MR = width - 48;
const CW = MR - ML;
const fmt = (v, d = 0) => `€ ${Number(v||0).toLocaleString('it-IT', {minimumFractionDigits:d, maximumFractionDigits:d})}`;
let y = height - 148;
let rowIdx = 0;
const titoloVeicolo = `Miglior prezzo concessionaria ${data.marcaVal || ''}`;
page.drawText(titoloVeicolo, { x: ML, y, font: helveticaBold, size: 14, color: nero });
const prezzoStr = fmt(data.p, 0);
page.drawText(prezzoStr, {
x: MR - helveticaBold.widthOfTextAtSize(prezzoStr, 18),
y,
font: helveticaBold,
size: 18,
color: rosso
});
y -= 14;
const subLabel = `${data.alimLabel} · ${kmAnnui().toLocaleString('it-IT')} km/anno · ${ANNI} anni · ${data.kmTot.toLocaleString('it-IT')} km totali`;
page.drawText(subLabel, { x: ML, y, font: helvetica, size: 7.5, color: grigio });
y -= 10;
page.drawLine({ start:{x:ML,y}, end:{x:MR,y}, thickness:0.8, color: nero });
y -= 12;
const RH = 16;
const secHeader = (titolo, valore = '') => {
page.drawRectangle({ x:ML, y:y-RH+2, width:CW, height:RH+4, color:scuro });
page.drawText(titolo, { x:ML+6, y:y-RH+7, font:helveticaBold, size:8, color:bianco });
if (valore) {
page.drawText(valore, {
x: MR - helveticaBold.widthOfTextAtSize(valore, 9) - 6,
y: y-RH+7,
font: helveticaBold,
size: 9,
color: bianco
});
}
y -= RH + 6;
rowIdx = 0;
};
const row = (label, valore, bold = false) => {
const bg = rowIdx % 2 === 0 ? bianco : grigioR;
page.drawRectangle({ x:ML, y:y-RH+2, width:CW, height:RH, color:bg });
page.drawText(label, { x:ML+6, y:y-RH+5, font:helvetica, size:7, color:nero });
page.drawText(valore, {
x: MR - (bold ? helveticaBold : helvetica).widthOfTextAtSize(valore, 7.5) - 6,
y: y-RH+5,
font: bold ? helveticaBold : helvetica,
size: 7.5,
color: nero
});
y -= RH;
rowIdx++;
};
const totRow = (label, valore) => {
page.drawRectangle({ x:ML, y:y-RH+2, width:CW, height:RH+2, color:rosso });
page.drawText(label, { x:ML+6, y:y-RH+6, font:helveticaBold, size:7.5, color:bianco });
page.drawText(valore, {
x: MR - helveticaBold.widthOfTextAtSize(valore, 9) - 6,
y: y-RH+6,
font: helveticaBold,
size: 9,
color: bianco
});
y -= RH + 4;
};
const gap = (n = 8) => { y -= n; };
secHeader('RIEPILOGO COSTI DI POSSESSO');
row('Prezzo auto', fmt(data.p, 0), true);
if (data.bolloAbilitato && data.bolloDet) {
row(`Bollo ${ANNI} anni · ${data.kwVal} kW · ${data.regNome}`, fmt(data.totBollo, 0));
}
row(`Manutenzione ${ANNI} anni · ${data.alimLabel}`, fmt(data.manTot, 0));
if (data.finOn) row(`Interessi finanziamento · ${data.durataVal} mesi · TAN 8,9%`, fmt(data.interessi, 0));
if (finanziamentoAttivo && data.rendimentoPersoAnticipo > 0) {
row(`Rendimento a cui rinunci (anticipo al 2% × ${ANNI} anni)`, fmt(data.rendimentoPersoAnticipo, 0));
}
gap(2);
totRow(`TOTALE ${ANNI} ANNI · ${data.kmTot.toLocaleString('it-IT')} km`, fmt(data.totale, 0));
totRow('COSTO MENSILE MEDIO', `€ ${Number(data.mensile).toLocaleString('it-IT',{minimumFractionDigits:2,maximumFractionDigits:2})} / mese`);
gap(12);
if (data.bolloAbilitato && data.bolloDet) {
secHeader('BOLLO AUTO', fmt(data.totBollo, 0));
gap(10);
}
secHeader(`MANUTENZIONE ${ANNI} ANNI · ${data.alimLabel.toUpperCase()}`, fmt(data.manTot, 0));
data.manDet.forEach(it => row(it.nome, fmt(it.totale, 0)));
gap(10);
secHeader(
data.finOn ? 'FINANZIAMENTO' : 'FINANZIAMENTO (non attivo)',
data.finOn ? `Interessi: ${fmt(data.interessi, 0)}` : 'Acquisto in contanti'
);
row('TAN fisso', '8,9%');
row('Capitale finanziato', data.finOn ? fmt(data.capFinanziato, 0) : '—', data.finOn);
row('Durata', data.finOn ? `${data.durataVal} mesi` : '—');
row('Rata mensile', data.finOn ? fmt(data.rataVal, 2) : '—', data.finOn);
row('Interessi totali', data.finOn ? fmt(data.interessi, 0) : '—');
if (finanziamentoAttivo && data.anticipoVal > 0) {
gap(10);
secHeader('ANTICIPO VERSATO', fmt(data.anticipoVal, 0));
row('Anticipo versato', fmt(data.anticipoVal, 0), true);
row('Rendimento a cui rinunci', fmt(data.rendimentoPersoAnticipo, 0));
row('Valore futuro anticipo (2% × 9 anni)', fmt(data.valFuturoAnticipo, 0));
}
gap(10);
page.drawText(
'Simulazione indicativa. Non costituisce offerta contrattuale. Bollo e manutenzione sono stime medie orientative. Finanziamento simulato con ammortamento francese e TAN 8,9% fisso.',
{ x:ML, y, font:helvetica, size:6, color:grigio, maxWidth:CW, lineHeight:8 }
);
const nomeVenditore = venditore();
if (nomeVenditore) {
const telefono = CONTATTI[nomeVenditore] || '';
const footerTxt = telefono ? `${nomeVenditore} · ${telefono}` : nomeVenditore;
page.drawText(footerTxt, {
x: ML,
y: 38,
font: helveticaBold,
size: 9,
color: nero
});
}
const safeStr = s => (s||'')
.toLowerCase()
.normalize('NFD')
.replace(/[\u0300-\u036f]/g,'')
.replace(/[^a-z0-9]+/g,'-')
.replace(/^-+|-+$/g,'')
.slice(0,40);
const nomeFile = ['rossomandi', safeStr(data.marcaVal), safeStr(data.modelloVal), 'simulazione']
.filter(Boolean)
.join('-')
.replace(/--+/g,'-') + '.pdf';
const pdfBytes = await pdfDoc.save();
const blob = new Blob([pdfBytes], { type:'application/pdf' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = nomeFile;
link.click();
} catch(err) {
alert('Impossibile generare il PDF: ' + err.message);
console.error(err);
} finally {
btn.disabled = false;
btn.innerHTML = ` Scarica riepilogo PDF`;
}
}
function setToggle(attivo) {
finanziamentoAttivo = !!attivo;
$('toggle-track').classList.toggle('on',finanziamentoAttivo);
$('toggle-label').classList.toggle('on',finanziamentoAttivo);
$('step2-num').classList.toggle('active',finanziamentoAttivo);
$('step2-lbl').classList.toggle('active',finanziamentoAttivo);
$('toggle-label').textContent = finanziamentoAttivo ? 'Sì' : 'No';
$('toggle-sub').textContent = finanziamentoAttivo ? 'Rata e interessi inclusi nel calcolo' : 'Attiva per aggiungere rata e interessi al calcolo';
$('toggle-row').setAttribute('aria-pressed',finanziamentoAttivo ? 'true' : 'false');
$('card-fin').style.display = finanziamentoAttivo ? 'block' : 'none';
if (!finanziamentoAttivo) {
lastCapitale = 0;
lastRata = 0;
lastTotFinanziato = 0;
setFinInfo('');
}
}
function aggiornaFinanziamento() {
if (!finanziamentoAttivo) {
setText('rata-num','—');
setText('rm-durata','—');
setText('rata-detail-cap','—');
setText('rata-detail-dur','—');
setText('anticipo-val','—');
setText('anticipo-sublbl','');
return;
}
if (!lastCapitale) {
setText('rata-num','—');
setText('rm-durata','—');
setText('rata-detail-cap','—');
setText('rata-detail-dur','—');
} else {
setText('rata-num',euro(lastRata,2));
setText('rm-durata',`${durata} mesi`);
setText('rata-detail-cap',`€ ${euro(lastCapitale,0)}`);
setText('rata-detail-dur',`${durata} mesi`);
}
const ant = anticipo();
if (ant > 0) {
const c = costoOpp(ant), f = valoreFuturo(ant);
setText('anticipo-val',`€ ${euro(c,0)}`);
setText('anticipo-sublbl',`Se € ${euro(ant,0)} restassero investiti al 2% annuo, dopo ${ANNI} anni diventerebbero € ${euro(f,0)}. La differenza, € ${euro(c,0)}, è il rendimento a cui rinunci.`);
} else {
setText('anticipo-val','—');
setText('anticipo-sublbl','');
}
}
function calcolaFinanziamento() {
if (!finanziamentoAttivo) {
lastCapitale = 0;
lastRata = 0;
lastTotFinanziato = 0;
aggiornaFinanziamento();
return;
}
const cap = capitale();
if (!cap || cap < 1) {
lastCapitale = 0;
lastRata = 0;
lastTotFinanziato = 0;
aggiornaFinanziamento();
return;
}
const r = TAN/12, n = durata;
const rata = r===0 ? cap/n : cap*(r*Math.pow(1+r,n))/(Math.pow(1+r,n)-1);
lastCapitale = cap;
lastRata = rata;
lastTotFinanziato = rata*n;
aggiornaFinanziamento();
}
function aggiornaBollo() {
const kwVal = kw();
const result = $('bollo-result');
const banner = $('bollo-esenzione');
if (!kwVal || kwVal 0 ? `${det.approx?'Circa ':''}€ ${euro(det.annuoPieno,2)}` : 'Esente');
setText('bollo-result-note',`${kwVal} kW · ${reg.nome} · Euro ${classeEuro()} · ${labelAlim(alimentazione())}`);
setText('bollo-totale',det.totale>0 ? `${det.approx?'Circa ':''}€ ${euro(det.totale,0)}` : '€ 0');
setText('bollo-footer-period',`Totale su ${ANNI} anni · ${kmTotali().toLocaleString('it-IT')} km`);
setText('bollo-sub',`${kwVal} kW · ${reg.nome} · Euro ${classeEuro()} · ${labelAlim(alimentazione())}`);
banner.className = `bollo-esenzione visible ${det.tone}`;
banner.textContent = 'Importo stimato a fini simulativi, già comprensivo di eventuali agevolazioni.';
}
function renderManutenzione() {
const rows = $('man-rows');
if (!rows) return;
rows.innerHTML = '';
const km = kmAnnui(), kmTot = kmTotali(), voci = getVoci();
let totale = 0;
voci.forEach(voce => {
const interventi = voce.interventi(km);
const sub = voce.costo*interventi;
totale += sub;
const row = document.createElement('div');
row.className = 'man-row';
row.innerHTML = `
Costo unitario€ ${euro(voce.costo,0)}
Interventi× ${interventi}
Totale€ ${euro(sub,0)}
${voce.tip}
`;
const head = row.querySelector('.man-row-head');
head.addEventListener('click',() => {
row.classList.toggle('open');
head.setAttribute('aria-expanded',row.classList.contains('open')?'true':'false');
});
rows.appendChild(row);
});
setText('man-sub',`${ANNI} anni · ${kmTot.toLocaleString('it-IT')} km · ${labelAlim(alimentazione())}`);
setText('man-head-anni',`${ANNI} anni / ${kmTot.toLocaleString('it-IT')} km`);
setText('man-footer-period',`Totale su ${ANNI} anni · ${kmTot.toLocaleString('it-IT')} km`);
setText('man-totale',`€ ${euro(totale,0)}`);
}
function aggiornaRiepilogo() {
const data = getSimData();
setText('rp-capitale',data.p>0 ? `€ ${euro(data.p,0)}` : '—');
setText('rp-bollo',data.bolloDet ? `${data.bolloDet.approx?'Circa ':''}€ ${euro(data.totBollo,0)}` : '—');
setText('rp-interessi',data.finOn ? `€ ${euro(data.interessi,0)}` : '—');
setText('rp-anticipo',finanziamentoAttivo&&data.anticipoVal>0 ? `€ ${euro(data.costoAnticipo,0)}` : '—');
setText('rp-man',`€ ${euro(data.manTot,0)}`);
setText('rp-totale',data.p>0 ? euro(data.totale,0) : '—');
setText('rp-mensile',data.p>0 ? Number(data.mensile||0).toLocaleString('it-IT',{minimumFractionDigits:2,maximumFractionDigits:2}) : '—');
setText('totale-anni',`in ${ANNI} anni · ${data.kmTot.toLocaleString('it-IT')} km`);
setText('bk-label-bollo-text',`${data.bolloDet&&data.bolloDet.approx?'Circa ':''}Bollo ${ANNI} anni (${kw()>0?`${kw()} kW`:'kW non inseriti'})`);
setText('bk-label-int-text',`Interessi finanziamento (${durata} mesi)`);
setText('bk-label-man-text',`Manutenzione ${ANNI} anni · ${data.alimLabel}`);
setText(
'bk-bollo-note',
data.bolloDet
? (
data.bolloDet.sgravoAttivo
? `${data.regNome} · Euro ${data.euroVal} · ${data.bolloDet.sgravoDescrizione} · ${data.bolloDet.sgravoCorrispondeA} · sgravio totale ${ANNI} anni: - € ${euro(data.bolloDet.sgravoTotale,0)}`
: data.bolloDet.superbolloTotale>0
? `Include superbollo stimato di € ${euro(data.bolloDet.superbolloTotale,0)}`
: `${data.regNome} · Euro ${data.euroVal}`
)
: ''
);
setText('bk-man-note',`${data.kmTot.toLocaleString('it-IT')} km totali stimati`);
setText('bk-anticipo-note',data.anticipoVal>0 ? `Rendimento mancato su ${ANNI} anni al 2% annuo` : '');
let mensileTxt = `Prezzo + bollo + manutenzione su ${ANNI} anni`;
if (data.finOn) mensileTxt += ' + interessi';
if (finanziamentoAttivo&&data.anticipoVal>0) mensileTxt += ' + costo reale anticipo';
mensileTxt += `, ÷ ${ANNI*12} mesi`;
setText('mensile-sub',mensileTxt);
$('bk-row-int').style.display = data.finOn ? 'flex' : 'none';
$('bk-row-anticipo').style.display = finanziamentoAttivo&&data.anticipoVal>0 ? 'flex' : 'none';
}
function refreshAll() {
normalizzaFinanziamento();
renderManutenzione();
aggiornaBollo();
calcolaFinanziamento();
aggiornaRiepilogo();
}
const durataEl = $('durata-sel');
if (durataEl) {
durataEl.addEventListener('change',e => {
durata = parseInt(e.target.value,10) || 36;
calcolaFinanziamento();
aggiornaRiepilogo();
});
}
['prezzo-auto','km-annui','kw','regione-bollo','alimentazione','classe-euro','anno-imm','anticipo','marca-auto','modello-auto'].forEach(id => {
const el = $(id);
if (!el) return;
const evt = ['km-annui','regione-bollo','alimentazione','classe-euro','anno-imm'].includes(id) ? 'change' : 'input';
el.addEventListener(evt,() => {
if(id==='anticipo') $('capitale').dataset.manuale = $('capitale').dataset.manuale || '0';
refreshAll();
});
});
const capEl = $('capitale');
if (capEl) {
capEl.addEventListener('input',() => {
capEl.dataset.manuale = capEl.value ? '1' : '0';
refreshAll();
});
}
$('toggle-row').addEventListener('click',() => {
setToggle(!finanziamentoAttivo);
if(finanziamentoAttivo && !$('capitale').value) $('capitale').dataset.manuale='0';
refreshAll();
});
$('pdfbtn').addEventListener('click',generaPDF);
const marcaSel = $('marca-auto');
const modelloSel = $('modello-auto');
if (marcaSel && modelloSel) {
marcaSel.addEventListener('change',function() {
const marca = this.value;
modelloSel.innerHTML = 'Seleziona modello';
if (marca && MODELLI[marca]) {
MODELLI[marca].forEach(m => {
const opt = document.createElement('option');
opt.value = m;
opt.textContent = m;
modelloSel.appendChild(opt);
});
} else {
modelloSel.innerHTML = '— prima seleziona la marca —';
}
});
}
function init() {
const capElInit = $('capitale');
if (capElInit) capElInit.dataset.manuale = '0';
const antEl = $('anticipo');
if (antEl) antEl.value = '';
setToggle(true);
normalizzaFinanziamento({forceAuto:true});
refreshAll();
}
init();
}); // closes loadPdfLib
})();