@@ -417,59 +417,77 @@ function fmt2(n) { return parseFloat(n).toFixed(2) + ' €'; }
function renderBreakdown(d, body) {
const dm = parseFloat(body.design_multiplier).toFixed(2);
const mgn = parseFloat(body.gross_margin_pct).toFixed(1);
+ const qty = body.order_qty || 1;
+ const ppp = body.pieces_per_plate || 1;
+ const multi = qty > 1;
- // Nom du materiau selectionne
- const matSel = document.getElementById('materialSelect');
- const matOpt = matSel.options[matSel.selectedIndex];
+ // Nom du materiau
+ const matSel = document.getElementById('materialSelect');
+ const matOpt = matSel.options[matSel.selectedIndex];
const matName = matOpt.value ? (matOpt.dataset.name || matOpt.text.split('—')[0].trim()) : 'global';
// TVA
const tvaLabel = d._tva_pct > 0 ? `TVA (${d._tva_pct}%)` : `TVA — franchise en base`;
const tvaClass = d._tva_pct > 0 ? '' : 'text-muted fst-italic';
- // VFL
- const vflRow = d._vfl_pct > 0
- ? `
` : '';
-
- // Multi-piece header
- const qty = body.order_qty || 1;
- const ppp = body.pieces_per_plate || 1;
- const nbPlateaux = Math.ceil(qty / ppp);
- const lastPlate = qty % ppp;
- const priceOrder = d.price_order || (d.final_price * qty);
- let plateauAlert = '';
- if (lastPlate !== 0) {
- plateauAlert = `
-
- Dernier plateau incomplet :
${lastPlate}/${ppp} pièces.
- Vous pourriez imprimer jusqu'à
${nbPlateaux * ppp} pièces pour le même coût fixe.
+ // Helper : génère une ligne avec 1 ou 2 colonnes de valeurs
+ // cls : classes CSS supplémentaires sur le div
+ function row(label, pieceVal, extraCls = '', isFmt4 = false) {
+ const fmtFn = isFmt4 ? fmt : fmt2;
+ const p = fmtFn(pieceVal);
+ const o = multi ? `
${fmt2(pieceVal * qty)}` : '';
+ return ``;
+ }
+ function rowFiscal(label, pieceVal, extraCls = '') {
+ const p = fmt2(pieceVal);
+ const o = multi ? `
${fmt2(pieceVal * qty)}` : '';
+ return ``;
}
- // Prix header (1 ou 2 colonnes)
- const multiPriceHeader = qty > 1
- ? `
-
-
Prix / pièce
-
${fmt2(d.final_price)}
-
-
-
Prix commande (×${qty})
-
${fmt2(priceOrder)}
-
-
`
- : '';
+ // Alerte plateau incomplet
+ const nbPlateaux = Math.ceil(qty / ppp);
+ const lastPlate = qty % ppp;
+ let plateauAlert = '';
+ if (lastPlate !== 0) {
+ plateauAlert = `
+
+ Dernier plateau incomplet : ${lastPlate}/${ppp} pièces —
+ vous pourriez imprimer ${nbPlateaux * ppp} pièces pour le même coût fixe.
+
`;
+ }
+
+ // En-tête colonnes (multi uniquement)
+ const colHeader = multi
+ ? `
+ / pièce
+ / commande ×${qty}
+
` : '';
+
+ // VFL / autres taxes
+ const vflRow = d._vfl_pct > 0 ? rowFiscal(`
VFL impot (${d._vfl_pct}%)`, d.vfl_amount) : '';
+ const otherRow = d._other_taxes_pct > 0 ? rowFiscal(`
Autres taxes / CFE (${d._other_taxes_pct}%)`, d.other_taxes_amount) : '';
+
+ // Remise (sur prix TTC/pièce)
+ let disRow = '';
+ if (body.discount_pct > 0) {
+ const remisePiece = d.prix_ttc * body.discount_pct / 100;
+ const o = multi ? `
-${fmt2(remisePiece * qty)}` : '';
+ disRow = `
+ Remise (${body.discount_pct}%)
+ -${fmt2(remisePiece)}${o}
+
`;
+ }
// Capacité
- const cap = d.capacity || {};
+ const cap = d.capacity || {};
const totalMin = d.total_print_min || 0;
const capBlock = `
@@ -479,31 +497,51 @@ function renderBreakdown(d, body) {
Pieces / semaine${cap.pieces_per_week||'—'}
Pieces / mois (30j)${cap.pieces_per_month||'—'}
`;
- document.getElementById('breakdown').innerHTML = plateauAlert + multiPriceHeader + `
+ // Prix finaux
+ const pricePiece = d.final_price;
+ const priceOrder = pricePiece * qty;
+ const finalLabel = multi
+ ? `
+
PRIX FINAL TTC
+
+ ${fmt2(pricePiece)}
+ × ${qty} = ${fmt2(priceOrder)}
+
+
`
+ : `
PRIX FINAL TTC${fmt2(pricePiece)}
`;
+
+ document.getElementById('breakdown').innerHTML = plateauAlert + colHeader + `
-
Matiere ${matName}${fmt(d.material_cost)}
-
Marge matiere (${d._material_margin_pct}%)${fmt(d.material_margin)}
-
Usure — imprimante${fmt(d.printer_wear)}
-
Usure — buse${fmt(d.nozzle_wear)}
-
Usure — plateau${fmt(d.plate_wear)}
-
Electricite ${parseFloat(d.kwh_used).toFixed(3)} kWh × ${d._elec_price} €${fmt(d.electricity_cost)}
-
Total cout fixe${fmt2(d.cout_fixe)}
+ ${row(`
Matiere ${matName}`, d.material_cost, '', true)}
+ ${row(`
Marge matiere (${d._material_margin_pct}%)`, d.material_margin, '', true)}
+ ${row(`
Usure — imprimante`, d.printer_wear, '', true)}
+ ${row(`
Usure — buse`, d.nozzle_wear, '', true)}
+ ${row(`
Usure — plateau`, d.plate_wear, '', true)}
+ ${row(`
Electricite ${parseFloat(d.kwh_used).toFixed(3)} kWh × ${d._elec_price} €`, d.electricity_cost, '', true)}
+ ${row(`
Total cout fixe`, d.cout_fixe, 'subtotal')}
-
Manutention ${d._handling_minutes} min × ${d._handling_rate} €/h${fmt(d.handling_cost)}
-
Design (x${dm})${fmt(d.design_cost)}
-
Marge brute (${mgn}%)${fmt2(d.margin_amount)}
-
Total marge (${d.marge_pct_on_ht}% du HT)${fmt2(d.total_marge)}
+ ${row(`
Manutention ${d._handling_minutes} min × ${d._handling_rate} €/h`, d.handling_cost, '', true)}
+ ${row(`
Design (x${dm})`, d.design_cost, '', true)}
+ ${row(`
Marge brute (${mgn}%)`, d.margin_amount)}
+ ${row(`
Total marge (${d.marge_pct_on_ht}% du HT)`, d.total_marge, 'subtotal')}
-
Cotisations BIC vente (${d._cot_pct}%)${fmt2(d.cotisations_amount)}
- ${vflRow}
- ${otherRow}
-
Prix HT${fmt2(d.prix_ht_net)}
-
${tvaLabel}${d._tva_pct > 0 ? fmt2(d.tva_amount) : ''}
+ ${rowFiscal(`
Cotisations BIC vente (${d._cot_pct}%)`, d.cotisations_amount)}
+ ${vflRow}${otherRow}
+
+ Prix HT
+ ${fmt2(d.prix_ht_net)}
+ ${multi ? `${fmt2(d.prix_ht_net * qty)}` : ''}
+
+
+ ${tvaLabel}
+ ${d._tva_pct > 0 ? fmt2(d.tva_amount) : ''}
+ ${multi && d._tva_pct > 0 ? `${fmt2(d.tva_amount * qty)}` : (multi ? '' : '')}
+
${disRow}
-
PRIX FINAL TTC${fmt2(d.final_price)}
- ` + capBlock;
+ ${finalLabel}
+ ` + capBlock;
}
// Init