Formulaire public : paiement de la cotisation via l'API SumUp (remplace Yapla)
ci-cd / build-backend (push) Failing after 4m12s
ci-cd / build-frontend (push) Skipped
ci-cd / deploy (push) Skipped

Remplace le simple lien Yapla statique par une vraie intégration API SumUp :
checkout hébergé créé à la soumission du formulaire, statut de paiement
(PENDING/PAID/FAILED/EXPIRED) tenu à jour par un webhook SumUp et visible sur
la fiche du bénévole. La cotisation n'est plus un montant unique : la
coordination configure autant de types de paiement qu'elle veut (libellé +
montant, ex. « Cotisation classique », « Mécénat »), et le bénévole en
choisit un à l'inscription — le libellé et le montant choisis sont figés sur
le bénévole, indépendamment d'une modification ultérieure de la config.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
AdamThomas
2026-09-29 19:56:04 +02:00
co-authored by Claude Sonnet 5
parent 0be5daa89c
commit 0bd38a6465
25 changed files with 1457 additions and 125 deletions
+59 -4
View File
@@ -113,10 +113,20 @@ export interface VolunteerRead {
companion_wish_note: string | null;
self_declared_available: boolean;
willing_to_pay_fee: boolean;
/** Paiement de la cotisation via SumUp (voir schema forms) —
* `fee_payment_label`/`fee_amount` : copie figée du type de paiement
* choisi (pas la config actuelle). `fee_payment_status` reste `null` tant
* qu'aucun checkout n'a jamais été créé pour ce bénévole. */
fee_payment_label: string | null;
fee_amount: number | null;
fee_payment_status: FeePaymentStatus | null;
fee_paid_at: string | null;
created_at: string;
updated_at: string;
}
export type FeePaymentStatus = 'PENDING' | 'PAID' | 'FAILED' | 'EXPIRED';
export interface VolunteerCreate {
first_name: string;
last_name: string;
@@ -573,14 +583,43 @@ export interface FormTemplateRead {
fields: FormFieldType[];
has_logo: boolean;
description: string | null;
yapla_url: string | null;
sumup_merchant_code: string | null;
/** `sumup_api_key` (secret) n'est jamais renvoyé — seulement s'il est défini. */
sumup_api_key_set: boolean;
}
/** `undefined`/absent = inchangé pour chaque champ. */
/** `undefined`/absent = inchangé pour chaque champ. Chaîne vide sur
* `sumup_api_key` efface le secret enregistré. */
export interface FormTemplateUpdate {
is_open?: boolean;
description?: string | null;
yapla_url?: string | null;
sumup_merchant_code?: string | null;
sumup_api_key?: string | null;
}
/** Un type de paiement proposé sur le formulaire public (ex. « Cotisation
* classique », « Mécénat ») — libellé + montant fixe, configurés librement
* par la coordination (comme les créneaux types `DayPart`). */
export interface FormPaymentOptionRead {
id: string;
edition_id: string;
label: string;
amount: number;
order: number;
created_at: string;
updated_at: string;
}
export interface FormPaymentOptionCreate {
label: string;
amount: number;
order?: number;
}
export interface FormPaymentOptionUpdate {
label?: string;
amount?: number;
order?: number;
}
export interface PublicPositionOption {
@@ -594,6 +633,14 @@ export interface PublicArtistOption {
performance_date: string;
}
/** Type de paiement affiché sur le formulaire public — un montant n'est pas
* un secret, contrairement aux identifiants SumUp. */
export interface PublicPaymentOption {
id: string;
label: string;
amount: number;
}
/** Tout ce qu'il faut pour afficher le formulaire public — jamais plus. */
export interface PublicFormConfig {
is_open: boolean;
@@ -602,11 +649,16 @@ export interface PublicFormConfig {
artists: PublicArtistOption[];
has_logo: boolean;
description: string | null;
yapla_url: string | null;
/** `true` si l'édition a configuré SumUp (identifiants + au moins un type
* de paiement). */
sumup_enabled: boolean;
payment_options: PublicPaymentOption[];
}
export interface FormSubmissionResult {
volunteer_id: string;
/** Lien de paiement hébergé SumUp, si un checkout a pu être créé. */
sumup_checkout_url: string | null;
}
/** Champs du formulaire public — envoyés en `multipart/form-data` (photo
@@ -622,6 +674,9 @@ export interface PublicFormSubmission {
companion_wish_note?: string;
available?: boolean;
willing_to_pay_fee?: boolean;
/** Type de paiement choisi (voir `PublicPaymentOption`) — `undefined` =
* aucun (le bénévole ne participe pas à la cotisation). */
payment_option_id?: string;
position_wish_ids?: string[];
artist_wish_ids?: string[];
photo?: File | null;