Files
3d-pricing/templates/job_detail.html
T
Jo 9cb7c71d6f
Deploy via Portainer / deploy (push) Successful in 0s
fix: HTML dans job_detail - lignes complexes écrites directement
2026-07-06 23:26:31 +02:00

206 lines
11 KiB
HTML
Raw 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.
{% extends 'base.html' %}
{% block title %}{{ job.name }}{% endblock %}
{% block content %}
<div class="page-header d-flex justify-content-between align-items-center">
<div>
<a href="{{ url_for('jobs') }}" class="text-muted text-decoration-none small">
<i class="bi bi-arrow-left"></i> Commandes
</a>
<h1 class="mt-1">{{ job.name }}</h1>
</div>
<form method="POST" action="{{ url_for('delete_job', id=job.id) }}"
onsubmit="return confirm('Supprimer cette commande ?')">
<button class="btn btn-sm btn-outline-danger"><i class="bi bi-trash"></i> Supprimer</button>
</form>
</div>
{% set qty = job.order_qty or 1 %}
{% set multi = qty > 1 %}
<div class="row g-4">
<div class="col-md-5">
<div class="card mb-3">
<div class="card-header py-3">Informations</div>
<div class="card-body">
<table class="table table-sm mb-0">
<tr><th class="text-muted fw-normal" style="width:45%">Client</th><td>{{ job.client_name or '—' }}</td></tr>
<tr><th class="text-muted fw-normal">Matiere</th>
<td>
{% if job.material_name %}
<span class="badge bg-secondary">{{ job.material_type }}</span> {{ job.material_name }}
{% else %}—{% endif %}
</td>
</tr>
<tr><th class="text-muted fw-normal">Fichier source</th>
<td class="small font-monospace">{{ job.source_file or '—' }}</td></tr>
<tr><th class="text-muted fw-normal">Date</th><td>{{ job.created_at[:10] }}</td></tr>
<tr><th class="text-muted fw-normal">Poids plateau</th><td>{{ job.weight_g }} g</td></tr>
<tr><th class="text-muted fw-normal">Pieces / plateau</th><td>{{ job.pieces_per_plate or 1 }}</td></tr>
<tr><th class="text-muted fw-normal">Quantite commandee</th><td>{{ qty }} pièce{{ 's' if qty > 1 else '' }}</td></tr>
<tr><th class="text-muted fw-normal">Duree plateau</th><td>{{ job.print_time_s | fmt_time }}</td></tr>
<tr><th class="text-muted fw-normal">Coeff design</th><td>×{{ job.design_multiplier }}</td></tr>
<tr><th class="text-muted fw-normal">Marge brute</th><td>{{ job.gross_margin_pct }} %</td></tr>
<tr><th class="text-muted fw-normal">Remise</th><td>{{ job.discount_pct }} %</td></tr>
{% if job.machine_profile_name %}
<tr><th class="text-muted fw-normal">Profil machine</th><td>{{ job.machine_profile_name }}</td></tr>
{% endif %}
{% if job.handling_profile_name %}
<tr><th class="text-muted fw-normal">Profil manutention</th><td>{{ job.handling_profile_name }}</td></tr>
{% endif %}
{% if job.pricing_profile_name %}
<tr><th class="text-muted fw-normal">Profil tarif</th><td>{{ job.pricing_profile_name }}</td></tr>
{% endif %}
</table>
{% if job.notes %}
<hr>
<small class="text-muted">{{ job.notes }}</small>
{% endif %}
</div>
</div>
</div>
<div class="col-md-7">
<div class="card">
<div class="card-header py-3 d-flex justify-content-between align-items-center">
<span><i class="bi bi-receipt me-2"></i>Decomposition du prix</span>
{% if multi %}
<span class="badge bg-secondary">{{ qty }} pièces commandées</span>
{% endif %}
</div>
<div class="card-body">
{# Macro pour une ligne à 1 ou 2 colonnes #}
{% macro brow(label, val_piece, cls='', precision=2) %}
<div class="breakdown-row {{ cls }}">
<span class="flex-fill">{{ label | safe }}</span>
<span class="text-end" style="min-width:85px">
{% if precision == 4 %}{{ "%.4f"|format(val_piece) }} €
{% else %}{{ "%.2f"|format(val_piece) }} €{% endif %}
</span>
{% if multi %}
<span class="text-end text-muted" style="min-width:85px">
{% if precision == 4 %}{{ "%.2f"|format(val_piece * qty) }} €
{% else %}{{ "%.2f"|format(val_piece * qty) }} €{% endif %}
</span>
{% endif %}
</div>
{% endmacro %}
{# En-tête colonnes #}
{% if multi %}
<div class="d-flex justify-content-end small text-muted mb-2 border-bottom pb-1 gap-0">
<span style="min-width:85px;text-align:right">/ pièce</span>
<span style="min-width:85px;text-align:right">/ commande ×{{ qty }}</span>
</div>
{% 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 %}
{# Macro pour une ligne simple (label = texte pur) #}
{# Pour les labels avec HTML, les lignes sont écrites directement ci-dessous #}
<!-- Cout fixe -->
<div class="breakdown-row section-header"><span>Cout fixe</span></div>
<div class="breakdown-row">
<span class="flex-fill breakdown-muted ps-2">Matiere{% if job.material_name %} <small class="text-secondary">{{ job.material_name }}</small>{% endif %}</span>
<span class="text-end" style="min-width:85px">{{ "%.4f"|format(job.material_cost) }} €</span>
{% if multi %}<span class="text-end text-muted" style="min-width:85px">{{ "%.2f"|format(job.material_cost * qty) }} €</span>{% endif %}
</div>
{{ brow('Marge matiere', job.material_margin, 'breakdown-muted ps-2', 4) }}
{{ brow('Usure machine', job.wear_cost, 'breakdown-muted ps-2', 4) }}
{{ brow('Electricite', job.electricity_cost, 'breakdown-muted ps-2', 4) }}
<div class="breakdown-row subtotal">
<span class="flex-fill fw-semibold">Total cout fixe</span>
<span class="text-end" style="min-width:85px">{{ "%.2f"|format(cout_f) }} €</span>
{% if multi %}<span class="text-end text-muted" style="min-width:85px">{{ "%.2f"|format(cout_f * qty) }} €</span>{% endif %}
</div>
<!-- Partie variable -->
<div class="breakdown-row section-header"><span>Partie variable</span></div>
{{ brow('Manutention', job.handling_cost, 'breakdown-muted ps-2', 4) }}
{{ brow('Design (×' ~ job.design_multiplier ~ ')', job.design_cost, 'breakdown-muted ps-2', 4) }}
{{ brow('Marge brute (' ~ job.gross_margin_pct ~ '%)', job.margin_amount, 'breakdown-muted ps-2') }}
<div class="breakdown-row subtotal">
<span class="flex-fill fw-semibold">Total marge <small class="text-muted fw-normal">({{ marge_pct_ht }}% du HT)</small></span>
<span class="text-end" style="min-width:85px">{{ "%.2f"|format(tot_m) }} €</span>
{% if multi %}<span class="text-end text-muted" style="min-width:85px">{{ "%.2f"|format(tot_m * qty) }} €</span>{% endif %}
</div>
<!-- Fiscal -->
<div class="breakdown-row section-header"><span>Fiscal</span></div>
{{ brow('Cotisations BIC vente', job.cotisations_amount or job.tax_amount or 0) }}
{% if job.vfl_amount and job.vfl_amount > 0 %}
{{ brow('VFL impot', job.vfl_amount) }}
{% endif %}
{% if job.other_taxes_amount and job.other_taxes_amount > 0 %}
{{ brow('Autres taxes / CFE', job.other_taxes_amount) }}
{% endif %}
<!-- Prix HT -->
<div class="breakdown-row" style="border-top:none">
<span class="fw-bold flex-fill">Prix HT</span>
<span class="final-price text-end" style="font-size:1.3rem;min-width:85px">{{ "%.2f"|format(prix_ht_net) }} €</span>
{% if multi %}<span class="final-price text-end" style="font-size:1.3rem;min-width:85px;opacity:.75">{{ "%.2f"|format(prix_ht_net * qty) }} €</span>{% endif %}
</div>
{% if job.tva_amount and job.tva_amount > 0 %}
<div class="breakdown-row">
<span class="ps-2 flex-fill">TVA</span>
<span class="text-end" style="min-width:85px">{{ "%.2f"|format(job.tva_amount) }} €</span>
{% if multi %}<span class="text-end text-muted" style="min-width:85px">{{ "%.2f"|format(job.tva_amount * qty) }} €</span>{% endif %}
</div>
{% endif %}
{% if job.discount_pct > 0 %}
<div class="breakdown-row text-danger">
<span class="ps-2 flex-fill">Remise ({{ job.discount_pct }}%)</span>
<span class="text-end" style="min-width:85px">{{ "%.2f"|format(prix_ttc * job.discount_pct / 100) }} €</span>
{% if multi %}<span class="text-end" style="min-width:85px">{{ "%.2f"|format(prix_ttc * qty * job.discount_pct / 100) }} €</span>{% endif %}
</div>
{% endif %}
<!-- Prix final -->
{% if multi %}
<div class="d-flex justify-content-between align-items-center mt-2 pt-2" style="border-top:2px solid #dee2e6">
<span class="fw-bold">PRIX FINAL TTC</span>
<div class="d-flex gap-3">
<span class="final-price" style="font-size:1.4rem">{{ "%.2f"|format(job.final_price) }} €</span>
<span class="final-price" style="font-size:1.4rem;opacity:.7">× {{ qty }} = {{ "%.2f"|format(job.final_price * qty) }} €</span>
</div>
</div>
{% else %}
<div class="breakdown-row total">
<span>PRIX FINAL TTC</span>
<span class="final-price">{{ "%.2f"|format(job.final_price) }} €</span>
</div>
{% endif %}
<!-- Barre de composition -->
{% 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) %}
{% if job.final_price > 0 %}
<div class="mt-4">
<div class="d-flex justify-content-between small text-muted mb-1">
<span>Cout fixe ({{ (cout_f/job.final_price*100)|round(1) }}%)</span>
<span>Marge ({{ (tot_m/job.final_price*100)|round(1) }}%)</span>
<span>Fiscal ({{ (fiscal/job.final_price*100)|round(1) }}%)</span>
</div>
<div class="progress" style="height:18px;border-radius:6px">
<div class="progress-bar bg-secondary" style="width:{{ (cout_f/job.final_price*100)|round(1) }}%"></div>
<div class="progress-bar" style="width:{{ (tot_m/job.final_price*100)|round(1) }}%;background:#ff6b35"></div>
<div class="progress-bar bg-warning text-dark" style="width:{{ (fiscal/job.final_price*100)|round(1) }}%"></div>
</div>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock %}