Journal des modifications
Les évolutions de Cohez.io, de la plus récente à la plus ancienne.
44 versions correspondent à « HelloAsso ».
Versions 21 à 30 sur 44
0.16.5.0 — 2026-06-04
Corrections
- Tâches planifiées jamais exécutées en production : le scheduler Laravel n'était jamais déclenché sur Clever Cloud (aucun
clevercloud/cron.json,crontab -lvide en prod). Conséquence :helloasso:sync-pending-payments(06:00),registrations:abandon-expired-deposits(07:00),documents:auditetinvitations:expirene tournaient pas — les paiements HelloAsso n'étaient pas réconciliés automatiquement et les réservations en attente expirées n'étaient jamais libérées. Le correctif précédent (0.16.4.0) reposait sur ce cron pour libérer les places ; il est désormais réellement actif.
Technique
- Ajout de
clevercloud/cron.json(appel chaque minute) etclevercloud/cron.sh(lancephp artisan schedule:rundepuis la racine de l'app). C'est le seul mécanisme cron disponible pour une app PHP Clever Cloud. stdout est jeté pour éviter le bruit « No scheduled commands are ready to run » à chaque minute ; stderr est conservé pour les erreurs. Un seul scaler en production → pas de double exécution.
0.16.4.0 — 2026-06-04
Corrections
- Cours affiché « complet » alors qu'il restait des places : un cours pouvait apparaître complet sur le formulaire d'inscription public alors que le compte admin affichait encore des places disponibles. Deux causes : (1) le formulaire et l'admin ne comptaient pas le même ensemble de statuts (les inscriptions
Draftcomptaient côté formulaire mais pas côté admin) ; (2) des inscriptionsDraftissues d'un checkout HelloAsso abandonné (paiement jamais finalisé) restaient bloquées indéfiniment et occupaient une place à vie. Le comptage de capacité est désormais unifié sur tous les écrans (formulaire public, Cours, Campagnes, Réglages > Cours) et les réservations en attente non finalisées sont automatiquement libérées après un délai.
Ajouts
- Délai d'expiration des réservations en attente : toute réservation non finalisée (
Draft) reçoit désormais une date limite. Passé ce délai sans paiement, elle est automatiquement annulée et sa place libérée. Le délai par défaut est de 7 jours (configurable viaREGISTRATION_DRAFT_TTL_DAYS). - Surcharge du délai par campagne : chaque campagne peut définir son propre délai d'expiration des réservations en attente, via un champ dédié dans le formulaire de campagne (laisser vide pour utiliser le défaut global).
- Édition de campagne accessible : un bouton « Modifier » permet désormais d'éditer une campagne existante depuis sa page (la page d'édition existait mais n'était reliée à aucun lien).
Technique
- Nouvelle colonne
registrations.draft_expires_at(date limite générique de réservation) etcampaigns.draft_ttl_days(surcharge par campagne). La date limite d'acompte (deposit_expires_at) reste prioritaire quand elle existe, avec repli surdraft_expires_at. - Les échéances de réservation et d'acompte sont désormais calées sur la fin de journée (
endOfDay()) à la création comme au backfill, cohérent avec un cron quotidien : l'expiration correspond à la date affichée à l'adhérent et lui laisse sa dernière journée entière. - Le job
registrations:abandon-expired-depositsannule désormais toutDraftexpiré (plus seulement les acomptes) ; il n'expire jamais unPendingValidationviadraft_expires_at(un paiement enregistré tient la place). Garde-fou : aucune réservation ayant déjà reçu un paiement n'est annulée (total_paidnon nul). Il est désormais planifié une fois par jour à 07:00, aprèshelloasso:sync-pending-payments(06:00) au lieu de toutes les heures : la synchronisation réconcilie d'abord les paiements HelloAsso réellement reçus, évitant d'abandonner par erreur une inscription payée mais pas encore synchronisée (syncignore les statuts terminaux). - Comptage de capacité centralisé sur
RegistrationStatus::terminalStatuses()(exclutCancelled/Refused/Abandoned, compte lesDraft) avecCOUNT(DISTINCT), partagé par le modèleCourse,CourseController,Settings/CourseControlleretCampaignController. Les listes de membres (roster, export CSV) continuent d'exclure lesDraft. - Nouvelle commande ponctuelle
registrations:backfill-draft-deadlines(avec--dry-run) pour poser une échéance sur lesDraftexistants créés avant ce correctif. À lancer une fois après déploiement. - Le balayage d'abandon parcourt les inscriptions avec
chunkById(et noneach/offset) : comme il fait sortir chaque ligne du jeu de résultats, une pagination par offset sauterait des lignes au-delà de la première page (places retenues à vie) —chunkByIdles traite toutes. - Garde de fraîcheur : si au moins un tenant utilise HelloAsso, l'abandon ne tourne que si
helloasso:sync-pending-paymentsa réussi dans les 6 dernières heures (heartbeat en cache). Sinon il s'abstient (log d'avertissement) pour ne pas abandonner une inscription payée mais pas encore réconciliée si le sync échoue.
0.16.3.0 — 2026-06-03
Ajouts
- Traçabilité des emails de relance : chaque email de relance envoyé pour un dossier d'inscription est désormais enregistré (paiement HelloAsso rejeté, paiement abandonné, ou acompte expirant), avec le destinataire, la raison, la référence de checkout et la date d'envoi.
- Historique des relances sur la vue dossier : une carte « Relances envoyées » liste les relances du dossier, avec un badge coloré par type (rejeté, abandonné, acompte) et l'horodatage de chaque envoi.
Technique
- Nouvelle table
registration_relance_emails(une ligne par email) et table pivot vers les dossiers concernés (un email groupé peut couvrir plusieurs dossiers). - L'enregistrement des traces est centralisé dans un recorder best-effort (
RegistrationRelanceEmail::record()), branché sur le goulot d'envoi HelloAsso et sur la relance d'acompte. Une défaillance de la trace n'interrompt jamais l'envoi du mail.
0.16.2.0 — 2026-06-03
Corrections
- Webhook HelloAsso
Refusedtardif : un webhook de refus livré en retard pour un checkout périmé (la référence ayant été écrasée lors d'un retry) ne re-marque plusRejectedun paiement déjà retenté sous une nouvelle référence.resolvePayments()filtre désormais sur la référence du checkout courant (filtre gardé : repli sur la résolution parregistration_idsi lecheckoutIntentIdest absent du payload). Évite qu'une inscription reste bloquée en Draft alors que le paiement a abouti sur le nouveau checkout. Contratdata.checkoutIntentIdconfirmé sur un webhook de production.
0.15.0.0 — 2026-06-02
Ajouts
- Relance paiement HelloAsso : les payeurs dont le paiement HelloAsso est rejeté par la banque ou abandonné depuis plus de 2h reçoivent automatiquement un email de relance avec le récapitulatif de leur inscription et un lien sécurisé pour relancer le paiement (URL signée, valable 7 jours).
- Route de retry HelloAsso (
/register/{token}/helloasso/retry) : crée un nouveau checkout HelloAsso à la volée sans effacer l'inscription existante. Protégée par URL signée temporaire pour prévenir les accès non autorisés. - Statuts de paiement HelloAsso dans l'interface admin : les inscriptions affichent désormais "HelloAsso en attente" (badge orange) et "Paiement refusé" (badge rouge) pour distinguer visuellement les checkouts en cours des paiements rejetés par la banque.
- Détail complet du panier dans l'email de relance : l'email de relance affiche désormais chaque adhérent inscrit avec le détail par rubrique, les réductions appliquées, le montant de l'acompte le cas échéant et sa date d'expiration.
- Planification nocturne :
helloasso:sync-pending-paymentss'exécute automatiquement chaque nuit à 06:00 (Europe/Paris) pour rattraper les paiements en attente non notifiés par webhook. - Annulation automatique : lorsqu'une inscription passe en statut Abandonné ou Annulé, les paiements HelloAsso Pending/Rejected associés sont automatiquement annulés pour éviter les relances intempestives.
Modifications
- La commande
helloasso:sync-pending-paymentsenvoie maintenant un email de relance lors de la détection d'un paiement rejeté ou d'un checkout abandonné (>2h), avec idempotence garantie par le flaghelloasso_relance_sent_atsur les paiements. - Le webhook HelloAsso (
Refused) envoie immédiatement un email de relance au payeur après avoir marqué le paiement comme rejeté. - Les inscriptions en statut terminal (Refusé, Annulé, Abandonné) sont exclues des relances automatiques.
- La logique d'envoi de l'email de relance est désormais centralisée dans
HelloAssoRelanceServicepour éviter la duplication entre le webhook et la commande de synchronisation.
Corrections
- Correction d'un bug de double-email : après un retry, le délai de grâce de 2h pour la relance des abandonnés repart maintenant correctement de la date de modification du paiement (et non de sa création initiale).
json_decodesur les notes de paiement corrompues retourne désormais[]au lieu denull, évitant un recalcul incorrect du montant lors d'un retry de dépôt.- La route de retry ne supprime plus les inscriptions existantes en cas d'échec de l'API HelloAsso (contrairement au flux initial d'inscription).
- L'URL de relance (bouton "Finaliser mon paiement") utilisait la racine de l'application au lieu du sous-domaine tenant, provoquant une erreur 404 à la réception de l'email.
- Ajout du statut
Cancelleddans l'enumPaymentStatus(manquant depuis la création, causait une erreur 500 lors de l'annulation d'inscription).
0.14.2.0 — 2026-06-01
Modifications
- Confirmation des paiements HelloAsso : la logique de confirmation (paiement reçu, transition de statut, envoi d'email) est désormais centralisée dans un service dédié, éliminant trois implémentations divergentes (retour URL, webhook, commande de synchronisation). Les guards d'idempotence sont désormais uniformes sur tous les états terminaux (
Received,Rejected,Refunded,Contested). - Checkout HelloAsso : les deux blocs de création de paiement dans le formulaire d'inscription (paiement standard et acompte) sont fusionnés en un service unique.
Corrections
- L'événement
RegistrationValidated(déclenchant la création de facture et l'email de confirmation) est maintenant émis après le commit de la transaction de paiement, garantissant que les listeners synchrones opèrent sur des données pleinement persistées. - L'idempotence du retour HelloAsso ignorait les états
Rejected,RefundedetContested— désormais alignée avec le webhook.
0.14.1.4 — 2026-06-01
Ajouts
- Couverture complète des états de paiement HelloAsso : le webhook et la commande
helloasso:sync-pending-paymentsgèrent désormais tous les états HelloAsso —Refused→Rejected,Refunding/Refunded→Remboursé,Contested→Contesté. L'interface affiche les badges correspondants avec les variantes visuelles adaptées.
Corrections
- Guard d'idempotence webhook étendu : lors d'un retry de webhook
Paid, le handler vérifie maintenant tous les états terminaux (Received,Refunded,Contested,Rejected) avant d'écrire — empêchant un webhook retardé d'écraser un remboursement déjà enregistré. - Guard d'idempotence sync étendu :
helloasso:sync-pending-paymentsapplique le même guard (tous les états terminaux) pour éviter qu'une exécution concurrente avec un webhook ne réécrive un paiementRefunded/ContestedavecReceived. - Filtre méthode de paiement dans
resolvePayments(): les paths 1 et 2 de résolution (parregistration_ids[]etregistration_id) filtraient tous les paiements d'une inscription ; ils filtrent maintenant uniquement ceux de méthodeHelloAsso, évitant de marquer des paiements espèces/chèque comme rejetés/remboursés. - Compteur
--dry-run: le compteur de paiements mis à jour n'était pas incrémenté dans le bon bloc conditionnel pour les checkouts refusés, affichant un compte erroné en mode dry-run. - Types TypeScript :
Payment.statusdans la page inscription inclut désormais'refunded'et'contested'; les badges s'affichent correctement pour ces états.
0.14.1.3 — 2026-05-30
Ajouts
- Commande
helloasso:sync-pending-payments: nouvelle commande artisan pour récupérer les paiements HelloAsso restés en attente après un webhook manquant. Pour chaque tenant avec credentials HelloAsso, interroge l'API pour tous les paiementsPendingayant une référence, et confirme automatiquement ceux qui sont payés (transitionDraft → Validated, email de confirmation). Options :--tenant=UUIDpour restreindre à un seul tenant,--dry-runpour prévisualiser sans modifier.
Corrections
- Webhook HelloAsso sans
webhook_secret: les tenants sans clé partenaire HelloAsso recevaient401 Webhook secret not configuredsur chaque notification, laissant les paiements enDraftindéfiniment. Le webhook accepte désormais les requêtes provenant des IPs officielles HelloAsso (51.138.206.200prod,4.233.135.234sandbox) quand aucun secret n'est configuré — conformément à la méthode de validation documentée par HelloAsso pour les non-partenaires. - Rejet HelloAsso sur
lastNameinvalide : l'API HelloAsso rejetait l'erreurLe champ nom est invalidequand le nom du payeur contenait un seul caractère, des chiffres ou des accents non supportés (ü, ñ…). Les champsfirstName/lastNamedu payeur sont maintenant omis du checkout intent — HelloAsso les collecte directement sur sa page de paiement.
0.14.1.2 — 2026-05-29
Corrections
- Régression HelloAsso : après le déploiement de la configuration per-tenant (v0.14.1.0), les tenants sans flag
hello_asso_sandboxexplicite se retrouvaient en mode production par défaut, causant une erreur401 unauthorizedpour ceux utilisant des credentials sandbox — et donc aucune redirection vers HelloAsso.helloAssoSandbox()retombe désormais sur la variable d'environnement globaleHELLOASSO_SANDBOXpour les tenants non encore configurés individuellement, préservant le comportement antérieur au déploiement.
0.14.1.1 — 2026-05-29
Corrections
- Modal HelloAsso : le Radio "sandbox / production" affiche maintenant l'environnement actuel du tenant à l'ouverture de la modale (correction de la valeur initiale manquante via
->fillForm()).