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>
80 lines
2.3 KiB
Python
80 lines
2.3 KiB
Python
"""Rendu des emails. Les textes vivent dans `locales/fr.json` (`email.*`)."""
|
|
|
|
from app.i18n import t
|
|
|
|
# Variables autorisées dans un modèle d'email de planning saisi par la
|
|
# coordination.
|
|
_PLANNING_PLACEHOLDERS = (
|
|
"prenom",
|
|
"nom",
|
|
"nb_creneaux",
|
|
"nb_heures",
|
|
"creneaux",
|
|
"lien_connexion",
|
|
)
|
|
|
|
|
|
def render_magic_link(*, link: str, minutes: int) -> tuple[str, str]:
|
|
return (
|
|
t("email.magic_link.subject"),
|
|
t("email.magic_link.body", link=link, minutes=minutes),
|
|
)
|
|
|
|
|
|
def render_registration_confirmation(*, first_name: str) -> tuple[str, str]:
|
|
"""Inscription prise en compte, sans paiement en ligne (case désactivée,
|
|
ou « je paierai sur place ») — voir `render_registration_paid_confirmation`
|
|
pour le cas d'un paiement confirmé."""
|
|
return (
|
|
t("email.registration_confirmation.subject"),
|
|
t("email.registration_confirmation.body", prenom=first_name),
|
|
)
|
|
|
|
|
|
def render_registration_paid_confirmation(
|
|
*, first_name: str, label: str, amount: float
|
|
) -> tuple[str, str]:
|
|
"""Inscription prise en compte **et** paiement en ligne confirmé — envoyé
|
|
une fois seulement, au moment de la promotion (`app/api/forms.py:
|
|
_promote_pending`). Sert de reçu (montant, type de paiement) en
|
|
l'absence de confirmation documentée que l'API SumUp Hosted Checkout en
|
|
envoie un elle-même."""
|
|
return (
|
|
t("email.registration_confirmation_paid.subject"),
|
|
t(
|
|
"email.registration_confirmation_paid.body",
|
|
prenom=first_name,
|
|
label=label,
|
|
montant=amount,
|
|
),
|
|
)
|
|
|
|
|
|
def _fill(template: str, values: dict[str, object]) -> str:
|
|
out = template
|
|
for key in _PLANNING_PLACEHOLDERS:
|
|
out = out.replace("{" + key + "}", str(values.get(key, "")))
|
|
return out
|
|
|
|
|
|
def render_planning(
|
|
*,
|
|
subject_template: str,
|
|
body_template: str,
|
|
first_name: str,
|
|
last_name: str,
|
|
shift_count: int,
|
|
hours: float,
|
|
shifts_text: str,
|
|
login_link: str,
|
|
) -> tuple[str, str]:
|
|
values: dict[str, object] = {
|
|
"prenom": first_name,
|
|
"nom": last_name,
|
|
"nb_creneaux": shift_count,
|
|
"nb_heures": hours,
|
|
"creneaux": shifts_text,
|
|
"lien_connexion": login_link,
|
|
}
|
|
return _fill(subject_template, values), _fill(body_template, values)
|