From 26b658acf88eeeb059b6c3f5d25cc90fad7652fd Mon Sep 17 00:00:00 2001 From: stephan Date: Wed, 22 Jul 2026 14:14:52 -0400 Subject: [PATCH] =?UTF-8?q?MSIN-4445=20=E2=80=94=20Refactor=20free=20assig?= =?UTF-8?q?nment=20logic=20to=20allow=20all=20solo=20races=20(with=20or=20?= =?UTF-8?q?without=20existing=20sequences)=20to=20be=20assigned=20without?= =?UTF-8?q?=20creating=20new=20sequences.=20Update=20related=20functions?= =?UTF-8?q?=20and=20improve=20documentation=20for=20clarity.=20Increment?= =?UTF-8?q?=20version=20code=20to=204.72.863.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ajax_bib_range.php | 15 ++----- php/inc_fx_bib_global_free.php | 47 ++++++++++++++++++---- php/inc_fx_bib_global_generated.php | 30 ++++++++++++-- php/inc_fx_promoteur.php | 5 ++- php/inc_settings.php | 2 +- sql/MSIN-4445-bib-global-free-all-solo.sql | 15 +++++++ 6 files changed, 88 insertions(+), 26 deletions(-) create mode 100644 sql/MSIN-4445-bib-global-free-all-solo.sql diff --git a/ajax_bib_range.php b/ajax_bib_range.php index 5ec5b8f..70dcc05 100644 --- a/ajax_bib_range.php +++ b/ajax_bib_range.php @@ -735,7 +735,7 @@ if ($action == 'batch_global_free_analysis') { $intEnd = (int)($_POST['end_bib'] ?? 0); list($strSort1, $strSort2) = fxBibParseBatchSortFromPost(); $eprIds = json_decode($_POST['epr_ids'] ?? '[]', true); - $tabEprIds = fxBibParseGlobalBatchGeneratedEprIds(is_array($eprIds) ? $eprIds : [], $int_eve_id); + $tabEprIds = fxBibParseGlobalBatchFreeEprIds(is_array($eprIds) ? $eprIds : [], $int_eve_id); if ($int_eve_id <= 0 || $intStart <= 0 || $intEnd < $intStart) { echo json_encode([ @@ -785,7 +785,7 @@ if ($action == 'batch_global_free_simulate') { $intEnd = (int)($_POST['end_bib'] ?? 0); list($strSort1, $strSort2) = fxBibParseBatchSortFromPost(); $eprIds = json_decode($_POST['epr_ids'] ?? '[]', true); - $tabEprIds = fxBibParseGlobalBatchGeneratedEprIds(is_array($eprIds) ? $eprIds : [], $int_eve_id); + $tabEprIds = fxBibParseGlobalBatchFreeEprIds(is_array($eprIds) ? $eprIds : [], $int_eve_id); if ($int_eve_id <= 0 || $intStart <= 0 || $intEnd < $intStart || $strSort1 === '' || empty($tabEprIds)) { echo json_encode([ @@ -818,7 +818,7 @@ if ($action == 'batch_global_free_plan') { $intEnd = (int)($_POST['end_bib'] ?? 0); list($strSort1, $strSort2) = fxBibParseBatchSortFromPost(); $eprIds = json_decode($_POST['epr_ids'] ?? '[]', true); - $tabEprIds = fxBibParseGlobalBatchGeneratedEprIds(is_array($eprIds) ? $eprIds : [], $int_eve_id); + $tabEprIds = fxBibParseGlobalBatchFreeEprIds(is_array($eprIds) ? $eprIds : [], $int_eve_id); if ($int_eve_id <= 0 || $intStart <= 0 || $intEnd < $intStart || $strSort1 === '' || empty($tabEprIds)) { echo json_encode([ @@ -1128,7 +1128,7 @@ if ($action == 'batch_apply_free_chunk') { exit; } - // Même filtre que le panneau : solo sans séquence. + // MSIN-4445 — Solo seulement ; une séquence existante n'empêche pas l'assignation libre. $intEveId = (int)($_POST['eve_id'] ?? 0); if ($intEveId > 0) { $checkEpr = fxBibAssertSoloEpreuveForGlobalBatch($epr_id, $intEveId); @@ -1136,13 +1136,6 @@ if ($action == 'batch_apply_free_chunk') { echo json_encode($checkEpr); exit; } - if (fxBibEpreuveHasAnySequence($epr_id)) { - echo json_encode([ - 'success' => false, - 'message' => fxBibMsg('bib_v4_global_batch_gen_has_seq'), - ]); - exit; - } } $strSessionKey = fxBibBatchExecSessionKey($epr_id) . '_free'; diff --git a/php/inc_fx_bib_global_free.php b/php/inc_fx_bib_global_free.php index 901890b..1dd9938 100644 --- a/php/inc_fx_bib_global_free.php +++ b/php/inc_fx_bib_global_free.php @@ -142,6 +142,43 @@ function fxBibFreeDuplicateRisk($int_eve_id, $tabPlan, $intStart = 0, $intEnd = ]; } +/** + * MSIN-4445 — Valide et ordonne les epr_id du bloc libre (solo, avec ou sans séquence). + * + * @return int[] + */ +function fxBibParseGlobalBatchFreeEprIds($eprIds, $int_eve_id) { + if (!is_array($eprIds)) { + return []; + } + + $int_eve_id = (int)$int_eve_id; + $tabWanted = []; + + foreach ($eprIds as $epr_id) { + $epr_id = (int)$epr_id; + if ($epr_id <= 0) { + continue; + } + + $check = fxBibAssertSoloEpreuveForGlobalBatch($epr_id, $int_eve_id); + if (!$check['success']) { + continue; + } + + $tabWanted[$epr_id] = true; + } + + if (empty($tabWanted)) { + return []; + } + + $tabIds = array_keys($tabWanted); + sort($tabIds, SORT_NUMERIC); + + return $tabIds; +} + /** * Plan de plages virtuelles bornées par Début/Fin (sans écriture BD). * Enchaîne les épreuves comme le bloc généré, mais s'arrête à $intEnd. @@ -152,7 +189,7 @@ function fxBibBuildFreeRangePlan($int_eve_id, $tabEprIds, $intStart, $intEnd, $s $int_eve_id = (int)$int_eve_id; $intStart = (int)$intStart; $intEnd = (int)$intEnd; - $tabEprIds = fxBibParseGlobalBatchGeneratedEprIds($tabEprIds, $int_eve_id); + $tabEprIds = fxBibParseGlobalBatchFreeEprIds($tabEprIds, $int_eve_id); $intCursor = $intStart; $tabPlan = []; @@ -242,13 +279,7 @@ function fxBibValidateFreeRangePlan($int_eve_id, $tabPlan, $intStart, $intEnd, $ ]; } - if (fxBibEpreuveHasAnySequence($epr_id)) { - return [ - 'success' => false, - 'message' => fxBibMsg('bib_v4_global_batch_gen_has_seq'), - ]; - } - + // MSIN-4445 — OK même si une séquence existe déjà (aucune création de séquence). $blnHasAssignable = true; } diff --git a/php/inc_fx_bib_global_generated.php b/php/inc_fx_bib_global_generated.php index 5218138..4ba33f6 100644 --- a/php/inc_fx_bib_global_generated.php +++ b/php/inc_fx_bib_global_generated.php @@ -25,11 +25,12 @@ function fxBibEpreuveHasAnySequence($epr_id) { } /** - * Épreuves solo sans aucune séquence, triées par epr_id (ordre page). + * Épreuves solo actives (avec ou sans séquence), triées par epr_id. + * MSIN-4445 — utilisé par l'assignation libre. * * @return array[] lignes inscriptions_epreuves */ -function fxBibGetSoloEpreuvesWithoutSequence($int_eve_id, $tabEpreuves = null) { +function fxBibGetSoloEpreuves($int_eve_id, $tabEpreuves = null) { global $objDatabase; $int_eve_id = (int)$int_eve_id; @@ -52,6 +53,21 @@ function fxBibGetSoloEpreuvesWithoutSequence($int_eve_id, $tabEpreuves = null) { continue; } + $out[] = $epr; + } + + return $out; +} + +/** + * Épreuves solo sans aucune séquence, triées par epr_id (ordre page). + * + * @return array[] lignes inscriptions_epreuves + */ +function fxBibGetSoloEpreuvesWithoutSequence($int_eve_id, $tabEpreuves = null) { + $out = []; + + foreach (fxBibGetSoloEpreuves($int_eve_id, $tabEpreuves) as $epr) { if (fxBibEpreuveHasAnySequence((int)$epr['epr_id'])) { continue; } @@ -90,10 +106,16 @@ function fxBibGlobalBatchHasGeneratedBlock($int_eve_id, $tabEpreuves) { return count(fxBibGetSoloEpreuvesWithoutSequence($int_eve_id, $tabEpreuves)) >= 1; } -/** Tuile / coquille assignation globale visible si l'un des deux blocs est utilisable. */ +/** MSIN-4445 — Bloc libre : au moins 1 épreuve solo (avec ou sans séquence). */ +function fxBibGlobalBatchHasFreeBlock($int_eve_id, $tabEpreuves) { + return count(fxBibGetSoloEpreuves($int_eve_id, $tabEpreuves)) >= 1; +} + +/** Tuile / coquille assignation globale visible si l'un des blocs est utilisable. */ function fxBibGlobalBatchToolIsAvailable($int_eve_id, $tabEpreuves) { return fxBibGlobalBatchHasExistingBlock($int_eve_id, $tabEpreuves) - || fxBibGlobalBatchHasGeneratedBlock($int_eve_id, $tabEpreuves); + || fxBibGlobalBatchHasGeneratedBlock($int_eve_id, $tabEpreuves) + || fxBibGlobalBatchHasFreeBlock($int_eve_id, $tabEpreuves); } /** diff --git a/php/inc_fx_promoteur.php b/php/inc_fx_promoteur.php index a78cfdf..63fe838 100644 --- a/php/inc_fx_promoteur.php +++ b/php/inc_fx_promoteur.php @@ -3602,7 +3602,7 @@ function fxBibStaticFallback($clef) { 'bib_v4_global_batch_go_complete_reload' => ['fr' => 'OK — Recharger la page', 'en' => 'OK — Reload page'], // MSIN-4445 — Assignation libre. 'bib_v4_global_batch_free_title' => ['fr' => 'Assignation libre', 'en' => 'Free assignment'], - 'bib_v4_global_batch_free_hint' => ['fr' => 'Épreuves solo sans séquence : choisissez Début et Fin (ou Qté). Les dossards sont assignés sans créer de séquence. Le Go reste disponible même si la quantité n\'est pas juste.', 'en' => 'Solo races without sequences: choose Start and End (or Qty). Bibs are assigned without creating a sequence. Go stays available even if the quantity is not exact.'], + 'bib_v4_global_batch_free_hint' => ['fr' => 'Toutes les épreuves solo : choisissez Début et Fin (ou Qté). Les dossards sont assignés sans créer de séquence, même si une séquence existe déjà. Le Go reste disponible même si la quantité n\'est pas juste.', 'en' => 'All solo races: choose Start and End (or Qty). Bibs are assigned without creating a sequence, even if a sequence already exists. Go stays available even if the quantity is not exact.'], 'bib_v4_global_batch_free_qty_juste' => ['fr' => 'Quantité juste', 'en' => 'Exact quantity'], 'bib_v4_global_batch_free_qty_manquante' => ['fr' => 'Quantité manquante : %d', 'en' => 'Missing quantity: %d'], 'bib_v4_global_batch_free_qty_supplementaire' => ['fr' => 'Quantité supplémentaire : %d', 'en' => 'Extra quantity: %d'], @@ -5542,10 +5542,11 @@ function renderBibGlobalBatchPanelGenerated($int_eve_id, $tabEpreuves, $strLangu /** * MSIN-4445 — Bloc assignation libre (Début/Qté/Fin, sans création de séquence). + * Liste toutes les épreuves solo, avec ou sans séquence existante. */ function renderBibGlobalBatchPanelFree($int_eve_id, $tabEpreuves, $strLangue) { $int_eve_id = (int)$int_eve_id; - $tabSolo = fxBibGetSoloEpreuvesWithoutSequence($int_eve_id, $tabEpreuves); + $tabSolo = fxBibGetSoloEpreuves($int_eve_id, $tabEpreuves); if (empty($tabSolo)) { return ''; diff --git a/php/inc_settings.php b/php/inc_settings.php index a637a96..6bff224 100644 --- a/php/inc_settings.php +++ b/php/inc_settings.php @@ -7,7 +7,7 @@ * Constantes * * **************/ -define('_VERSION_CODE', '4.72.862'); // MSIN-4473 +define('_VERSION_CODE', '4.72.863'); // MSIN-4445 — assignation libre : toutes épreuves solo define('_DATE_CODE', '2026-07-22'); //MSIN-4290 define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe'); diff --git a/sql/MSIN-4445-bib-global-free-all-solo.sql b/sql/MSIN-4445-bib-global-free-all-solo.sql new file mode 100644 index 0000000..0dccd26 --- /dev/null +++ b/sql/MSIN-4445-bib-global-free-all-solo.sql @@ -0,0 +1,15 @@ +-- MSIN-4445 — Assignation libre : toutes les épreuves solo (avec ou sans séquence) +-- Idempotent. Met à jour le hint Info du bloc libre. +-- Prérequis : sql/MSIN-4445-bib-global-free.sql déjà exécuté. + +UPDATE info +SET info_texte = 'Toutes les épreuves solo : choisissez Début et Fin (ou Qté). Les dossards sont assignés sans créer de séquence, même si une séquence existe déjà. Le Go reste disponible même si la quantité n''est pas juste.' +WHERE info_clef = 'bib_v4_global_batch_free_hint' + AND info_langue = 'fr' + AND info_prg = 'compte.php'; + +UPDATE info +SET info_texte = 'All solo races: choose Start and End (or Qty). Bibs are assigned without creating a sequence, even if a sequence already exists. Go stays available even if the quantity is not exact.' +WHERE info_clef = 'bib_v4_global_batch_free_hint' + AND info_langue = 'en' + AND info_prg = 'compte.php';