feat: systeme complet echeancier SEPA, E-Flex, attestations, avertissements clients

Echeancier - Webhooks DocuSeal:
- Webhook form.completed: telecharge PDF signe + audit, state SIGNED, prepare SEPA, notifie client + admin
- Webhook form.declined: state CANCELLED, notifie client + admin
- Reference EC_ECH_XXXXX affichee dans PDF, emails, pages client, admin
- Attestation fin de paiement auto via DocuSeal au completion

Echeancier - SEPA Direct Debit (remplace Subscriptions):
- Page /echeancier/setup-payment/{id}: formulaire IBAN Stripe Elements + mandat SEPA
- Confirmation SetupIntent -> stocke PaymentMethod -> state ACTIVE
- Commande cron app:echeancier:process-payments: preleve les echeances dues via PaymentIntent off_session
- Webhooks payment_intent.succeeded/failed: met a jour EcheancierLine, notifie client
- Regularisation CB via Stripe Checkout en cas d'echec prelevement
- Bouton "Forcer prelevement" par echeance dans admin
- Infos SEPA stockees (last4, bank_code, country) + affichees admin
- Page setup_payment_done quand SEPA deja configure
- Annulation auto apres 2 rejets + sync paiements vers Advert lie

Echeancier - Lien Advert:
- Champ advert (ManyToOne nullable) sur Echeancier
- Select "Avis lie" dans formulaire creation
- AdvertPayment cree a chaque echeance payee
- Advert passe en accepted quand echeancier completed

Comptabilite:
- Export echeanciers CSV/JSON/PDF/PDF signe dans /admin/comptabilite
- Colonnes: reference, client, creance, majoration, total, paye, restant, Stripe PI, avis lie

Stats:
- Case "Total impaye global" = factures impayees + echeances non payees
- Tableau echeanciers en cours avec restant du

Confiance client:
- Statut Confiant/Attention/Danger calcule dynamiquement
- Badge en haut a droite de la fiche client
- Integre warningLevel (1st=Attention, 2nd=Attention, last=Danger)
- Creation echeancier bloquee si Danger (template + controller)

Avertissements client (tab Controle, ROLE_ROOT):
- 3 niveaux: 1st, 2nd (procedure suspension preparee), last (48h)
- Motifs cochables: impayes, irrespect, hors horaires, services gratuits
- PDF signe DocuSeal pour chaque avertissement (ClientWarningPdf)
- PDF levee avertissement signe (ClientWarningResetPdf)
- Webhooks DocuSeal client_warning + client_warning_reset
- Barre progression 4 etapes dans admin
- Mentions legales: huis clos, contestation direction@e-cosplay.fr

Cloture compte:
- Bouton "Envoyer notification de cloture" apres dernier avertissement
- PDF signe DocuSeal (ClientClosurePdf): suppression 24h, recouvrement, commissaire justice, forces ordre
- Bouton "Suspendre le compte" (state suspended)
- Webhook DocuSeal client_closure: envoie PDF signe a client + admin + direction

Factures:
- Auto-generation PDF si absent lors de l'envoi
- Bouton "Envoyer" visible meme sans PDF pour factures payees

E-Flex (financement services):
- Entites EFlex + EFlexLine (reference E_FLEX_XXXXX)
- Methodes: SEPA, CB (Stripe Checkout), virement manuel
- PDF contrat avec 2 signatures DocuSeal (Company + Client)
- Controller admin CRUD + force payment + paiement manuel
- Pages client: verify, process, sign, signed, setup SEPA, paiement CB
- Webhook DocuSeal eflex: telecharge PDFs, prepare Stripe, notifie
- Webhooks Stripe payment_intent: gestion paiements E-Flex
- Cron traite aussi les E-Flex SEPA dans process-payments
- Tab E-Flex dans fiche client avec liste + modal creation
- Emails: signature, signed, verify_code, echeance_payee, echeance_echec

Attestations custom (ROLE_ROOT):
- Entite AttestationCustom avec items JSON + HMAC SHA-256
- Repeater dynamique pour ajouter elements a attester
- PDF avec phrase officielle "Je soussigne(e)..." + QR code verification
- Signature manuelle dans DocuSeal (redirection)
- Webhook attestation_custom: telecharge PDF signe + audit
- Page publique /attestation/verify/{id}/{hmac} avec validation HMAC
- Lien dans sidebar Super Admin

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-04-09 07:45:22 +02:00
parent 5b3706e282
commit 18daf096fa
108 changed files with 9017 additions and 115 deletions

View File

@@ -97,6 +97,10 @@
<svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
Tarification
</a>
<a href="{{ path('app_admin_attestation_custom_index') }}" class="sidebar-nav-item {{ current_route starts with 'app_admin_attestation_custom' ? 'active-danger' : '' }}" style="color: {{ current_route starts with 'app_admin_attestation_custom' ? 'white' : 'rgba(248,113,113,0.7)' }}">
<svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
Attestations
</a>
</div>
{% endif %}
</nav>

View File

