Conception du module "Jauges de places"
Ce document détaille la conception d'un module permettant de regrouper et de suivre les limites de ventes de plusieurs produits de manière transversale.
Objectifs
- Regroupement : Créer des objets permettant de mutualiser les quotas de vente de plusieurs produits.
- Suivi dynamique : Suivre les ventes en temps réel pour calculer les paliers de tarifs correspondants.
- Intégration : S'intégrer aux flux de configuration existants (Template > Groupe de produits > Disponibilité de ventes).
- Granularité : Permettre un paramétrage par catégorie de public (disponibilité de ventes), par catégorie de place et par configuration de stade.
Architecture Proposée
L'arborescence des objets se structure de la manière suivante :
- Objet
Jauge: Défini au niveau du club. - Objet
JaugeCategoriePublic: Enfant deJauge. - Objet
JaugeCategoriePlace: Enfant deJaugeCategoriePublic.- Comprend un compteur (Entier, optionnel, ≥ 0).
- Liaisons : Un générateur/parent de produit est lié à une
Jauge. Ses enfants sont automatiquement liés auxJaugeCategoriePubliccorrespondantes. Les articles vendus sont ensuite décomptés desJaugeCategoriePlacerattachées. - Spécificités par Stade : Pour chaque
ConfigurationStade, on génère desConfigurationJaugeCategoriePlace(copies desJaugeCategoriePlace), paramétrables de manière indépendante.
Logique d'Incrémentation et Intégrité des Données
Le système repose sur un mécanisme de propagation automatique de l'impact des ventes, basé sur la hiérarchie des objets et les points de contact entre événements.
1. Mécanisme de propagation (Vente active)
Lorsqu'un article est vendu (passage de la commande à l'état "payé"), le système exécute les étapes suivantes : 1. Incrémentation directe : Mise à jour du compteur de la jauge explicitement liée à l'article. 2. Incrémentation par propagation : Identification et mise à jour de toutes les jauges répondant aux critères cumulatifs suivants : * Même lignée : Partagent les mêmes ancêtres (Jauge mère, Catégorie de public, Catégorie de place). * Intersection d'événements : Possèdent au moins un match en commun avec le produit vendu.
2. Gestion des modifications structurelles (Calcul de Delta)
Toute modification de la configuration alors que les ventes sont ouvertes nécessite une synchronisation : * Cas concernés : Changement de la jauge d'un produit, introduction d'une nouvelle jauge en cours de saison, ou modification des matchs inclus dans un Pass/Formule. * Action : Déclencher un calcul de delta basé sur l'historique des ventes réelles pour réaligner les compteurs de toutes les jauges impactées par le changement de périmètre.
3. Conseils techniques de mise en œuvre
Pour garantir la fiabilité et les performances, les principes suivants sont recommandés :
- Atomicité SQL : Ne pas charger les objets en mémoire pour les incrémenter. Utiliser des requêtes SQL directes (
UPDATE ... SET counter = counter + 1) pour éviter les race conditions lors d'achats simultanés. - Transactions : L'ensemble des incrémentations (directes et propagées) doit être encapsulé dans une transaction unique pour garantir la cohérence (tout est mis à jour ou rien ne l'est).
- Traitement Asynchrone pour les Deltas : Le recalcul des jauges lors d'un changement structurel peut être lourd. Il est préférable de l'exécuter via un Background Job (ex: Sidekiq) pour ne pas bloquer l'interface d'administration.
- Indexation : Assurer une indexation performante sur les colonnes pivots (
parent_id,match_id,type_jauge) pour que la recherche des jauges liées soit instantanée malgré le volume de données.
📋 Feuille de route d'implémentation (TODO)
1. Gestion des Jauges (Dashboard Admin)
- Configuration des Jauges Mères :
- Interface CRUD pour l'objet
Jauge. - Gestion des relations avec les catégories de public (
JaugeCategoriePublic).
- Interface CRUD pour l'objet
- Déclinaison par Catégories :
- Gestion des
JaugeCategoriePlace(liées aux catégories de public). - Paramétrage des quotas de base (tailles par défaut).
- Gestion des
- Spécification par
ConfiguratonStade:- Interface de paramétrage fin pour les
ConfigurationJaugeCategoriePlaceau sein de chaqueConfigurationStade.
- Interface de paramétrage fin pour les
2. Module d'attribution et cycle de vie
- Intégration aux Formulaires :
- Ajout d'un sélecteur de jauge dans les formulaires de création/édition des produits et générateurs de produits.
- Héritage et Génération :
- Automatisation de l'attribution des jauges lors de la génération automatique des produits.
- Gestion du Changement :
- Mise en place des hooks de mise à jour lors de la modification d'un produit ou de son rattachement à une jauge (calcul du delta...).
3. Moteur de vente (Front-end & API)
- Logique de Pricing :
- Calcul dynamique des paliers tarifaires en fonction de l'état actuel de la jauge.
- Flux de Vente :
- Incrémentation : Mise à jour des compteurs lors de la validation de commande.
- Contrôle de disponibilité : Vérification stricte des capacités lors de l'ajout au panier, de la finalisation du tunnel d'achat et pour l'affichage des jauges de disponibilité sur le site.
💡 Réflexions Métiers & Évolutions
Vers une structure de jauges "cross-catégories" ?
Question : Doit-on faire évoluer la structure vers un modèle plus flexible de type Jauge => JaugeItems avec une relation HABTM (Has And Belongs To Many) vers les CategoriePublic et CategoriePlace ?
Analyse : * Avantages : Cela permettrait de créer des jauges très spécifiques (ex: une jauge commune pour "Familles de joueurs" et "Licensiés" sur une ou plusieurs catégories de place données). * Complexité : La logique de propagation des ventes deviendrait plus complexe à calculer (plusieurs chemins possibles pour atteindre une ressource), à moins d'empecher les doublons au sein d'une même jauge (Pour une categorie de place et une catégorie de public données, impossible d'avoir une ambiguités de `JaugeItem)
Compte rendu de la réunion du 08/01/2026
- Possibilité de propager les modifications du template de Jauge à ses enfants.
- Ajout d'un 2eme compteur à l'ajout au panier (puis au retrait) afin de valider la disponibilité.
- Création d'un script pour migrer les festivals => 1 Produit, 1 Jauge
- Implémentation de la variante
JaugeItem