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>
Apres signature du contrat, le webhook envoie un email avec lien
vers /process/contrat/{id}/setup-payment
Page setup-payment :
- Resume montant mensuel HT
- Choix CB (Stripe Checkout avec setup_future_usage) ou SEPA
- Formulaire IBAN Stripe Elements avec mandat SEPA
- Confirmation SEPA via endpoint POST /confirm
- Page succes apres paiement
Routes :
- /process/contrat/{id}/setup-payment : page choix CB/SEPA
- /process/contrat/{id}/setup-payment/confirm : confirmation SEPA
- /process/contrat/{id}/payment-success : page succes
Email contrat_setup_payment : lien vers la page de configuration,
detail montant, mention 1er paiement CB/SEPA obligatoire
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Page process contrat avec :
- Header avec reference et type
- Statut (signe/annule)
- Infos association (SIRET, RNA, president, contact)
- Infos client (raison sociale, email)
- Tableau services inclus avec total HT/mois
- Conditions importantes (paiement, impayes, avertissements)
- Liens utiles (page migration, tarifs, CGV)
- Bouton "Signer le contrat" (redirige vers DocuSeal)
- Contact
Controller ContratProcessController :
- /process/contrat/{id} : page de detail
- /process/contrat/{id}/sign : redirection vers DocuSeal
Email contrat_signature : lien vers /process/contrat/{id}
au lieu du lien DocuSeal direct
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- contact@e-cosplay.fr remplace par client@e-cosplay.fr dans 87 fichiers
(PDFs, templates, emails, controllers, DocuSeal submitters)
- monitor@e-cosplay.fr remplace par notification@e-cosplay.fr dans 4 fichiers
(webhooks DocuSeal, commandes DNS/NDD, controller echeancier)
- Ajout lien "En savoir plus sur notre association" vers www.e-cosplay.fr
sur la page migration SITECONSEIL
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Annulation automatique:
- Apres 2 echecs de prelevement, E-Flex passe en STATE_CANCELLED
- Email d'annulation envoye au client (detail: total, paye, restant,
rejets) + notification admin
- Template eflex_cancelled.html.twig
Blocage creation:
- Controller: refuse la creation si un E-Flex est en cours (active,
pending_setup, draft) ou en defaut (cancelled avec nbFailed > 0)
- Template: bouton "Creer" remplace par "Creation bloquee (defaut)"
ou "E-Flex en cours" selon le cas
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ajout "Un credit vous engage et doit etre rembourse. Verifiez votre
capacite de remboursement avant de vous engager." dans :
- Page process E-Flex (bandeau orange avant le bouton signer)
- PDF contrat E-Flex (section dediee avant les signatures)
- Email de signature E-Flex (encadre orange)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Email eflex_paiement_recu au client lors du paiement manuel admin
(reference, echeance, montant, methode, date, progression)
- Bandeau vert si toutes echeances payees
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Nouveau template emails/echeancier_verify_code.html.twig
(sans reference a advert.orderNumber)
- Controller utilise le nouveau template au lieu de order_verify_code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remplace "vous autorisez le prelevement automatique" par
"un email vous sera envoye pour effectuer la configuration
des prelevements automatiques" dans tous les templates.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entite Echeancier :
- MAJORATION_RATE = 0.05 constante
- getMajoration() : montant de la majoration
- getTotalWithMajoration() : total creance + 5%
- getMonthlyAmount() : calcule sur le total majore
Controller create :
- Echeances calculees sur le total majore (pas le total brut)
PDF EcheancierPdf :
- Bloc resume : creance, majoration (rouge), total a payer
- Tableau total : "TOTAL (creance + majoration 5%)"
Email proposition :
- Lignes creance, majoration +5% (rouge), total a payer
Page process (client) :
- 4 colonnes : creance, majoration 5%, total a payer, mensualite
Admin show :
- Carte "Creance + majoration 5%" avec detail
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Page publique /echeancier/process/{id} avec detail complet avant signature
(motif, resume, tableau echeances, conditions)
- Redirige vers page signed si deja signe/actif/termine
- Bouton unique "Envoyer pour signature" / "Renvoyer signature" selon state
- Suppression bouton "Envoyer proposition" (remplace par signature directe)
- Email signature : ajout bouton "Voir les details" + lien processUrl
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Webhook Stripe :
- handleInvoicePaid : trouve echeancier par subscriptionId, marque la
prochaine ligne en attente comme payee, envoie email confirmation,
passe echeancier en 'completed' si toutes les echeances payees
- handleInvoiceFailed : marque ligne en echec avec raison, envoie email
echec au client + notification admin, passe en 'default' apres 2 echecs
Emails :
- echeancier_echeance_payee.html.twig : confirmation prelevement reussi
- echeancier_echeance_echec.html.twig : notification echec prelevement
Fix DevisController :
- Route #[Route] deplacee de sendDevisSignEmail vers createAdvert
(erreur "controller not callable" corrigee)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Email bienvenue (templates/emails/client_created.html.twig) :
- Envoyé automatiquement à la création du client
- Contenu : plateforme client.siteconseil.fr, identifiant email,
bouton "Choisir mon mot de passe" avec lien app_set_password
- Compatible tous clients mail (table-based, CSS longhand)
ClientsController :
- sendWelcomeEmail() : génère le lien set_password et envoie via MailerService
- Appelé dans create() après ensureDefaultContact
- Route POST /{id}/resend-welcome : renvoie l'email si tempPassword disponible
Fiche client (show.html.twig, onglet Info) :
- Si tempPassword existe : bandeau indigo "Espace client non activé"
+ lien direct vers la page activation + bouton "Renvoyer email bienvenue"
- Si tempPassword null : bandeau vert "Espace client activé"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
src/Controller/DnsReportController.php (nouveau):
- Route /email/configuration/{token} accessible via le lien dans le mail
- Utilise le messageId de l'EmailTracking comme token d'acces
(seuls les destinataires du mail ont le lien)
- Execute tous les checks en temps reel: DnsCheckService (SPF, DMARC, MX,
Bounce via dig @1.1.1.1), AwsSesService (domaine, 3 DKIM CNAME,
MAIL FROM MX/TXT, bounce notif), CloudflareService (zone, records),
MailcowService (domaine, DKIM, MX, autodiscover, autoconfig, SRV, MTA-STS)
- Enrichit chaque check avec la colonne Cloudflare
- Passe les resultats au template Twig pour affichage complet
templates/dns_report/index.html.twig (nouveau):
- Page glassmorphism avec header glass
- Resume en haut: 3 cards (verifications OK, erreurs, avertissements)
avec bordures laterales colorees vert/rouge/jaune
- Tableau par domaine avec 6 colonnes: Source (badge colore par type:
orange AWS, violet Mailcow, bleu Cloudflare, gris DNS), Verification,
Attendu, Dig (actuel), Cloudflare, Statut (rond colore)
- Section erreurs detaillees avec liste
- Section avertissements avec liste
- Footer "Esy-Infra - Service de monitoring d'infra"
templates/emails/dns_report.html.twig (simplifie):
- Mail ne contient plus les details: seulement un tableau avec
chaque domaine et son statut (OK vert / WARN jaune / KO rouge)
- Bouton "Voir le rapport complet" avec lien vers la page web
(VML fallback pour Outlook)
- Le lien utilise le placeholder __DNS_REPORT_URL__ remplace par
le MailerService avec le messageId du mail
src/Service/MailerService.php:
- Ajout du remplacement de __DNS_REPORT_URL__ par l'URL absolue
/email/configuration/{messageId} dans sendEmail(), au meme
endroit que __VIEW_URL__
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
src/Service/DnsCheckService.php:
- Methode check() enrichie avec 4 nouveaux champs: expected (valeur attendue),
dig (valeur actuelle trouvee par dig), cloudflare (valeur dans la zone CF),
cf_status (statut de la colonne CF: ok/error/vide)
- checkSpf(): expected = "include:X dans le SPF", dig = contenu SPF complet
- checkDmarc(): expected = "p=reject ou p=quarantine", dig = contenu DMARC
- checkDkim(): expected = "FQDN CNAME/TXT", dig = cible CNAME ou debut TXT
- checkMx(): expected = MX attendu, dig = liste des MX trouves avec priorite
- checkBounce(): expected = "feedback-smtp.*.amazonses.com", dig = valeur trouvee
src/Command/CheckDnsCommand.php:
- Nouveau champ MONITOR_EMAIL = 'monitor@siteconseil.fr' pour l'envoi du rapport
- loadCloudflareRecords(): charge les records CF une seule fois par domaine
au debut de l'execution, retourne un array indexe par domaine
- enrichWithCloudflare(): apres chaque check DNS, parcourt les records CF
pour trouver l'enregistrement correspondant et remplir les colonnes
cloudflare et cf_status dans chaque check
- checkAwsSes(): utilise DnsCheckService::check() avec expected/dig
(ex: expected="Success", dig="Absent" pour la verification domaine)
- checkMailcow(): utilise DnsCheckService::check() avec expected/dig
(ex: expected="Cle Mailcow: abc...", dig="Cle DNS: xyz..." pour DKIM)
- sendReport(): envoie a MONITOR_EMAIL au lieu de l'admin email
templates/emails/dns_report.html.twig:
- Tableau par domaine avec 6 colonnes: Type, Check, Attendu, Dig (actuel),
Cloudflare, Statut (OK/erreur/warning)
- Colonne Dig coloree en vert/rouge/jaune selon le statut du check
- Colonne Cloudflare coloree selon cf_status
- Colonnes avec word-break: break-all pour les longues valeurs DNS
- Bandeau resume en haut avec compteurs succes/erreurs/warnings
avec bordures laterales colorees
- Pied de mail: "Rapport par Esy-Infra - Service de monitoring d'infra"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Architecture:
- Les domaines (siteconseil.fr, esy-web.dev) sont definis en constante
dans la commande uniquement, pas dans les services
- 3 services independants reutilisables:
src/Service/DnsCheckService.php (nouveau):
- Methodes publiques checkSpf(), checkDmarc(), checkDkim(), checkMx(),
checkBounce() qui prennent le domaine en parametre
- Verification SPF: presence des includes amazonses.com et mail.esy-web.dev
- Verification DMARC: politique, presence de rua
- Verification DKIM: test de 10 selecteurs en CNAME et TXT
- Verification MX: le MX attendu est passe en parametre par la commande
- Verification Bounce: MX/CNAME/TXT sur bounce.*
src/Service/AwsSesService.php (nouveau):
- Authentification AWS Signature V4 via HTTP direct (pas de SDK)
- isDomainVerified(): verification du statut du domaine dans SES
- getDkimStatus(): statut DKIM (enabled, verified, tokens)
- getNotificationStatus(): bounce_topic, complaint_topic, forwarding
- listVerifiedIdentities(): liste des domaines verifies
- isAvailable(): test de connectivite API
src/Service/CloudflareService.php (nouveau):
- Authentification Bearer token via HTTP direct (pas de SDK)
- getZoneId(): recupere le zone ID dynamiquement par nom de domaine
(plus besoin de CLOUDFLARE_ZONE_ID en dur)
- getDnsRecords(): tous les enregistrements d'une zone
- getDnsRecordsByType(): filtrage par type (TXT, MX, CNAME...)
- getZone(): informations d'une zone
- isAvailable(): verification du token API
src/Command/CheckDnsCommand.php (reecrit):
- Utilise les 3 services pour orchestrer les verifications
- Affichage console colore avec icones OK/ERREUR/ATTENTION
- Envoie un rapport email via le template Twig dns_report.html.twig
templates/emails/dns_report.html.twig (nouveau):
- Template email compatible tous clients (table-based, CSS inline,
margin/padding longhand, mso-line-height-rule, pas de rgba/border-radius)
- Bandeau colore vert/jaune/rouge selon le statut global
- Section succes avec checkmarks verts dans un tableau alterne
- Section erreurs en rouge avec croix dans un tableau fond #fef2f2
- Section avertissements en jaune avec triangles fond #fffbeb
- Detail par domaine avec tableau type/verification/statut
- Utilise le template email/base.html.twig (header gold, footer dark)
Variables d'environnement ajoutees:
- .env: AWS_PK, AWS_SECRET, AWS_REGION (eu-west-3), CLOUDFLARE_KEY (vides)
- .env.local: valeurs reelles des cles AWS et Cloudflare
- ansible/vault.yml: aws_pk, aws_secret, cloudflare_key
- ansible/env.local.j2: AWS_PK, AWS_SECRET, AWS_REGION, CLOUDFLARE_KEY
avec references au vault
- CLOUDFLARE_ZONE_ID supprime (recupere dynamiquement via l'API)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Outlook Windows (2007-2019) ne supporte pas la propriete height sur
les elements div, span et p. AOL et Yahoo remplacent height par
min-height ce qui casse le rendu.
templates/emails/revendeur_created.html.twig:
- 2 div spacers <div style="height: 8px;"> remplaces par des table
spacers avec td font-size: 1px et mso-line-height-rule: exactly
line-height: 8px + pour forcer la hauteur sur tous les clients
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
src/Command/TestMailCommand.php (nouveau fichier):
- Commande Symfony app:mail:test <email> --mode=dev|prod
- Envoie un email de test complet pour verifier le rendu sur tous les clients
- Option --mode pour afficher un bandeau DEV (jaune) ou PROD (rouge)
templates/emails/test_mail.html.twig (nouveau fichier):
- Bandeau environnement colore (dev: #f59e0b jaune, prod: #dc2626 rouge)
- Bloc info sombre avec destinataire, environnement et date/heure
- Tableau de donnees avec 3 services (Esy-Web, Esy-Mail, Esy-Defender Pro),
tarifs, statuts (ACTIF vert, IMPAYE rouge) et ligne TOTAL
- Liste de verification des styles: gras, italique, souligne, lien, couleurs
- Bloc alerte avec bordure laterale gold et fond gris
- 2 boutons centres (Gold #fabf04 et Dark #111827) avec fallback VML
pour Outlook via v:roundrect
- Tableau des 5 applications SITECONSEIL avec liens et descriptions
- Simulation de fichier joint avec icone trombone
- Pied de mail avec mention de la commande utilisee
- Tout en CSS inline compatible: padding longhand, margin longhand,
mso-line-height-rule:exactly, line-height en px, background-color,
pas de rgba/border-radius/box-shadow
templates/emails/test_mail.html.twig:
- Balise <u> remplacee par span avec text-decoration: underline en inline
(la balise <u> n'est pas supportee par ProtonMail, Orange iOS, SFR iOS)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Outlook Windows (2007-2019) a un bug avec line-height en em et sans unite:
le rendu est imprevisible. La solution est d'utiliser des valeurs en px
avec mso-line-height-rule:exactly.
templates/email/base.html.twig:
- cellule contenu: line-height: 1.6 remplace par line-height: 22px
avec ajout de mso-line-height-rule: exactly
templates/emails/2fa_code.html.twig:
- 3 paragraphes: line-height: 1.6 remplace par 22px + mso-line-height-rule
templates/emails/forgot_password_code.html.twig:
- 3 paragraphes: line-height: 1.6 remplace par 22px + mso-line-height-rule
templates/emails/membre_created.html.twig:
- 4 paragraphes: line-height: 1.6 remplace par 22px + mso-line-height-rule
- 2 listes ul: line-height: 1.8 remplace par 25px (font 14px)
et 23px (font 13px) + mso-line-height-rule
templates/emails/password_changed.html.twig:
- 4 paragraphes: line-height: 1.6 remplace par 22px + mso-line-height-rule
templates/emails/revendeur_created.html.twig:
- 5 paragraphes: line-height: 1.6 remplace par 22px + mso-line-height-rule
templates/emails/rgpd_access.html.twig:
- 4 paragraphes: line-height: 1.6 remplace par 22px + mso-line-height-rule
templates/emails/rgpd_attestation_signed.html.twig:
- 4 paragraphes: line-height: 1.6 remplace par 22px + mso-line-height-rule
templates/emails/rgpd_deletion.html.twig:
- 4 paragraphes: line-height: 1.6 remplace par 22px + mso-line-height-rule
templates/emails/rgpd_no_data.html.twig:
- 5 paragraphes: line-height: 1.6 remplace par 22px + mso-line-height-rule
Suppression de box-shadow dans tous les templates email (non supporte
par Outlook Windows, Orange, GMX, WEB.DE, Samsung Email).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Outlook Windows (2007-2019) a un bug ou le padding vertical d'une cellule
est applique a toutes les cellules de la meme ligne avec la plus grande
valeur. SFR, Samsung Email, GMX, WEB.DE, HEY ne supportent que
partiellement le shorthand.
templates/emails/2fa_code.html.twig:
- span code: padding: 16px 32px remplace par padding-top/right/bottom/left
templates/emails/forgot_password_code.html.twig:
- span code: padding: 16px 32px remplace par padding-top/right/bottom/left
templates/emails/membre_created.html.twig:
- bloc identifiants: padding: 20px remplace par les 4 proprietes longhand
- 2 divs internes: padding: 4px 0 remplace par longhand
- bouton connexion: padding: 12px 24px remplace par longhand
templates/emails/revendeur_created.html.twig:
- bloc identifiants: padding: 20px remplace par longhand
- 3 blocs etapes: padding: 12px 16px remplace par longhand
- bouton mot de passe: padding: 14px 24px remplace par longhand
- bouton connexion: padding: 12px 24px remplace par longhand
- bloc info: padding: 16px remplace par longhand
- 3 divs internes: padding: 2px 0 remplace par longhand
templates/emails/rgpd_attestation_signed.html.twig:
- 3 blocs info: padding: 8px 12px remplace par longhand
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Outlook Windows (2007-2019) ne supporte que background-color, pas
le shorthand background. rgba() et border-radius ne sont pas non plus
supportes par Outlook Windows Mail, GMX, Samsung Email, Orange.
templates/emails/2fa_code.html.twig:
- code de verification: background: #111827 remplace par background-color: #111827
templates/emails/forgot_password_code.html.twig:
- code de verification: background: #111827 remplace par background-color: #111827
templates/emails/membre_created.html.twig:
- bloc identifiants: background: #111827 remplace par background-color: #111827
- bouton connexion: background: #fabf04 remplace par background-color: #fabf04,
border rgba(0,0,0,0.1) remplace par #e5e5e5, border-radius: 8px supprime
templates/emails/revendeur_created.html.twig:
- bloc identifiants: background: #111827 remplace par background-color: #111827
- 3 blocs etapes: background: #f9fafb remplace par background-color: #f9fafb
- bouton mot de passe: background: #fabf04 remplace par background-color: #fabf04,
border rgba supprime, border-radius supprime
- bouton connexion: background: #fff remplace par background-color: #ffffff,
border rgba supprime, border-radius supprime
- bloc info: background: #f9fafb remplace par background-color: #f9fafb
templates/emails/rgpd_attestation_signed.html.twig:
- 2 blocs info: background: #f9fafb remplace par background-color: #f9fafb
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
templates/email/base.html.twig:
- Remplacement de la structure div par une structure table-based (role=presentation)
pour compatibilite Outlook/Orange/SFR/Yahoo
- Suppression de rgba(), linear-gradient(), border-radius, box-shadow
(non supportes par Outlook Windows 2007-2019)
- Ajout du doctype XHTML 1.0 Transitional pour Outlook
- Ajout du bloc conditionnel <!--[if mso]> pour forcer Arial sur Outlook
- Remplacement de margin: 0 par margin-top/right/bottom/left: 0
(margin shorthand non supporte par Orange, SFR, certains Outlook)
- Remplacement de padding shorthand par padding-top/right/bottom/left
dans le body et les cellules principales
- Ajout de -webkit-text-size-adjust et -ms-text-size-adjust sur body
- Logo: ajout de width et height auto explicites + border: 0
- Fond semi-transparent rgba(255,255,255,0.92) remplace par #ffffff opaque
- Gradient gold remplace par background-color: #fabf04 fixe
- Couleur footer rgba(255,255,255,0.7) remplacee par #b0b0b0 fixe
- Entite • remplacee par • pour compatibilite XHTML
templates/emails/*.html.twig (9 fichiers):
- Remplacement de toutes les proprietes margin shorthand par les
proprietes longhand margin-top/margin-right/margin-bottom/margin-left
dans 2fa_code, forgot_password_code, membre_created, password_changed,
revendeur_created, rgpd_access, rgpd_attestation_signed, rgpd_deletion,
rgpd_no_data
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Email templates: replace table/tr/td with div-based CSS layout
- PDF templates: replace table with display:table/table-row/table-cell CSS (Dompdf compatible)
- Only table.data (RGPD access session data) remains as actual HTML table
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace email layout tables with CSS divs in base.html.twig
- Replace deprecated width/align attributes with CSS styles in PDF templates
- Add role="presentation" to email layout tables
- Convert td to th[scope=row] in profil and attestation verify tables
- Reduce function nesting in app.js by extracting renderHit/performSearch
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add for/id attributes to all form labels for accessibility compliance
- Add <title> tags to PDF templates (rgpd_access, rgpd_no_data, rgpd_deletion, contrat_revendeur)
- Add role="presentation" to email layout tables
- Remove deprecated cellpadding/cellspacing attributes from all templates
- Fix PHPUnit notices by replacing createMock with createStub where no expectations are set
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>