Inscription en deux temps, emails de confirmation et export Excel des bénévoles
ci-cd / build-backend (push) Successful in 30s
ci-cd / build-frontend (push) Successful in 18s
ci-cd / deploy (push) Successful in 12s

Formulaire public — paiement en ligne :
- Le bénévole n'est plus compté en base tant qu'un paiement en ligne choisi
  n'est pas confirmé (PendingFormSubmission, promu en Volunteer à la
  confirmation, webhook ou vérification en direct).
- Type de paiement « mécénat » : étape d'adresse postale avant le paiement,
  conservée sur le bénévole pour un reçu fiscal (cerfa) ultérieur.
- Page de confirmation au retour de SumUp, avec relance possible après
  échec/expiration sans ressaisir le formulaire.
- « Je paierai sur place » remplace « je ne participe pas » ; tous les
  champs activés par la coordination sont désormais obligatoires.
- La fiche bénévole n'affiche plus l'état des cases à cocher, seulement le
  résultat réel du paiement (libellé, montant, statut).

Emails :
- Email de confirmation d'inscription à la création du bénévole (tient lieu
  de reçu de paiement quand une cotisation est payée en ligne).
- Mise en forme HTML au thème de l'application (logo de l'édition en
  en-tête) pour tous les emails envoyés, texte brut conservé en repli.

Export Excel des bénévoles (COORDINATION) : coordonnées, vœux résolus en
noms lisibles, cotisation et mécénat.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
AdamThomas
2026-09-30 07:41:58 +02:00
co-authored by Claude Sonnet 5
parent 68d42ee303
commit a2b748566b
34 changed files with 2318 additions and 291 deletions
+76
View File
@@ -0,0 +1,76 @@
"""Version HTML des emails — même thème que l'appli (couleurs/typographie de
`frontend/tailwind.config.js`), logo de l'édition en en-tête si défini.
Chaque email reste envoyé en `multipart/alternative` (texte + HTML, voir
`app/email/sender.py:build_message`) : le texte brut reste la source de
vérité (accessibilité, clients sans HTML, RGPD — rien de plus dans le HTML
que dans le texte déjà journalisable). Pas de CSS externe ni de police web
(rarement chargées par les clients mail) : mise en page par tableau, styles
en ligne, polices système en repli du style « Archivo »/« DM Mono »."""
import html as _html
_INK = "#14110E"
_CREAM = "#F5EFE1"
_PAPER = "#FFFDF7"
_YELLOW = "#FFD23F"
_FONT_DISPLAY = "Arial, Helvetica, sans-serif"
_FONT_MONO = "'Courier New', Courier, monospace"
def _paragraphs(body: str) -> str:
"""`\n\n` sépare les paragraphes, un simple `\n` reste un retour à la
ligne — même convention que les modèles texte (`app/email/templates.py`)."""
blocks = body.strip().split("\n\n")
return "".join(
f'<p style="margin:0 0 14px;">{_html.escape(block).replace(chr(10), "<br>")}</p>'
for block in blocks
if block.strip()
)
def render_html(*, subject: str, body: str, logo_url: str | None) -> str:
"""`logo_url` : voir `app/email/branding.py:edition_logo_url` — `None`
tant que l'édition n'a pas importé de logo, l'en-tête retombe alors sur
un simple bandeau texte (le sujet, en capitales)."""
if logo_url:
header = (
f'<img src="{_html.escape(logo_url)}" alt="" width="160" '
'style="max-height:64px;width:auto;display:block;margin:0 auto;'
'border:0;">'
)
else:
header = (
f'<span style="font-family:{_FONT_DISPLAY};font-weight:800;'
f"text-transform:uppercase;letter-spacing:1px;color:{_YELLOW};"
f'font-size:14px;">{_html.escape(subject)}</span>'
)
return f"""<!doctype html>
<html lang="fr">
<head><meta charset="utf-8"></head>
<body style="margin:0;padding:24px 16px;background:{_CREAM};">
<table role="presentation" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table role="presentation" width="520" cellpadding="0" cellspacing="0"
style="max-width:520px;width:100%;">
<tr>
<td style="background:{_INK};padding:18px;text-align:center;
border:3px solid {_INK};">
{header}
</td>
</tr>
<tr>
<td style="background:{_PAPER};border:3px solid {_INK};
border-top:none;padding:22px;font-size:13px;
line-height:1.6;color:{_INK};font-family:{_FONT_MONO};">
{_paragraphs(body)}
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>"""