From 614ea23a7c64ff59cb23a441332cbabc37a1fb97 Mon Sep 17 00:00:00 2001 From: Jo Date: Mon, 6 Jul 2026 20:12:14 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20colonnes=20prix/pi=C3=A8ce=20et=20prix/?= =?UTF-8?q?commande=20dans=20les=20deux=20r=C3=A9caps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/job_detail.html | 138 ++++++++++++++++++++------------ templates/new_job.html | 162 +++++++++++++++++++++++--------------- 2 files changed, 189 insertions(+), 111 deletions(-) diff --git a/templates/job_detail.html b/templates/job_detail.html index 60e211e..adc139e 100644 --- a/templates/job_detail.html +++ b/templates/job_detail.html @@ -15,6 +15,9 @@ +{% set qty = job.order_qty or 1 %} +{% set multi = qty > 1 %} +
@@ -32,8 +35,10 @@ Fichier source {{ job.source_file or '—' }} Date{{ job.created_at[:10] }} - Poids filament{{ job.weight_g }} g - Duree impression{{ job.print_time_s | fmt_time }} + Poids plateau{{ job.weight_g }} g + Pieces / plateau{{ job.pieces_per_plate or 1 }} + Quantite commandee{{ qty }} pièce{{ 's' if qty > 1 else '' }} + Duree plateau{{ job.print_time_s | fmt_time }} Coeff design×{{ job.design_multiplier }} Marge brute{{ job.gross_margin_pct }} % Remise{{ job.discount_pct }} % @@ -57,91 +62,126 @@
-
Decomposition du prix
+
+ Decomposition du prix + {% if multi %} + {{ qty }} pièces commandées + {% endif %} +
- -
Cout fixe
-
Matiere{% if job.material_name %} {{ job.material_name }}{% endif %}{{ "%.4f"|format(job.material_cost) }} €
-
Marge matiere{{ "%.4f"|format(job.material_margin) }} €
-
Usure machine{{ "%.4f"|format(job.wear_cost) }} €
-
Electricite{{ "%.4f"|format(job.electricity_cost) }} €
- {% set cout_f = job.cout_fixe or (job.material_cost + job.material_margin + job.wear_cost + job.electricity_cost) %} -
- Total cout fixe - {{ "%.2f"|format(cout_f) }} € + {# Macro pour une ligne à 1 ou 2 colonnes #} + {% macro brow(label, val_piece, cls='', precision=2) %} +
+ {{ label }} + + {% if precision == 4 %}{{ "%.4f"|format(val_piece) }} € + {% else %}{{ "%.2f"|format(val_piece) }} €{% endif %} + + {% if multi %} + + {% if precision == 4 %}{{ "%.2f"|format(val_piece * qty) }} € + {% else %}{{ "%.2f"|format(val_piece * qty) }} €{% endif %} + + {% endif %}
+ {% endmacro %} - -
Partie variable
-
Manutention{{ "%.4f"|format(job.handling_cost) }} €
-
Design (×{{ job.design_multiplier }}){{ "%.4f"|format(job.design_cost) }} €
-
Marge brute ({{ job.gross_margin_pct }}%){{ "%.2f"|format(job.margin_amount) }} €
+ {# En-tête colonnes #} + {% if multi %} +
+ / pièce + / commande ×{{ qty }} +
+ {% endif %} + + {% set cout_f = job.cout_fixe or (job.material_cost + job.material_margin + job.wear_cost + job.electricity_cost) %} {% set tot_m = job.total_marge or (job.handling_cost + job.design_cost + job.margin_amount) %} {% set prix_ttc = job.final_price / (1 - job.discount_pct / 100) if job.discount_pct < 100 else job.final_price %} {% set prix_ht_net = prix_ttc - (job.tva_amount or 0) %} {% set marge_pct_ht = (tot_m / prix_ht_net * 100)|round(1) if prix_ht_net > 0 else 0 %} -
- Total marge ({{ marge_pct_ht }}% du HT) - {{ "%.2f"|format(tot_m) }} € -
+ + +
Cout fixe
+ {{ brow('Matiere' + (' ' + job.material_name + '' if job.material_name else ''), job.material_cost, '', 4) }} + {{ brow('Marge matiere', job.material_margin, '', 4) }} + {{ brow('Usure machine', job.wear_cost, '', 4) }} + {{ brow('Electricite', job.electricity_cost, '', 4) }} + {{ brow('Total cout fixe', cout_f, 'subtotal') }} + + +
Partie variable
+ {{ brow('Manutention', job.handling_cost, '', 4) }} + {{ brow('Design (×' + job.design_multiplier|string + ')', job.design_cost, '', 4) }} + {{ brow('Marge brute (' + job.gross_margin_pct|string + '%)', job.margin_amount) }} + {{ brow('Total marge (' + marge_pct_ht|string + '% du HT)', tot_m, 'subtotal') }}
Fiscal
-
- Cotisations BIC vente - {% if job.cotisations_amount %}{{ "%.2f"|format(job.cotisations_amount) }}{% else %}{{ "%.2f"|format(job.tax_amount or 0) }}{% endif %} € -
+ {{ brow('Cotisations BIC vente', job.cotisations_amount or job.tax_amount or 0) }} {% if job.vfl_amount and job.vfl_amount > 0 %} -
- VFL impot - {{ "%.2f"|format(job.vfl_amount) }} € -
+ {{ brow('VFL impot', job.vfl_amount) }} {% endif %} {% if job.other_taxes_amount and job.other_taxes_amount > 0 %} -
- Autres taxes / CFE - {{ "%.2f"|format(job.other_taxes_amount) }} € -
+ {{ brow('Autres taxes / CFE', job.other_taxes_amount) }} {% endif %} -
- Prix HT - {{ "%.2f"|format(prix_ht_net) }} € + + +
+ Prix HT + {{ "%.2f"|format(prix_ht_net) }} € + {% if multi %}{{ "%.2f"|format(prix_ht_net * qty) }} €{% endif %}
+ {% if job.tva_amount and job.tva_amount > 0 %}
- TVA - {{ "%.2f"|format(job.tva_amount) }} € + TVA + {{ "%.2f"|format(job.tva_amount) }} € + {% if multi %}{{ "%.2f"|format(job.tva_amount * qty) }} €{% endif %}
{% endif %} + {% if job.discount_pct > 0 %}
- Remise ({{ job.discount_pct }}%) - −{{ "%.2f"|format(prix_ttc * job.discount_pct / 100) }} € + Remise ({{ job.discount_pct }}%) + −{{ "%.2f"|format(prix_ttc * job.discount_pct / 100) }} € + {% if multi %}−{{ "%.2f"|format(prix_ttc * qty * job.discount_pct / 100) }} €{% endif %}
{% endif %} + + + {% if multi %} +
+ PRIX FINAL TTC +
+ {{ "%.2f"|format(job.final_price) }} € + × {{ qty }} = {{ "%.2f"|format(job.final_price * qty) }} € +
+
+ {% else %}
PRIX FINAL TTC {{ "%.2f"|format(job.final_price) }} €
+ {% endif %} {% set fiscal = (job.cotisations_amount or job.tax_amount or 0) + (job.vfl_amount or 0) + (job.other_taxes_amount or 0) + (job.tva_amount or 0) %} - {% set total = job.final_price %} - {% if total > 0 %} + {% if job.final_price > 0 %}
- Cout fixe ({{ (cout_f/total*100)|round(1) }}%) - Marge ({{ (tot_m/total*100)|round(1) }}%) - Fiscal ({{ (fiscal/total*100)|round(1) }}%) + Cout fixe ({{ (cout_f/job.final_price*100)|round(1) }}%) + Marge ({{ (tot_m/job.final_price*100)|round(1) }}%) + Fiscal ({{ (fiscal/job.final_price*100)|round(1) }}%)
-
-
-
+
+
+
{% endif %} +
diff --git a/templates/new_job.html b/templates/new_job.html index 52c40a4..282c578 100644 --- a/templates/new_job.html +++ b/templates/new_job.html @@ -73,10 +73,10 @@
- + -
Champ Modele dans Bambu
+
Poids total du plateau Bambu (toutes pièces)
@@ -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 - ? `
VFL impot (${d._vfl_pct}%)${fmt2(d.vfl_amount)}
` : ''; - - // Autres taxes - const otherRow = d._other_taxes_pct > 0 - ? `
Autres taxes / CFE (${d._other_taxes_pct}%)${fmt2(d.other_taxes_amount)}
` : ''; - - // Remise - const disRow = body.discount_pct > 0 - ? `
Remise (${body.discount_pct}%)-${fmt2(d.prix_ttc * body.discount_pct / 100)}
` : ''; - - // 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 `
+ ${label} + ${p} + ${o} +
`; + } + function rowFiscal(label, pieceVal, extraCls = '') { + const p = fmt2(pieceVal); + const o = multi ? `${fmt2(pieceVal * qty)}` : ''; + return `
+ ${label} + ${p} + ${o}
`; } - // 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 = `
Capacite de production
@@ -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 + `
Cout fixe
-
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')}
Partie variable
-
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')}
Fiscal
-
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