Journal des modifications
Les évolutions de Cohez.io, de la plus récente à la plus ancienne.
52 versions correspondent à « paiement ».
Versions 51 à 52 sur 52
0.3.0.0 - 2026-04-08
Ajouts
- Formulaire public d'inscription — les associations peuvent générer un lien public (token signé, expirable) depuis les paramètres d'une campagne. Ce lien donne accès à un wizard en 4 étapes (informations membre, chargement des propositions, sélection + payeur, récapitulatif) accessible sans compte. Aucun compte HelloAsso requis.
- Token public de campagne (
CampaignPublicToken) — modèle avec expiration configurable, génération viaStr::uuid()->toString()(UUID v4, colchar(36)), révocation instantanée depuis les settings. Un token révoqué retourne 410. - Déduplication silencieuse — si l'email soumis correspond à une
Personexistante dans le tenant, le service réutilise le membre ou crée unMemberlié sans jamais révéler au visiteur si son compte existait. - Détection des doublons d'inscription — si le même membre tente de s'inscrire deux fois à la même campagne, une erreur de validation claire est retournée sur le champ
member_email. Contrainte unique(member_id, campaign_id)ajoutée en base. - Mail de confirmation (
PublicRegistrationConfirmationMail) — envoyé en queue après inscription réussie si un email est fourni, avec récapitulatif des propositions sélectionnées et du mode de paiement. - Page de confirmation (
/register/{token}/success) — page dédiée après soumission réussie, protégée par le même middleware token. - Branding dans le layout public — le nom de l'association est affiché au-dessus du titre de la page pour que le visiteur sache à quelle organisation il s'inscrit.
- Throttling — les routes publiques d'inscription sont limitées à 10 req/min par IP pour limiter l'abus.
Modifications
- Middleware
ResolveCampaignPublicToken— vérifie désormais que la campagne est en statutOpen(en plus du contrôle d'expiration du token). Une campagneDraftouClosedretourne 410. PersonDeduplicationService—is_minorcalculé dynamiquement depuisdateNaissance(Carbon::age < 18) au lieu d'être codé àfalse.
Corrections
- Migration
add_unique_member_campaign_to_registrations: guard contre les doublons existants avant d'appliquer la contrainte unique (évite un crash silencieux en production si des données corrompues sont présentes).
Unreleased
Ajouts
Synchronisation automatique du statut d'inscription - 2026-03-19
Le statut d'une inscription (RegistrationStatus) se met désormais à jour automatiquement lorsque les paiements associés évoluent, sans intervention manuelle de l'administrateur.
Comportement :
- Paiement reçu couvrant le montant total →
Validated / PaidPartial → Paid - Paiement reçu couvrant partiellement →
Validated → PaidPartial - Paiement rejeté ramenant le solde à zéro →
Paid / PaidPartial → Validated - Paiement rejeté laissant un solde partiel →
Paid → PaidPartial - Les inscriptions en
DraftouCancelledne sont jamais auto-transitionnées
Architecture :
PaymentObserver(app/Observers/PaymentObserver.php) : écoutePayment::createdetPayment::updatedRegistrationStatus::canTransitionTo()étendu pour autoriser les transitions de retour depuisPaidetPaidPartial(nécessaires lors des rejets)- Enregistrement dans
AppServiceProvider::boot()au même niveau quePersonObserveretUserObserver - 10 tests feature dans
tests/Feature/Observers/PaymentObserverTest.php
Groupes Organisationnels - 2026-02-13
Ajout d'un système de gestion de groupes organisationnels pour structurer les membres de l'association (Bureau, CA, Commissions, etc.).
Fonctionnalités:
- CRUD complet des groupes (création, édition, suppression, consultation)
- Gestion des membres par groupe (ajout/retrait)
- Support du statut actif/inactif pour archiver des groupes
- Personnalisation visuelle avec couleur d'identification
- Slug unique pour identification technique
- Navigation dédiée dans la sidebar
Architecture:
- Modèle
OrganizationalGroupavec relations multi-tenant:tenant_idpour isolation des donnéespersonsrelation many-to-many via table pivotcreated_byetupdated_bypour traçabilité- Query scopes (
forTenant,active,inactive)
- Migration
create_organizational_groups_table:- Contraintes d'intégrité référentielle
- Unicité du nom et slug par tenant
- Protection par foreign keys avec cascade
- Table pivot
organizational_group_person
- Controller
OrganizationalGroupControlleravec:- Pagination sur la liste (15 éléments/page)
- Transactions DB pour intégrité des données
- Endpoint
availablePersonspour sélection de membres - Gestion des doublons avec exceptions spécifiques
- Policy
OrganizationalGroupPolicy:- Permission
MANAGE_SETTINGSrequise - Isolation stricte par tenant
- Support AdminUser avec accès total
- Permission
- Factory et Seeder pour développement et tests
Interface:
- Pages Vue avec Inertia v2:
groups/Index.vue- Liste avec grille et statsgroups/Create.vue- Formulaire avec auto-génération du sluggroups/Edit.vue- Édition avec switch actif/inactifgroups/Show.vue- Détails avec liste des membres
- Composant
AddPersonDialog.vue:- Recherche en temps réel par nom/email
- Sélection depuis personnes disponibles
- Intégration Wayfinder pour routes typées
- Composant UI
Switch.vue(Reka UI) - Structure de layout standardisée (
flex flex-1 flex-col gap-4 p-4) - Support complet du dark mode
- Types TypeScript générés automatiquement
Tests:
- 66 tests complets (14 modèle + 26 policy + 26 controller) avec 187 assertions:
- Relations et méthodes du modèle
- Query scopes et casts
- Règles d'autorisation (AdminUser, User avec permissions)
- CRUD complet avec validations
- Gestion des personnes (ajout, retrait, disponibles)
- Isolation tenant et unicité des contraintes
- Backward compatibility et null safety
- Suite complète: 946 tests passent
Améliorations et corrections (2026-02-15):
- Pagination sur la liste des membres (15 éléments/page) pour cohérence avec groupes
- Création composants UI Table avec Reka UI (Table, TableHeader, TableBody, TableRow, TableHead, TableCell)
- Correction typage TypeScript pour pagination Laravel (
LengthAwarePaginator<int, TValue>) - Correction ESLint (v-html sur composants)
- Migration tests unitaires vers tests feature (ListMembersQuery maintenant compatible avec pagination DB)
- Corrections PHPStan (annotations génériques, vérifications null redondantes)
Commits:
c570ba8 feat(groups): add organizational groups backend infrastructure
9f4acd9 feat(groups): add organizational groups frontend (Vue/Inertia)
0818406 Update .gitignore: add /.claude/worktrees to exclude directory
72ac5e1 feat(groups): add navigation link to organizational groups
5a8d2f3 fix(groups): correct critical bugs in UI components
f943d91 refactor(groups): align pages layout with application standards
56a3d33 fix(groups): correct pagination typing and add Table components with Reka UI
1f83a8e feat(members): add pagination to members list for consistency and performance
7ee05a8 fix(members): adjust focus-visible class order for consistency with Tailwind conventions
cc4244a fix(phpstan): correct type annotations and remove redundant null checks in ListMembersQuery
d36706c test(members): fix tests for pagination support
Types d'Utilisateurs (MEMBER/EMPLOYEE) - 2026-02-05
Ajout d'un système de différenciation entre membres adhérents et personnel salarié.
Fonctionnalités:
- Enum
UserTypeavec deux valeurs:MEMBER(membre adhérent) etEMPLOYEE(personnel) - Les employés peuvent accéder au système sans être des membres de l'association
- Section "Personnel" dédiée dans les paramètres (
/settings/staff) - Interface de création et gestion des comptes employés
- Scopes pour filtrer les utilisateurs par type:
User::members()etUser::employees()
Architecture:
- Migration
add_user_type_to_users_table:- Colonne
user_type(enum: 'member' | 'employee') - Colonnes
first_nameetlast_namepour les employés member_iddevient nullable (NULL pour les employés)- Backfill automatique de tous les users existants en
MEMBER - Validation d'intégrité des données avant migration
- Colonne
- Modèle
Userétendu avec:- Cast
user_typevers enum - Méthodes
isMember()etisEmployee() - Accessor
display_nameintelligent (membre ou user selon le type) - Scopes
members()etemployees()
- Cast
- Use Case
CreateEmployeepour la création d'employés - Factory
UserFactoryavec étatemployee()
Interface:
- Controller
StaffControlleravec CRUD complet - Form Request
CreateEmployeeRequestavec validation - Pages Vue:
Staff/Index.vue- Liste des employés avec rôlesStaff/Create.vue- Formulaire de création
- Types TypeScript
UserTypeetEmployee - Routes Wayfinder générées automatiquement
Tests:
- 40+ tests ajoutés couvrant:
- Enum (valeurs, labels, helpers)
- Model (types, scopes, accessors)
- Factory (états MEMBER/EMPLOYEE)
- Use Cases (création, validations, exceptions)
- Controller (CRUD, permissions, isolation tenant)
- Intégration (null safety, backward compatibility)
Documentation:
Rétrocompatibilité:
- ✅ 100% compatible: tous les users existants deviennent automatiquement
MEMBER - ✅ Aucun changement de comportement pour l'existant
- ✅ Tous les tests passent (680 passed)
Commits:
9239a5e feat(identity): add UserType enum for MEMBER and EMPLOYEE
0b8c432 fix(tests): add user_type to manual User::create calls
7ea7d43 feat(identity): add Staff frontend pages and types
1a2ac47 feat(identity): add Staff controller for employee management
f5732f8 feat(identity): add CreateEmployee use case
803d9c3 feat(identity): add employee state to UserFactory
6734c12 feat(identity): enhance User model with type support
450e26e feat(identity): add user_type column to support employees
ece1f30 fix(identity): add null-safe access for member properties
bb65dd1 test(identity): complete UserType enum unit tests