682 lines
16 KiB
PHP
682 lines
16 KiB
PHP
<?php
|
||
session_start();
|
||
|
||
// MSIN-4379 — Contexte traduction = compte.php (pas ajax_bib_range.php) ; pas d'auto-création info en AJAX.
|
||
define('MS1_BIB_AJAX', true);
|
||
$_SERVER['PHP_SELF'] = '/compte.php';
|
||
|
||
require_once('php/inc_fonctions.php');
|
||
require_once('php/inc_fx_promoteur.php');
|
||
global $objDatabase, $vPage, $strLangue, $vtexte_page;
|
||
|
||
if (empty($strLangue)) {
|
||
$strLangue = $_SESSION['lang'] ?? 'fr';
|
||
}
|
||
$vPage = 'compte.php';
|
||
$vtexte_page = obtenirTextepage($vPage, $strLangue, 2);
|
||
|
||
header('Content-Type: application/json; charset=utf-8');
|
||
|
||
$action = $_REQUEST['action'] ?? '';
|
||
|
||
|
||
// =====================
|
||
// CREATE
|
||
// =====================
|
||
if ($action == 'create') {
|
||
|
||
$epr_id = intval($_REQUEST['epr_id'] ?? 0);
|
||
|
||
if ($epr_id > 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, $epr_id);
|
||
|
||
$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, $epr_id);
|
||
|
||
$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;
|
||
}
|
||
|
||
// MSIN-4379 — Étape 2
|
||
// Endpoint AJAX : sauvegarde ou désactivation de la config auto (epr_bib_auto).
|
||
// Paramètres : epr_id, active (0|1), ranges (JSON des epr_bib_id), csrf_token.
|
||
// Prochain tour : étape 6–7 (assignation réelle à l'achat, sans passer par cet endpoint).
|
||
if ($action == 'save_auto_config') {
|
||
|
||
if (!fxBibRequirePromoteurSession()) {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => 'Session invalide'
|
||
]);
|
||
exit;
|
||
}
|
||
|
||
if (!fxBibValidateCsrf($_POST['csrf_token'] ?? '')) {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => 'Requête non autorisée'
|
||
]);
|
||
exit;
|
||
}
|
||
|
||
$epr_id = intval($_POST['epr_id'] ?? 0);
|
||
$active = intval($_POST['active'] ?? 1) === 1;
|
||
$ranges = json_decode($_POST['ranges'] ?? '[]', true);
|
||
|
||
if ($epr_id <= 0) {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => 'epr_id invalide'
|
||
]);
|
||
exit;
|
||
}
|
||
|
||
$result = fxSaveBibAutoConfig($epr_id, is_array($ranges) ? $ranges : [], $active);
|
||
|
||
if (!$result['success']) {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => $result['message'] ?? 'Erreur'
|
||
]);
|
||
exit;
|
||
}
|
||
|
||
$tabBibStats = fxInfosBibRange($epr_id);
|
||
|
||
echo json_encode([
|
||
'success' => true,
|
||
'auto_active' => !empty($result['auto_active']),
|
||
'html' => renderBibRanges($tabBibStats, $epr_id, 'assign')
|
||
]);
|
||
exit;
|
||
}
|
||
|
||
// =====================
|
||
// ACTION INVALIDE
|
||
// =====================
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => 'Action invalide'
|
||
]);
|
||
exit; |