0) { // ⚠️ On ne crée PLUS en DB // On récupère les ranges existants AVEC stats $tabBibRanges = fxInfosBibRange($epr_id); // 👉 On ajoute UNE ligne vide (UI seulement) $tabBibRanges[] = [ 'epr_bib_id' => 0, // ID temporaire 'epr_id' => $epr_id, 'epr_bib_start' => '', 'epr_bib_finish' => '', 'dernier_bib' => '', 'nb_utilises' => '', 'liste_trous' => '', 'liste_doublons' => '' ]; echo json_encode([ 'success' => true, 'html' => renderBibRanges($tabBibRanges, $epr_id), 'error' => '' ]); exit; } echo json_encode([ 'success' => false, 'message' => 'epr_id invalide' ]); exit; } // ===================== // DELETE // ===================== if ($action == 'delete') { $id = intval($_REQUEST['id'] ?? 0); if ($id > 0) { $range = fxInfosBibRange(0,$id); $epr_id = $range[1]["epr_id"]; if (!$range) { echo json_encode([ 'success' => false, 'message' => 'Range introuvable' ]); exit; } if ((int)$range[1]['nb_utilises'] > 0) { echo json_encode([ 'success' => false, 'message' => 'Impossible de supprimer : des dossards sont déjà utilisés dans ce range' ]); exit; } $sql = " DELETE FROM inscriptions_epreuves_bib WHERE epr_bib_id = $id "; $objDatabase->fxQuery($sql); $tabBibRanges = fxInfosBibRange($epr_id); echo json_encode([ 'success' => true, 'html' => renderBibRanges($tabBibRanges,$epr_id), 'error' => '' ]); exit; } echo json_encode([ 'success' => false, 'message' => 'id invalide' ]); exit; } // ===================== // SAVE // ===================== if ($action == 'save') { $id = intval($_REQUEST['id'] ?? 0); $epr_id = intval($_REQUEST['epr_id'] ?? 0); $start = intval($_REQUEST['start'] ?? 0); $end = intval($_REQUEST['end'] ?? 0); $is_new = ($id == 0); // ===================== // VALIDATION 1 — epr_id // ===================== if ($is_new && $epr_id <= 0) { echo json_encode(['success' => false, 'message' => 'epr_id invalide']); exit; } // ===================== // recherche eve_id // ===================== $sqlGet = "SELECT eve_id FROM inscriptions_epreuves WHERE epr_id = $epr_id"; $eve_id = (int)$objDatabase->fxGetVar($sqlGet); // ===================== // VALIDATION 2 — VALEURS NUMÉRIQUES // ===================== if ($start <= 0 || $end <= 0) { echo json_encode(['success' => false, 'message' => 'Valeurs invalides']); exit; } // ===================== // VALIDATION 3 — LOGIQUE INTERVALLE // ===================== if ($start > $end) { echo json_encode(['success' => false, 'message' => 'Début doit être < fin']); exit; } // ===================== // RÉCUPÉRER epr_id + PROTÉGER LES DOSSARDS SI UPDATE // ===================== if (!$is_new) { $sqlGet = "SELECT epr_id FROM inscriptions_epreuves_bib WHERE epr_bib_id = $id"; $epr_id = (int)$objDatabase->fxGetVar($sqlGet); if ($epr_id <= 0) { echo json_encode(['success' => false, 'message' => 'Range introuvable']); exit; } $sqlCheckOrphans = " SELECT COUNT(*) FROM resultats_participants rp INNER JOIN inscriptions_epreuves_bib b ON b.epr_bib_id = $id WHERE rp.epr_id = b.epr_id AND rp.no_bib BETWEEN b.epr_bib_start AND b.epr_bib_finish AND ( rp.no_bib < $start OR rp.no_bib > $end ) "; $nbOrphans = (int)$objDatabase->fxGetVar($sqlCheckOrphans); if ($nbOrphans > 0) { echo json_encode([ 'success' => false, 'message' => 'Modification impossible : des dossards sortiraient du range' ]); exit; } } // ===================== // VALIDATION 4 — OVERLAP pas de double epreuves // ===================== $sqlOverlap = " SELECT COUNT(*) FROM inscriptions_epreuves_bib WHERE eve_id = $eve_id AND epr_bib_start IS NOT NULL AND epr_bib_finish IS NOT NULL " . (!$is_new ? "AND epr_bib_id <> $id" : "") . " AND ( $start <= epr_bib_finish AND $end >= epr_bib_start ) "; $hasOverlap = (int)$objDatabase->fxGetVar($sqlOverlap); if ($hasOverlap > 0) { echo json_encode([ 'success' => false, 'message' => 'Conflit avec un autre intervalle de dossards' ]); exit; } // ===================== // INSERT OU UPDATE // ===================== if ($is_new) { $sql = " INSERT INTO inscriptions_epreuves_bib (epr_id, epr_bib_start, epr_bib_finish, update_date, update_qui, eve_id) VALUES ($epr_id, $start, $end, NOW(), 'admin', $eve_id) "; } else { $sql = " UPDATE inscriptions_epreuves_bib SET epr_bib_start = $start, epr_bib_finish = $end, update_date = NOW(), eve_id = $eve_id WHERE epr_bib_id = $id "; } $objDatabase->fxQuery($sql); // ===================== // RELOAD HTML // ===================== $tabBibRanges = fxInfosBibRange($epr_id); echo json_encode([ 'success' => true, 'html' => renderBibRanges($tabBibRanges, $epr_id) ]); exit; } // ===================== // VIEW // ===================== if ($action == 'view') { $epr_id = intval($_REQUEST['epr_id'] ?? 0); $range_id = intval($_REQUEST['range_id'] ?? 0); if ($epr_id <= 0 || $range_id < 0) { echo json_encode([ 'success' => false, 'message' => 'Paramètres invalides' ]); exit; } // TEMPORAIRE : affichage simple pour test ob_start(); $html = renderBibView($epr_id, $range_id); echo json_encode([ 'success' => true, 'html' => $html ]); exit; } // ===================== // ANALYSE BATCH // ===================== if ($action == 'batch_analysis') { $epr_id = intval($_POST['epr_id'] ?? 0); if ($epr_id <= 0) { echo json_encode([ 'success' => false, 'message' => 'epr_id invalide' ]); exit; } $infoBib = fxInfosBibEpreuve($epr_id); echo json_encode([ 'success' => true, 'info' => $infoBib ]); exit; } if ($action == 'refresh_ranges') { $epr_id = intval($_POST['epr_id'] ?? $_GET['epr_id'] ?? 0); $mode = $_POST['mode'] ?? $_GET['mode'] ?? 'assign'; if ($epr_id <= 0) { echo json_encode([ 'success' => false, 'message' => 'epr_id invalide' ]); exit; } $tabBibStats = fxInfosBibRange($epr_id); echo json_encode([ 'success' => true, 'html' => renderBibRanges($tabBibStats, $epr_id, $mode) ]); exit; } if ($action == 'refresh_ranges_data') { $epr_id = intval($_POST['epr_id'] ?? 0); if ($epr_id <= 0) { echo json_encode(['success' => false]); exit; } $tab = fxInfosBibRange($epr_id); $out = []; foreach ($tab as $r) { $nb_total = $r['nb_total_range'] ?? 0; $nb_used = (int)($r['nb_utilises'] ?? 0); $out[] = [ 'id' => (int)$r['epr_bib_id'], 'last' => (int)$r['dernier_bib'], 'used' => $nb_used, 'dispo' => $nb_total - $nb_used, 'trous' => $r['liste_trous'] ?? '', 'doublons' => $r['liste_doublons'] ?? '' ]; } echo json_encode([ 'success' => true, 'ranges' => $out ]); exit; } // ===================== // BATCH GO (DEBUG SEULEMENT) // ===================== // Objectif : // - recevoir les données du bouton GO // - NE RIEN ÉCRIRE en DB // - retourner les infos pour validation if ($action == 'batch_go') { // ID de l’épreuve $epr_id = intval($_POST['epr_id'] ?? 0); // Liste des ranges sélectionnés (JSON → array PHP) $ranges = json_decode($_POST['ranges'] ?? '[]', true); // Ordre choisi (table bib_assignements) $ba_id = intval($_POST['ba_id'] ?? 0); // DEBUG : on retourne tout pour validation // ===================== // TEST fxGetParticipantsForBatchAssign // ===================== $participants = fxGetParticipantsForBatchAssign($epr_id, $ba_id); // ===================== // UTILISER LA FONCTION PROPRE // ===================== $tabRanges = fxGetRangesForBatchAssign($epr_id, $ranges); $tabRangesInfos = fxInfosBibRange($epr_id); // ← ICI $ids = array_map('intval', $ranges); $tabRangesInfos = array_filter($tabRangesInfos, function($r) use ($ids) { return in_array((int)$r['epr_bib_id'], $ids); }); $nextBib = fxGetNextAvailableBib($epr_id, $tabRanges); $simu = fxProcessBatchAssignments($epr_id, $participants, $tabRanges, 'simulation'); $summary = fxBuildBatchSummaryFromRanges($tabRangesInfos, $participants); $info = "{$summary['nb_dispo']} disponibles / {$summary['nb_participants']} à assigner → manque {$summary['nb_manque']}"; // ===================== // SIMULATION (temporaire simple) // ===================== // ===================== // RENDER VIEW EN MODE SIMULATION // ===================== $html = renderBibView( $epr_id, 0, 'fr', 'simulation', $simu, 'Résultats de la simulation', $info ); echo json_encode([ 'success' => true, 'html' => $html ]); exit; } if ($action == 'batch_apply') { // ===================== // GO BATCH (EXÉCUTION RÉELLE) // - Assigne les BIB en DB // - Utilise fxProcessBatchAssignments en mode 'execute' // - Affiche le résultat réel ($exec), pas de simulation // ===================== $epr_id = intval($_POST['epr_id'] ?? 0); $ranges = json_decode($_POST['ranges'] ?? '[]', true); $ba_id = intval($_POST['ba_id'] ?? 0); $participants = fxGetParticipantsForBatchAssign($epr_id, $ba_id); $tabRanges = fxGetRangesForBatchAssign($epr_id, $ranges); $exec = fxProcessBatchAssignments($epr_id, $participants, $tabRanges, 'execute'); $tabRangesInfos = fxInfosBibRange($epr_id); $ids = array_map('intval', $ranges); $tabRangesInfos = array_filter($tabRangesInfos, function($r) use ($ids) { return in_array((int)$r['epr_bib_id'], $ids); }); $summary = fxBuildBatchSummaryFromRanges($tabRangesInfos, $participants); $assigned = count($exec); $total = count($participants); $remaining = max(0, $total - $assigned); $status = 'success'; if ($assigned === 0) { $status = 'error'; } elseif ($assigned < $total) { $status = 'partial'; } if ($assigned === 0) { $info = "Aucun dossard n’a pu être assigné."; } elseif ($assigned === $total) { $info = "Assignation complétée : $assigned dossards assignés avec succès."; } else { $info = "Assignation partielle complétée : $assigned dossards assignés avec succès. $remaining participants restent à assigner."; } $html = renderBibView( $epr_id, 0, 'fr', 'execute', $exec, 'Résultats de l’assignation', $info,$status ); echo json_encode([ 'success' => true, 'html' => $html ]); exit; } // ===================== // RESET PREVIEW // ===================== if ($action == 'reset_preview') { $epr_id = intval($_POST['epr_id'] ?? 0); $ranges = json_decode($_POST['ranges'] ?? '[]', true); $participants = fxGetParticipantsForBatchReset($epr_id, $ranges); $html = renderBibView( $epr_id, 0, 'fr', 'reset', $participants, 'Prévisualisation de la réinitialisation', count($participants) . ' dossards seront retirés', 'warning' ); echo json_encode([ 'success' => true, 'html' => $html ]); exit; } // ===================== // RESET APPLY // ===================== if ($action == 'reset_apply') { $epr_id = intval($_POST['epr_id'] ?? 0); $ranges = json_decode($_POST['ranges'] ?? '[]', true); $participants = fxGetParticipantsForBatchReset($epr_id, $ranges); $count = 0; foreach ($participants as $p) { $par_id = intval($p['par_id']); if ($par_id <= 0) { continue; } $sql = " UPDATE resultats_participants SET no_bib = NULL WHERE par_id = $par_id AND is_cancelled = 0 "; $objDatabase->fxQuery($sql); $count++; } $html = renderBibView( $epr_id, 0, 'fr', 'reset', $participants, 'Réinitialisation terminée', $count . ' dossards retirés', 'success' ); echo json_encode([ 'success' => true, 'html' => $html ]); exit; } // ===================== // SAVE TEAM MODE // ===================== if ($action == 'save_team_mode') { $epr_id = intval($_REQUEST['epr_id'] ?? 0); $team_mode = intval($_REQUEST['team_mode'] ?? 0); if ($epr_id <= 0 || !in_array($team_mode, [1, 2, 3])) { echo json_encode([ 'success' => false, 'message' => 'Paramètres invalides' ]); exit; } $sql = " UPDATE inscriptions_epreuves SET epr_bib_team_mode = $team_mode WHERE epr_id = $epr_id LIMIT 1 "; $objDatabase->fxQuery($sql); echo json_encode([ 'success' => true ]); exit; } // ===================== // ACTION INVALIDE // ===================== echo json_encode([ 'success' => false, 'message' => 'Action invalide' ]); exit;