{% extends 'base.html' %} {% block title %}{{ job.name }}{% endblock %} {% block content %} {% set qty = job.order_qty or 1 %} {% set multi = qty > 1 %}
Informations
{% if job.plate_name %} {% endif %} {% if job.machine_profile_name %} {% endif %} {% if job.handling_profile_name %} {% endif %} {% if job.pricing_profile_name %} {% endif %}
Client{{ job.client_name or '—' }}
Matiere {% if job.material_name %} {{ job.material_type }} {{ job.material_name }} {% else %}—{% endif %}
Fichier source {% if job.source_file %} {{ job.source_file.split('/')[-1] }} {% set ext = job.source_file.rsplit('.',1)[-1].lower() %} {% if ext in ['stl','3mf','step','stp','obj'] %} {% set is_nc_path = job.source_file.startswith('/') %} {% if is_nc_path %} {% else %} {% endif %} {% endif %} {% else %}—{% endif %}
Référence plateau {{ job.plate_name }}
Date{{ job.created_at[:10] }}
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 }} %
Profil machine{{ job.machine_profile_name }}
Profil manutention{{ job.handling_profile_name }}
Profil tarif{{ job.pricing_profile_name }}
{% if job.notes %}
{{ job.notes }} {% endif %}
Decomposition du prix {% if multi %} {{ qty }} pièces commandées {% endif %}
{# Macro pour une ligne à 1 ou 2 colonnes #} {% macro brow(label, val_piece, cls='', precision=2) %}
{{ label | safe }} {% 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 %} {# 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 %} {# Macro pour une ligne simple (label = texte pur) #} {# Pour les labels avec HTML, les lignes sont écrites directement ci-dessous #}
Cout fixe
Matiere{% if job.material_name %} {{ job.material_name }}{% endif %} {{ "%.4f"|format(job.material_cost) }} € {% if multi %}{{ "%.2f"|format(job.material_cost * qty) }} €{% endif %}
{{ 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) }}
Total cout fixe {{ "%.2f"|format(cout_f) }} € {% if multi %}{{ "%.2f"|format(cout_f * qty) }} €{% endif %}
Partie variable
{{ 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') }}
Total marge ({{ marge_pct_ht }}% du HT) {{ "%.2f"|format(tot_m) }} € {% if multi %}{{ "%.2f"|format(tot_m * qty) }} €{% endif %}
Fiscal
{{ 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 {{ "%.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) }} € {% 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) }} € {% 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) %} {% if job.final_price > 0 %}
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 %}
{% set plates_done = slots | selectattr('status','in',['done']) | list | length %} {% set plates_running = slots | selectattr('status','equalto','running') | list | length %} {% set plates_planned = slots | selectattr('status','in',['planned','running']) | list | length %} {% set plates_total = slots | rejectattr('status','in',['cancelled']) | list | length %} {% set missing_plates = [total_plates_needed - plates_total, 0] | max %}
Plateaux d'impression
{% if total_plates_needed > 1 %} {{ plates_done }}/{{ total_plates_needed }} terminé{{ 's' if plates_done > 1 else '' }} {% endif %} {% if missing_plates > 0 %} {{ missing_plates }} plateau{{ 'x' if missing_plates > 1 else '' }} à planifier {% endif %} Planning
{% if slots %}
{% for s in slots %} {% if s.status != 'cancelled' %} {% if s.status == 'running' and s.ha_entity_prefix %} {% endif %} {% endif %} {% endfor %}
# Début Machine Pièces Statut / Progression
{{ loop.index }} {{ s.planned_start[:16].replace('T',' ') }} {{ s.printer_name }} {% set ep = s.effective_pieces %} {% set ig = s.pieces_ignored %} {% if ig > 0 %} {{ ep - ig }}/{{ ep }} ({{ ig }} ignorée{{ 's' if ig > 1 }}) {% else %} {{ ep }} {% endif %} {% set sc = {'planned':'secondary','running':'primary','done':'success','failed':'danger'} %} {% set sl = {'planned':'Planifié','running':'En cours','done':'Terminé','failed':'Échec'} %} {{ sl.get(s.status, s.status) }} {% if s.status == 'running' and s.ha_entity_prefix %} {% endif %} {% if s.failure_note %}
{{ s.failure_note }} {% endif %}
{% else %}
Aucun créneau planifié pour cette commande.
Aller au planning
{% endif %} {% if total_plates_needed > 1 %} {% endif %}
{% set plates_done = slots | selectattr('status','in',['done']) | list | length %} {% set plates_running = slots | selectattr('status','equalto','running') | list | length %} {% set plates_planned = slots | selectattr('status','in',['planned','running']) | list | length %} {% set plates_total = slots | rejectattr('status','in',['cancelled']) | list | length %} {% set missing_plates = [total_plates_needed - plates_total, 0] | max %}
Plateaux d'impression
{% if total_plates_needed > 1 %} {{ plates_done }}/{{ total_plates_needed }} terminé{{ 's' if plates_done > 1 else '' }} {% endif %} {% if missing_plates > 0 %} {{ missing_plates }} plateau{{ 'x' if missing_plates > 1 else '' }} à planifier {% endif %} Planning
{% if slots %}
{% for s in slots %} {% if s.status != 'cancelled' %} {% if s.status == 'running' and s.ha_entity_prefix %} {% endif %} {% endif %} {% endfor %}
# Début Machine Pièces Statut / Progression
{{ loop.index }} {{ s.planned_start[:16].replace('T',' ') }} {{ s.printer_name }} {% set ep = s.effective_pieces %} {% set ig = s.pieces_ignored %} {% if ig > 0 %} {{ ep - ig }}/{{ ep }} ({{ ig }} ignorée{{ 's' if ig > 1 }}) {% else %}{{ ep }}{% endif %} {% set sc = {'planned':'secondary','running':'primary','done':'success','failed':'danger'} %} {% set sl = {'planned':'Planifié','running':'En cours','done':'Terminé','failed':'Échec'} %} {{ sl.get(s.status, s.status) }} {% if s.status == 'running' and s.ha_entity_prefix %} {% endif %} {% if s.failure_note %}
{{ s.failure_note }}{% endif %}
{% else %}
Aucun créneau planifié.
Aller au planning
{% endif %} {% if total_plates_needed > 1 %} {% endif %}
{% endblock %} {% block scripts %} {% set running_slots = slots | selectattr('status','equalto','running') | selectattr('ha_entity_prefix') | list %} {% if running_slots %} {% endif %} {% set running_slots = slots | selectattr('status','equalto','running') | selectattr('ha_entity_prefix') | list %} {% if running_slots %} {% endif %} {% endblock %}