feat: CustomerPaymentMethod + prelevement auto avis dernier jour du mois
Entity CustomerPaymentMethod: - customer, stripePaymentMethodId, type (sepa_debit/card) - last4, brand, country, isDefault - getDisplayLabel() pour affichage Sauvegarde automatique du moyen de paiement: - Contrat SEPA setup: cree CustomerPaymentMethod type SEPA - Contrat CB premier paiement: webhook sauvegarde la carte - Retire le default des anciens moyens de paiement Commande cron app:advert:auto-payment: - S'execute uniquement le dernier jour du mois - Trouve les avis envoyes (state=send) avec client ayant un moyen de paiement par defaut - Envoie un email d'annonce de prelevement au client - Cree un PaymentIntent off_session avec le moyen de paiement - Le webhook payment_intent.succeeded traite le paiement Admin fiche client tab info: - Affiche les moyens de paiement enregistres (type, last4, defaut) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -219,6 +219,33 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{# Moyens de paiement #}
|
||||
{% if paymentMethods|length > 0 %}
|
||||
<div class="glass p-5 mt-6">
|
||||
<h2 class="text-sm font-bold uppercase tracking-wider mb-3">Moyens de paiement enregistres</h2>
|
||||
<div class="space-y-2">
|
||||
{% for pm in paymentMethods %}
|
||||
<div class="glass p-3 flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
{% if pm.type == 'sepa_debit' %}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/></svg>
|
||||
{% else %}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-purple-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/></svg>
|
||||
{% endif %}
|
||||
<div>
|
||||
<p class="text-xs font-bold">{{ pm.displayLabel }}</p>
|
||||
<p class="text-[10px] text-gray-400">Ajoute le {{ pm.createdAt|date('d/m/Y') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% if pm.isDefault %}
|
||||
<span class="px-2 py-0.5 bg-green-500/20 text-green-700 font-bold uppercase text-[9px]">Par defaut</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Tab: Contacts #}
|
||||
{% elseif tab == 'contacts' %}
|
||||
<section class="glass p-6 mb-6">
|
||||
|
||||
43
templates/emails/advert_auto_payment_notice.html.twig
Normal file
43
templates/emails/advert_auto_payment_notice.html.twig
Normal file
@@ -0,0 +1,43 @@
|
||||
{% 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;">
|
||||
Nous vous informons qu'un prelevement automatique sera effectue pour votre avis de paiement <strong>{{ advert.orderNumber.numOrder }}</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%;">Avis</td>
|
||||
<td style="padding: 10px 16px; font-family: monospace; font-size: 13px; font-weight: 700;">{{ advert.orderNumber.numOrder }}</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: #fabf04;">{{ amount|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;">Moyen de paiement</td>
|
||||
<td style="padding: 10px 16px; font-size: 13px; font-weight: 700;">{{ methodLabel }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Date du prelevement</td>
|
||||
<td style="padding: 10px 16px; font-size: 13px; font-weight: 700;">{{ "now"|date('d/m/Y') }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: #374151; line-height: 22px; margin: 16px 0;">
|
||||
Ce prelevement sera effectue automatiquement via votre moyen de paiement enregistre. Vous recevrez un email de confirmation une fois le paiement traite.
|
||||
</p>
|
||||
|
||||
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #9ca3af; margin: 16px 0 0;">
|
||||
Pour toute question : <a href="mailto:client@e-cosplay.fr" style="color: #fabf04;">client@e-cosplay.fr</a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user