diff --git a/php/inc_fx_promoteur.php b/php/inc_fx_promoteur.php index 1adb7e5..dbb5c8b 100644 --- a/php/inc_fx_promoteur.php +++ b/php/inc_fx_promoteur.php @@ -6337,15 +6337,20 @@ function fxBibSqlNoBibUnsigned($strColumn = 'no_bib') { /** * SQL — nombre d'unités partageant un no_bib pour une épreuve. * Solo / équipe « dossards individuels » : une personne = une unité (COUNT participants). - * Équipe « 1 équipe = 1 dossard » (epr_bib_team_mode = 3) : une équipe = une unité (DISTINCT pec_id). + * Équipe « 1 équipe = 1 dossard » (epr_bib_team_mode = 3) : une équipe = une unité (nom d'équipe). */ function fxBibSqlDuplicateUnitCount($strEprIdExpr, $strBibNumExpr) { $strBibP2 = fxBibSqlNoBibUnsigned('p2.no_bib'); $strTeamMode = "(SELECT CASE WHEN e.epr_equipe = 1 THEN IFNULL(NULLIF(e.epr_bib_team_mode, 0), 1) ELSE 1 END FROM inscriptions_epreuves e WHERE e.epr_id = ($strEprIdExpr) LIMIT 1)"; + $strTeamName = "TRIM(IFNULL(NULLIF(c2.pec_nom_equipe, ''), IFNULL(p2.par_nom_equipe, '')))"; + $strTeamUnit = "IF($strTeamName <> '', LOWER($strTeamName), CONCAT('pec:', IF(p2.pec_id > 0, p2.pec_id, p2.par_id)))"; return "(CASE WHEN $strTeamMode = 3 THEN ( - SELECT COUNT(DISTINCT IF(p2.pec_id > 0, p2.pec_id, p2.par_id)) + SELECT COUNT(DISTINCT $strTeamUnit) FROM resultats_participants p2 + LEFT JOIN resultats_epreuves_commandees c2 + ON c2.pec_id_original = p2.pec_id + AND c2.epr_id = p2.epr_id WHERE p2.epr_id = ($strEprIdExpr) AND $strBibP2 = ($strBibNumExpr) AND p2.is_cancelled = 0 @@ -7939,20 +7944,23 @@ function fxAssignAutoBibForParticipant($epr_id, $par_id) { $teamMode = 1; } - $teamKey = fxGetBatchTeamKey($p); $foundBib = null; $teamNumber = 0; - // Mode équipe 3 : reprendre le dossard déjà posé sur un coéquipier. - if ($isTeamEvent && $teamMode === 3 && $teamKey > 0) { - $existingBib = fxGetExistingTeamBibInDb($epr_id, $teamKey); + // Mode équipe 3 : reprendre le dossard déjà posé sur un coéquipier (même nom d'équipe). + $strShareKey = ''; + if ($isTeamEvent && $teamMode === 3) { + $strShareKey = fxGetBatchTeamShareKey($p); + if ($strShareKey !== '') { + $existingBib = fxGetExistingTeamBibByShareKeyInDb($epr_id, $p); - if ($existingBib !== null && (int)$existingBib > 0) { - $foundBib = (int)$existingBib; - $teamNumber = $foundBib; + if ($existingBib !== null && (int)$existingBib > 0) { + $foundBib = (int)$existingBib; + $teamNumber = $foundBib; - if (fxApplyBatchParticipantBib($epr_id, $par_id, $foundBib) <= 0) { - return ['success' => false, 'message' => 'assignation équipe impossible']; + if (fxApplyBatchParticipantBib($epr_id, $par_id, $foundBib) <= 0) { + return ['success' => false, 'message' => 'assignation équipe impossible']; + } } } } @@ -7991,6 +7999,7 @@ function fxAssignAutoBibForParticipant($epr_id, $par_id) { return ['success' => false, 'message' => 'aucun dossard disponible']; } + $teamKey = fxGetBatchTeamKey($p); if ($isTeamEvent && $teamKey > 0) { $updatedTeams = []; @@ -8056,18 +8065,23 @@ function fxInfosBibEpreuve($epr_id){ && (int)($tabEpreuve['epr_bib_team_mode'] ?? 1) === 3; if ($blnTeamOneBib) { - // MSIN-4432 — aligné sur fxGetQuantites / fxCountBatchAssignUnits : une équipe = une unité. + // MSIN-4379 — 1 équipe = 1 dossard : unité = nom d'équipe (repli pec_id si nom vide). + $strTeamName = "TRIM(IFNULL(NULLIF(c.pec_nom_equipe, ''), IFNULL(p.par_nom_equipe, '')))"; + $strTeamUnit = "IF($strTeamName <> '', LOWER($strTeamName), CONCAT('pec:', p.pec_id))"; $sql = " SELECT - COUNT(DISTINCT p.pec_id) AS total, + COUNT(DISTINCT $strTeamUnit) AS total, COUNT(DISTINCT CASE - WHEN p.no_bib IS NOT NULL AND p.no_bib > 0 THEN p.pec_id + WHEN p.no_bib IS NOT NULL AND p.no_bib > 0 THEN $strTeamUnit ELSE NULL END) AS avec_bib FROM resultats_participants p + LEFT JOIN resultats_epreuves_commandees c + ON c.pec_id_original = p.pec_id + AND c.epr_id = p.epr_id WHERE p.epr_id = $epr_id AND p.is_cancelled = 0 - AND p.pec_id > 0 + AND p.rol_id NOT IN (3, 4) "; $row = $objDatabase->fxGetRow($sql); $intTotal = (int)($row['total'] ?? 0); @@ -8899,9 +8913,7 @@ function fxBuildBatchAssignmentRow($p, $foundBib, $teamNumber) { } /** - * MSIN-4379 — Clé d'équipe pour le batch. - * Source de vérité = p.pec_id (tous les coéquipiers partagent le même). - * pec_id_original (jointure) n'est qu'un repli si pec_id absent. + * MSIN-4379 — Clé pec pour dossards individuels / écriture no_equipe sur la commande. */ function fxGetBatchTeamKey($p) { $intPec = (int)($p['pec_id'] ?? 0); @@ -8912,9 +8924,39 @@ function fxGetBatchTeamKey($p) { return (int)($p['pec_id_original'] ?? 0); } +/** + * MSIN-4379 — Nom d'équipe affiché (colonne Équipe), source pour « 1 équipe = 1 dossard ». + */ +function fxGetBatchTeamDisplayName($p) { + $str = trim((string)($p['pec_nom_equipe'] ?? '')); + if ($str === '') { + $str = trim((string)($p['par_nom_equipe'] ?? '')); + } + + return $str; +} + +/** + * MSIN-4379 — Clé de partage mode 3 : nom d'équipe (insensible à la casse). + * Sans nom → pec_id seul (ne fusionne pas tous les « sans nom » ensemble). + */ +function fxGetBatchTeamShareKey($p) { + $strName = fxGetBatchTeamDisplayName($p); + if ($strName !== '') { + if (function_exists('mb_strtolower')) { + return 'n:' . mb_strtolower($strName, 'UTF-8'); + } + + return 'n:' . strtolower($strName); + } + + $intPec = fxGetBatchTeamKey($p); + + return $intPec > 0 ? 'p:' . $intPec : ''; +} + /** * MSIN-4379 — Persiste le mode équipe envoyé par l'UI (Simuler / GO). - * Évite la course : radio cochée mais save_team_mode AJAX pas encore terminé. * * @return int Mode effectif (1 ou 3), 0 si rien à appliquer */ @@ -8939,7 +8981,57 @@ function fxBibSyncTeamModeFromRequest($epr_id) { } /** - * MSIN-4433 — Mode équipe 3 : dossard déjà posé sur un coéquipier (batch par paquets). + * MSIN-4433 / MSIN-4379 — Mode 3 : dossard déjà posé sur un coéquipier (même nom d'équipe). + */ +function fxGetExistingTeamBibByShareKeyInDb($epr_id, $p) { + global $objDatabase; + + $epr_id = (int)$epr_id; + $sqlBibNum = fxBibSqlNoBibUnsigned('p.no_bib'); + $strName = fxGetBatchTeamDisplayName($p); + $strEscName = $objDatabase->fxEscape($strName); + + if ($epr_id <= 0) { + return null; + } + + if ($strName !== '') { + $sql = " + SELECT $sqlBibNum + FROM resultats_participants p + LEFT JOIN resultats_epreuves_commandees c + ON c.pec_id_original = p.pec_id + AND c.epr_id = p.epr_id + WHERE p.epr_id = $epr_id + AND p.is_cancelled = 0 + AND $sqlBibNum > 0 + AND LOWER(TRIM(IFNULL(NULLIF(c.pec_nom_equipe, ''), IFNULL(p.par_nom_equipe, '')))) + = LOWER('$strEscName') + LIMIT 1 + "; + } else { + $teamKey = fxGetBatchTeamKey($p); + if ($teamKey <= 0) { + return null; + } + $sql = " + SELECT $sqlBibNum + FROM resultats_participants p + WHERE p.epr_id = $epr_id + AND p.pec_id = $teamKey + AND p.is_cancelled = 0 + AND $sqlBibNum > 0 + LIMIT 1 + "; + } + + $bib = (int)$objDatabase->fxGetVar($sql); + + return $bib > 0 ? $bib : null; +} + +/** + * @deprecated MSIN-4379 — préférer fxGetExistingTeamBibByShareKeyInDb (nom d'équipe). */ function fxGetExistingTeamBibInDb($epr_id, $teamKey) { global $objDatabase; @@ -9027,24 +9119,29 @@ function fxCountBatchAssignUnits($epr_id, $participants = null) { $teams = []; foreach ($participants as $p) { - $teamKey = fxGetBatchTeamKey($p); + $strShareKey = fxGetBatchTeamShareKey($p); - if ($teamKey > 0) { - $teams[$teamKey] = true; + if ($strShareKey !== '') { + $teams[$strShareKey] = true; } } return count($teams); } + $strTeamName = "TRIM(IFNULL(NULLIF(c.pec_nom_equipe, ''), IFNULL(p.par_nom_equipe, '')))"; + $strTeamUnit = "IF($strTeamName <> '', LOWER($strTeamName), CONCAT('pec:', p.pec_id))"; + return (int)$objDatabase->fxGetVar(" - SELECT COUNT(DISTINCT p.pec_id) + SELECT COUNT(DISTINCT $strTeamUnit) FROM resultats_participants p + LEFT JOIN resultats_epreuves_commandees c + ON c.pec_id_original = p.pec_id + AND c.epr_id = p.epr_id WHERE p.epr_id = $epr_id AND p.is_cancelled = 0 AND (p.no_bib IS NULL OR p.no_bib = '' OR p.no_bib = 0) AND p.rol_id NOT IN (3, 4) - AND p.pec_id > 0 "); } @@ -9107,12 +9204,17 @@ function fxProcessBatchAssignmentsEquipe($epr_id, $participants, $tabRanges, $mo $teamNumber = 0; $foundBib = null; - // MSIN-4379 — Mode 1 équipe = 1 dossard : un numéro pour toute l'équipe (même pec_id). - if ($teamMode === 3 && $teamKey > 0) { - if (isset($teamBibMap[$teamKey])) { - $foundBib = $teamBibMap[$teamKey]; + // MSIN-4379 — Mode 1 équipe = 1 dossard : regrouper sur le NOM d'équipe (colonne Équipe). + if ($teamMode === 3) { + $strShareKey = fxGetBatchTeamShareKey($p); + if ($strShareKey === '') { + continue; + } + + if (isset($teamBibMap[$strShareKey])) { + $foundBib = $teamBibMap[$strShareKey]; } else { - $foundBib = fxGetExistingTeamBibInDb($epr_id, $teamKey); + $foundBib = fxGetExistingTeamBibByShareKeyInDb($epr_id, $p); } if ($foundBib === null) { @@ -9127,14 +9229,16 @@ function fxProcessBatchAssignmentsEquipe($epr_id, $participants, $tabRanges, $mo if ($foundBib === null) { break; } - // Premier membre déjà écrit en execute par fxTryAssignNextBibForParticipant. if ($mode === 'execute') { $processedParIds[$par_id] = true; $assignments[] = fxBuildBatchAssignmentRow($p, $foundBib, $foundBib); + if ($teamKey > 0) { + fxApplyBatchTeamNumber($epr_id, $teamKey, $foundBib, $updatedTeams); + } } } - $teamBibMap[$teamKey] = (int)$foundBib; + $teamBibMap[$strShareKey] = (int)$foundBib; $teamNumber = (int)$foundBib; foreach ($participants as $mate) { @@ -9142,23 +9246,22 @@ function fxProcessBatchAssignmentsEquipe($epr_id, $participants, $tabRanges, $mo if ($mateId <= 0 || isset($processedParIds[$mateId])) { continue; } - if (fxGetBatchTeamKey($mate) !== $teamKey) { + if (fxGetBatchTeamShareKey($mate) !== $strShareKey) { continue; } if ($mode === 'execute') { - // 0 affected = déjà ce dossard (paquet précédent) : OK, on continue le regroupement. fxApplyBatchParticipantBib($epr_id, $mateId, $teamNumber); + $matePec = fxGetBatchTeamKey($mate); + if ($matePec > 0) { + fxApplyBatchTeamNumber($epr_id, $matePec, $teamNumber, $updatedTeams); + } } $assignments[] = fxBuildBatchAssignmentRow($mate, $teamNumber, $teamNumber); $processedParIds[$mateId] = true; } - if ($mode === 'execute') { - fxApplyBatchTeamNumber($epr_id, $teamKey, $teamNumber, $updatedTeams); - } - continue; } diff --git a/php/inc_settings.php b/php/inc_settings.php index 13aa47a..2c9ed19 100644 --- a/php/inc_settings.php +++ b/php/inc_settings.php @@ -7,7 +7,7 @@ * Constantes * * **************/ -define('_VERSION_CODE', '4.72.911'); // MSIN-4379 — GO batch 1 équipe = 1 dossard (mode UI + regroupement) +define('_VERSION_CODE', '4.72.912'); // MSIN-4379 — 1 équipe = 1 dossard : regroupement sur nom d'équipe define('_DATE_CODE', '2026-07-30'); //MSIN-4290 define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe');