Formulaire d'infos de facturation avant paiement (#abonnement)

- Nouvelle page /compte/abonnement/mes-infos avec formulaire deux
  colonnes (prénom, nom, SIRET, entreprise, adresse, CP, ville, pays)
- Lookup SIRET via l'annuaire des entreprises pour pré-remplissage
- Cases à cocher obligatoires : renonciation rétractation + CGU (modale)
- Le bouton Valider est désactivé tant que les deux cases ne sont pas cochées
- Pays : liste déroulante des 20 pays de la zone euro, France par défaut
- Le SIRET est stocké dans users.siret (migration 0002) pour pré-remplissage
- Pré-remplissage des infos Frisbii (GET customer) si déjà client
- Côté Frisbii : update_customer si client existant, create_customer sinon
- Les URLs accept/cancel sont désormais transmises dans le body Frisbii
- Mise à jour des CGU : distinction données decp.info vs Frisbii

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Colin Maudry
2026-06-29 13:21:10 +02:00
parent 5e5c5170a7
commit b5f529c789
7 changed files with 479 additions and 52 deletions
+17 -19
View File
@@ -31,7 +31,7 @@ def _plan_card(meta: dict, trial: int | None, trial_used: bool):
className="text-muted mb-2",
)
elif trial:
badge = html.Div(f"{trial} jours d'essai gratuit", className="mb-2")
badge = html.Div(f"{trial} jours d'essai gratuit", className="mb-3")
else:
badge = None
return dbc.Card(
@@ -41,23 +41,18 @@ def _plan_card(meta: dict, trial: int | None, trial_used: bool):
html.P(f"{meta['prix_ht']} € HT / mois", className="text-muted mb-3"),
html.P(meta["description"], className="mb-3"),
badge,
html.Form(
method="POST",
action="/subscriptions/subscribe",
children=[
_csrf_input(),
dcc.Input(type="hidden", name="plan", value=meta["key"]),
html.Button(
"S'abonner",
type="submit",
className=(
"btn btn-secondary disabled"
if TOUS_ABONNES
else "btn btn-primary"
),
disabled=TOUS_ABONNES,
),
],
html.A(
"S'abonner",
href=(
"#"
if TOUS_ABONNES
else f"/compte/abonnement/mes-infos?plan={meta['key']}"
),
className=(
"btn btn-secondary disabled"
if TOUS_ABONNES
else "btn btn-primary"
),
),
],
className="p-4",
@@ -166,7 +161,10 @@ def _active_view(row):
def _feedback(query):
msgs = {
"succes": ("Merci, votre abonnement est en cours d'activation.", "success"),
"succes": (
"Merci, votre abonnement est activé. Bonne exploration !",
"success",
),
"annule": ("Paiement annulé.", "secondary"),
}
out = []