diff --git a/css/style.css b/css/style.css
index 6a95e6c..f25a965 100644
--- a/css/style.css
+++ b/css/style.css
@@ -5223,6 +5223,17 @@ button.inscr-gestion-list-remis:hover{
font-size: 1.85rem;
}
+/* MSIN-4451 — sous-ligne « N participants » sous le KPI épreuves vendues */
+.phub-flash-sub {
+ display: block;
+ margin-top: 0.2rem;
+ font-size: 0.72rem;
+ font-weight: 600;
+ color: #6b7280;
+ letter-spacing: 0.01em;
+ text-transform: none;
+}
+
/* --- Badges d'alerte --- */
.promoteur-hub-badges {
display: flex;
diff --git a/php/inc_fx_promoteur_hub.php b/php/inc_fx_promoteur_hub.php
index f089296..5e1a10d 100644
--- a/php/inc_fx_promoteur_hub.php
+++ b/php/inc_fx_promoteur_hub.php
@@ -553,6 +553,7 @@ function fxPromoteurHubStaticFallback($clef, $strLangParam = '')
'promoteur_hub_menu_features' => array('fr' => 'Menu des fonctionnalités', 'en' => 'Features menu'),
// MSIN-4451 — total = somme des inscriptions par épreuve (pas d'humains uniques)
'promoteur_hub_flash_inscrits' => array('fr' => 'épreuves vendues', 'en' => 'entries sold'),
+ 'promoteur_hub_flash_participants' => array('fr' => 'participants', 'en' => 'participants'),
'promoteur_hub_flash_rempli' => array('fr' => 'rempli', 'en' => 'filled'),
'promoteur_hub_flash_places' => array('fr' => 'places restantes', 'en' => 'spots left'),
'promoteur_hub_flash_revenus' => array('fr' => 'revenus est.', 'en' => 'est. revenue'),
@@ -979,6 +980,26 @@ function fxPromoteurHubGetEpreuveStats($intEveId, $strLangue = 'fr')
}
}
+ // MSIN-4451 — Humains uniques (même personne sur 2 épreuves = 1).
+ // Clé : courriel normalisé ; sans courriel → par_id_original (pas de fusion).
+ $intFlashParticipants = 0;
+ $sqlParticipants = "
+ SELECT COUNT(DISTINCT
+ CASE
+ WHEN TRIM(IFNULL(p.par_courriel, '')) <> '' THEN LOWER(TRIM(p.par_courriel))
+ ELSE CONCAT('id:', p.par_id_original)
+ END
+ ) AS nb
+ FROM resultats_epreuves_commandees e
+ JOIN resultats_participants p
+ ON p.epr_id = e.epr_id AND p.pec_id = e.pec_id_original
+ WHERE p.is_cancelled = 0 AND p.epr_id IN (" . $strIds . ")
+ ";
+ $tabParticipants = $objDatabase->fxGetResults($sqlParticipants);
+ if (is_array($tabParticipants) && isset($tabParticipants[1]['nb'])) {
+ $intFlashParticipants = intval($tabParticipants[1]['nb']);
+ }
+
// ---- Check-in (dossards remis) ----
$arrCheckin = array();
$sqlCheckin = "
@@ -1184,6 +1205,7 @@ function fxPromoteurHubGetEpreuveStats($intEveId, $strLangue = 'fr')
$arrFlash = array(
'total_vendus' => $intFlashVendus,
+ 'total_participants' => $intFlashParticipants,
'total_max' => $intFlashMax,
'total_restant' => max(0, $intFlashMax - $intFlashVendus),
'pct_global' => $intPctGlobal,
@@ -1214,9 +1236,14 @@ function fxPromoteurHubRenderFlash($arrStats, $strLangue = 'fr')
// ---- Bande flash ----
$html .= '
';
+ // MSIN-4451 — Duo : épreuves vendues (KPI) + participants uniques (sous-ligne)
$html .= '
';
$html .= '' . intval($arrFlash['total_vendus']) . '';
$html .= '' . fxPromoteurHubEsc(fxPromoteurHubTexte('promoteur_hub_flash_inscrits', 0)) . '';
+ $html .= ''
+ . intval($arrFlash['total_participants']) . ' '
+ . fxPromoteurHubEsc(fxPromoteurHubTexte('promoteur_hub_flash_participants', 0))
+ . '';
$html .= '
';
if (intval($arrFlash['total_max']) > 0) {
diff --git a/php/inc_settings.php b/php/inc_settings.php
index db4e2a1..b8274f8 100644
--- a/php/inc_settings.php
+++ b/php/inc_settings.php
@@ -7,7 +7,7 @@
* Constantes *
*
**************/
-define('_VERSION_CODE', '4.72.833');
+define('_VERSION_CODE', '4.72.834');
define('_DATE_CODE', '2026-07-16');
//MSIN-4290
define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe');
diff --git a/sql/MSIN-4451-hub-flash-epreuves-vendues.sql b/sql/MSIN-4451-hub-flash-epreuves-vendues.sql
index 5743855..758587f 100644
--- a/sql/MSIN-4451-hub-flash-epreuves-vendues.sql
+++ b/sql/MSIN-4451-hub-flash-epreuves-vendues.sql
@@ -1,7 +1,9 @@
--- MSIN-4451 — Hub flash : libellé « épreuves vendues » (pas « inscrits »)
--- Contexte : le chiffre agrège déjà les places vendues par épreuve
--- (même personne sur 2 épreuves = 2). Seul le libellé était trompeur.
--- Notes : idempotent. Clé inchangée : promoteur_hub_flash_inscrits.
+-- MSIN-4451 — Hub flash : « épreuves vendues » + sous-ligne participants
+-- Contexte : le KPI principal agrège les places vendues par épreuve
+-- (même personne sur 2 épreuves = 2). La sous-ligne compte les humains
+-- uniques (courriel) : même personne sur 2 épreuves = 1.
+-- Notes : idempotent. Clé flash inchangée : promoteur_hub_flash_inscrits.
+-- Ordre : un seul script.
UPDATE info
SET info_texte = 'épreuves vendues'
@@ -14,3 +16,17 @@ SET info_texte = 'entries sold'
WHERE info_clef = 'promoteur_hub_flash_inscrits'
AND info_langue = 'en'
AND info_prg = 'compte.php';
+
+INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
+SELECT 'promoteur_hub_flash_participants', 'fr', 'participants', '', 'compte.php', '', 0, 1, '', '', '', NOW()
+FROM DUAL WHERE NOT EXISTS (
+ SELECT 1 FROM info
+ WHERE info_clef = 'promoteur_hub_flash_participants' AND info_langue = 'fr' AND info_prg = 'compte.php'
+);
+
+INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
+SELECT 'promoteur_hub_flash_participants', 'en', 'participants', '', 'compte.php', '', 0, 1, '', '', '', NOW()
+FROM DUAL WHERE NOT EXISTS (
+ SELECT 1 FROM info
+ WHERE info_clef = 'promoteur_hub_flash_participants' AND info_langue = 'en' AND info_prg = 'compte.php'
+);