{% extends 'app/base.html.twig' %} {% block title %}EGAlim — GestRestoSco{% endblock %} {% block body %}
{# ── Alerte légale ── #}
Loi EGAlim — Obligations depuis le 1er janvier 2022 : ≥ 50% de produits durables et de qualité (dont ≥ 20% bio) dans les approvisionnements alimentaires. 1 repas végétarien par semaine recommandé.
{# ── En-tête + sélecteur de période ── #}

Suivi EGAlim

{{ periodeLibelle }}
Télédéclaration ma-cantine
{# ── Période personnalisée ── #} {% if periodeSelectionnee == 'personnalisee' %}
{% endif %} {# ── Onglets ── #}
{# ════════════════════════════════════════════════════════════ ONGLET MENUS ═══════════════════════════════════════════════════════════════ #}
{% if statsMenus.total_jours == 0 %}
Aucun menu saisi pour cette période. Saisir des menus →
{% else %} {# ── Score global de conformité ─────────────────────────────── #} {% set conf = statsMenus.conformite %} {% if conf >= 90 %}{% set confEmoji = '🏆' %}{% set confMsg = 'Excellent ! Votre établissement est exemplaire en matière d\'alimentation durable.' %}{% set confColor = 'success' %} {% elseif conf >= 80 %}{% set confEmoji = '✅' %}{% set confMsg = 'Très bien ! Vous respectez la quasi-totalité des objectifs EGAlim.' %}{% set confColor = 'success' %} {% elseif conf >= 60 %}{% set confEmoji = '👍' %}{% set confMsg = 'Bonne progression ! Continuez vos efforts pour atteindre tous les objectifs.' %}{% set confColor = 'warning' %} {% elseif conf >= 40 %}{% set confEmoji = '📈' %}{% set confMsg = 'Des progrès notables. Il reste du chemin mais vous êtes sur la bonne voie.' %}{% set confColor = 'warning' %} {% elseif conf >= 20 %}{% set confEmoji = '🌱' %}{% set confMsg = 'Un bon départ. Chaque action compte pour améliorer votre alimentation durable.' %}{% set confColor = 'danger' %} {% elseif conf >= 10 %}{% set confEmoji = '💪' %}{% set confMsg = 'C\'est un début. Concentrez-vous sur un indicateur à la fois pour progresser.' %}{% set confColor = 'danger' %} {% else %}{% set confEmoji = '🚀' %}{% set confMsg = 'Tout reste à construire. Commencez par identifier des fournisseurs bio et locaux.' %}{% set confColor = 'danger' %} {% endif %}
{{ confEmoji }} Score global de conformité EGAlim

{{ confMsg }}

{{ conf }}%
{% if conf > 10 %}{{ conf }}%{% endif %}
{{ statsMenus.total_composantes }} composante{{ statsMenus.total_composantes > 1 ? 's' : '' }} saisie{{ statsMenus.total_composantes > 1 ? 's' : '' }} {% if statsMenus.total_theorique > 0 %} / {{ statsMenus.total_theorique }} théorique{{ statsMenus.total_theorique > 1 ? 's' : '' }} ({{ statsMenus.jours_service_theo }}j × 5 compo. × {{ statsMenus.nb_services }} service{{ statsMenus.nb_services > 1 ? 's' : '' }}) {% endif %}
{# ── 3 cartes détaillées : Bio / Local / Durable ─────────────── #}
{# Bio #} {% set b = statsMenus.bio %} {% set bPctRel = b.objectif > 0 ? (b.pourcentage / b.objectif * 100)|round : 0 %}
🌱 Bio {{ b.conforme ? '✓ Conforme' : '✗ Non conforme' }}
Objectif légal {{ b.objectif }}%
Réalisé {{ b.pourcentage }}%
{{ b.nombre }} composante{{ b.nombre > 1 ? 's' : '' }} bio sur {{ b.total }} saisie{{ b.total > 1 ? 's' : '' }} ({{ b.total_theorique }} théorique{{ b.total_theorique > 1 ? 's' : '' }})
{% if not b.conforme %}
+{{ (b.objectif - b.pourcentage)|round(1) }}% nécessaire pour atteindre l'objectif
{% endif %}
{# Local #} {% set l = statsMenus.local %} {% set lPctRel = l.objectif > 0 ? (l.pourcentage / l.objectif * 100)|round : 0 %}
🌟 Local {{ l.conforme ? '✓ Conforme' : '⚠ À améliorer' }}
Objectif recommandé {{ l.objectif }}%
Réalisé {{ l.pourcentage }}%
{{ l.nombre }} composante{{ l.nombre > 1 ? 's' : '' }} locale{{ l.nombre > 1 ? 's' : '' }} sur {{ l.total }} saisie{{ l.total > 1 ? 's' : '' }} ({{ l.total_theorique }} théorique{{ l.total_theorique > 1 ? 's' : '' }})
{% if not l.conforme %}
+{{ (l.objectif - l.pourcentage)|round(1) }}% nécessaire pour atteindre l'objectif
{% endif %}
{# Durable #} {% set d = statsMenus.durable %} {% set dPctRel = d.objectif > 0 ? (d.pourcentage / d.objectif * 100)|round : 0 %}
🌍 Durable {{ d.conforme ? '✓ Conforme' : '✗ Non conforme' }}
Objectif légal {{ d.objectif }}%
Réalisé {{ d.pourcentage }}%
{{ d.nombre }} composante{{ d.nombre > 1 ? 's' : '' }} durable{{ d.nombre > 1 ? 's' : '' }} sur {{ d.total }} saisie{{ d.total > 1 ? 's' : '' }} ({{ d.total_theorique }} théorique{{ d.total_theorique > 1 ? 's' : '' }})
{% if not d.conforme %}
+{{ (d.objectif - d.pourcentage)|round(1) }}% nécessaire pour atteindre l'objectif
{% endif %}
{# ── Carte végétarien ─────────────────────────────────────────── #} {% set v = statsMenus.vegetarien %}
🥗 Menu végétarien hebdomadaire {{ v.semaines_conformes }} / {{ v.total_semaines }} semaine{{ v.total_semaines > 1 ? 's' : '' }} conforme{{ v.semaines_conformes > 1 ? 's' : '' }}  {{ v.pourcentage }}%
{% if v.detail is not empty %}
{% for sem in v.detail %} {{ sem.label }} {{ sem.conforme ? '✅' : '❌' }} {% endfor %}
{% else %}

Aucune donnée de semaine disponible.

{% endif %} {% if not v.conforme %}
⚠ La loi Egalim impose au moins 1 repas végétarien par semaine. {{ v.total_semaines - v.semaines_conformes }} semaine{{ (v.total_semaines - v.semaines_conformes) > 1 ? 's' : '' }} non conforme{{ (v.total_semaines - v.semaines_conformes) > 1 ? 's' : '' }}.
{% endif %}
{# ── Alertes + Suggestions ────────────────────────────────────── #}
{# Alertes #}
Alertes {% if statsMenus.alertes is empty %} ✓ Aucune alerte {% else %} {{ statsMenus.alertes|length }} {% endif %}
{% if statsMenus.alertes is empty %}
Tous les objectifs sont atteints pour cette période.
{% else %}
    {% for alerte in statsMenus.alertes %}
  • {{ alerte.icone }}
    {{ alerte.titre }}
    {{ alerte.message }}
  • {% endfor %}
{% endif %}
{# Suggestions #}
Suggestions {% if statsMenus.suggestions is not empty %} {{ statsMenus.suggestions|length }} {% endif %}
{% if statsMenus.suggestions is empty %}
Félicitations, aucune suggestion d'amélioration !
{% else %}
    {% for sug in statsMenus.suggestions %}
  • {{ sug.icone }}
    {{ sug.titre }}
    {{ sug.message }}
    {% if sug.action is defined and sug.action %} {{ sug.action }} {% endif %}
  • {% endfor %}
{% endif %}
{# ── Évolution annuelle ───────────────────────────────────────── #} {% if evolution is not empty %}
📈 Évolution annuelle — Progression EGAlim Comparaison des performances sur les {{ evolution|length }} dernière{{ evolution|length > 1 ? 's' : '' }} année{{ evolution|length > 1 ? 's' : '' }}
{% for loop_e, e in evolution %} {# Bio #} {# Local #} {# Durable #} {# Végétarien #} {# Score global #} {% endfor %}
Année 🌱 Bio 🌟 Local 🌍 Durable 🥗 Végétarien 🏆 Suivi Global
{{ e.libelle }} {% if e.est_en_cours %}
En cours...{% endif %}
{{ e.bio }}%
Objectif : 20% {% if loop_e > 0 %} {% set delta = (e.bio - evolution[loop_e - 1].bio)|round(1) %}
{{ delta >= 0 ? '▲ +' : '▼ ' }}{{ delta }}% {% endif %}
{{ e.local }}%
Objectif : 30% {% if loop_e > 0 %} {% set delta = (e.local - evolution[loop_e - 1].local)|round(1) %}
{{ delta >= 0 ? '▲ +' : '▼ ' }}{{ delta }}% {% endif %}
{{ e.durable }}%
Objectif : 50% {% if loop_e > 0 %} {% set delta = (e.durable - evolution[loop_e - 1].durable)|round(1) %}
{{ delta >= 0 ? '▲ +' : '▼ ' }}{{ delta }}% {% endif %}
{{ e.vegetarien }}%
Objectif : 100% {% if loop_e > 0 %} {% set delta = (e.vegetarien - evolution[loop_e - 1].vegetarien)|round(1) %}
{{ delta >= 0 ? '▲ +' : '▼ ' }}{{ delta }}% {% endif %}
{{ e.conformite }}% {% if e.conformite >= 80 %} {% elseif e.conformite >= 60 %} {% else %} {% endif %}
{% if loop_e > 0 %} {% set delta = (e.conformite - evolution[loop_e - 1].conformite)|round(1) %} {{ delta >= 0 ? '▲ +' : '▼ ' }}{{ delta }}% {% endif %}
{# ── Analyse de progression (N vs N-1) ── #} {% if evolution|length >= 2 %} {% set eCur = evolution[evolution|length - 1] %} {% set ePrev = evolution[evolution|length - 2] %} {% if eCur.est_en_cours %} {% set dBio = (eCur.bio - ePrev.bio) |round(1) %} {% set dLocal = (eCur.local - ePrev.local) |round(1) %} {% set dDur = (eCur.durable - ePrev.durable) |round(1) %} {% set dConf = (eCur.conformite - ePrev.conformite)|round(1) %}
📊 Analyse de progression :
Évolution par rapport à l'année précédente :  Bio : {{ dBio >= 0 ? '+' : '' }}{{ dBio }}%  |  Local : {{ dLocal >= 0 ? '+' : '' }}{{ dLocal }}%  |  Durable : {{ dDur >= 0 ? '+' : '' }}{{ dDur }}%  |  Suivi global : {{ dConf >= 0 ? '+' : '' }}{{ dConf }}%    {% if dConf >= 5 %} 🎉 Excellente progression ! {% elseif dConf >= 0 %} 👍 Progression positive {% else %} ⚠️ Attention : régression {% endif %}
{% endif %} {% endif %}
{% endif %} {# ── Actions rapides ──────────────────────────────────────────── #} {% endif %}{# end if total_jours > 0 #}
{# end tab-menus #} {# ════════════════════════════════════════════════════════════ ONGLET ACHATS OFFICIELS ═══════════════════════════════════════════════════════════════ #}
Suivi Mensuel EGAlim {{ anneeSelection }} : Basé sur les achats réels en € HT, calcul identique à la télédéclaration ma-cantine.
{# ─── Tableau suivi mensuel ─────────────────────────────── #}
Suivi mensuel {{ anneeSelection }}
{% for ligne in suiviMensuel.lignes %} {% endfor %} {# Ligne cumul annuel #} {# Ligne projection si année en cours #} {% if suiviMensuel.projection %} {% endif %}
Mois Total achats HT Bio % (obj. 20%) Durables % (obj. 50%) Conformité
{{ ligne.mois_abr }} {% if ligne.total > 0 %} {{ ligne.total|number_format(2, ',', ' ') }} € {% else %} {% endif %} {% if ligne.total > 0 %}
{{ ligne.pct_bio }}%
{% else %} {% endif %}
{% if ligne.total > 0 %}
{{ ligne.pct_durable }}%
{% else %} {% endif %}
{% if ligne.total > 0 %} {{ ligne.conforme ? '✅' : '⚠️' }} {% else %} {% endif %}
Cumul annuel {{ suiviMensuel.cumul.total|number_format(2, ',', ' ') }} €
{{ suiviMensuel.cumul.pct_bio }}%
{{ suiviMensuel.cumul.pct_durable }}%
{{ suiviMensuel.cumul.conforme ? '✅' : '⚠️' }}
Projection déc. ≈ {{ suiviMensuel.projection.total|number_format(2, ',', ' ') }} € Bio : {{ suiviMensuel.projection.pct_bio }}% {{ suiviMensuel.projection.pct_bio >= 20 ? '✅' : '❌' }} Dur. : {{ suiviMensuel.projection.pct_durable }}% {{ suiviMensuel.projection.pct_durable >= 50 ? '✅' : '❌' }} {{ suiviMensuel.projection.conforme ? '✅' : '⚠️' }}

Détail — période sélectionnée ({{ periodeLibelle }})
{% if statsAchats.total_achats == 0 %}
Aucun achat enregistré pour cette période.
{% else %} {# Détail par label #}
Détail par type de label
{% set labelRows = [ {'nom': 'Bio (AB, Bio européen)', 'code': 'bio', 'cat': 'BIO', 'badge': 'success'}, {'nom': 'Label Rouge', 'code': 'label_rouge', 'cat': 'DURABLE', 'badge': 'primary'}, {'nom': 'AOP / AOC / IGP / STG', 'code': 'aop_igp', 'cat': 'DURABLE', 'badge': 'primary'}, {'nom': 'HVE (Haute Valeur Env.)', 'code': 'hve', 'cat': 'DURABLE', 'badge': 'primary'}, {'nom': 'Pêche durable (MSC/ASC)', 'code': 'peche_durable', 'cat': 'DURABLE', 'badge': 'primary'}, {'nom': 'Commerce équitable', 'code': 'commerce_equitable', 'cat': 'DURABLE', 'badge': 'primary'}, {'nom': 'Autres labels durables', 'code': 'autres_durables', 'cat': 'DURABLE', 'badge': 'primary'}, ] %} {% for row in labelRows %} {% set montant = attribute(statsAchats.detail_labels, row.code) %} {% if montant > 0 %} {% endif %} {% endfor %} {% if statsAchats.standard.montant > 0 %} {% endif %}
Label Montant HT % du total Catégorie
{{ row.nom }} {{ montant|number_format(2, ',', ' ') }} € {{ ((montant / statsAchats.total_achats) * 100)|round(1) }}% {{ row.cat }}
Produits standard (sans label) {{ statsAchats.standard.montant|number_format(2, ',', ' ') }} € {{ ((statsAchats.standard.montant / statsAchats.total_achats) * 100)|round(1) }}% STANDARD
TOTAL {{ statsAchats.total_achats|number_format(2, ',', ' ') }} € 100%
{% endif %}{# end if total_achats > 0 #}
{# end tab-achats #}
{# end tab-content #}
{% endblock %}