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:
@@ -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>
|
||||
|
||||
121
templates/admin/attestation_custom/index.html.twig
Normal file
121
templates/admin/attestation_custom/index.html.twig
Normal 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 %}
|
||||
107
templates/admin/attestation_custom/show.html.twig
Normal file
107
templates/admin/attestation_custom/show.html.twig
Normal 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 %}
|
||||
@@ -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 }} €)</option>
|
||||
<option value="{{ ech.id }}">{{ ech.reference }} - {{ ech.description|length > 30 ? ech.description[:30] ~ '...' : ech.description }} ({{ ech.totalAmountHt }} €)</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, ',', ' ') }} €</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 }} €)</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, ',', ' ') }} €</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">
|
||||
|
||||
@@ -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 #}
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
168
templates/admin/eflex/show.html.twig
Normal file
168
templates/admin/eflex/show.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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 %}
|
||||
@@ -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>
|
||||
|
||||
105
templates/attestation_custom/verify.html.twig
Normal file
105
templates/attestation_custom/verify.html.twig
Normal 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 %}
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
38
templates/echeancier/regularize_success.html.twig
Normal file
38
templates/echeancier/regularize_success.html.twig
Normal 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, ',', ' ') }} €</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 %}
|
||||
184
templates/echeancier/setup_payment.html.twig
Normal file
184
templates/echeancier/setup_payment.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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 %}
|
||||
112
templates/echeancier/setup_payment_done.html.twig
Normal file
112
templates/echeancier/setup_payment_done.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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 %}
|
||||
@@ -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, ',', ' ') }} €</p>
|
||||
<p class="text-xs text-gray-500"><strong>Echeances :</strong> {{ echeancier.nbLines }} x {{ echeancier.monthlyAmount|number_format(2, ',', ' ') }} €/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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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>
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
143
templates/eflex/process.html.twig
Normal file
143
templates/eflex/process.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €)
|
||||
</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 %}
|
||||
116
templates/eflex/setup_payment.html.twig
Normal file
116
templates/eflex/setup_payment.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €</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 %}
|
||||
82
templates/eflex/setup_payment_done.html.twig
Normal file
82
templates/eflex/setup_payment_done.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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 %}
|
||||
34
templates/eflex/signed.html.twig
Normal file
34
templates/eflex/signed.html.twig
Normal 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, ',', ' ') }} €</p>
|
||||
<p class="text-xs text-gray-500"><strong>Echeances :</strong> {{ eflex.nbLines }} x {{ eflex.monthlyAmount|number_format(2, ',', ' ') }} €/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 %}
|
||||
32
templates/eflex/verify.html.twig
Normal file
32
templates/eflex/verify.html.twig
Normal 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 %}
|
||||
48
templates/emails/client_closure.html.twig
Normal file
48
templates/emails/client_closure.html.twig
Normal 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 %}
|
||||
98
templates/emails/client_warning.html.twig
Normal file
98
templates/emails/client_warning.html.twig
Normal 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 %}
|
||||
30
templates/emails/client_warning_reset.html.twig
Normal file
30
templates/emails/client_warning_reset.html.twig
Normal 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 %}
|
||||
103
templates/emails/echeancier_attestation.html.twig
Normal file
103
templates/emails/echeancier_attestation.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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 %}
|
||||
41
templates/emails/echeancier_cancelled_admin.html.twig
Normal file
41
templates/emails/echeancier_cancelled_admin.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} € ({{ 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 %}
|
||||
51
templates/emails/echeancier_cancelled_client.html.twig
Normal file
51
templates/emails/echeancier_cancelled_client.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €</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 %}
|
||||
@@ -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, ',', ' ') }} €</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, ',', ' ') }} € ({{ 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, ',', ' ') }} €</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 %}
|
||||
@@ -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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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 %}
|
||||
40
templates/emails/echeancier_completed_admin.html.twig
Normal file
40
templates/emails/echeancier_completed_admin.html.twig
Normal 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, ',', ' ') }} €</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 %}
|
||||
76
templates/emails/echeancier_completed_client.html.twig
Normal file
76
templates/emails/echeancier_completed_client.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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 %}
|
||||
@@ -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;">
|
||||
|
||||
@@ -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;">
|
||||
|
||||
@@ -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;">
|
||||
|
||||
41
templates/emails/echeancier_refused_admin.html.twig
Normal file
41
templates/emails/echeancier_refused_admin.html.twig
Normal 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, ',', ' ') }} €</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 %}
|
||||
45
templates/emails/echeancier_refused_client.html.twig
Normal file
45
templates/emails/echeancier_refused_client.html.twig
Normal 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, ',', ' ') }} €</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 %}
|
||||
@@ -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;">
|
||||
|
||||
49
templates/emails/echeancier_signed_admin.html.twig
Normal file
49
templates/emails/echeancier_signed_admin.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €/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 %}
|
||||
61
templates/emails/echeancier_signed_client.html.twig
Normal file
61
templates/emails/echeancier_signed_client.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €</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, ',', ' ') }} €/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, ',', ' ') }} €/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 %}
|
||||
60
templates/emails/echeancier_stripe_setup.html.twig
Normal file
60
templates/emails/echeancier_stripe_setup.html.twig
Normal 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, ',', ' ') }} €/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, ',', ' ') }} €</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, ',', ' ') }} €<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 %}
|
||||
25
templates/emails/eflex_echeance_echec.html.twig
Normal file
25
templates/emails/eflex_echeance_echec.html.twig
Normal 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 }} €</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 %}
|
||||
21
templates/emails/eflex_echeance_payee.html.twig
Normal file
21
templates/emails/eflex_echeance_payee.html.twig
Normal 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 }} €</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 %}
|
||||
26
templates/emails/eflex_signature.html.twig
Normal file
26
templates/emails/eflex_signature.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €/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 %}
|
||||
18
templates/emails/eflex_signed_admin.html.twig
Normal file
18
templates/emails/eflex_signed_admin.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €/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 %}
|
||||
37
templates/emails/eflex_signed_client.html.twig
Normal file
37
templates/emails/eflex_signed_client.html.twig
Normal 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, ',', ' ') }} €</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, ',', ' ') }} €/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 %}
|
||||
14
templates/emails/eflex_verify_code.html.twig
Normal file
14
templates/emails/eflex_verify_code.html.twig
Normal 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 %}
|
||||
Reference in New Issue
Block a user