@@ -0,0 +1,121 @@
{% extends 'admin/_layout.html.twig' %}
{% block title %}Attestations - Association E-Cosplay{% endblock %}
{% block admin_content %}
<div class="page-container">
<div class="flex items-center justify-between mb-6">
<h1 class="text-2xl font-bold heading-page">Attestations</h1>
<button type="button" data-modal-open="modal-attestation" class="btn-gold px-4 py-2 font-bold uppercase text-[10px] tracking-wider text-gray-900">Creer une attestation</button>
</div>
{% for type, messages in app.flashes %}
{% for message in messages %}
<div class="mb-4 p-4 glass font-medium text-sm {{ type == 'success' ? 'border-green-300 text-green-800' : 'border-red-300 text-red-800' }}">{{ message }}</div>
{% endfor %}
{% endfor %}
{% if attestations|length > 0 %}
<div class="glass overflow-x-auto overflow-hidden">
<table class="w-full text-sm">
<thead>
<tr class="glass-dark text-white">
<th class="px-4 py-3 text-left font-bold uppercase text-xs tracking-widest">Reference</th>
<th class="px-4 py-3 text-left font-bold uppercase text-xs tracking-widest">Titre</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Elements</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Statut</th>
<th class="px-4 py-3 text-left font-bold uppercase text-xs tracking-widest">Date</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Actions</th>
</tr>
</thead>
<tbody>
{% for att in attestations %}
<tr class="border-b border-white/20 hover:bg-white/50">
<td class="px-4 py-3 font-mono font-bold text-[10px]">{{ att.reference }}</td>
<td class="px-4 py-3 font-bold text-xs">{{ att.title|length > 50 ? att.title[:50] ~ '...' : att.title }}</td>
<td class="px-4 py-3 text-center text-xs">{{ att.items|length }}</td>
<td class="px-4 py-3 text-center">
{% if att.state == 'signed' %}
<span class="px-2 py-0.5 bg-green-500/20 text-green-700 font-bold uppercase text-[10px]">Signee</span>
{% else %}
<span class="px-2 py-0.5 bg-yellow-100 text-yellow-800 font-bold uppercase text-[10px]">Brouillon</span>
{% endif %}
</td>
<td class="px-4 py-3 text-xs text-gray-500">{{ att.createdAt|date('d/m/Y H:i') }}</td>
<td class="px-4 py-3 text-center">
<a href="{{ path('app_admin_attestation_custom_show', {id: att.id}) }}" class="px-3 py-1 bg-gray-900 text-white hover:bg-[#fabf04] hover:text-gray-900 font-bold uppercase text-[10px] transition-all">Voir</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="glass p-8 text-center text-gray-400 font-bold">Aucune attestation.</div>
{% endif %}
{# Modal creation #}
<div id="modal-attestation" class="hidden fixed inset-0 z-50 flex items-center justify-center bg-black/50">
<div class="glass-heavy p-6 w-full max-w-lg max-h-[90vh] overflow-y-auto">
<h2 class="text-lg font-bold uppercase mb-4">Nouvelle attestation</h2>
<form method="post" action="{{ path('app_admin_attestation_custom_create') }}">
<div class="mb-4">
<label for="att-title" class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Titre de l'attestation *</label>
<input type="text" id="att-title" name="title" required class="input-glass w-full px-3 py-2 text-xs font-bold" placeholder="Ex: Attestation de conformite des services">
</div>
<div class="mb-4">
<label class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-2">Elements a attester *</label>
<div id="items-container" class="space-y-2">
<div class="flex gap-2">
<input type="text" name="items[]" required class="input-glass flex-1 px-3 py-2 text-xs font-bold" placeholder="Element 1">
<button type="button" class="remove-item px-2 py-1 bg-red-500/20 text-red-700 font-bold text-xs hidden">X</button>
</div>
</div>
<button type="button" id="add-item-btn" class="mt-2 px-3 py-1 glass text-xs font-bold uppercase tracking-wider hover:bg-gray-900 hover:text-white transition-all">+ Ajouter un element</button>
</div>
<div class="glass p-3 mb-4 text-[10px] text-gray-400 leading-relaxed">
<strong>Apercu :</strong> "Je soussigne(e), President(e) de l'Association E-Cosplay et le bureau de l'association, atteste les elements suivants : [vos elements]. La presente attestation est etablie pour faire valoir les droits de l'association. Les elements presentes sont conformes et veridiques."
</div>
<div class="flex justify-end gap-2">
<button type="button" data-modal-close="modal-attestation" class="px-4 py-2 glass font-bold uppercase text-[10px] tracking-widest">Annuler</button>
<button type="submit" class="btn-gold px-4 py-2 font-bold uppercase text-[10px] tracking-wider text-gray-900">Creer</button>
</div>
</form>
</div>
</div>
</div>
<script nonce="{{ csp_nonce('script') }}">
(function() {
var container = document.getElementById('items-container');
var addBtn = document.getElementById('add-item-btn');
var count = 1;
function updateRemoveButtons() {
var items = container.querySelectorAll('.flex');
items.forEach(function(item) {
var btn = item.querySelector('.remove-item');
if (btn) btn.classList.toggle('hidden', items.length <= 1);
});
}
addBtn.addEventListener('click', function() {
count++;
var div = document.createElement('div');
div.className = 'flex gap-2';
div.innerHTML = '<input type="text" name="items[]" required class="input-glass flex-1 px-3 py-2 text-xs font-bold" placeholder="Element ' + count + '">'
+ '<button type="button" class="remove-item px-2 py-1 bg-red-500/20 text-red-700 font-bold text-xs">X</button>';
container.appendChild(div);
div.querySelector('.remove-item').addEventListener('click', function() { div.remove(); updateRemoveButtons(); });
updateRemoveButtons();
});
container.addEventListener('click', function(e) {
if (e.target.classList.contains('remove-item')) { e.target.parentElement.remove(); updateRemoveButtons(); }
});
})();
</script>
{% endblock %}

View File

@@ -0,0 +1,107 @@
{% extends 'admin/_layout.html.twig' %}
{% block title %}Attestation {{ attestation.reference }} - Association E-Cosplay{% endblock %}
{% block admin_content %}
<div class="page-container">
<div class="flex items-center justify-between mb-6">
<div>
<h1 class="text-2xl font-bold heading-page">{{ attestation.reference }}</h1>
<p class="text-xs text-gray-400 mt-1">{{ attestation.title }}</p>
</div>
<div class="flex items-center gap-3">
{% if attestation.state == 'signed' %}
<span class="px-3 py-1 bg-green-500/20 text-green-700 font-bold uppercase text-xs">Signee</span>
{% else %}
<span class="px-3 py-1 bg-yellow-100 text-yellow-800 font-bold uppercase text-xs">Brouillon</span>
{% endif %}
<a href="{{ path('app_admin_attestation_custom_index') }}" class="px-4 py-2 glass font-bold uppercase text-xs tracking-widest hover:bg-gray-900 hover:text-white transition-all">Retour</a>
</div>
</div>
{% for type, messages in app.flashes %}
{% for message in messages %}
<div class="mb-4 p-4 glass font-medium text-sm {{ type == 'success' ? 'border-green-300 text-green-800' : 'border-red-300 text-red-800' }}">{{ message }}</div>
{% endfor %}
{% endfor %}
{# Contenu de l'attestation #}
<div class="glass p-6 mb-6">
<h2 class="text-sm font-bold uppercase tracking-wider mb-4">{{ attestation.title }}</h2>
<p class="text-sm text-gray-600 mb-4 italic">
"Je soussigne(e), President(e) de l'Association E-Cosplay et le bureau de l'association, atteste les elements suivants :"
</p>
<div class="space-y-2 mb-4">
{% for item in attestation.items %}
<div class="flex items-start gap-3 glass p-3">
<span class="text-xs font-bold text-gray-400 mt-0.5">{{ loop.index }}.</span>
<p class="text-sm text-gray-700">{{ item }}</p>
</div>
{% endfor %}
</div>
<p class="text-sm text-gray-600 italic">
"La presente attestation est etablie pour faire valoir les droits de l'Association E-Cosplay. Les elements presentes ci-dessus sont conformes et veridiques."
</p>
</div>
{# Infos techniques #}
<div class="glass p-5 mb-6">
<div class="grid grid-cols-2 md:grid-cols-4 gap-3 text-xs">
<div>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Reference</p>
<p class="font-mono font-bold mt-1">{{ attestation.reference }}</p>
</div>
<div>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">HMAC</p>
<p class="font-mono font-bold mt-1 text-[10px]">{{ attestation.hmac[:16] }}...</p>
</div>
<div>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Creee le</p>
<p class="font-bold mt-1">{{ attestation.createdAt|date('d/m/Y H:i') }}</p>
</div>
{% if attestation.signedAt %}
<div>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Signee le</p>
<p class="font-bold mt-1 text-green-600">{{ attestation.signedAt|date('d/m/Y H:i') }}</p>
</div>
{% endif %}
</div>
</div>
{# Actions #}
<div class="flex flex-wrap gap-2 mb-6">
{% if attestation.pdfUnsigned %}
<a href="{{ vich_uploader_asset(attestation, 'pdfUnsignedFile') }}" target="_blank"
class="px-4 py-2 bg-gray-900 text-white font-bold uppercase text-[10px] tracking-wider hover:bg-[#fabf04] hover:text-gray-900 transition-all">
Voir PDF
</a>
{% endif %}
{% if attestation.state == 'draft' %}
<form method="post" action="{{ path('app_admin_attestation_custom_regenerate_pdf', {id: attestation.id}) }}" data-confirm="Regenerer le PDF ?">
<button type="submit" class="px-4 py-2 bg-yellow-500/20 text-yellow-700 hover:bg-yellow-500 hover:text-white font-bold uppercase text-[10px] tracking-wider transition-all">Regenerer PDF</button>
</form>
<form method="post" action="{{ path('app_admin_attestation_custom_sign', {id: attestation.id}) }}" data-confirm="Signer electroniquement cette attestation via DocuSeal ?">
<button type="submit" class="px-4 py-2 bg-purple-500/20 text-purple-700 hover:bg-purple-500 hover:text-white font-bold uppercase text-[10px] tracking-wider transition-all">Signer (DocuSeal)</button>
</form>
{% endif %}
{% if attestation.pdfSigned %}
<a href="{{ vich_uploader_asset(attestation, 'pdfSignedFile') }}" target="_blank"
class="px-4 py-2 bg-green-500/20 text-green-700 font-bold uppercase text-[10px] tracking-wider hover:bg-green-500 hover:text-white transition-all">
PDF signe
</a>
{% endif %}
{% if attestation.pdfAudit %}
<a href="{{ vich_uploader_asset(attestation, 'pdfAuditFile') }}" target="_blank"
class="px-4 py-2 bg-blue-500/20 text-blue-700 font-bold uppercase text-[10px] tracking-wider hover:bg-blue-500 hover:text-white transition-all">
Audit signature
</a>
{% endif %}
<form method="post" action="{{ path('app_admin_attestation_custom_delete', {id: attestation.id}) }}" data-confirm="Supprimer definitivement cette attestation ?">
<button type="submit" class="px-4 py-2 bg-red-500/20 text-red-700 hover:bg-red-500 hover:text-white font-bold uppercase text-[10px] tracking-wider transition-all">Supprimer</button>
</form>
</div>
</div>
{% endblock %}

View File

@@ -12,8 +12,17 @@
{% endif %}
</div>
<div class="flex items-center gap-3">
{% if trustStatus.status == 'confiant' %}
<span class="px-3 py-1 bg-green-500/20 text-green-700 font-bold uppercase text-xs" title="{{ trustStatus.reason }}">Confiant</span>
{% elseif trustStatus.status == 'attention' %}
<span class="px-3 py-1 bg-yellow-500/20 text-yellow-700 font-bold uppercase text-xs" title="{{ trustStatus.reason }}">Attention</span>
{% elseif trustStatus.status == 'danger' %}
<span class="px-3 py-1 bg-red-600 text-white font-bold uppercase text-xs animate-pulse" title="{{ trustStatus.reason }}">Danger</span>
{% endif %}
{% if customer.state == 'active' %}
<span class="px-3 py-1 bg-green-500/20 text-green-700 font-bold uppercase text-xs">Actif</span>
{% elseif customer.state == 'suspended' %}
<span class="px-3 py-1 bg-red-900 text-white font-bold uppercase text-xs animate-pulse">Suspendu</span>
{% elseif customer.state == 'pending_delete' %}
<span class="px-3 py-1 bg-red-500/20 text-red-700 font-bold uppercase text-xs animate-pulse">Suppression</span>
{% else %}
@@ -41,11 +50,14 @@
'impayes': 'Impayes',
'echeancier': 'Echeancier',
'ndd': 'Noms de domaine',
'esyflex': 'EsyFlex',
'esyflex': 'E-Flex',
'sites': 'Sites Internet',
'services': 'Services',
'securite': 'Securite'
} %}
{% if is_granted('ROLE_ROOT') %}
{% set tabs = tabs|merge({'controle': 'Controle'}) %}
{% endif %}
<div class="flex flex-wrap gap-1 mb-6">
{% for key, label in tabs %}
@@ -543,6 +555,11 @@
<form method="post" action="{{ path('app_admin_facture_generate_pdf', {id: f.id}) }}" class="inline">
<button type="submit" class="px-3 py-1 bg-green-500/20 text-green-700 hover:bg-green-500 hover:text-white font-bold uppercase text-[10px]transition-all">Generer PDF</button>
</form>
{% if f.state == 'paid' and f.state != 'send' %}
<form method="post" action="{{ path('app_admin_facture_send', {id: f.id}) }}" class="inline" data-confirm="Generer et envoyer la facture {{ f.invoiceNumber }} au client ?">
<button type="submit" class="px-3 py-1 bg-purple-500/20 text-purple-700 hover:bg-purple-500 hover:text-white font-bold uppercase text-[10px]transition-all">Envoyer</button>
</form>
{% endif %}
{% endif %}
</div>
{% else %}
@@ -726,7 +743,7 @@
<select id="mp-echeancier-{{ a.id }}" name="echeancierId" class="input-glass w-full px-3 py-2 text-xs font-bold">
<option value="">— Selectionner —</option>
{% for ech in echeancierList %}
<option value="{{ ech.id }}">{{ ech.description|length > 40 ? ech.description[:40] ~ '...' : ech.description }} ({{ ech.nbPaid }}/{{ ech.nbLines }} - {{ ech.totalAmountHt }} &euro;)</option>
<option value="{{ ech.id }}">{{ ech.reference }} - {{ ech.description|length > 30 ? ech.description[:30] ~ '...' : ech.description }} ({{ ech.totalAmountHt }} &euro;)</option>
{% endfor %}
</select>
</div>
@@ -887,8 +904,22 @@
{# Tab: Echeancier #}
{% elseif tab == 'echeancier' %}
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-bold uppercase">Echeanciers</h2>
<button type="button" data-modal-open="modal-echeancier" class="btn-gold px-4 py-2 font-bold uppercase text-[10px] tracking-wider text-gray-900">Creer un echeancier</button>
<div class="flex items-center gap-3">
<h2 class="text-lg font-bold uppercase">Echeanciers</h2>
{% if trustStatus.status == 'confiant' %}
<span class="px-2 py-0.5 bg-green-500/20 text-green-700 font-bold uppercase text-[10px]">Confiant</span>
{% elseif trustStatus.status == 'attention' %}
<span class="px-2 py-0.5 bg-yellow-500/20 text-yellow-700 font-bold uppercase text-[10px]">Attention</span>
{% elseif trustStatus.status == 'danger' %}
<span class="px-2 py-0.5 bg-red-600 text-white font-bold uppercase text-[10px] animate-pulse">Danger</span>
{% endif %}
<span class="text-[10px] text-gray-400">{{ trustStatus.reason }}</span>
</div>
{% if trustStatus.status == 'danger' %}
<span class="px-4 py-2 bg-red-500/20 text-red-700 font-bold uppercase text-[10px] tracking-wider cursor-not-allowed" title="Creation bloquee : {{ trustStatus.reason }}">Creation bloquee</span>
{% else %}
<button type="button" data-modal-open="modal-echeancier" class="btn-gold px-4 py-2 font-bold uppercase text-[10px] tracking-wider text-gray-900">Creer un echeancier</button>
{% endif %}
</div>
{# Liste des echeanciers existants #}
@@ -897,6 +928,7 @@
<table class="w-full text-sm">
<thead>
<tr class="glass-dark text-white">
<th class="px-4 py-3 text-left font-bold uppercase text-xs tracking-widest">Reference</th>
<th class="px-4 py-3 text-left font-bold uppercase text-xs tracking-widest">Description</th>
<th class="px-4 py-3 text-right font-bold uppercase text-xs tracking-widest">Total HT</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Echeances</th>
@@ -908,6 +940,7 @@
<tbody>
{% for e in echeancierList %}
<tr class="border-b border-white/20 hover:bg-white/50">
<td class="px-4 py-3 font-mono font-bold text-[10px]">{{ e.reference }}</td>
<td class="px-4 py-3 font-bold text-xs">{{ e.description|length > 50 ? e.description[:50] ~ '...' : e.description }}</td>
<td class="px-4 py-3 text-right font-bold text-xs">{{ e.totalAmountHt|number_format(2, ',', ' ') }} &euro;</td>
<td class="px-4 py-3 text-center text-xs">{{ e.nbPaid }}/{{ e.nbLines }}</td>
@@ -963,6 +996,15 @@
<label for="ech-startDate" class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Date 1ere echeance *</label>
<input type="date" id="ech-startDate" name="startDate" required class="input-glass w-full px-3 py-2 text-xs font-bold">
</div>
<div class="md:col-span-2">
<label for="ech-advertId" class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Avis de paiement lie (optionnel)</label>
<select id="ech-advertId" name="advertId" class="input-glass w-full px-3 py-2 text-xs font-bold">
<option value="">— Aucun —</option>
{% for a in advertsList %}
<option value="{{ a.id }}">{{ a.orderNumber.numOrder }} ({{ a.totalTtc }} &euro;)</option>
{% endfor %}
</select>
</div>
</div>
<div class="flex justify-end gap-2">
<button type="button" data-modal-close="modal-echeancier" class="px-4 py-2 glass font-bold uppercase text-[10px] tracking-widest">Annuler</button>
@@ -1041,6 +1083,228 @@
</section>
{% endif %}
{# Tab: Controle (ROLE_ROOT uniquement) #}
{% elseif tab == 'controle' and is_granted('ROLE_ROOT') %}
<div class="flex items-center justify-between mb-4">
<div class="flex items-center gap-3">
<h2 class="text-lg font-bold uppercase">Controle client</h2>
{% if trustStatus.status == 'confiant' %}
<span class="px-2 py-0.5 bg-green-500/20 text-green-700 font-bold uppercase text-[10px]">Confiant</span>
{% elseif trustStatus.status == 'attention' %}
<span class="px-2 py-0.5 bg-yellow-500/20 text-yellow-700 font-bold uppercase text-[10px]">Attention</span>
{% elseif trustStatus.status == 'danger' %}
<span class="px-2 py-0.5 bg-red-600 text-white font-bold uppercase text-[10px] animate-pulse">Danger</span>
{% endif %}
</div>
</div>
{# Resume confiance #}
<div class="glass p-5 mb-6">
<h3 class="text-sm font-bold uppercase tracking-wider mb-2">Statut de confiance</h3>
<p class="text-sm text-gray-600">{{ trustStatus.reason }}</p>
</div>
{# Historique avertissements #}
<div class="glass p-5 mb-6">
<h3 class="text-sm font-bold uppercase tracking-wider mb-3">Avertissements</h3>
{% if customer.warningLevel %}
<div class="flex items-center gap-3 mb-4">
<span class="text-xs text-gray-500">Dernier avertissement :</span>
{% if customer.warningLevel == '1st' %}
<span class="px-3 py-1 bg-yellow-500/20 text-yellow-700 font-bold uppercase text-xs">1er avertissement</span>
{% elseif customer.warningLevel == '2nd' %}
<span class="px-3 py-1 bg-orange-500/20 text-orange-700 font-bold uppercase text-xs">2eme avertissement</span>
{% elseif customer.warningLevel == 'last' %}
<span class="px-3 py-1 bg-red-600 text-white font-bold uppercase text-xs animate-pulse">Dernier avertissement</span>
{% endif %}
{% if customer.warningAt %}
<span class="text-[10px] text-gray-400">envoye le {{ customer.warningAt|date('d/m/Y H:i') }}</span>
{% endif %}
</div>
{% else %}
<p class="text-xs text-gray-400 mb-4">Aucun avertissement envoye.</p>
{% endif %}
{# Motifs + Boutons d'envoi #}
{% set nextWarning = customer.warningLevel is null ? '1st' : (customer.warningLevel == '1st' ? '2nd' : 'last') %}
{% set warningLabels = {'1st': '1er avertissement', '2nd': '2eme avertissement', 'last': 'Dernier avertissement (suspension)'} %}
{% if customer.warningLevel != 'last' %}
<form method="post" action="{{ path('app_admin_clients_send_warning', {id: customer.id, level: nextWarning}) }}"
data-confirm="Envoyer le {{ warningLabels[nextWarning] }} au client {{ customer.fullName }} ?">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-2">Motifs de l'avertissement</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-2 mb-4">
<label class="flex items-center gap-2 text-xs cursor-pointer">
<input type="checkbox" name="reasons[]" value="impayes" checked class="accent-yellow-500">
Impayes et/ou rejets de prelevement
</label>
<label class="flex items-center gap-2 text-xs cursor-pointer">
<input type="checkbox" name="reasons[]" value="irrespect" class="accent-yellow-500">
Manque de respect / insultes
</label>
<label class="flex items-center gap-2 text-xs cursor-pointer">
<input type="checkbox" name="reasons[]" value="hors_horaires" class="accent-yellow-500">
Appels hors des heures d'ouverture (refus de payer le service hors horaire)
</label>
<label class="flex items-center gap-2 text-xs cursor-pointer">
<input type="checkbox" name="reasons[]" value="gratuit" class="accent-yellow-500">
Exige des services gratuits
</label>
</div>
<div class="flex flex-wrap gap-2">
<button type="submit" class="px-4 py-2 {{ nextWarning == 'last' ? 'bg-red-600 text-white hover:bg-red-700' : (nextWarning == '2nd' ? 'bg-orange-500/20 text-orange-700 hover:bg-orange-500 hover:text-white' : 'bg-yellow-500/20 text-yellow-700 hover:bg-yellow-500 hover:text-white') }} font-bold uppercase text-[10px] tracking-wider transition-all">
Envoyer {{ warningLabels[nextWarning] }}
</button>
</div>
</form>
{% else %}
<p class="text-xs text-red-600 font-bold mb-4">Tous les avertissements ont ete envoyes.</p>
<div class="flex flex-wrap gap-3 mb-4">
{# Bouton notification (faire peur - n'effectue pas la suppression) #}
<form method="post" action="{{ path('app_admin_clients_close_account', {id: customer.id}) }}"
data-confirm="Envoyer la notification de cloture au client {{ customer.fullName }} ? (Le compte ne sera PAS supprime, c'est uniquement un courrier officiel)">
<button type="submit" class="px-5 py-3 bg-orange-600 text-white hover:bg-orange-800 font-bold uppercase text-[10px] tracking-wider transition-all">
Envoyer notification de cloture (avertissement)
</button>
</form>
{# Bouton reel de suspension #}
<form method="post" action="{{ path('app_admin_clients_suspend_account', {id: customer.id}) }}"
data-confirm="ATTENTION IRREVERSIBLE : Suspendre le compte de {{ customer.fullName }} ? Le statut passera en SUSPENDU.">
<button type="submit" class="px-5 py-3 bg-red-800 text-white hover:bg-red-950 font-bold uppercase text-[10px] tracking-wider transition-all animate-pulse">
Suspendre le compte
</button>
</form>
</div>
{% endif %}
{% if customer.warningLevel %}
<form method="post" action="{{ path('app_admin_clients_reset_warning', {id: customer.id}) }}" class="mt-3"
data-confirm="Reinitialiser les avertissements du client {{ customer.fullName }} ?">
<button type="submit" class="px-4 py-2 glass font-bold uppercase text-[10px] tracking-wider hover:bg-gray-900 hover:text-white transition-all">Reinitialiser</button>
</form>
{% endif %}
</div>
{# Progression des avertissements #}
<div class="glass p-5 mb-6">
<h3 class="text-sm font-bold uppercase tracking-wider mb-3">Progression</h3>
<div class="flex items-center gap-2">
<div class="flex-1 h-3 {{ customer.warningLevel in ['1st', '2nd', 'last'] ? 'bg-yellow-500' : 'bg-gray-200' }}"></div>
<div class="flex-1 h-3 {{ customer.warningLevel in ['2nd', 'last'] ? 'bg-orange-500' : 'bg-gray-200' }}"></div>
<div class="flex-1 h-3 {{ customer.warningLevel == 'last' ? 'bg-red-600' : 'bg-gray-200' }}"></div>
<div class="flex-1 h-3 {{ customer.state == 'pending_delete' ? 'bg-red-900' : 'bg-gray-200' }}"></div>
</div>
<div class="flex justify-between mt-1">
<span class="text-[9px] text-gray-400 font-bold uppercase">1er avert.</span>
<span class="text-[9px] text-gray-400 font-bold uppercase">2eme avert.</span>
<span class="text-[9px] text-gray-400 font-bold uppercase">Dernier avert.</span>
<span class="text-[9px] text-gray-400 font-bold uppercase">Cloture</span>
</div>
</div>
{# Tab: E-Flex #}
{% elseif tab == 'esyflex' %}
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-bold uppercase">E-Flex</h2>
<button type="button" data-modal-open="modal-eflex" class="btn-gold px-4 py-2 font-bold uppercase text-[10px] tracking-wider text-gray-900">Creer un E-Flex</button>
</div>
{% if eflexList|length > 0 %}
<div class="glass overflow-x-auto overflow-hidden">
<table class="w-full text-sm">
<thead>
<tr class="glass-dark text-white">
<th class="px-4 py-3 text-left font-bold uppercase text-xs tracking-widest">Reference</th>
<th class="px-4 py-3 text-left font-bold uppercase text-xs tracking-widest">Description</th>
<th class="px-4 py-3 text-right font-bold uppercase text-xs tracking-widest">Total</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Echeances</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Methode</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Progression</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Statut</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Actions</th>
</tr>
</thead>
<tbody>
{% for e in eflexList %}
<tr class="border-b border-white/20 hover:bg-white/50">
<td class="px-4 py-3 font-mono font-bold text-[10px]">{{ e.reference }}</td>
<td class="px-4 py-3 font-bold text-xs">{{ e.description|length > 40 ? e.description[:40] ~ '...' : e.description }}</td>
<td class="px-4 py-3 text-right font-bold text-xs">{{ e.totalAmount|number_format(2, ',', ' ') }} &euro;</td>
<td class="px-4 py-3 text-center text-xs">{{ e.nbPaid }}/{{ e.nbLines }}</td>
<td class="px-4 py-3 text-center text-xs">{{ e.paymentMethodLabel }}</td>
<td class="px-4 py-3 text-center">
<div class="w-full bg-gray-200 h-2"><div class="bg-green-500 h-2" style="width: {{ e.progress }}%"></div></div>
</td>
<td class="px-4 py-3 text-center">
{% if e.state == 'active' %}
<span class="px-2 py-0.5 bg-green-500/20 text-green-700 font-bold uppercase text-[10px]">Actif</span>
{% elseif e.state == 'completed' %}
<span class="px-2 py-0.5 bg-emerald-500/20 text-emerald-700 font-bold uppercase text-[10px]">Termine</span>
{% elseif e.state == 'cancelled' %}
<span class="px-2 py-0.5 bg-red-500/20 text-red-700 font-bold uppercase text-[10px]">Annule</span>
{% elseif e.state == 'draft' %}
<span class="px-2 py-0.5 bg-yellow-100 text-yellow-800 font-bold uppercase text-[10px]">Brouillon</span>
{% elseif e.state == 'pending_setup' %}
<span class="px-2 py-0.5 bg-orange-500/20 text-orange-700 font-bold uppercase text-[10px]">En attente</span>
{% else %}
<span class="px-2 py-0.5 bg-blue-500/20 text-blue-700 font-bold uppercase text-[10px]">{{ e.state }}</span>
{% endif %}
</td>
<td class="px-4 py-3 text-center">
<a href="{{ path('app_admin_eflex_show', {id: e.id}) }}" class="px-3 py-1 bg-gray-900 text-white hover:bg-[#fabf04] hover:text-gray-900 font-bold uppercase text-[10px] transition-all">Voir</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="glass p-8 text-center text-gray-400 font-bold">Aucun contrat E-Flex pour ce client.</div>
{% endif %}
{# Modal creation E-Flex #}
<div id="modal-eflex" class="hidden fixed inset-0 z-50 flex items-center justify-center bg-black/50">
<div class="glass-heavy p-6 w-full max-w-lg">
<h2 class="text-lg font-bold uppercase mb-4">Nouveau contrat E-Flex</h2>
<form method="post" action="{{ path('app_admin_eflex_create', {customerId: customer.id}) }}">
<div class="grid grid-cols-1 md:grid-cols-2 gap-3 mb-4">
<div class="md:col-span-2">
<label for="eflex-description" class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Description / Service *</label>
<textarea id="eflex-description" name="description" required rows="2" class="input-glass w-full px-3 py-2 text-xs font-bold" placeholder="Ex: Financement site internet + hebergement 12 mois"></textarea>
</div>
<div>
<label for="eflex-totalAmount" class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Montant total *</label>
<input type="number" id="eflex-totalAmount" name="totalAmount" step="0.01" min="1" required class="input-glass w-full px-3 py-2 text-xs font-bold">
</div>
<div>
<label for="eflex-nbEcheances" class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Nombre d'echeances *</label>
<input type="number" id="eflex-nbEcheances" name="nbEcheances" min="2" max="36" value="3" required class="input-glass w-full px-3 py-2 text-xs font-bold">
</div>
<div>
<label for="eflex-startDate" class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Date 1ere echeance *</label>
<input type="date" id="eflex-startDate" name="startDate" required class="input-glass w-full px-3 py-2 text-xs font-bold">
</div>
<div>
<label for="eflex-paymentMethod" class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Methode de paiement</label>
<select id="eflex-paymentMethod" name="paymentMethod" class="input-glass w-full px-3 py-2 text-xs font-bold">
<option value="sepa">Prelevement SEPA</option>
<option value="cb">Carte bancaire</option>
<option value="virement">Virement bancaire</option>
</select>
</div>
</div>
<div class="flex justify-end gap-2">
<button type="button" data-modal-close="modal-eflex" class="px-4 py-2 glass font-bold uppercase text-[10px] tracking-widest">Annuler</button>
<button type="submit" class="btn-gold px-4 py-2 font-bold uppercase text-[10px] tracking-wider text-gray-900">Creer</button>
</div>
</form>
</div>
</div>
{# Tabs placeholder #}
{% else %}
<div class="glass p-12 text-center">

View File

@@ -160,6 +160,35 @@
</div>
</div>
</div>
{# Echeanciers #}
<div class="glass overflow-hidden">
<div class="px-4 py-3 glass-dark text-white">
<span class="font-bold text-sm uppercase tracking-wider">Echeanciers de paiement</span>
</div>
<div class="p-4">
<p class="text-xs text-gray-500 mb-3">Export des echeanciers et echeances : reference, client, creance, majoration, paiements recus, statut SEPA.</p>
<ul class="text-[10px] text-gray-400 space-y-1 mb-4">
<li>- Detail par echeance (date, montant, statut)</li>
<li>- Majoration 5% incluse</li>
<li>- Avis de paiement lie</li>
</ul>
<div class="flex gap-2">
<button type="button" class="compta-export-btn flex-1 btn-gold px-3 py-2 font-bold uppercase text-[10px] tracking-wider text-gray-900"
data-url="{{ path('app_admin_comptabilite_export_echeanciers') }}">
CSV / JSON
</button>
<button type="button" class="compta-pdf-btn flex-1 px-3 py-2 bg-gray-900 text-white hover:bg-[#fabf04] hover:text-gray-900 font-bold uppercase text-[10px] tracking-wider transition-all"
data-url="{{ path('app_admin_comptabilite_export_pdf', {type: 'echeanciers'}) }}">
PDF
</button>
<button type="button" class="compta-sign-btn px-3 py-2 bg-purple-500/20 text-purple-700 hover:bg-purple-500 hover:text-white font-bold uppercase text-[10px] tracking-wider transition-all"
data-url="{{ path('app_admin_comptabilite_export_pdf_sign', {type: 'echeanciers'}) }}"
title="PDF + Signature electronique">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"/></svg>
</button>
</div>
</div>
</div>
</div>
{# Rapport financier public #}

View File

@@ -7,7 +7,7 @@
<div class="flex items-center justify-between mb-6">
<div>
<h1 class="text-2xl font-bold heading-page">Echeancier</h1>
<p class="text-xs text-gray-400 mt-1">{{ customer.fullName }} - {{ echeancier.description }}</p>
<p class="text-xs text-gray-400 mt-1">{{ echeancier.reference }} - {{ customer.fullName }} - {{ echeancier.description }}</p>
</div>
<div class="flex items-center gap-3">
{% if echeancier.state == 'draft' %}
@@ -16,6 +16,8 @@
<span class="px-3 py-1 bg-blue-500/20 text-blue-700 font-bold uppercase text-xs">Envoye</span>
{% elseif echeancier.state == 'signed' %}
<span class="px-3 py-1 bg-purple-500/20 text-purple-700 font-bold uppercase text-xs">Signe</span>
{% elseif echeancier.state == 'pending_setup' %}
<span class="px-3 py-1 bg-orange-500/20 text-orange-700 font-bold uppercase text-xs">En attente SEPA</span>
{% elseif echeancier.state == 'active' %}
<span class="px-3 py-1 bg-green-500/20 text-green-700 font-bold uppercase text-xs">Actif</span>
{% elseif echeancier.state == 'completed' %}
@@ -64,11 +66,14 @@
<div class="glass p-5 mb-6">
<h2 class="text-sm font-bold uppercase tracking-wider mb-2">Motif</h2>
<p class="text-sm text-gray-600">{{ echeancier.description }}</p>
{% if echeancier.advert %}
<p class="text-xs text-gray-400 mt-2">Avis lie : <a href="{{ path('app_admin_advert_show', {id: echeancier.advert.id}) }}" class="text-[#fabf04] font-bold">{{ echeancier.advert.orderNumber.numOrder }}</a></p>
{% endif %}
</div>
{# Actions #}
<div class="flex flex-wrap gap-2 mb-6">
{% if echeancier.state not in ['cancelled', 'completed'] %}
{% if echeancier.state in ['draft', 'send'] %}
{% if echeancier.pdfUnsigned %}
<form method="post" action="{{ path('app_admin_echeancier_generate_pdf', {id: echeancier.id}) }}" data-confirm="Regenerer le PDF ? Le fichier existant sera remplace.">
<button type="submit" class="px-4 py-2 bg-yellow-500/20 text-yellow-700 hover:bg-yellow-500 hover:text-white font-bold uppercase text-[10px] tracking-wider transition-all">Regenerer PDF</button>
@@ -79,7 +84,7 @@
</form>
{% endif %}
{% endif %}
{% if echeancier.pdfUnsigned %}
{% if echeancier.pdfUnsigned and echeancier.state in ['draft', 'send'] %}
<a href="{{ vich_uploader_asset(echeancier, 'pdfUnsignedFile') }}" target="_blank"
class="px-4 py-2 bg-gray-900 text-white font-bold uppercase text-[10px] tracking-wider hover:bg-[#fabf04] hover:text-gray-900 transition-all">
Voir PDF
@@ -90,18 +95,34 @@
<button type="submit" class="px-4 py-2 bg-purple-500/20 text-purple-700 hover:bg-purple-500 hover:text-white font-bold uppercase text-[10px] tracking-wider transition-all">{{ echeancier.state == 'send' ? 'Renvoyer signature' : 'Envoyer pour signature' }}</button>
</form>
{% endif %}
{% if echeancier.state == 'signed' %}
<form method="post" action="{{ path('app_admin_echeancier_activate', {id: echeancier.id}) }}" data-confirm="Activer la subscription Stripe ? Le client sera preleve automatiquement chaque mois.">
<button type="submit" class="px-4 py-2 bg-green-600 text-white font-bold uppercase text-[10px] tracking-wider hover:bg-green-700 transition-all">Activer Stripe</button>
</form>
{% endif %}
{% if echeancier.pdfSigned %}
<a href="{{ vich_uploader_asset(echeancier, 'pdfSignedFile') }}" target="_blank"
class="px-4 py-2 bg-green-500/20 text-green-700 font-bold uppercase text-[10px] tracking-wider hover:bg-green-500 hover:text-white transition-all">
PDF signe
Voir echeancier signe
</a>
{% endif %}
{% if echeancier.state in ['draft', 'send', 'signed', 'active'] %}
{% if echeancier.pdfAudit %}
<a href="{{ vich_uploader_asset(echeancier, 'pdfAuditFile') }}" target="_blank"
class="px-4 py-2 bg-blue-500/20 text-blue-700 font-bold uppercase text-[10px] tracking-wider hover:bg-blue-500 hover:text-white transition-all">
Audit de signature
</a>
{% endif %}
{% if echeancier.state in ['signed', 'pending_setup'] %}
<form method="post" action="{{ path('app_admin_echeancier_send_sepa', {id: echeancier.id}) }}" data-confirm="{{ echeancier.state == 'pending_setup' ? 'Renvoyer le lien de configuration SEPA au client ?' : 'Envoyer le lien de configuration SEPA au client ?' }}">
<button type="submit" class="px-4 py-2 bg-orange-500/20 text-orange-700 hover:bg-orange-500 hover:text-white font-bold uppercase text-[10px] tracking-wider transition-all">{{ echeancier.state == 'pending_setup' ? 'Renvoyer lien SEPA' : 'Envoyer lien SEPA' }}</button>
</form>
{% endif %}
{% if echeancier.stripePaymentMethodId and echeancier.state in ['active', 'pending_setup'] %}
<form method="post" action="{{ path('app_admin_echeancier_reset_sepa', {id: echeancier.id}) }}" data-confirm="Reinitialiser le moyen de paiement SEPA ? Le client devra reconfigurer son IBAN.">
<button type="submit" class="px-4 py-2 bg-yellow-500/20 text-yellow-700 hover:bg-yellow-500 hover:text-white font-bold uppercase text-[10px] tracking-wider transition-all">Reinitialiser SEPA</button>
</form>
{% endif %}
{% if echeancier.state not in ['draft'] %}
<form method="post" action="{{ path('app_admin_echeancier_send_attestation', {id: echeancier.id}) }}" data-confirm="Envoyer une attestation d'etat de l'echeancier au client ?">
<button type="submit" class="px-4 py-2 bg-blue-500/20 text-blue-700 hover:bg-blue-500 hover:text-white font-bold uppercase text-[10px] tracking-wider transition-all">Envoyer attestation</button>
</form>
{% endif %}
{% if echeancier.state in ['draft', 'send', 'signed', 'pending_setup', 'active'] %}
<form method="post" action="{{ path('app_admin_echeancier_cancel', {id: echeancier.id}) }}" data-confirm="Annuler cet echeancier ? La subscription Stripe sera annulee.">
<button type="submit" class="px-4 py-2 bg-red-500/20 text-red-700 hover:bg-red-500 hover:text-white font-bold uppercase text-[10px] tracking-wider transition-all">Annuler</button>
</form>
@@ -119,6 +140,7 @@
<th class="px-4 py-3 text-right font-bold uppercase text-xs tracking-widest">Montant</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Statut</th>
<th class="px-4 py-3 text-left font-bold uppercase text-xs tracking-widest">Paye le</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Actions</th>
</tr>
</thead>
<tbody>
@@ -142,14 +164,50 @@
<span class="text-red-500 ml-1">{{ line.failureReason }}</span>
{% endif %}
</td>
<td class="px-4 py-3 text-center">
{% if line.isPending and echeancier.stripePaymentMethodId and not line.stripePaymentIntentId %}
<form method="post" action="{{ path('app_admin_echeancier_force_payment', {id: echeancier.id, lineId: line.id}) }}" data-confirm="Forcer le prelevement de {{ line.amount|number_format(2, ',', ' ') }} EUR pour l'echeance {{ line.position }} ?">
<button type="submit" class="px-2 py-1 bg-orange-500/20 text-orange-700 hover:bg-orange-500 hover:text-white font-bold uppercase text-[9px] tracking-wider transition-all">Forcer</button>
</form>
{% elseif line.isFailed and echeancier.stripePaymentMethodId %}
<form method="post" action="{{ path('app_admin_echeancier_force_payment', {id: echeancier.id, lineId: line.id}) }}" data-confirm="Retenter le prelevement de {{ line.amount|number_format(2, ',', ' ') }} EUR pour l'echeance {{ line.position }} ?">
<button type="submit" class="px-2 py-1 bg-red-500/20 text-red-700 hover:bg-red-500 hover:text-white font-bold uppercase text-[9px] tracking-wider transition-all">Retenter</button>
</form>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if echeancier.stripeSubscriptionId %}
<p class="mt-3 text-[10px] text-gray-400 font-mono">Stripe Subscription: {{ echeancier.stripeSubscriptionId }}</p>
{% if echeancier.stripePaymentMethodId %}
<div class="glass p-4 mt-4">
<h3 class="text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-2">Mandat SEPA</h3>
<div class="grid grid-cols-2 md:grid-cols-4 gap-3 text-xs">
<div>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">IBAN</p>
<p class="font-mono font-bold mt-1">**** **** **** {{ echeancier.stripeSepaLast4 ?: '****' }}</p>
</div>
{% if echeancier.stripeSepaBankName %}
<div>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Code banque</p>
<p class="font-bold mt-1">{{ echeancier.stripeSepaBankName }}</p>
</div>
{% endif %}
{% if echeancier.stripeSepaCountry %}
<div>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Pays</p>
<p class="font-bold mt-1">{{ echeancier.stripeSepaCountry }}</p>
</div>
{% endif %}
<div>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Statut</p>
<p class="font-bold mt-1 text-green-600">Actif</p>
</div>
</div>
<p class="text-[10px] text-gray-400 font-mono mt-2">{{ echeancier.stripePaymentMethodId }}</p>
</div>
{% endif %}
</div>
{% endblock %}

View File

@@ -0,0 +1,168 @@
{% extends 'admin/_layout.html.twig' %}
{% block title %}E-Flex {{ eflex.reference }} - {{ customer.fullName }}{% endblock %}
{% block admin_content %}
<div class="page-container">
<div class="flex items-center justify-between mb-6">
<div>
<h1 class="text-2xl font-bold heading-page">E-Flex {{ eflex.reference }}</h1>
<p class="text-xs text-gray-400 mt-1">{{ eflex.reference }} - {{ customer.fullName }} - {{ eflex.description }}</p>
</div>
<div class="flex items-center gap-3">
{% if eflex.state == 'active' %}
<span class="px-3 py-1 bg-green-500/20 text-green-700 font-bold uppercase text-xs">Actif</span>
{% elseif eflex.state == 'completed' %}
<span class="px-3 py-1 bg-emerald-600 text-white font-bold uppercase text-xs">Termine</span>
{% elseif eflex.state == 'cancelled' %}
<span class="px-3 py-1 bg-red-500/20 text-red-700 font-bold uppercase text-xs">Annule</span>
{% elseif eflex.state == 'draft' %}
<span class="px-3 py-1 bg-yellow-100 text-yellow-800 font-bold uppercase text-xs">Brouillon</span>
{% elseif eflex.state == 'pending_setup' %}
<span class="px-3 py-1 bg-orange-500/20 text-orange-700 font-bold uppercase text-xs">En attente paiement</span>
{% else %}
<span class="px-3 py-1 bg-blue-500/20 text-blue-700 font-bold uppercase text-xs">{{ eflex.state }}</span>
{% endif %}
<a href="{{ path('app_admin_clients_show', {id: customer.id, tab: 'esyflex'}) }}" class="px-4 py-2 glass font-bold uppercase text-xs tracking-widest hover:bg-gray-900 hover:text-white transition-all">Retour</a>
</div>
</div>
{# Resume #}
<div class="grid grid-cols-2 md:grid-cols-4 gap-3 mb-6">
<div class="glass p-4 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Montant total</p>
<p class="text-xl font-bold mt-1">{{ eflex.totalAmount|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-4 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Mensualite</p>
<p class="text-xl font-bold mt-1" style="color: #fabf04;">{{ eflex.monthlyAmount|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-4 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Progression</p>
<p class="text-xl font-bold mt-1">{{ eflex.nbPaid }}/{{ eflex.nbLines }}</p>
<div class="w-full bg-gray-200 h-2 mt-2"><div class="bg-green-500 h-2" style="width: {{ eflex.progress }}%"></div></div>
</div>
<div class="glass p-4 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Methode</p>
<p class="text-sm font-bold mt-1">{{ eflex.paymentMethodLabel }}</p>
</div>
</div>
{# Description #}
<div class="glass p-5 mb-6">
<h2 class="text-sm font-bold uppercase tracking-wider mb-2">Description</h2>
<p class="text-sm text-gray-600">{{ eflex.description }}</p>
</div>
{# Actions #}
<div class="flex flex-wrap gap-2 mb-6">
{% if eflex.state == 'draft' %}
{% if eflex.pdfUnsigned %}
<form method="post" action="{{ path('app_admin_eflex_generate_pdf', {id: eflex.id}) }}" data-confirm="Regenerer le PDF ?">
<button type="submit" class="px-4 py-2 bg-yellow-500/20 text-yellow-700 hover:bg-yellow-500 hover:text-white font-bold uppercase text-[10px] tracking-wider transition-all">Regenerer PDF</button>
</form>
<a href="{{ vich_uploader_asset(eflex, 'pdfUnsignedFile') }}" target="_blank" class="px-4 py-2 bg-gray-900 text-white font-bold uppercase text-[10px] tracking-wider hover:bg-[#fabf04] hover:text-gray-900 transition-all">Voir PDF</a>
<form method="post" action="{{ path('app_admin_eflex_send_signature', {id: eflex.id}) }}" data-confirm="Envoyer le contrat E-Flex pour signature au client ?">
<button type="submit" class="px-4 py-2 bg-purple-500/20 text-purple-700 hover:bg-purple-500 hover:text-white font-bold uppercase text-[10px] tracking-wider transition-all">Envoyer pour signature</button>
</form>
{% else %}
<form method="post" action="{{ path('app_admin_eflex_generate_pdf', {id: eflex.id}) }}">
<button type="submit" class="px-4 py-2 bg-gray-900 text-white font-bold uppercase text-[10px] tracking-wider hover:bg-[#fabf04] hover:text-gray-900 transition-all">Generer PDF</button>
</form>
{% endif %}
{% endif %}
{% if eflex.pdfSigned %}
<a href="{{ vich_uploader_asset(eflex, 'pdfSignedFile') }}" target="_blank" class="px-4 py-2 bg-green-500/20 text-green-700 font-bold uppercase text-[10px] tracking-wider hover:bg-green-500 hover:text-white transition-all">Voir contrat signe</a>
{% endif %}
{% if eflex.pdfAudit %}
<a href="{{ vich_uploader_asset(eflex, 'pdfAuditFile') }}" target="_blank" class="px-4 py-2 bg-blue-500/20 text-blue-700 font-bold uppercase text-[10px] tracking-wider hover:bg-blue-500 hover:text-white transition-all">Audit signature</a>
{% endif %}
{% if eflex.state in ['draft', 'active', 'pending_setup'] %}
<form method="post" action="{{ path('app_admin_eflex_cancel', {id: eflex.id}) }}" data-confirm="Annuler ce contrat E-Flex ?">
<button type="submit" class="px-4 py-2 bg-red-500/20 text-red-700 hover:bg-red-500 hover:text-white font-bold uppercase text-[10px] tracking-wider transition-all">Annuler</button>
</form>
{% endif %}
</div>
{# SEPA info #}
{% if eflex.stripePaymentMethodId %}
<div class="glass p-4 mb-6">
<h3 class="text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-2">Mandat SEPA</h3>
<div class="grid grid-cols-2 md:grid-cols-4 gap-3 text-xs">
<div>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">IBAN</p>
<p class="font-mono font-bold mt-1">**** **** **** {{ eflex.stripeSepaLast4 ?: '****' }}</p>
</div>
{% if eflex.stripeSepaCountry %}
<div>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Pays</p>
<p class="font-bold mt-1">{{ eflex.stripeSepaCountry }}</p>
</div>
{% endif %}
<div>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Statut</p>
<p class="font-bold mt-1 text-green-600">Actif</p>
</div>
</div>
</div>
{% endif %}
{# Echeances #}
<h2 class="text-lg font-bold uppercase mb-4">Echeances</h2>
<div class="glass overflow-x-auto overflow-hidden">
<table class="w-full text-sm">
<thead>
<tr class="glass-dark text-white">
<th class="px-4 py-3 text-left font-bold uppercase text-xs tracking-widest">N</th>
<th class="px-4 py-3 text-left font-bold uppercase text-xs tracking-widest">Date prevue</th>
<th class="px-4 py-3 text-right font-bold uppercase text-xs tracking-widest">Montant</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Statut</th>
<th class="px-4 py-3 text-left font-bold uppercase text-xs tracking-widest">Paye le</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Actions</th>
</tr>
</thead>
<tbody>
{% for line in eflex.lines %}
<tr class="border-b border-white/20 hover:bg-white/50">
<td class="px-4 py-3 font-bold">{{ line.position }}</td>
<td class="px-4 py-3 text-xs">{{ line.scheduledAt|date('d/m/Y') }}</td>
<td class="px-4 py-3 text-right font-bold text-xs">{{ line.amount|number_format(2, ',', ' ') }} &euro;</td>
<td class="px-4 py-3 text-center">
{% if line.isPaid %}
<span class="px-2 py-0.5 bg-green-500/20 text-green-700 font-bold uppercase text-[10px]">Paye</span>
{% elseif line.isFailed %}
<span class="px-2 py-0.5 bg-red-500/20 text-red-700 font-bold uppercase text-[10px]">Echoue</span>
{% else %}
<span class="px-2 py-0.5 bg-yellow-100 text-yellow-800 font-bold uppercase text-[10px]">En attente</span>
{% endif %}
</td>
<td class="px-4 py-3 text-xs text-gray-500">
{{ line.paidAt ? line.paidAt|date('d/m/Y H:i') : '—' }}
{% if line.paidMethod %}<span class="text-gray-400 ml-1">({{ line.paidMethod }})</span>{% endif %}
{% if line.failureReason %}<span class="text-red-500 ml-1">{{ line.failureReason }}</span>{% endif %}
</td>
<td class="px-4 py-3 text-center">
{% if line.isPending and eflex.stripePaymentMethodId and not line.stripePaymentIntentId %}
<form method="post" action="{{ path('app_admin_eflex_force_payment', {id: eflex.id, lineId: line.id}) }}" class="inline" data-confirm="Forcer le prelevement de {{ line.amount|number_format(2, ',', ' ') }} EUR ?">
<button type="submit" class="px-2 py-1 bg-orange-500/20 text-orange-700 hover:bg-orange-500 hover:text-white font-bold uppercase text-[9px] tracking-wider transition-all">Forcer</button>
</form>
{% endif %}
{% if (line.isPending or line.isFailed) and not line.stripePaymentIntentId %}
<form method="post" action="{{ path('app_admin_eflex_manual_payment', {id: eflex.id, lineId: line.id}) }}" class="inline" data-confirm="Marquer l'echeance {{ line.position }} comme payee manuellement ?">
<select name="method" class="text-[9px] px-1 py-0.5 border">
<option value="virement">Virement</option>
<option value="cb_externe">CB externe</option>
<option value="cheque">Cheque</option>
<option value="especes">Especes</option>
</select>
<button type="submit" class="px-2 py-1 bg-green-500/20 text-green-700 hover:bg-green-500 hover:text-white font-bold uppercase text-[9px] tracking-wider transition-all">Paye</button>
</form>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}

View File

@@ -96,12 +96,47 @@
<p class="text-[10px] text-gray-400 mt-1">{{ global.factures_payees }} facture(s)</p>
</div>
<div class="glass p-4" style="border-color: rgba(220,38,38,0.3);">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Impayees</p>
<p class="text-2xl font-bold mt-1 text-red-600">{{ global.montant_impaye|number_format(2, ',', ' ') }} €</p>
<p class="text-[10px] text-gray-400 mt-1">{{ global.factures_impayees }} facture(s)</p>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Total impaye (global)</p>
<p class="text-2xl font-bold mt-1 text-red-600">{{ (global.montant_impaye + echeancierStats.montantImpaye)|number_format(2, ',', ' ') }} €</p>
<p class="text-[10px] text-gray-400 mt-1">{{ global.factures_impayees }} facture(s) + {{ echeancierStats.nbEcheancesImpayees }} echeance(s)</p>
<div class="mt-2 space-y-1">
<p class="text-[10px] text-gray-400">Factures : <span class="font-bold text-red-500">{{ global.montant_impaye|number_format(2, ',', ' ') }} €</span></p>
<p class="text-[10px] text-gray-400">Echeanciers : <span class="font-bold text-orange-500">{{ echeancierStats.montantImpaye|number_format(2, ',', ' ') }} €</span> ({{ echeancierStats.nbEcheanciers }} en cours)</p>
</div>
</div>
</div>
{# Detail echeanciers en cours #}
{% if echeancierStats.echeanciers|length > 0 %}
<h2 class="text-xl font-bold uppercase mb-4">Echeanciers en cours</h2>
<div class="glass overflow-x-auto overflow-hidden mb-8">
<table class="w-full text-sm">
<thead>
<tr class="glass-dark text-white">
<th class="px-4 py-3 text-left font-bold uppercase text-xs tracking-widest">Reference</th>
<th class="px-4 py-3 text-left font-bold uppercase text-xs tracking-widest">Client</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Echeances restantes</th>
<th class="px-4 py-3 text-right font-bold uppercase text-xs tracking-widest">Restant du</th>
<th class="px-4 py-3 text-center font-bold uppercase text-xs tracking-widest">Actions</th>
</tr>
</thead>
<tbody>
{% for ech in echeancierStats.echeanciers %}
<tr class="border-b border-white/20 hover:bg-white/50">
<td class="px-4 py-3 font-mono font-bold text-xs">{{ ech.reference }}</td>
<td class="px-4 py-3 text-xs">{{ ech.customer }}</td>
<td class="px-4 py-3 text-center font-bold text-xs text-orange-600">{{ ech.nbPending }}</td>
<td class="px-4 py-3 text-right font-mono font-bold text-xs text-red-600">{{ ech.restant|number_format(2, ',', ' ') }} €</td>
<td class="px-4 py-3 text-center">
<a href="{{ path('app_admin_echeancier_show', {id: ech.id}) }}" class="px-3 py-1 bg-gray-900 text-white hover:bg-[#fabf04] hover:text-gray-900 font-bold uppercase text-[10px] transition-all">Voir</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
{# Services #}
<h2 class="text-xl font-bold uppercase mb-4">Services</h2>

View File

@@ -0,0 +1,105 @@
{% extends 'base.html.twig' %}
{% block title %}Verification attestation - Association E-Cosplay{% endblock %}
{% block body %}
<div class="min-h-screen flex items-center justify-center p-4" style="background: linear-gradient(135deg, #f5f5f0 0%, #e8e8e0 100%);">
<div class="glass-heavy w-full max-w-2xl overflow-hidden">
<div class="glass-dark text-white px-8 py-6">
<div class="flex items-center gap-3">
<img src="/logo.jpg" alt="E-Cosplay" class="h-10 w-auto">
<div>
<h1 class="text-lg font-bold uppercase tracking-widest">Verification d'attestation</h1>
<p class="text-xs text-white/60">Association E-Cosplay</p>
</div>
</div>
</div>
<div class="p-8">
{% if valid and attestation %}
{# Attestation valide #}
<div class="glass p-4 mb-6 flex items-center gap-3" style="border-left: 4px solid #16a34a;">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-green-500 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div>
<p class="text-sm font-bold text-green-700">Attestation authentique et verifiee</p>
<p class="text-xs text-gray-500 mt-1">Ce document a ete emis par l'Association E-Cosplay et son integrite est confirmee.</p>
</div>
</div>
<div class="glass p-5 mb-6">
<h2 class="text-sm font-bold uppercase tracking-wider mb-4">{{ attestation.title }}</h2>
<p class="text-sm text-gray-600 mb-4 italic">
"Je soussigne(e), President(e) de l'Association E-Cosplay et le bureau de l'association, atteste les elements suivants :"
</p>
<div class="space-y-2 mb-4">
{% for item in attestation.items %}
<div class="flex items-start gap-3 glass p-3">
<span class="text-xs font-bold text-gray-400 mt-0.5">{{ loop.index }}.</span>
<p class="text-sm text-gray-700">{{ item }}</p>
</div>
{% endfor %}
</div>
<p class="text-sm text-gray-600 italic">
"La presente attestation est etablie pour faire valoir les droits de l'Association E-Cosplay. Les elements presentes ci-dessus sont conformes et veridiques."
</p>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-3 mb-6">
<div class="glass p-3">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Reference</p>
<p class="font-mono font-bold text-xs mt-1">{{ attestation.reference }}</p>
</div>
<div class="glass p-3">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Emise le</p>
<p class="font-bold text-xs mt-1">{{ attestation.createdAt|date('d/m/Y') }}</p>
</div>
<div class="glass p-3">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Statut</p>
{% if attestation.state == 'signed' %}
<p class="font-bold text-xs mt-1 text-green-600">Signee electroniquement</p>
{% else %}
<p class="font-bold text-xs mt-1 text-yellow-600">Brouillon</p>
{% endif %}
</div>
{% if attestation.signedAt %}
<div class="glass p-3">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Signee le</p>
<p class="font-bold text-xs mt-1">{{ attestation.signedAt|date('d/m/Y H:i') }}</p>
</div>
{% endif %}
</div>
<div class="glass p-3 mb-4">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Code HMAC d'integrite</p>
<p class="font-mono text-[10px] text-gray-500 break-all">{{ attestation.hmac }}</p>
</div>
{% else %}
{# Attestation invalide #}
<div class="glass p-4 mb-6 flex items-center gap-3" style="border-left: 4px solid #dc2626;">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-red-500 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div>
<p class="text-sm font-bold text-red-700">Attestation non valide</p>
<p class="text-xs text-gray-500 mt-1">Ce document n'a pas pu etre verifie. Il est possible qu'il ait ete falsifie ou que le lien soit incorrect.</p>
</div>
</div>
<p class="text-sm text-gray-600 mb-4">
Si vous pensez qu'il s'agit d'une erreur, veuillez contacter l'Association E-Cosplay.
</p>
{% endif %}
<p class="text-center text-xs text-gray-400 mt-6">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" class="font-bold" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</div>
</div>
</div>
{% endblock %}

View File

@@ -10,7 +10,7 @@
<img src="/logo.jpg" alt="E-Cosplay" class="h-10 w-auto">
<div>
<h1 class="text-lg font-bold uppercase tracking-widest">Echeancier de paiement</h1>
<p class="text-xs text-white/60">Association E-Cosplay</p>
<p class="text-xs text-white/60">{{ echeancier.reference }} - Association E-Cosplay</p>
</div>
</div>
</div>

View File

@@ -10,10 +10,11 @@
<path stroke-linecap="round" stroke-linejoin="round" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<h1 class="text-xl font-bold uppercase tracking-widest">Echeancier refuse</h1>
<p class="text-xs text-white/60 mt-1">{{ echeancier.reference }}</p>
</div>
<div class="p-8 text-center">
<p class="text-sm text-gray-600 mb-4">
L'echeancier de paiement a ete refuse.
L'echeancier de paiement <strong>{{ echeancier.reference }}</strong> a ete refuse.
</p>
<p class="text-xs text-gray-400">
Si vous souhaitez discuter d'autres modalites de paiement, contactez-nous a

View File

@@ -0,0 +1,38 @@
{% extends 'base.html.twig' %}
{% block title %}Paiement effectue - {{ echeancier.reference }} - Association E-Cosplay{% endblock %}
{% block body %}
<div class="min-h-screen flex items-center justify-center p-4" style="background: linear-gradient(135deg, #f5f5f0 0%, #e8e8e0 100%);">
<div class="glass-heavy w-full max-w-lg overflow-hidden">
<div class="glass-dark text-white px-8 py-6">
<div class="flex items-center gap-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div>
<h1 class="text-lg font-bold uppercase tracking-widest">Paiement effectue</h1>
<p class="text-xs text-white/60">{{ echeancier.reference }}</p>
</div>
</div>
</div>
<div class="p-8 text-center">
<p class="text-sm text-gray-600 mb-4">
Votre echeance <strong>{{ line.label }}</strong> a ete regularisee avec succes par carte bancaire.
</p>
<div class="glass p-4 mb-4 text-left">
<p class="text-xs text-gray-500"><strong>Reference :</strong> {{ echeancier.reference }}</p>
<p class="text-xs text-gray-500"><strong>Echeance :</strong> {{ line.position }}/{{ echeancier.nbLines }}</p>
<p class="text-xs text-gray-500"><strong>Montant paye :</strong> {{ line.amount|number_format(2, ',', ' ') }} &euro;</p>
</div>
<p class="text-xs text-gray-400">
Vous recevrez un email de confirmation lorsque le paiement sera traite.
</p>
<p class="text-xs text-gray-400 mt-4">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" class="font-bold" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,184 @@
{% extends 'base.html.twig' %}
{% block title %}Configuration prelevement SEPA - {{ echeancier.reference }} - Association E-Cosplay{% endblock %}
{% block body %}
<div class="min-h-screen flex items-center justify-center p-4" style="background: linear-gradient(135deg, #f5f5f0 0%, #e8e8e0 100%);">
<div class="glass-heavy w-full max-w-2xl overflow-hidden">
<div class="glass-dark text-white px-8 py-6">
<div class="flex items-center gap-3">
<img src="/logo.jpg" alt="E-Cosplay" class="h-10 w-auto">
<div>
<h1 class="text-lg font-bold uppercase tracking-widest">Prelevement SEPA</h1>
<p class="text-xs text-white/60">{{ echeancier.reference }} - Association E-Cosplay</p>
</div>
</div>
</div>
<div class="p-8">
<p class="text-sm text-gray-600 mb-6">
Pour finaliser la mise en place de votre echeancier, veuillez renseigner votre IBAN ci-dessous.
Les prelevements seront effectues automatiquement aux dates prevues.
</p>
{# Resume #}
<div class="grid grid-cols-2 md:grid-cols-3 gap-3 mb-6">
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Total a payer</p>
<p class="text-lg font-bold mt-1">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Mensualite</p>
<p class="text-lg font-bold mt-1" style="color: #fabf04;">{{ echeancier.monthlyAmount|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Echeances</p>
<p class="text-lg font-bold mt-1">{{ echeancier.nbLines }} mois</p>
</div>
</div>
{# Informations du mandat #}
<div class="glass p-4 mb-6">
<h2 class="text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-2">Informations du mandat SEPA</h2>
<div class="grid grid-cols-2 gap-2 text-xs">
<p class="text-gray-500"><strong>Crediteur :</strong> Association E-Cosplay</p>
<p class="text-gray-500"><strong>Reference :</strong> {{ echeancier.reference }}</p>
<p class="text-gray-500"><strong>Montant/echeance :</strong> {{ echeancier.monthlyAmount|number_format(2, ',', ' ') }} &euro;</p>
<p class="text-gray-500"><strong>Nombre d'echeances :</strong> {{ echeancier.nbLines }}</p>
<p class="text-gray-500"><strong>1ere echeance :</strong> {{ echeancier.lines|first ? echeancier.lines|first.scheduledAt|date('d/m/Y') : '—' }}</p>
<p class="text-gray-500"><strong>Derniere echeance :</strong> {{ echeancier.lines|last ? echeancier.lines|last.scheduledAt|date('d/m/Y') : '—' }}</p>
</div>
</div>
{# Formulaire IBAN #}
<form id="sepa-form">
<div class="mb-4">
<label for="account-name" class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Titulaire du compte</label>
<input type="text" id="account-name" required
value="{{ customer.raisonSociale ?: customer.fullName }}"
class="input-glass w-full px-4 py-3 text-sm font-bold">
</div>
<div class="mb-4">
<label for="account-email" class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Email</label>
<input type="email" id="account-email" required
value="{{ customer.email }}"
class="input-glass w-full px-4 py-3 text-sm font-bold">
</div>
<div class="mb-4">
<label class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">IBAN</label>
<div id="iban-element" class="input-glass w-full px-4 py-3"></div>
<div id="iban-errors" class="text-red-500 text-xs mt-1 hidden"></div>
</div>
{# Mandat SEPA #}
<div class="glass p-4 mb-6 text-xs text-gray-500 leading-relaxed">
<p class="font-bold text-[9px] uppercase tracking-wider text-gray-400 mb-2">Mandat de prelevement SEPA</p>
<p>En fournissant vos informations de paiement et en confirmant ce mandat, vous autorisez (A) Association E-Cosplay et Stripe, notre prestataire de paiement, a envoyer des instructions a votre banque pour debiter votre compte et (B) votre banque a debiter votre compte conformement a ces instructions.</p>
<p class="mt-2">Vous beneficiez d'un droit a remboursement par votre banque selon les conditions decrites dans la convention que vous avez conclue avec elle. Toute demande de remboursement doit etre presentee dans les 8 semaines suivant la date de debit de votre compte.</p>
</div>
<div id="form-error" class="mb-4 p-3 bg-red-500/20 text-red-700 font-bold text-xs hidden"></div>
<button type="submit" id="submit-btn"
class="w-full btn-gold px-4 py-3 font-bold uppercase text-xs tracking-wider text-gray-900 disabled:opacity-50 disabled:cursor-not-allowed">
<span id="btn-text">Autoriser le prelevement SEPA</span>
<span id="btn-loading" class="hidden">Traitement en cours...</span>
</button>
</form>
<p class="text-center text-xs text-gray-400 mt-6">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" class="font-bold" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</div>
</div>
</div>
<script src="https://js.stripe.com/v3/" nonce="{{ csp_nonce('script') }}"></script>
<script nonce="{{ csp_nonce('script') }}">
(function() {
var stripe = Stripe('{{ stripePk }}');
var elements = stripe.elements();
var style = {
base: {
color: '#111827',
fontSize: '14px',
fontFamily: 'Arial, sans-serif',
'::placeholder': { color: '#9ca3af' }
},
invalid: { color: '#dc2626' }
};
var iban = elements.create('iban', { style: style, supportedCountries: ['SEPA'] });
iban.mount('#iban-element');
var errorEl = document.getElementById('iban-errors');
iban.on('change', function(event) {
if (event.error) {
errorEl.textContent = event.error.message;
errorEl.classList.remove('hidden');
} else {
errorEl.classList.add('hidden');
}
});
var form = document.getElementById('sepa-form');
var submitBtn = document.getElementById('submit-btn');
var btnText = document.getElementById('btn-text');
var btnLoading = document.getElementById('btn-loading');
var formError = document.getElementById('form-error');
form.addEventListener('submit', function(e) {
e.preventDefault();
submitBtn.disabled = true;
btnText.classList.add('hidden');
btnLoading.classList.remove('hidden');
formError.classList.add('hidden');
var name = document.getElementById('account-name').value;
var email = document.getElementById('account-email').value;
stripe.confirmSepaDebitSetup('{{ clientSecret }}', {
payment_method: {
sepa_debit: iban,
billing_details: { name: name, email: email }
}
}).then(function(result) {
if (result.error) {
formError.textContent = result.error.message;
formError.classList.remove('hidden');
submitBtn.disabled = false;
btnText.classList.remove('hidden');
btnLoading.classList.add('hidden');
return;
}
// Envoyer le payment_method au serveur
fetch('{{ path('app_echeancier_setup_payment_confirm', {id: echeancier.id}) }}', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payment_method: result.setupIntent.payment_method })
}).then(function(res) {
return res.json();
}).then(function(data) {
if (data.status === 'ok') {
window.location.reload();
} else {
formError.textContent = data.error || 'Erreur lors de la configuration.';
formError.classList.remove('hidden');
submitBtn.disabled = false;
btnText.classList.remove('hidden');
btnLoading.classList.add('hidden');
}
}).catch(function() {
formError.textContent = 'Erreur de connexion. Veuillez reessayer.';
formError.classList.remove('hidden');
submitBtn.disabled = false;
btnText.classList.remove('hidden');
btnLoading.classList.add('hidden');
});
});
});
})();
</script>
{% endblock %}

View File

@@ -0,0 +1,112 @@
{% extends 'base.html.twig' %}
{% block title %}Mandat SEPA configure - {{ echeancier.reference }} - Association E-Cosplay{% endblock %}
{% block body %}
<div class="min-h-screen flex items-center justify-center p-4" style="background: linear-gradient(135deg, #f5f5f0 0%, #e8e8e0 100%);">
<div class="glass-heavy w-full max-w-2xl overflow-hidden">
<div class="glass-dark text-white px-8 py-6">
<div class="flex items-center gap-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div>
<h1 class="text-lg font-bold uppercase tracking-widest">Mandat SEPA configure</h1>
<p class="text-xs text-white/60">{{ echeancier.reference }} - Association E-Cosplay</p>
</div>
</div>
</div>
<div class="p-8">
<div class="glass p-4 mb-6 flex items-center gap-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-green-500 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
<div>
<p class="text-sm font-bold text-green-700">Votre mandat de prelevement SEPA est actif</p>
<p class="text-xs text-gray-500 mt-1">Les echeances seront prelevees automatiquement aux dates prevues.</p>
</div>
</div>
{# Motif #}
<div class="glass p-4 mb-6">
<h2 class="text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Motif</h2>
<p class="text-sm font-bold">{{ echeancier.description }}</p>
</div>
{# Resume #}
<div class="grid grid-cols-2 md:grid-cols-4 gap-3 mb-6">
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Creance</p>
<p class="text-lg font-bold mt-1">{{ echeancier.totalAmountHt|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Majoration 5%</p>
<p class="text-lg font-bold mt-1 text-red-500">+ {{ echeancier.majoration|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Total a payer</p>
<p class="text-lg font-bold mt-1">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</p>
<p class="text-[10px] text-gray-400">en {{ echeancier.nbLines }} mois</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Mensualite</p>
<p class="text-lg font-bold mt-1" style="color: #fabf04;">{{ echeancier.monthlyAmount|number_format(2, ',', ' ') }} &euro;</p>
</div>
</div>
{# Tableau echeances avec statut #}
<div class="glass overflow-hidden mb-6">
<table class="w-full text-sm">
<thead>
<tr class="glass-dark text-white">
<th class="px-4 py-2 text-left font-bold uppercase text-[10px] tracking-widest">N</th>
<th class="px-4 py-2 text-left font-bold uppercase text-[10px] tracking-widest">Date prevue</th>
<th class="px-4 py-2 text-right font-bold uppercase text-[10px] tracking-widest">Montant</th>
<th class="px-4 py-2 text-center font-bold uppercase text-[10px] tracking-widest">Statut</th>
</tr>
</thead>
<tbody>
{% for line in echeancier.lines %}
<tr class="border-b border-white/20 {{ loop.index is odd ? 'bg-white/30' : '' }}">
<td class="px-4 py-2 font-bold">{{ line.position }}</td>
<td class="px-4 py-2 text-xs">{{ line.scheduledAt|date('d/m/Y') }}</td>
<td class="px-4 py-2 text-right font-bold">{{ line.amount|number_format(2, ',', ' ') }} &euro;</td>
<td class="px-4 py-2 text-center">
{% if line.isPaid %}
<span class="px-2 py-0.5 bg-green-500/20 text-green-700 font-bold uppercase text-[10px]">Paye</span>
{% elseif line.isFailed %}
<span class="px-2 py-0.5 bg-red-500/20 text-red-700 font-bold uppercase text-[10px]">Echoue</span>
{% else %}
<span class="px-2 py-0.5 bg-yellow-100 text-yellow-800 font-bold uppercase text-[10px]">A prelever</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if echeancier.nbPaid > 0 %}
<div class="glass p-4 mb-6">
<div class="flex justify-between items-center mb-2">
<span class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Progression</span>
<span class="text-sm font-bold">{{ echeancier.nbPaid }}/{{ echeancier.nbLines }}</span>
</div>
<div class="w-full bg-gray-200 h-2">
<div class="bg-green-500 h-2" style="width: {{ echeancier.progress }}%"></div>
</div>
</div>
{% endif %}
<p class="text-xs text-gray-500 mb-4">
Vous recevrez un email de confirmation a chaque prelevement effectue.
</p>
<p class="text-center text-xs text-gray-400 mt-6">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" class="font-bold" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</div>
</div>
</div>
{% endblock %}

View File

@@ -4,27 +4,88 @@
{% block body %}
<div class="min-h-screen flex items-center justify-center p-4" style="background: linear-gradient(135deg, #f5f5f0 0%, #e8e8e0 100%);">
<div class="glass-heavy w-full max-w-lg overflow-hidden">
<div class="glass-dark text-white px-8 py-6 text-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 mx-auto mb-3 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<h1 class="text-xl font-bold uppercase tracking-widest">Echeancier signe</h1>
</div>
<div class="p-8 text-center">
<p class="text-sm text-gray-600 mb-4">
Merci <strong>{{ customer.firstName }}</strong>, votre echeancier de paiement a ete signe avec succes.
</p>
<div class="glass p-4 mb-4 text-left">
<p class="text-xs text-gray-500"><strong>Montant total :</strong> {{ echeancier.totalAmountHt|number_format(2, ',', ' ') }} &euro;</p>
<p class="text-xs text-gray-500"><strong>Echeances :</strong> {{ echeancier.nbLines }} x {{ echeancier.monthlyAmount|number_format(2, ',', ' ') }} &euro;/mois</p>
<p class="text-xs text-gray-500"><strong>Motif :</strong> {{ echeancier.description }}</p>
<div class="glass-heavy w-full max-w-2xl overflow-hidden">
<div class="glass-dark text-white px-8 py-6">
<div class="flex items-center gap-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div>
<h1 class="text-lg font-bold uppercase tracking-widest">Echeancier signe</h1>
<p class="text-xs text-white/60">{{ echeancier.reference }} - Association E-Cosplay</p>
</div>
</div>
<p class="text-xs text-gray-400">
Vous allez recevoir un email pour configurer les prelevements automatiques.
</div>
<div class="p-8">
<p class="text-sm text-gray-600 mb-6">
Votre echeancier de paiement a ete signe avec succes.
</p>
<p class="text-xs text-gray-400 mt-4">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" class="text-[#fabf04] font-bold">contact@e-cosplay.fr</a>
{# Motif #}
<div class="glass p-4 mb-6">
<h2 class="text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Motif</h2>
<p class="text-sm font-bold">{{ echeancier.description }}</p>
</div>
{# Resume #}
<div class="grid grid-cols-2 md:grid-cols-4 gap-3 mb-6">
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Creance</p>
<p class="text-lg font-bold mt-1">{{ echeancier.totalAmountHt|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Majoration 5%</p>
<p class="text-lg font-bold mt-1 text-red-500">+ {{ echeancier.majoration|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Total a payer</p>
<p class="text-lg font-bold mt-1">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</p>
<p class="text-[10px] text-gray-400">en {{ echeancier.nbLines }} mois</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Mensualite</p>
<p class="text-lg font-bold mt-1" style="color: #fabf04;">{{ echeancier.monthlyAmount|number_format(2, ',', ' ') }} &euro;</p>
</div>
</div>
{# Tableau echeances #}
<div class="glass overflow-hidden mb-6">
<table class="w-full text-sm">
<thead>
<tr class="glass-dark text-white">
<th class="px-4 py-2 text-left font-bold uppercase text-[10px] tracking-widest">N</th>
<th class="px-4 py-2 text-left font-bold uppercase text-[10px] tracking-widest">Date prevue</th>
<th class="px-4 py-2 text-right font-bold uppercase text-[10px] tracking-widest">Montant</th>
</tr>
</thead>
<tbody>
{% for line in echeancier.lines %}
<tr class="border-b border-white/20 {{ loop.index is odd ? 'bg-white/30' : '' }}">
<td class="px-4 py-2 font-bold">{{ line.position }}</td>
<td class="px-4 py-2 text-xs">{{ line.scheduledAt|date('d/m/Y') }}</td>
<td class="px-4 py-2 text-right font-bold">{{ line.amount|number_format(2, ',', ' ') }} &euro;</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if echeancier.stripePaymentMethodId %}
<div class="glass p-4 mb-4 flex items-center gap-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-green-500 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
<p class="text-sm font-bold text-green-700">Mandat SEPA configure - Les prelevements seront effectues automatiquement.</p>
</div>
{% else %}
<p class="text-sm text-gray-600 mb-4">
Vous allez recevoir un email pour configurer les prelevements automatiques.
</p>
{% endif %}
<p class="text-center text-xs text-gray-400 mt-6">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" class="font-bold" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</div>
</div>

View File

@@ -7,7 +7,7 @@
<div class="glass-heavy w-full max-w-md overflow-hidden">
<div class="glass-dark text-white px-8 py-6 text-center">
<h1 class="text-lg font-bold uppercase tracking-widest">Verification</h1>
<p class="text-xs text-white/60 mt-1">Un code a ete envoye a {{ customer.email }}</p>
<p class="text-xs text-white/60 mt-1">{{ echeancier.reference }} - Un code a ete envoye a {{ customer.email }}</p>
</div>
<div class="p-8">
{% if error %}

View File

@@ -0,0 +1,143 @@
{% extends 'base.html.twig' %}
{% block title %}E-Flex {{ eflex.reference }} - Association E-Cosplay{% endblock %}
{% block body %}
<div class="min-h-screen flex items-center justify-center p-4" style="background: linear-gradient(135deg, #f5f5f0 0%, #e8e8e0 100%);">
<div class="glass-heavy w-full max-w-2xl overflow-hidden">
<div class="glass-dark text-white px-8 py-6">
<div class="flex items-center gap-3">
<img src="/logo.jpg" alt="E-Cosplay" class="h-10 w-auto">
<div>
<h1 class="text-lg font-bold uppercase tracking-widest">Contrat E-Flex</h1>
<p class="text-xs text-white/60">{{ eflex.reference }} - Association E-Cosplay</p>
</div>
</div>
</div>
<div class="p-8">
<p class="text-sm text-gray-600 mb-6">
{% if customer.raisonSociale %}Chez {{ customer.raisonSociale }}{% else %}Bonjour {{ customer.firstName }}{% endif %},
voici le detail de votre contrat de financement E-Flex.
</p>
{# Description #}
<div class="glass p-4 mb-6">
<h2 class="text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Service finance</h2>
<p class="text-sm font-bold">{{ eflex.description }}</p>
</div>
{# Resume #}
<div class="grid grid-cols-2 md:grid-cols-3 gap-3 mb-6">
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Montant total</p>
<p class="text-lg font-bold mt-1">{{ eflex.totalAmount|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Mensualite</p>
<p class="text-lg font-bold mt-1" style="color: #fabf04;">{{ eflex.monthlyAmount|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Echeances</p>
<p class="text-lg font-bold mt-1">{{ eflex.nbLines }} mois</p>
</div>
</div>
{# Tableau echeances #}
<div class="glass overflow-hidden mb-6">
<table class="w-full text-sm">
<thead>
<tr class="glass-dark text-white">
<th class="px-4 py-2 text-left font-bold uppercase text-[10px] tracking-widest">N</th>
<th class="px-4 py-2 text-left font-bold uppercase text-[10px] tracking-widest">Date prevue</th>
<th class="px-4 py-2 text-right font-bold uppercase text-[10px] tracking-widest">Montant</th>
<th class="px-4 py-2 text-center font-bold uppercase text-[10px] tracking-widest">Statut</th>
</tr>
</thead>
<tbody>
{% for line in eflex.lines %}
<tr class="border-b border-white/20 {{ loop.index is odd ? 'bg-white/30' : '' }}">
<td class="px-4 py-2 font-bold">{{ line.position }}</td>
<td class="px-4 py-2 text-xs">{{ line.scheduledAt|date('d/m/Y') }}</td>
<td class="px-4 py-2 text-right font-bold">{{ line.amount|number_format(2, ',', ' ') }} &euro;</td>
<td class="px-4 py-2 text-center">
{% if line.isPaid %}
<span class="px-2 py-0.5 bg-green-500/20 text-green-700 font-bold uppercase text-[10px]">Paye</span>
{% elseif line.isFailed %}
<span class="px-2 py-0.5 bg-red-500/20 text-red-700 font-bold uppercase text-[10px]">Echoue</span>
{% else %}
<span class="px-2 py-0.5 bg-yellow-100 text-yellow-800 font-bold uppercase text-[10px]">A payer</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{# Conditions #}
<div class="text-xs text-gray-500 mb-6 space-y-1">
<p class="font-bold uppercase text-[9px] tracking-wider text-gray-400 mb-2">Conditions</p>
<p>E-Flex est une solution de financement sans frais supplementaires proposee par l'Association E-Cosplay.</p>
<p>Les prelevements seront effectues automatiquement a chaque date prevue.</p>
</div>
{# Boutons signer / refuser (si pas encore signe) #}
{% if eflex.submissionId and eflex.state == 'draft' %}
<div class="flex justify-center gap-4 mb-6">
<a href="{{ path('app_eflex_sign', {id: eflex.id}) }}"
class="px-6 py-3 bg-green-600 text-white font-bold uppercase text-xs tracking-wider hover:bg-green-700 transition-all">
Signer le contrat
</a>
</div>
{% endif %}
{# Boutons paiement (si actif ou pending_setup) #}
{% if eflex.state in ['active', 'pending_setup'] %}
<div class="flex justify-center gap-4 mb-6">
{% if eflex.paymentMethod == 'sepa' and not eflex.stripePaymentMethodId %}
<a href="{{ path('app_eflex_setup_payment', {id: eflex.id}) }}"
class="px-6 py-3 bg-green-600 text-white font-bold uppercase text-xs tracking-wider hover:bg-green-700 transition-all">
Configurer le prelevement SEPA
</a>
{% endif %}
{% for line in eflex.lines %}
{% if line.isPending or line.isFailed %}
<a href="{{ path('app_eflex_pay', {id: eflex.id, lineId: line.id}) }}"
class="px-4 py-2 bg-gray-900 text-white font-bold uppercase text-[10px] tracking-wider hover:bg-[#fabf04] hover:text-gray-900 transition-all">
Payer echeance {{ line.position }} ({{ line.amount|number_format(2, ',', ' ') }} &euro;)
</a>
{% endif %}
{% endfor %}
</div>
{% endif %}
{# SEPA configure #}
{% if eflex.stripePaymentMethodId %}
<div class="glass p-4 mb-6 flex items-center gap-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-green-500 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
<p class="text-sm font-bold text-green-700">Prelevement SEPA configure - IBAN **** {{ eflex.stripeSepaLast4 ?: '****' }}</p>
</div>
{% endif %}
{% if eflex.nbPaid > 0 %}
<div class="glass p-4 mb-6">
<div class="flex justify-between items-center mb-2">
<span class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Progression</span>
<span class="text-sm font-bold">{{ eflex.nbPaid }}/{{ eflex.nbLines }}</span>
</div>
<div class="w-full bg-gray-200 h-2">
<div class="bg-green-500 h-2" style="width: {{ eflex.progress }}%"></div>
</div>
</div>
{% endif %}
<p class="text-center text-xs text-gray-400 mt-6">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" class="font-bold" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,116 @@
{% extends 'base.html.twig' %}
{% block title %}Configuration prelevement SEPA - {{ eflex.reference }} - Association E-Cosplay{% endblock %}
{% block body %}
<div class="min-h-screen flex items-center justify-center p-4" style="background: linear-gradient(135deg, #f5f5f0 0%, #e8e8e0 100%);">
<div class="glass-heavy w-full max-w-2xl overflow-hidden">
<div class="glass-dark text-white px-8 py-6">
<div class="flex items-center gap-3">
<img src="/logo.jpg" alt="E-Cosplay" class="h-10 w-auto">
<div>
<h1 class="text-lg font-bold uppercase tracking-widest">Prelevement SEPA - E-Flex</h1>
<p class="text-xs text-white/60">{{ eflex.reference }}</p>
</div>
</div>
</div>
<div class="p-8">
<p class="text-sm text-gray-600 mb-6">Renseignez votre IBAN pour activer les prelevements automatiques.</p>
<div class="grid grid-cols-3 gap-3 mb-6">
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Total</p>
<p class="text-lg font-bold mt-1">{{ eflex.totalAmount|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Mensualite</p>
<p class="text-lg font-bold mt-1" style="color: #fabf04;">{{ eflex.monthlyAmount|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Echeances</p>
<p class="text-lg font-bold mt-1">{{ eflex.nbLines }} mois</p>
</div>
</div>
<form id="sepa-form">
<div class="mb-4">
<label for="account-name" class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Titulaire du compte</label>
<input type="text" id="account-name" required value="{{ customer.raisonSociale ?: customer.fullName }}" class="input-glass w-full px-4 py-3 text-sm font-bold">
</div>
<div class="mb-4">
<label for="account-email" class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Email</label>
<input type="email" id="account-email" required value="{{ customer.email }}" class="input-glass w-full px-4 py-3 text-sm font-bold">
</div>
<div class="mb-4">
<label class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">IBAN</label>
<div id="iban-element" class="input-glass w-full px-4 py-3"></div>
<div id="iban-errors" class="text-red-500 text-xs mt-1 hidden"></div>
</div>
<div class="glass p-4 mb-6 text-xs text-gray-500 leading-relaxed">
<p class="font-bold text-[9px] uppercase tracking-wider text-gray-400 mb-2">Mandat de prelevement SEPA</p>
<p>En fournissant vos informations de paiement et en confirmant ce mandat, vous autorisez (A) Association E-Cosplay et Stripe, notre prestataire de paiement, a envoyer des instructions a votre banque pour debiter votre compte et (B) votre banque a debiter votre compte conformement a ces instructions.</p>
</div>
<div id="form-error" class="mb-4 p-3 bg-red-500/20 text-red-700 font-bold text-xs hidden"></div>
<button type="submit" id="submit-btn" class="w-full btn-gold px-4 py-3 font-bold uppercase text-xs tracking-wider text-gray-900 disabled:opacity-50 disabled:cursor-not-allowed">
<span id="btn-text">Autoriser le prelevement SEPA</span>
<span id="btn-loading" class="hidden">Traitement en cours...</span>
</button>
</form>
<p class="text-center text-xs text-gray-400 mt-6">Pour toute question : <a href="mailto:contact@e-cosplay.fr" class="font-bold" style="color: #fabf04;">contact@e-cosplay.fr</a></p>
</div>
</div>
</div>
<script src="https://js.stripe.com/v3/" nonce="{{ csp_nonce('script') }}"></script>
<script nonce="{{ csp_nonce('script') }}">
(function() {
var stripe = Stripe('{{ stripePk }}');
var elements = stripe.elements();
var style = { base: { color: '#111827', fontSize: '14px', fontFamily: 'Arial, sans-serif', '::placeholder': { color: '#9ca3af' } }, invalid: { color: '#dc2626' } };
var iban = elements.create('iban', { style: style, supportedCountries: ['SEPA'] });
iban.mount('#iban-element');
var errorEl = document.getElementById('iban-errors');
iban.on('change', function(event) {
if (event.error) { errorEl.textContent = event.error.message; errorEl.classList.remove('hidden'); }
else { errorEl.classList.add('hidden'); }
});
var form = document.getElementById('sepa-form');
var submitBtn = document.getElementById('submit-btn');
var btnText = document.getElementById('btn-text');
var btnLoading = document.getElementById('btn-loading');
var formError = document.getElementById('form-error');
form.addEventListener('submit', function(e) {
e.preventDefault();
submitBtn.disabled = true;
btnText.classList.add('hidden');
btnLoading.classList.remove('hidden');
formError.classList.add('hidden');
stripe.confirmSepaDebitSetup('{{ clientSecret }}', {
payment_method: { sepa_debit: iban, billing_details: { name: document.getElementById('account-name').value, email: document.getElementById('account-email').value } }
}).then(function(result) {
if (result.error) {
formError.textContent = result.error.message; formError.classList.remove('hidden');
submitBtn.disabled = false; btnText.classList.remove('hidden'); btnLoading.classList.add('hidden');
return;
}
fetch('{{ path('app_eflex_setup_payment_confirm', {id: eflex.id}) }}', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payment_method: result.setupIntent.payment_method })
}).then(function(res) { return res.json(); }).then(function(data) {
if (data.status === 'ok') { window.location.reload(); }
else { formError.textContent = data.error || 'Erreur.'; formError.classList.remove('hidden'); submitBtn.disabled = false; btnText.classList.remove('hidden'); btnLoading.classList.add('hidden'); }
}).catch(function() { formError.textContent = 'Erreur de connexion.'; formError.classList.remove('hidden'); submitBtn.disabled = false; btnText.classList.remove('hidden'); btnLoading.classList.add('hidden'); });
});
});
})();
</script>
{% endblock %}

View File

@@ -0,0 +1,82 @@
{% extends 'base.html.twig' %}
{% block title %}SEPA configure - {{ eflex.reference }} - Association E-Cosplay{% endblock %}
{% block body %}
<div class="min-h-screen flex items-center justify-center p-4" style="background: linear-gradient(135deg, #f5f5f0 0%, #e8e8e0 100%);">
<div class="glass-heavy w-full max-w-2xl overflow-hidden">
<div class="glass-dark text-white px-8 py-6">
<div class="flex items-center gap-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div>
<h1 class="text-lg font-bold uppercase tracking-widest">Mandat SEPA configure</h1>
<p class="text-xs text-white/60">{{ eflex.reference }}</p>
</div>
</div>
</div>
<div class="p-8">
<div class="glass p-4 mb-6 flex items-center gap-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-green-500 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
<div>
<p class="text-sm font-bold text-green-700">Prelevement SEPA actif</p>
<p class="text-xs text-gray-500 mt-1">IBAN **** {{ eflex.stripeSepaLast4 ?: '****' }} - Les echeances seront prelevees automatiquement.</p>
</div>
</div>
<div class="grid grid-cols-3 gap-3 mb-6">
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Total</p>
<p class="text-lg font-bold mt-1">{{ eflex.totalAmount|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Mensualite</p>
<p class="text-lg font-bold mt-1" style="color: #fabf04;">{{ eflex.monthlyAmount|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Progression</p>
<p class="text-lg font-bold mt-1">{{ eflex.nbPaid }}/{{ eflex.nbLines }}</p>
</div>
</div>
{# Tableau echeances avec statut #}
<div class="glass overflow-hidden mb-6">
<table class="w-full text-sm">
<thead>
<tr class="glass-dark text-white">
<th class="px-4 py-2 text-left font-bold uppercase text-[10px] tracking-widest">N</th>
<th class="px-4 py-2 text-left font-bold uppercase text-[10px] tracking-widest">Date</th>
<th class="px-4 py-2 text-right font-bold uppercase text-[10px] tracking-widest">Montant</th>
<th class="px-4 py-2 text-center font-bold uppercase text-[10px] tracking-widest">Statut</th>
</tr>
</thead>
<tbody>
{% for line in eflex.lines %}
<tr class="border-b border-white/20 {{ loop.index is odd ? 'bg-white/30' : '' }}">
<td class="px-4 py-2 font-bold">{{ line.position }}</td>
<td class="px-4 py-2 text-xs">{{ line.scheduledAt|date('d/m/Y') }}</td>
<td class="px-4 py-2 text-right font-bold">{{ line.amount|number_format(2, ',', ' ') }} &euro;</td>
<td class="px-4 py-2 text-center">
{% if line.isPaid %}
<span class="px-2 py-0.5 bg-green-500/20 text-green-700 font-bold uppercase text-[10px]">Paye</span>
{% elseif line.isFailed %}
<span class="px-2 py-0.5 bg-red-500/20 text-red-700 font-bold uppercase text-[10px]">Echoue</span>
{% else %}
<span class="px-2 py-0.5 bg-yellow-100 text-yellow-800 font-bold uppercase text-[10px]">A prelever</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<p class="text-center text-xs text-gray-400 mt-6">Pour toute question : <a href="mailto:contact@e-cosplay.fr" class="font-bold" style="color: #fabf04;">contact@e-cosplay.fr</a></p>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,34 @@
{% extends 'base.html.twig' %}
{% block title %}E-Flex signe - {{ eflex.reference }} - Association E-Cosplay{% endblock %}
{% block body %}
<div class="min-h-screen flex items-center justify-center p-4" style="background: linear-gradient(135deg, #f5f5f0 0%, #e8e8e0 100%);">
<div class="glass-heavy w-full max-w-lg overflow-hidden">
<div class="glass-dark text-white px-8 py-6">
<div class="flex items-center gap-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div>
<h1 class="text-lg font-bold uppercase tracking-widest">E-Flex signe</h1>
<p class="text-xs text-white/60">{{ eflex.reference }}</p>
</div>
</div>
</div>
<div class="p-8 text-center">
<p class="text-sm text-gray-600 mb-4">
Votre contrat E-Flex a ete signe avec succes. Vous allez recevoir un email pour configurer vos paiements.
</p>
<div class="glass p-4 mb-4 text-left">
<p class="text-xs text-gray-500"><strong>Montant total :</strong> {{ eflex.totalAmount|number_format(2, ',', ' ') }} &euro;</p>
<p class="text-xs text-gray-500"><strong>Echeances :</strong> {{ eflex.nbLines }} x {{ eflex.monthlyAmount|number_format(2, ',', ' ') }} &euro;/mois</p>
<p class="text-xs text-gray-500"><strong>Methode :</strong> {{ eflex.paymentMethodLabel }}</p>
</div>
<p class="text-xs text-gray-400 mt-4">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" class="font-bold" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,32 @@
{% extends 'base.html.twig' %}
{% block title %}Verification - E-Flex {{ eflex.reference }} - Association E-Cosplay{% endblock %}
{% block body %}
<div class="min-h-screen flex items-center justify-center p-4" style="background: linear-gradient(135deg, #f5f5f0 0%, #e8e8e0 100%);">
<div class="glass-heavy w-full max-w-md overflow-hidden">
<div class="glass-dark text-white px-8 py-6 text-center">
<h1 class="text-lg font-bold uppercase tracking-widest">Verification</h1>
<p class="text-xs text-white/60 mt-1">{{ eflex.reference }} - Un code a ete envoye a {{ customer.email }}</p>
</div>
<div class="p-8">
{% if error %}
<div class="mb-4 p-3 bg-red-500/20 text-red-700 font-bold text-xs">{{ error }}</div>
{% endif %}
<p class="text-sm text-gray-600 mb-4">Saisissez le code de verification a 6 chiffres recu par email.</p>
<form method="post" action="{{ path('app_eflex_verify', {id: eflex.id}) }}">
<div class="mb-4">
<label for="code" class="block text-[9px] font-bold uppercase tracking-wider text-gray-400 mb-1">Code de verification</label>
<input type="text" id="code" name="code" maxlength="6" pattern="[0-9]{6}" required autofocus
class="input-glass w-full px-4 py-3 text-center text-2xl font-bold tracking-[0.5em]" placeholder="000000">
</div>
<button type="submit" class="w-full btn-gold px-4 py-3 font-bold uppercase text-xs tracking-wider text-gray-900">Verifier</button>
</form>
<p class="text-center text-xs text-gray-400 mt-4">Le code expire dans 15 minutes.</p>
<form method="post" action="{{ path('app_eflex_resend_code', {id: eflex.id}) }}" class="mt-3 text-center">
<button type="submit" class="text-xs font-bold uppercase tracking-wider text-gray-500 hover:text-gray-900 underline transition-all">Renvoyer le code</button>
</form>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,48 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<div style="background: #7f1d1d; color: #fff; padding: 16px; margin: 0 0 20px;">
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: 700; margin: 0;">
Notification de cloture definitive de votre compte
</p>
</div>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Malgre les avertissements qui vous ont ete adresses et en l'absence de changement de votre part, le bureau de l'Association E-Cosplay, reuni a huis clos, a decide d'effectuer la procedure de cloture definitive de votre compte.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 700; color: #dc2626; line-height: 22px; margin: 0 0 12px;">
Les mesures suivantes seront appliquees :
</p>
<ul style="font-family: Arial, Helvetica, sans-serif; font-size: 13px; color: #374151; line-height: 22px; margin: 0 0 16px; padding-left: 20px;">
<li style="margin-bottom: 8px;">La <strong>totalite de vos services</strong> (sites internet, emails, noms de domaine) seront <strong>supprimes et detruits dans un delai de 24 heures</strong>, sans possibilite de recuperation.</li>
<li style="margin-bottom: 8px;">Un <strong>depot aupres d'une societe de recouvrement</strong> sera effectue pour les factures restant dues.</li>
<li style="margin-bottom: 8px;">Une <strong>mise en demeure sera deposee aupres d'un commissaire de justice</strong>.</li>
<li style="margin-bottom: 8px;">En cas de manque de respect ou d'insultes constatees, un <strong>depot aupres des forces de l'ordre</strong> sera effectue.</li>
<li style="margin-bottom: 8px;">L'ensemble de vos donnees sera supprime conformement au RGPD.</li>
</ul>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 700; color: #dc2626; line-height: 22px; margin: 16px 0;">
Cette decision est definitive et irrevocable.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 20px 0 0;">
Toute contestation devra etre adressee a <a href="mailto:direction@e-cosplay.fr" style="color: #fabf04; font-weight: 700;">direction@e-cosplay.fr</a> dans un delai de 24 heures.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 10px; color: #d1d5db; margin: 16px 0 0;">
Le present document constitue une notification officielle de cloture de compte. Il fait foi en cas de litige.<br>
Toutes les decisions sont prises par le bureau de l'association a huis clos.<br>
Le PDF signe electroniquement est joint a ce courrier.
</p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,98 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
{% if level == '1st' %}
<div style="background: #fef3c7; border-left: 4px solid #f59e0b; padding: 16px; margin: 0 0 20px;">
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 700; color: #92400e; margin: 0;">
1er avertissement
</p>
</div>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Nous constatons des manquements sur votre compte. Nous vous invitons a regulariser votre situation dans les meilleurs delais.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
<strong>En cas de repetition, un 2eme avertissement sera decide et pourra entrainer la suspension de vos services.</strong>
</p>
{% elseif level == '2nd' %}
<div style="background: #fff7ed; border-left: 4px solid #ea580c; padding: 16px; margin: 0 0 20px;">
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 700; color: #9a3412; margin: 0;">
2eme avertissement - Procedure de suspension engagee
</p>
</div>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Malgre notre precedent avertissement, nous constatons que votre situation n'a pas ete regularisee.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #ea580c; line-height: 22px; margin: 0 0 16px; font-weight: 700;">
Ceci est votre 2eme avertissement. Nous vous informons que la procedure de suspension a ete preparee :
</p>
<ul style="font-family: Arial, Helvetica, sans-serif; font-size: 13px; color: #374151; line-height: 22px; margin: 0 0 16px; padding-left: 20px;">
<li style="margin-bottom: 8px;">La <strong>resiliation de vos services</strong> (sites internet, emails, noms de domaine) a ete preparee</li>
<li style="margin-bottom: 8px;">La <strong>fermeture de votre compte</strong> a ete programmee</li>
<li style="margin-bottom: 8px;">Ces mesures seront <strong>effectives au prochain avertissement</strong> en l'absence de regularisation</li>
</ul>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Nous vous invitons a regulariser votre situation dans les plus brefs delais afin d'eviter la suspension definitive de vos services.
</p>
{% elseif level == 'last' %}
<div style="background: #fef2f2; border-left: 4px solid #dc2626; padding: 16px; margin: 0 0 20px;">
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 700; color: #991b1b; margin: 0;">
Dernier avertissement avant suspension
</p>
</div>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Malgre nos precedents avertissements, votre situation n'a toujours pas ete regularisee.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #dc2626; line-height: 22px; margin: 0 0 16px; font-weight: 700;">
Ceci est votre dernier avertissement. Sans regularisation sous 48 heures, nous procederons a la suspension immediate de votre compte et de l'ensemble de vos services (sites internet, emails, noms de domaine).
</p>
{% endif %}
{% if reasons is defined and reasons|length > 0 %}
{% set reasonLabels = {
'impayes': 'Impayes et/ou rejets de prelevement',
'irrespect': 'Manque de respect et/ou insultes envers notre equipe',
'hors_horaires': 'Appels repetes hors des heures d\'ouverture avec refus de payer le service hors horaire',
'gratuit': 'Exigence de services gratuits non prevus dans votre contrat'
} %}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 13px; font-weight: 700; color: #374151; margin: 16px 0 8px;">Motifs constates :</p>
<ul style="font-family: Arial, Helvetica, sans-serif; font-size: 13px; color: #374151; line-height: 22px; margin: 0 0 16px; padding-left: 20px;">
{% for reason in reasons %}
<li style="margin-bottom: 6px;">{{ reasonLabels[reason] ?? reason }}</li>
{% endfor %}
</ul>
{% endif %}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 16px 0;">
Nous vous invitons a regulariser votre situation dans les meilleurs delais ou a contacter notre service pour trouver une solution.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 20px 0 0;">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" style="color: #fabf04; font-weight: 700;">contact@e-cosplay.fr</a>
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 10px; color: #d1d5db; margin: 16px 0 0;">
Ce message est un avertissement officiel de l'Association E-Cosplay. Il fait foi en cas de litige.<br>
Toutes les decisions relatives aux avertissements sont prises par le bureau de l'association a huis clos.<br>
Toute contestation devra etre adressee a <a href="mailto:direction@e-cosplay.fr" style="color: #d1d5db;">direction@e-cosplay.fr</a>
</p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,30 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<div style="background: #f0fdf4; border-left: 4px solid #16a34a; padding: 16px; margin: 0 0 20px;">
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 700; color: #166534; margin: 0;">
Situation regularisee
</p>
</div>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Nous vous confirmons que votre situation a ete regularisee. Les avertissements precedemment emis ont ete leves.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Vos services restent actifs et votre compte est en regle. Nous vous remercions pour votre regularisation.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 20px 0 0;">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" style="color: #fabf04; font-weight: 700;">contact@e-cosplay.fr</a>
</p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,103 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Veuillez trouver ci-dessous l'attestation de situation de votre echeancier <strong>{{ echeancier.reference }}</strong>.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 35%;">Reference</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ echeancier.reference }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Motif</td>
<td style="padding: 10px 16px; font-size: 13px;">{{ echeancier.description }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Statut</td>
<td style="padding: 10px 16px; font-size: 13px; font-weight: 700;">
{% if echeancier.state == 'completed' %}
<span style="color: #16a34a;">Termine</span>
{% elseif echeancier.state == 'active' %}
<span style="color: #2563eb;">Actif</span>
{% elseif echeancier.state == 'cancelled' %}
<span style="color: #dc2626;">Annule</span>
{% else %}
{{ echeancier.state }}
{% endif %}
</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Creance initiale</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 13px;">{{ echeancier.totalAmountHt|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Majoration (5%)</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 13px; color: #dc2626;">+ {{ echeancier.majoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total a payer</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700;">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Deja paye</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700; color: #16a34a;">{{ echeancier.totalPaid|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Restant du</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 16px; font-weight: 700; color: {{ remaining > 0 ? '#dc2626' : '#16a34a' }};">{{ remaining|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Progression</td>
<td style="padding: 10px 16px; font-size: 13px; font-weight: 700;">{{ echeancier.nbPaid }}/{{ echeancier.nbLines }} echeances payees ({{ echeancier.progress }}%)</td>
</tr>
{% if echeancier.stripeSepaLast4 %}
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">RIB (IBAN)</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 13px;">**** **** **** {{ echeancier.stripeSepaLast4 }}{% if echeancier.stripeSepaCountry %} ({{ echeancier.stripeSepaCountry }}){% endif %}</td>
</tr>
{% endif %}
</table>
<h2 style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 700; color: #111827; margin: 20px 0 10px;">Detail des echeances :</h2>
<table width="100%" cellpadding="0" cellspacing="0" style="border: 1px solid #e5e7eb;">
<tr>
<th style="padding: 8px 12px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #fff; background: #111827; text-align: left;">N</th>
<th style="padding: 8px 12px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #fff; background: #111827; text-align: left;">Date</th>
<th style="padding: 8px 12px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #fff; background: #111827; text-align: right;">Montant</th>
<th style="padding: 8px 12px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #fff; background: #111827; text-align: center;">Statut</th>
</tr>
{% for line in echeancier.lines %}
<tr style="background: {{ loop.index is odd ? '#f9fafb' : '#fff' }};">
<td style="padding: 8px 12px; font-size: 12px;">{{ line.position }}</td>
<td style="padding: 8px 12px; font-size: 12px;">{{ line.scheduledAt|date('d/m/Y') }}</td>
<td style="padding: 8px 12px; font-size: 12px; font-weight: 700; text-align: right;">{{ line.amount|number_format(2, ',', ' ') }} &euro;</td>
<td style="padding: 8px 12px; font-size: 12px; text-align: center;">
{% if line.isPaid %}
<span style="color: #16a34a; font-weight: 700;">Paye{{ line.paidAt ? ' le ' ~ line.paidAt|date('d/m/Y') : '' }}</span>
{% elseif line.isFailed %}
<span style="color: #dc2626; font-weight: 700;">Echoue</span>
{% else %}
<span style="color: #d97706;">En attente</span>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 20px 0 0;">
Attestation emise le {{ "now"|date('d/m/Y') }} par Association E-Cosplay.<br>
Pour toute question : <a href="mailto:contact@e-cosplay.fr" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,41 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
<div style="background: #dc2626; color: #fff; padding: 12px 20px; display: inline-block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 16px;">Subscription annulee</div>
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 20px; font-weight: 700; color: #111827; margin: 0 0 12px;">Echeancier {{ echeancier.reference }} annule via Stripe</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 13px; color: #374151; line-height: 20px; margin: 0 0 16px;">
La subscription Stripe a ete annulee (manuellement ou automatiquement). L'echeancier a ete passe en statut <strong>Annule</strong>.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 40%;">Reference</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ echeancier.reference }}</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Client</td>
<td style="padding: 12px 16px; font-family: Arial; font-size: 13px;">{{ customer.fullName }}{% if customer.email %}<br><span style="color: #9ca3af; font-size: 11px;">{{ customer.email }}</span>{% endif %}</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 14px; font-weight: 700;">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Deja paye</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 13px; color: #16a34a;">{{ echeancier.totalPaid|number_format(2, ',', ' ') }} &euro; ({{ echeancier.nbPaid }}/{{ echeancier.nbLines }})</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Stripe ID</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 11px; color: #9ca3af;">{{ echeancier.stripeSubscriptionId }}</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Annule le</td>
<td style="padding: 12px 16px; font-family: Arial; font-size: 13px;">{{ "now"|date('d/m/Y H:i') }}</td>
</tr>
</table>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,51 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Votre echeancier de paiement <strong>{{ echeancier.reference }}</strong> a ete annule. Les prelevements automatiques ont ete desactives.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 35%;">Reference</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ echeancier.reference }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Motif</td>
<td style="padding: 10px 16px; font-size: 13px; font-weight: 700;">{{ echeancier.description }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700;">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Deja paye</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700; color: #16a34a;">{{ echeancier.totalPaid|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Progression</td>
<td style="padding: 10px 16px; font-size: 13px; font-weight: 700;">{{ echeancier.nbPaid }}/{{ echeancier.nbLines }} echeances payees</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Statut</td>
<td style="padding: 10px 16px; font-size: 13px; font-weight: 700; color: #dc2626;">Annule</td>
</tr>
</table>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 16px 0;">
Si cette annulation n'est pas de votre fait, veuillez nous contacter immediatement.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 16px 0 0;">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,38 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
<div style="background: #dc2626; color: #fff; padding: 12px 20px; display: inline-block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 16px;">Echeancier annule - 2 rejets</div>
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 20px; font-weight: 700; color: #111827; margin: 0 0 12px;">{{ echeancier.reference }} - {{ customer.fullName }}</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 13px; color: #374151; line-height: 20px; margin: 0 0 16px;">
L'echeancier a ete automatiquement annule apres 2 rejets de prelevement SEPA.
{% if echeancier.advert %}L'avis {{ echeancier.advert.orderNumber.numOrder }} est concerne.{% endif %}
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr>
<td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 40%;">Client</td>
<td style="padding: 12px 16px; font-size: 13px;">{{ customer.fullName }}{% if customer.email %}<br><span style="color: #9ca3af; font-size: 11px;">{{ customer.email }}</span>{% endif %}</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 14px; font-weight: 700;">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Deja paye</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 13px; color: #16a34a;">{{ echeancier.totalPaid|number_format(2, ',', ' ') }} &euro; ({{ echeancier.nbPaid }}/{{ echeancier.nbLines }})</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Restant du</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 14px; font-weight: 700; color: #dc2626;">{{ (echeancier.totalWithMajoration - echeancier.totalPaid)|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Rejets</td>
<td style="padding: 12px 16px; font-size: 13px; font-weight: 700; color: #dc2626;">{{ echeancier.nbFailed }} echecs</td>
</tr>
</table>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,53 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<div style="background: #fef2f2; border: 1px solid #fecaca; padding: 16px; margin: 0 0 20px;">
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 700; color: #dc2626; margin: 0;">
Echeancier {{ echeancier.reference }} annule suite a des rejets de prelevement
</p>
</div>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Votre echeancier de paiement a ete annule en raison de rejets repetes de prelevement SEPA. Le solde restant reste du.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 35%;">Reference</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ echeancier.reference }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total echeancier</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700;">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Deja paye</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700; color: #16a34a;">{{ echeancier.totalPaid|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Restant du</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 16px; font-weight: 700; color: #dc2626;">{{ (echeancier.totalWithMajoration - echeancier.totalPaid)|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Echeances payees</td>
<td style="padding: 10px 16px; font-size: 13px;">{{ echeancier.nbPaid }}/{{ echeancier.nbLines }}</td>
</tr>
</table>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 16px 0;">
Veuillez contacter notre service pour regulariser votre situation dans les plus brefs delais.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 16px 0 0;">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,40 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
<div style="background: #16a34a; color: #fff; padding: 12px 20px; display: inline-block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 16px;">Echeancier termine</div>
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 20px; font-weight: 700; color: #111827; margin: 0 0 12px;">{{ echeancier.reference }} - {{ customer.fullName }}</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 13px; color: #374151; line-height: 20px; margin: 0 0 16px;">
Toutes les echeances ont ete payees. L'echeancier est termine.
{% if echeancier.advert %}L'avis {{ echeancier.advert.orderNumber.numOrder }} a ete passe en accepte.{% endif %}
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr>
<td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 40%;">Reference</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ echeancier.reference }}</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Client</td>
<td style="padding: 12px 16px; font-size: 13px;">{{ customer.fullName }}</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total paye</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 14px; font-weight: 700; color: #16a34a;">{{ echeancier.totalPaid|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Echeances</td>
<td style="padding: 12px 16px; font-size: 13px; font-weight: 700;">{{ echeancier.nbPaid }}/{{ echeancier.nbLines }}</td>
</tr>
{% if echeancier.advert %}
<tr>
<td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Avis lie</td>
<td style="padding: 12px 16px; font-size: 13px; font-weight: 700;">{{ echeancier.advert.orderNumber.numOrder }}</td>
</tr>
{% endif %}
</table>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,76 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<div style="background: #f0fdf4; border: 1px solid #bbf7d0; padding: 16px; margin: 0 0 20px;">
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: 700; color: #16a34a; margin: 0;">
Echeancier {{ echeancier.reference }} - Paiement termine
</p>
</div>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Nous vous confirmons que l'integralite de votre echeancier de paiement a ete reglee. Voici l'attestation de fin de paiement :
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 35%;">Reference</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ echeancier.reference }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Motif</td>
<td style="padding: 10px 16px; font-size: 13px;">{{ echeancier.description }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Creance initiale</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 13px;">{{ echeancier.totalAmountHt|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Majoration (5%)</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 13px; color: #dc2626;">+ {{ echeancier.majoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total paye</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 16px; font-weight: 700; color: #16a34a;">{{ echeancier.totalPaid|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Echeances</td>
<td style="padding: 10px 16px; font-size: 13px; font-weight: 700; color: #16a34a;">{{ echeancier.nbPaid }}/{{ echeancier.nbLines }} payees</td>
</tr>
</table>
<h2 style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 700; color: #111827; margin: 20px 0 10px;">Detail des echeances :</h2>
<table width="100%" cellpadding="0" cellspacing="0" style="border: 1px solid #e5e7eb;">
<tr>
<th style="padding: 8px 12px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #fff; background: #111827; text-align: left;">N</th>
<th style="padding: 8px 12px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #fff; background: #111827; text-align: left;">Date</th>
<th style="padding: 8px 12px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #fff; background: #111827; text-align: right;">Montant</th>
<th style="padding: 8px 12px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #fff; background: #111827; text-align: center;">Statut</th>
</tr>
{% for line in echeancier.lines %}
<tr style="background: {{ loop.index is odd ? '#f9fafb' : '#fff' }};">
<td style="padding: 8px 12px; font-size: 12px;">{{ line.position }}</td>
<td style="padding: 8px 12px; font-size: 12px;">{{ line.paidAt ? line.paidAt|date('d/m/Y') : line.scheduledAt|date('d/m/Y') }}</td>
<td style="padding: 8px 12px; font-size: 12px; font-weight: 700; text-align: right;">{{ line.amount|number_format(2, ',', ' ') }} &euro;</td>
<td style="padding: 8px 12px; font-size: 12px; text-align: center; color: #16a34a; font-weight: 700;">Paye</td>
</tr>
{% endfor %}
</table>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 20px 0;">
Ce document fait office d'attestation de fin de paiement pour l'echeancier {{ echeancier.reference }}.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 16px 0 0;">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -8,7 +8,7 @@
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Le prelevement de votre echeance <strong>{{ line.position }}/{{ echeancier.nbLines }}</strong> a echoue.
Le prelevement de votre echeance <strong>{{ line.position }}/{{ echeancier.nbLines }}</strong> de l'echeancier <strong>{{ echeancier.reference }}</strong> a echoue.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
@@ -30,9 +30,22 @@
</tr>
</table>
{% if regularizeUrl is defined and regularizeUrl %}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Vous pouvez regulariser cette echeance immediatement par carte bancaire en cliquant sur le bouton ci-dessous :
</p>
<table cellpadding="0" cellspacing="0" style="margin: 24px auto;">
<tr>
<td style="background-color: #fabf04; padding: 14px 32px;">
<a href="{{ regularizeUrl }}" style="font-family: Arial, Helvetica, sans-serif; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #111827; text-decoration: none;">Regulariser par carte bancaire</a>
</td>
</tr>
</table>
{% endif %}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Veuillez verifier votre moyen de paiement et contacter notre service si le probleme persiste.
Une nouvelle tentative de prelevement sera effectuee automatiquement par Stripe.
Si vous ne regularisez pas, veuillez verifier votre moyen de paiement. Une nouvelle tentative de prelevement SEPA sera effectuee.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 16px 0 0;">

View File

@@ -8,7 +8,7 @@
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Votre echeance <strong>{{ line.position }}/{{ echeancier.nbLines }}</strong> a ete prelevee avec succes.
Votre echeance <strong>{{ line.position }}/{{ echeancier.nbLines }}</strong> de l'echeancier <strong>{{ echeancier.reference }}</strong> a ete prelevee avec succes.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">

View File

@@ -8,7 +8,7 @@
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Nous vous proposons un echeancier de paiement pour faciliter le reglement de votre solde.
Nous vous proposons un echeancier de paiement <strong>{{ echeancier.reference }}</strong> pour faciliter le reglement de votre solde.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">

View File

@@ -0,0 +1,41 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
<div style="background: #dc2626; color: #fff; padding: 12px 20px; display: inline-block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 16px;">Echeancier refuse</div>
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 20px; font-weight: 700; color: #111827; margin: 0 0 12px;">Le client {{ customer.fullName }} a refuse l'echeancier {{ echeancier.reference }}</h1>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 40%;">Reference</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ echeancier.reference }}</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Client</td>
<td style="padding: 12px 16px; font-family: Arial; font-size: 13px;">{{ customer.fullName }}{% if customer.email %}<br><span style="color: #9ca3af; font-size: 11px;">{{ customer.email }}</span>{% endif %}</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Motif</td>
<td style="padding: 12px 16px; font-family: Arial; font-size: 13px;">{{ echeancier.description }}</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 14px; font-weight: 700;">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
{% if reason %}
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Motif du refus</td>
<td style="padding: 12px 16px; font-family: Arial; font-size: 13px; color: #dc2626;">{{ reason }}</td>
</tr>
{% endif %}
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Refuse le</td>
<td style="padding: 12px 16px; font-family: Arial; font-size: 13px;">{{ "now"|date('d/m/Y H:i') }}</td>
</tr>
</table>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,45 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
L'echeancier de paiement <strong>{{ echeancier.reference }}</strong> a ete refuse.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 35%;">Reference</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ echeancier.reference }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Motif</td>
<td style="padding: 10px 16px; font-size: 13px; font-weight: 700;">{{ echeancier.description }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700;">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
{% if reason %}
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Motif du refus</td>
<td style="padding: 10px 16px; font-size: 13px; color: #dc2626;">{{ reason }}</td>
</tr>
{% endif %}
</table>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 16px 0;">
Si vous souhaitez discuter d'autres modalites de paiement, n'hesitez pas a nous contacter.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 16px 0 0;">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -8,7 +8,7 @@
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Votre echeancier de paiement est pret a etre signe. Veuillez cliquer sur le bouton ci-dessous pour signer electroniquement le document.
Votre echeancier de paiement <strong>{{ echeancier.reference }}</strong> est pret a etre signe. Veuillez cliquer sur le bouton ci-dessous pour signer electroniquement le document.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">

View File

@@ -0,0 +1,49 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
<div style="background: #16a34a; color: #fff; padding: 12px 20px; display: inline-block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 16px;">Echeancier signe</div>
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 20px; font-weight: 700; color: #111827; margin: 0 0 12px;">Le client {{ customer.fullName }} a signe l'echeancier {{ echeancier.reference }}</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 13px; color: #374151; line-height: 20px; margin: 0 0 16px;">
Le PDF signe et le certificat d'audit DocuSeal sont en piece jointe.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 40%;">Reference</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ echeancier.reference }}</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Client</td>
<td style="padding: 12px 16px; font-family: Arial; font-size: 13px;">{{ customer.fullName }}{% if customer.email %}<br><span style="color: #9ca3af; font-size: 11px;">{{ customer.email }}</span>{% endif %}</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Motif</td>
<td style="padding: 12px 16px; font-family: Arial; font-size: 13px;">{{ echeancier.description }}</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Creance</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 13px;">{{ echeancier.totalAmountHt|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Majoration (5%)</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 13px; color: #dc2626;">+ {{ echeancier.majoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total a payer</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 14px; font-weight: 700;">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Mensualite</td>
<td style="padding: 12px 16px; font-family: monospace; font-size: 13px; color: #fabf04;">{{ echeancier.monthlyAmount|number_format(2, ',', ' ') }} &euro;/mois x {{ echeancier.nbLines }}</td>
</tr>
<tr>
<td style="padding: 12px 16px; font-family: Arial; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Signe le</td>
<td style="padding: 12px 16px; font-family: Arial; font-size: 13px;">{{ "now"|date('d/m/Y H:i') }}</td>
</tr>
</table>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,61 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Votre echeancier de paiement <strong>{{ echeancier.reference }}</strong> a ete signe avec succes. Vous trouverez en piece jointe le document signe ainsi que le certificat d'audit.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 35%;">Reference</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ echeancier.reference }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Motif</td>
<td style="padding: 10px 16px; font-size: 13px; font-weight: 700;">{{ echeancier.description }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Creance</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700;">{{ echeancier.totalAmountHt|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Majoration (5%)</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700; color: #dc2626;">+ {{ echeancier.majoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total a payer</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 16px; font-weight: 700;">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Mensualite</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700; color: #fabf04;">{{ echeancier.monthlyAmount|number_format(2, ',', ' ') }} &euro;/mois x {{ echeancier.nbLines }}</td>
</tr>
</table>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 16px 0;">
Vous allez recevoir un email pour configurer votre prelevement SEPA. Il vous suffira de renseigner votre IBAN pour que les echeances soient prelevees automatiquement aux dates prevues.
</p>
<div style="background: #f0fdf4; border: 1px solid #bbf7d0; padding: 12px 16px; margin: 16px 0;">
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #16a34a; margin: 0 0 6px;">Mandat de prelevement SEPA</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 11px; color: #374151; line-height: 18px; margin: 0;">
Crediteur : Association E-Cosplay<br>
Reference echeancier : {{ echeancier.reference }}<br>
Montant : {{ echeancier.monthlyAmount|number_format(2, ',', ' ') }} &euro;/mois x {{ echeancier.nbLines }} echeances<br>
Premiere echeance : {{ echeancier.lines|first ? echeancier.lines|first.scheduledAt|date('d/m/Y') : '—' }}
</p>
</div>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 16px 0 0;">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,60 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Votre echeancier <strong>{{ echeancier.reference }}</strong> a ete signe. Pour finaliser la mise en place des prelevements automatiques, veuillez configurer votre IBAN en cliquant sur le bouton ci-dessous.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 35%;">Reference</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ echeancier.reference }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Mensualite</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700; color: #fabf04;">{{ echeancier.monthlyAmount|number_format(2, ',', ' ') }} &euro;/mois x {{ echeancier.nbLines }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 16px; font-weight: 700;">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
</table>
{% if setupUrl is defined and setupUrl %}
<table cellpadding="0" cellspacing="0" style="margin: 24px auto;">
<tr>
<td style="background-color: #fabf04; padding: 14px 32px;">
<a href="{{ setupUrl }}" style="font-family: Arial, Helvetica, sans-serif; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #111827; text-decoration: none;">Configurer mon prelevement SEPA</a>
</td>
</tr>
</table>
{% endif %}
<div style="background: #f9fafb; border: 1px solid #e5e7eb; padding: 12px 16px; margin: 16px 0;">
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; margin: 0 0 6px;">Informations du mandat SEPA</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 11px; color: #374151; line-height: 18px; margin: 0;">
Crediteur : Association E-Cosplay<br>
Reference : {{ echeancier.reference }}<br>
Montant par echeance : {{ echeancier.monthlyAmount|number_format(2, ',', ' ') }} &euro;<br>
Nombre d'echeances : {{ echeancier.nbLines }}<br>
Premiere echeance : {{ echeancier.lines|first ? echeancier.lines|first.scheduledAt|date('d/m/Y') : '—' }}
</p>
</div>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 16px 0;">
Il vous suffit de renseigner votre IBAN. Chaque echeance sera ensuite prelevee automatiquement a la date prevue.
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 16px 0 0;">
Pour toute question : <a href="mailto:contact@e-cosplay.fr" style="color: #fabf04;">contact@e-cosplay.fr</a>
</p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,25 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Le prelevement de votre echeance <strong>{{ line.position }}/{{ eflex.nbLines }}</strong> du contrat <strong>{{ eflex.reference }}</strong> a echoue.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr><td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 35%;">Echeance</td><td style="padding: 10px 16px; font-size: 13px; font-weight: 700;">{{ line.label }}</td></tr>
<tr><td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Montant</td><td style="padding: 10px 16px; font-family: monospace; font-size: 16px; font-weight: 700;">{{ line.amount }} &euro;</td></tr>
<tr><td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Raison</td><td style="padding: 10px 16px; font-size: 13px; color: #dc2626;">{{ errorMessage }}</td></tr>
</table>
{% if payUrl is defined and payUrl %}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">Vous pouvez regulariser par carte bancaire :</p>
<table cellpadding="0" cellspacing="0" style="margin: 24px auto;"><tr><td style="background-color: #fabf04; padding: 14px 32px;"><a href="{{ payUrl }}" style="font-family: Arial, Helvetica, sans-serif; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #111827; text-decoration: none;">Payer par carte bancaire</a></td></tr></table>
{% endif %}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 16px 0 0;">Pour toute question : <a href="mailto:contact@e-cosplay.fr" style="color: #fabf04;">contact@e-cosplay.fr</a></p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,21 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Votre echeance <strong>{{ line.position }}/{{ eflex.nbLines }}</strong> du contrat <strong>{{ eflex.reference }}</strong> a ete payee.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr><td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 35%;">Echeance</td><td style="padding: 10px 16px; font-size: 13px; font-weight: 700;">{{ line.label }}</td></tr>
<tr><td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Montant</td><td style="padding: 10px 16px; font-family: monospace; font-size: 16px; font-weight: 700; color: #16a34a;">{{ line.amount }} &euro;</td></tr>
<tr><td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Progression</td><td style="padding: 10px 16px; font-size: 13px; font-weight: 700;">{{ eflex.nbPaid }}/{{ eflex.nbLines }} echeances payees ({{ eflex.progress }}%)</td></tr>
</table>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 16px 0 0;">Pour toute question : <a href="mailto:contact@e-cosplay.fr" style="color: #fabf04;">contact@e-cosplay.fr</a></p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,26 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Votre contrat de financement E-Flex <strong>{{ eflex.reference }}</strong> est pret a etre signe.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr><td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 35%;">Reference</td><td style="padding: 10px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ eflex.reference }}</td></tr>
<tr><td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Montant total</td><td style="padding: 10px 16px; font-family: monospace; font-size: 16px; font-weight: 700;">{{ eflex.totalAmount|number_format(2, ',', ' ') }} &euro;</td></tr>
<tr><td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Mensualite</td><td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700; color: #fabf04;">{{ eflex.monthlyAmount|number_format(2, ',', ' ') }} &euro;/mois x {{ eflex.nbLines }}</td></tr>
<tr><td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Methode</td><td style="padding: 10px 16px; font-size: 13px; font-weight: 700;">{{ eflex.paymentMethodLabel }}</td></tr>
</table>
{% if processUrl is defined and processUrl %}
<table cellpadding="0" cellspacing="0" style="margin: 24px auto;"><tr><td style="background-color: #fabf04; padding: 14px 32px;"><a href="{{ processUrl }}" style="font-family: Arial, Helvetica, sans-serif; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #111827; text-decoration: none;">Voir le contrat E-Flex</a></td></tr></table>
{% endif %}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 16px 0;">E-Flex est une solution de financement sans frais supplementaires proposee par l'Association E-Cosplay.</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 16px 0 0;">Pour toute question : <a href="mailto:contact@e-cosplay.fr" style="color: #fabf04;">contact@e-cosplay.fr</a></p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,18 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
<div style="background: #16a34a; color: #fff; padding: 12px 20px; display: inline-block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 16px;">E-Flex signe</div>
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 20px; font-weight: 700; color: #111827; margin: 0 0 12px;">{{ eflex.reference }} - {{ customer.fullName }}</h1>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr><td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 40%;">Client</td><td style="padding: 12px 16px; font-size: 13px;">{{ customer.fullName }}{% if customer.email %}<br><span style="color: #9ca3af; font-size: 11px;">{{ customer.email }}</span>{% endif %}</td></tr>
<tr><td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total</td><td style="padding: 12px 16px; font-family: monospace; font-size: 14px; font-weight: 700;">{{ eflex.totalAmount|number_format(2, ',', ' ') }} &euro;</td></tr>
<tr><td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Mensualite</td><td style="padding: 12px 16px; font-family: monospace; font-size: 13px; color: #fabf04;">{{ eflex.monthlyAmount|number_format(2, ',', ' ') }} &euro;/mois x {{ eflex.nbLines }}</td></tr>
<tr><td style="padding: 12px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Methode</td><td style="padding: 12px 16px; font-size: 13px;">{{ eflex.paymentMethodLabel }}</td></tr>
</table>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,37 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px;">
{% set greeting = customer.raisonSociale ? 'Chez ' ~ customer.raisonSociale : 'Bonjour ' ~ customer.firstName %}
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">{{ greeting }},</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Votre contrat E-Flex <strong>{{ eflex.reference }}</strong> a ete signe avec succes. Le contrat signe et le certificat d'audit sont en piece jointe.
</p>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 20px 0; border: 1px solid #e5e7eb;">
<tr><td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb; width: 35%;">Reference</td><td style="padding: 10px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ eflex.reference }}</td></tr>
<tr><td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Montant total</td><td style="padding: 10px 16px; font-family: monospace; font-size: 16px; font-weight: 700;">{{ eflex.totalAmount|number_format(2, ',', ' ') }} &euro;</td></tr>
<tr><td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Mensualite</td><td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700; color: #fabf04;">{{ eflex.monthlyAmount|number_format(2, ',', ' ') }} &euro;/mois x {{ eflex.nbLines }}</td></tr>
</table>
<h2 style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 700; color: #111827; margin: 20px 0 10px;">Coordonnees bancaires pour virement :</h2>
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 10px 0 20px; border: 1px solid #e5e7eb;">
<tr><td style="padding: 8px 16px; font-size: 11px; font-weight: 700; color: #9ca3af; background: #f9fafb; width: 30%;">Titulaire</td><td style="padding: 8px 16px; font-size: 13px; font-weight: 700;">Association E-Cosplay</td></tr>
<tr><td style="padding: 8px 16px; font-size: 11px; font-weight: 700; color: #9ca3af; background: #f9fafb;">IBAN</td><td style="padding: 8px 16px; font-family: monospace; font-size: 13px;">FR76 XXXX XXXX XXXX XXXX XXXX XXX</td></tr>
<tr><td style="padding: 8px 16px; font-size: 11px; font-weight: 700; color: #9ca3af; background: #f9fafb;">BIC</td><td style="padding: 8px 16px; font-family: monospace; font-size: 13px;">XXXXXXXX</td></tr>
<tr><td style="padding: 8px 16px; font-size: 11px; font-weight: 700; color: #9ca3af; background: #f9fafb;">Reference</td><td style="padding: 8px 16px; font-family: monospace; font-size: 13px;">{{ eflex.reference }}</td></tr>
</table>
{% if processUrl is defined and processUrl %}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 0 0 16px;">
Pour configurer le prelevement automatique ou payer par carte bancaire, cliquez ci-dessous :
</p>
<table cellpadding="0" cellspacing="0" style="margin: 24px auto;"><tr><td style="background-color: #fabf04; padding: 14px 32px;"><a href="{{ processUrl }}" style="font-family: Arial, Helvetica, sans-serif; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #111827; text-decoration: none;">Configurer mes paiements</a></td></tr></table>
{% endif %}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 16px 0 0;">Pour toute question : <a href="mailto:contact@e-cosplay.fr" style="color: #fabf04;">contact@e-cosplay.fr</a></p>
</td>
</tr>
</table>
{% endblock %}

View File

@@ -0,0 +1,14 @@
{% extends 'email/base.html.twig' %}
{% block content %}
<table width="600" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
<tr>
<td style="padding: 32px; text-align: center;">
<h1 style="font-family: Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; color: #111827; margin: 0 0 16px;">Code de verification E-Flex</h1>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; margin: 0 0 20px;">Voici votre code de verification :</p>
<div style="background: #111827; color: #fabf04; font-family: monospace; font-size: 36px; font-weight: 700; letter-spacing: 12px; padding: 20px; display: inline-block;">{{ code }}</div>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 20px 0 0;">Ce code expire dans 15 minutes.</p>
</td>
</tr>
</table>
{% endblock %}