Comptabilite (Super Admin) : - ComptabiliteController avec 7 exports CSV/JSON compatibles SAGE (journal ventes, grand livre, FEC, balance agee, reglements, commissions Stripe 1.5%+0.25E, couts services) - Export PDF via ComptaPdf (FPDF) avec bloc legal pre-rempli, tableau pagine, champ signature DocuSeal - Signature electronique DocuSeal + callback + envoi email signe avec template dedie (compta_export_signed.html.twig) - Rapport financier public (RapportFinancierPdf) : recettes par service, depenses (Stripe, infra, prestataires), bilan excedent/deficit - Codes comptables clients EC-XXXX (plus de 411xxx) Prestataires (Super Admin) : - Entite Prestataire (raisonSociale, siret, email, phone, adresse) - Entite FacturePrestataire (numFacture, montantHt, montantTtc, year, month, isPaid, PDF via Vich) - CRUD complet avec recherche SIRET via proxy API data.gouv.fr - Commande cron app:reminder:factures-prestataire (5 du mois) - Factures prestataires integrees dans export couts services - Sidebar Super Admin : entree Prestataires + Comptabilite Stats (/admin/stats) : - Cout prestataire dynamique depuis FacturePrestataire - Fusion Infra + Prestataire en "Cout de fonctionnement" - Commission Stripe corrigee (1.5% + 0.25E par transaction) Divers : - DocuSealService::sendComptaForSignature() + getApi() - Customer::generateCodeComptable() format EC-XXXX-XXXXX - Protection double prefixe EC- a la creation client - Bouton regenerer PDF cache quand advert state=accepted - Modals sans script inline (data-modal-open/close dans app.js) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
189 lines
11 KiB
Twig
189 lines
11 KiB
Twig
{% extends 'legal/_layout.html.twig' %}
|
|
|
|
{% block title %}Status des services - E-Cosplay{% endblock %}
|
|
{% block description %}Etat en temps reel des services proposes par la Association E-Cosplay.{% endblock %}
|
|
|
|
{% block body %}
|
|
<div class="page-container">
|
|
{# Banner global #}
|
|
<div class="mb-8 p-6 glass text-center
|
|
{% if globalStatus == 'up' %}bg-green-50
|
|
{% elseif globalStatus == 'degraded' %}bg-yellow-50
|
|
{% elseif globalStatus == 'down' %}bg-red-50
|
|
{% else %}bg-blue-50
|
|
{% endif %}
|
|
">
|
|
<div class="flex items-center justify-center gap-3 mb-2">
|
|
<span class="w-4 h-4
|
|
{% if globalStatus == 'up' %}bg-green-500
|
|
{% elseif globalStatus == 'degraded' %}bg-yellow-500
|
|
{% elseif globalStatus == 'down' %}bg-red-500
|
|
{% else %}bg-blue-500
|
|
{% endif %}
|
|
"></span>
|
|
<h1 class="text-2xl font-bold">
|
|
{% if globalStatus == 'up' %}Tous les systemes sont operationnels
|
|
{% elseif globalStatus == 'degraded' %}Performances degradees
|
|
{% elseif globalStatus == 'down' %}Incident en cours
|
|
{% else %}Maintenance en cours
|
|
{% endif %}
|
|
</h1>
|
|
</div>
|
|
<p class="text-xs text-gray-500">Derniere verification : {{ "now"|date('d/m/Y a H:i') }}</p>
|
|
</div>
|
|
|
|
{# Messages globaux actifs #}
|
|
{% if globalMessages|length > 0 %}
|
|
<div class="mb-8 flex flex-col gap-3">
|
|
{% for msg in globalMessages %}
|
|
<div class="p-4 border-2
|
|
{% if msg.severity == 'critical' %}border-red-600 bg-red-50
|
|
{% elseif msg.severity == 'warning' %}border-yellow-600 bg-yellow-50
|
|
{% else %}border-blue-600 bg-blue-50
|
|
{% endif %}
|
|
">
|
|
<div class="flex items-center gap-2 mb-1">
|
|
<span class="px-2 py-0.5 font-bold uppercase text-[10px] tracking-widest
|
|
{% if msg.severity == 'critical' %}bg-red-600 text-white
|
|
{% elseif msg.severity == 'warning' %}bg-yellow-600 text-white
|
|
{% else %}bg-blue-600 text-white
|
|
{% endif %}
|
|
">{{ msg.severity }}</span>
|
|
<span class="font-bold text-sm">{{ msg.title }}</span>
|
|
<span class="text-[10px] text-gray-400 ml-auto">{{ msg.createdAt|date('d/m/Y H:i') }}</span>
|
|
</div>
|
|
<p class="text-xs text-gray-700">{{ msg.content }}</p>
|
|
{% if msg.author %}
|
|
<p class="text-[10px] text-gray-400 mt-1">Par {{ msg.author.fullName }}</p>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="flex flex-col gap-8">
|
|
{% for data in servicesData %}
|
|
<section>
|
|
<h2 class="text-xl font-bold uppercase mb-4">{{ data.category.name }}</h2>
|
|
|
|
<div class="flex flex-col gap-4">
|
|
{% for item in data.services %}
|
|
{% set service = item.service %}
|
|
{% set uptime = item.uptime %}
|
|
{% set dailyStatus = item.dailyStatus %}
|
|
|
|
<div class="glass">
|
|
{# Header service #}
|
|
<div class="flex items-center justify-between px-4 py-3">
|
|
<div class="flex items-center gap-3">
|
|
<span class="w-3 h-3 flex-shrink-0
|
|
{% if service.status == 'up' %}bg-green-500
|
|
{% elseif service.status == 'degraded' %}bg-yellow-500
|
|
{% elseif service.status == 'down' %}bg-red-500
|
|
{% elseif service.status == 'maintenance' %}bg-blue-500
|
|
{% else %}bg-gray-400
|
|
{% endif %}
|
|
"></span>
|
|
<span class="font-bold text-sm uppercase">{{ service.name }}</span>
|
|
{% if service.external %}
|
|
<span class="px-1.5 py-0.5 bg-gray-100 text-gray-500 text-[8px] font-bold uppercase">Externe</span>
|
|
{% endif %}
|
|
</div>
|
|
<div class="flex items-center gap-3">
|
|
<span class="px-2 py-0.5 font-bold uppercase text-[10px] tracking-widest
|
|
{% if service.status == 'up' %}bg-green-100 text-green-800
|
|
{% elseif service.status == 'degraded' %}bg-yellow-100 text-yellow-800
|
|
{% elseif service.status == 'down' %}bg-red-100 text-red-800
|
|
{% elseif service.status == 'maintenance' %}bg-blue-100 text-blue-800
|
|
{% else %}bg-gray-100 text-gray-600
|
|
{% endif %}
|
|
">
|
|
{% if service.status == 'up' %}Operationnel
|
|
{% elseif service.status == 'degraded' %}Degrade
|
|
{% elseif service.status == 'down' %}Hors service
|
|
{% elseif service.status == 'maintenance' %}Maintenance
|
|
{% else %}Bientot
|
|
{% endif %}
|
|
</span>
|
|
<span class="text-xs font-bold {{ uptime >= 99 ? 'text-green-600' : (uptime >= 95 ? 'text-yellow-600' : 'text-red-600') }}">{{ uptime }}%</span>
|
|
</div>
|
|
</div>
|
|
|
|
{# Message service #}
|
|
{% if service.message %}
|
|
<div class="px-4 py-2 bg-gray-50 text-xs text-gray-600 border-t border-gray-200">
|
|
{{ service.message }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Messages actifs #}
|
|
{% for msg in item.messages %}
|
|
<div class="px-4 py-2 border-t text-xs
|
|
{% if msg.severity == 'critical' %}border-red-200 bg-red-50 text-red-700
|
|
{% elseif msg.severity == 'warning' %}border-yellow-200 bg-yellow-50 text-yellow-700
|
|
{% else %}border-blue-200 bg-blue-50 text-blue-700
|
|
{% endif %}
|
|
">
|
|
<strong>{{ msg.title }}</strong> — {{ msg.content }}
|
|
<span class="text-[10px] opacity-70 ml-1">{{ msg.createdAt|date('H:i') }}</span>
|
|
</div>
|
|
{% endfor %}
|
|
|
|
{# Graphique 30 jours #}
|
|
<div class="px-4 py-2 border-t border-gray-200 flex items-center gap-[2px]">
|
|
{% for day in dailyStatus %}
|
|
<div class="flex-1 h-5
|
|
{% if day.status == 'up' %}bg-green-400
|
|
{% elseif day.status == 'degraded' %}bg-yellow-400
|
|
{% elseif day.status == 'down' %}bg-red-400
|
|
{% elseif day.status == 'maintenance' %}bg-blue-400
|
|
{% else %}bg-gray-300
|
|
{% endif %}
|
|
" title="{{ day.date }} : {{ day.status }}"></div>
|
|
{% endfor %}
|
|
</div>
|
|
<div class="px-4 pb-1 flex justify-between text-[9px] text-gray-400">
|
|
<span>30 jours</span>
|
|
<span>Aujourd'hui</span>
|
|
</div>
|
|
|
|
{# Logs recents #}
|
|
{% if item.logs|length > 0 %}
|
|
<div class="px-4 py-2 border-t border-gray-200">
|
|
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Historique (7j)</p>
|
|
{% for log in item.logs %}
|
|
<div class="flex items-center gap-2 text-[10px] text-gray-500 py-0.5">
|
|
<span class="text-gray-400">{{ log.createdAt|date('d/m H:i') }}</span>
|
|
<span class="px-1 py-0.5 font-bold uppercase text-[8px]
|
|
{% if log.fromStatus == 'up' %}text-green-600
|
|
{% elseif log.fromStatus == 'down' %}text-red-600
|
|
{% else %}text-yellow-600
|
|
{% endif %}
|
|
">{{ log.fromStatus }}</span>
|
|
<span>→</span>
|
|
<span class="px-1 py-0.5 font-bold uppercase text-[8px]
|
|
{% if log.toStatus == 'up' %}text-green-600
|
|
{% elseif log.toStatus == 'down' %}text-red-600
|
|
{% else %}text-yellow-600
|
|
{% endif %}
|
|
">{{ log.toStatus }}</span>
|
|
<span class="text-gray-300">({{ log.source }})</span>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</section>
|
|
{% else %}
|
|
<p class="text-gray-400 text-sm font-bold">Aucun service configure.</p>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<div class="mt-8 text-center text-xs text-gray-400">
|
|
<p>Page de status — <a href="https://www.e-cosplay.fr" class="underline hover:text-gray-600">Association E-Cosplay</a></p>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|