Implement reset all apply functionality for epreuve and update version code to 4.72.747
This commit introduces a new action, `reset_all_apply`, in the AJAX handler to reset all bib numbers for participants in a specified epreuve. It includes validation for locked ranges and updates the database accordingly. Additionally, new CSS styles are added for the reset button, and JavaScript functions are implemented to manage the button's state based on participant conditions. The version code is incremented to reflect these changes.
This commit is contained in:
@ -34,6 +34,7 @@ $arrBibAjaxActions = [
|
||||
'batch_apply_chunk',
|
||||
'reset_preview',
|
||||
'reset_apply',
|
||||
'reset_all_apply',
|
||||
'save_team_mode',
|
||||
'toggle_lock',
|
||||
'save_auto_config',
|
||||
@ -905,6 +906,72 @@ if ($action == 'reset_apply') {
|
||||
exit;
|
||||
}
|
||||
// =====================
|
||||
// RESET ALL ÉPREUVE
|
||||
// =====================
|
||||
if ($action == 'reset_all_apply') {
|
||||
|
||||
$epr_id = intval($_POST['epr_id'] ?? 0);
|
||||
|
||||
if ($epr_id <= 0) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => fxBibMsg('bib_v4_ajax_params_invalid'),
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$lockCheck = fxBibAssertEpreuveNoLockedRanges($epr_id);
|
||||
if (!$lockCheck['success']) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => $lockCheck['message'] ?? fxBibMsg('bib_v4_js_reset_all_locked'),
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$participants = fxGetParticipantsForEpreuveResetAll($epr_id);
|
||||
|
||||
$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,
|
||||
$strLangue,
|
||||
'reset',
|
||||
$participants,
|
||||
fxBibTexte('bib_v4_ajax_title_reset_all_done'),
|
||||
fxBibMsg('bib_v4_ajax_reset_done_count', $count),
|
||||
'success'
|
||||
);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'html' => $html,
|
||||
]);
|
||||
|
||||
exit;
|
||||
}
|
||||
// =====================
|
||||
// SAVE TEAM MODE
|
||||
// =====================
|
||||
if ($action == 'save_team_mode') {
|
||||
|
||||
@ -1288,6 +1288,22 @@ ul.ms1-menu-compte li a:hover, ul.ms1-menu-compte li a:active {
|
||||
margin-top:0;
|
||||
}
|
||||
|
||||
/* MSIN-4436 — Réinitialisation totale, sous l'en-tête identité. */
|
||||
.epr-identity-reset-all{
|
||||
flex-shrink:0;
|
||||
padding:6px 8px 8px;
|
||||
background:#fff;
|
||||
border-top:1px solid #e8edf5;
|
||||
}
|
||||
|
||||
.epr-identity-reset-all .btn-reset-all-epr{
|
||||
width:100%;
|
||||
white-space:normal;
|
||||
line-height:1.25;
|
||||
font-size:11px;
|
||||
padding:5px 8px;
|
||||
}
|
||||
|
||||
.epr-col-right{
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
|
||||
@ -1544,6 +1544,33 @@
|
||||
});
|
||||
}
|
||||
|
||||
function bibSyncResetAllEprButton(row) {
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
|
||||
let wrap = row.querySelector('.epr-identity-reset-all');
|
||||
if (!wrap) {
|
||||
return;
|
||||
}
|
||||
|
||||
let avecBib = parseInt(bibQuery(row, '.bib-avec')?.textContent || '0', 10) || 0;
|
||||
if (avecBib <= 0) {
|
||||
wrap.classList.add('bib-ui-hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
wrap.classList.remove('bib-ui-hidden');
|
||||
|
||||
let btn = wrap.querySelector('.btn-reset-all-epr');
|
||||
if (!btn) {
|
||||
return;
|
||||
}
|
||||
|
||||
let hasLock = row.querySelector('.btn-bib-lock--closed') !== null;
|
||||
btn.disabled = hasLock;
|
||||
}
|
||||
|
||||
function syncBibUiState(row) {
|
||||
if (!row) return;
|
||||
|
||||
@ -1599,6 +1626,7 @@
|
||||
bibSetVisible('.epr-batch-order-wrap', showBatchReady && !modes.reset, row);
|
||||
bibSetVisible('.epr-action-sim-group', showBatchReady && !modes.reset, row);
|
||||
bibSetVisible('.epr-action-go-group', showBatchReady, row);
|
||||
bibSyncResetAllEprButton(row);
|
||||
}
|
||||
|
||||
function updateBatchAnalysis(row) {
|
||||
@ -1903,12 +1931,65 @@
|
||||
|
||||
if (data.html) {
|
||||
setBibContainerHtml(row, data.html);
|
||||
bibSyncResetAllEprButton(row);
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// =====================
|
||||
// MSIN-4436 — Réinitialiser tous les dossards (épreuve entière)
|
||||
// =====================
|
||||
let btnResetAllEpr = e.target.closest('.btn-reset-all-epr');
|
||||
if (btnResetAllEpr) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
let row = btnResetAllEpr.closest('.epr-row');
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (btnResetAllEpr.disabled) {
|
||||
alert(bibJsConfirm('jsResetAllLocked'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (row.querySelector('.btn-bib-lock--closed')) {
|
||||
alert(bibJsConfirm('jsResetAllLocked'));
|
||||
bibSyncResetAllEprButton(row);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!confirm(bibJsConfirm('jsResetAllConfirm'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
bibFetch('/ajax_bib_range.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body:
|
||||
'action=reset_all_apply'
|
||||
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
|
||||
+ bibAjaxLangSuffix()
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
|
||||
if (!data.success) {
|
||||
alert(data.message || bibJs('jsErrGeneric'));
|
||||
return;
|
||||
}
|
||||
|
||||
bibAfterBatchGoSuccess(row, data, false);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// =====================
|
||||
// DELETE
|
||||
// =====================
|
||||
|
||||
@ -2742,6 +2742,35 @@ function fxBibRequirePromoteurSession() {
|
||||
return !empty($_SESSION['com_id']) || !empty($_SESSION['usa_id']);
|
||||
}
|
||||
|
||||
/** MSIN-4436 — Au moins une séquence verrouillée sur l'épreuve. */
|
||||
function fxBibEpreuveHasLockedRanges($epr_id) {
|
||||
global $objDatabase;
|
||||
|
||||
$epr_id = (int)$epr_id;
|
||||
|
||||
if ($epr_id <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sql = "
|
||||
SELECT COUNT(*)
|
||||
FROM inscriptions_epreuves_bib
|
||||
WHERE epr_id = $epr_id
|
||||
AND epr_bib_locked = 1
|
||||
";
|
||||
|
||||
return (int)$objDatabase->fxGetVar($sql) > 0;
|
||||
}
|
||||
|
||||
/** MSIN-4436 — Réinitialisation totale : aucun cadenas sur l'épreuve. */
|
||||
function fxBibAssertEpreuveNoLockedRanges($epr_id) {
|
||||
if (fxBibEpreuveHasLockedRanges($epr_id)) {
|
||||
return ['success' => false, 'message' => fxBibMsg('bib_v4_js_reset_all_locked')];
|
||||
}
|
||||
|
||||
return ['success' => true];
|
||||
}
|
||||
|
||||
/** Resout eve_id depuis la requete AJAX bib (eve_id direct ou via epr_id). */
|
||||
function fxBibResolveEveIdFromRequest() {
|
||||
global $objDatabase;
|
||||
@ -3114,6 +3143,8 @@ function fxBibModuleJsDataAttrs() {
|
||||
'batch-progress' => 'bib_v4_js_batch_progress',
|
||||
'global-no-epr' => 'bib_v4_js_global_no_epr',
|
||||
'global-no-seq' => 'bib_v4_js_global_no_seq',
|
||||
'reset-all-confirm' => 'bib_v4_js_reset_all_confirm',
|
||||
'reset-all-locked' => 'bib_v4_js_reset_all_locked',
|
||||
'assign-full' => 'bib_v4_ajax_assign_full',
|
||||
'assign-partial' => 'bib_v4_ajax_assign_partial',
|
||||
'assign-none' => 'bib_v4_ajax_assign_none',
|
||||
@ -3502,6 +3533,29 @@ function renderBibEpreuveIdentityHeader($tabEpreuve, $infoBib, $strLangue = 'fr'
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/** MSIN-4436 — Réinitialiser tous les dossards de l'épreuve (sans sélection de séquences). */
|
||||
function renderBibEpreuveResetAllButton($epr_id, $infoBib, $blnHasLockedRanges = false) {
|
||||
if ((int)($infoBib['avec_bib'] ?? 0) <= 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$strTipClef = $blnHasLockedRanges ? 'bib_v4_tip_reset_all_locked' : 'bib_v4_tip_reset_all';
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<div class="epr-identity-reset-all">
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-danger btn-reset-all-epr"
|
||||
data-epr-id="<?php echo (int)$epr_id; ?>"
|
||||
<?php echo $blnHasLockedRanges ? ' disabled' : ''; ?>
|
||||
<?php echo fxBibTippyAttr($strTipClef); ?>>
|
||||
<?php fxBibTexte('bib_v4_reset_all', 1); ?>
|
||||
</button>
|
||||
</div>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/** Bouton réduire / développer le corps du bloc (en-tête reste visible). */
|
||||
function fxBibBlockCollapseToggle($strLangue = 'fr', $blnCollapsed = true) {
|
||||
$strCollapse = fxBibTexte('bib_v4_collapse', 0);
|
||||
@ -4131,6 +4185,7 @@ function fxShowBibTool4($str_code, $int_eve_id, $strLangue){
|
||||
// MSIN-4379 — Étape 2 : détecte si l'auto est actif (au moins une séquence epr_bib_auto=1).
|
||||
// Prochain tour : étape 6–7 (assignation à l'achat).
|
||||
$blnAutoActive = fxIsBibAutoActive((int)$tabEpreuves[$i]['epr_id']);
|
||||
$blnHasLockedRanges = fxBibEpreuveHasLockedRanges((int)$tabEpreuves[$i]['epr_id']);
|
||||
|
||||
?>
|
||||
|
||||
@ -4149,6 +4204,7 @@ function fxShowBibTool4($str_code, $int_eve_id, $strLangue){
|
||||
<!-- GAUCHE — identité épreuve (titre dans la bande bleue, cohérent avec la droite) -->
|
||||
<div class="epr-block epr-block-identity">
|
||||
<?php echo renderBibEpreuveIdentityHeader($tabEpreuves[$i], $infoBib, $strLangue); ?>
|
||||
<?php echo renderBibEpreuveResetAllButton((int)$tabEpreuves[$i]['epr_id'], $infoBib, $blnHasLockedRanges); ?>
|
||||
<?php if ((int)$tabEpreuves[$i]['epr_equipe'] === 1) { ?>
|
||||
<div class="epr-content epr-content--identity">
|
||||
<?php
|
||||
@ -6591,6 +6647,31 @@ function fxBuildBatchSummaryFromRanges($tabRangesInfos, $participants, $epr_id =
|
||||
'nb_manque' => $nbManque
|
||||
];
|
||||
}
|
||||
/** MSIN-4436 — Tous les participants avec dossard sur l'épreuve (y compris hors séquences). */
|
||||
function fxGetParticipantsForEpreuveResetAll($epr_id) {
|
||||
global $objDatabase;
|
||||
|
||||
$epr_id = (int)$epr_id;
|
||||
|
||||
if ($epr_id <= 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$sqlBibNumP = fxBibSqlNoBibUnsigned('p.no_bib');
|
||||
|
||||
$sql = "
|
||||
SELECT p.*
|
||||
FROM resultats_participants p
|
||||
WHERE p.epr_id = $epr_id
|
||||
AND p.is_cancelled = 0
|
||||
AND p.no_bib IS NOT NULL
|
||||
AND p.no_bib > 0
|
||||
ORDER BY $sqlBibNumP
|
||||
";
|
||||
|
||||
return $objDatabase->fxGetResults($sql);
|
||||
}
|
||||
|
||||
function fxGetParticipantsForBatchReset($epr_id, $ranges) {
|
||||
|
||||
global $objDatabase;
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
* Constantes *
|
||||
*
|
||||
**************/
|
||||
define('_VERSION_CODE', '4.72.745');
|
||||
define('_VERSION_CODE', '4.72.747');
|
||||
define('_DATE_CODE', '2026-07-08');
|
||||
//MSIN-4290
|
||||
define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe');
|
||||
|
||||
50
sql/MSIN-4436-reset-all-epr.sql
Normal file
50
sql/MSIN-4436-reset-all-epr.sql
Normal file
@ -0,0 +1,50 @@
|
||||
-- MSIN-4436 — Réinitialiser tous les dossards d'une épreuve
|
||||
-- Idempotent. Exécuter après déploiement PHP/JS.
|
||||
|
||||
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 'bib_v4_reset_all', 'fr', 'Réinitialiser tous les dossards', 'Retire tous les numéros assignés sur cette épreuve, y compris les dossards saisis manuellement. Aucune sélection de séquence requise.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_reset_all' 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 'bib_v4_reset_all', 'en', 'Reset all bibs', 'Removes every assigned bib on this race, including manually entered numbers. No sequence selection required.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_reset_all' 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 'bib_v4_tip_reset_all', 'fr', 'Retire tous les dossards de l''épreuve (assignation batch, auto et manuelle).', '', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_tip_reset_all' 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 'bib_v4_tip_reset_all', 'en', 'Removes all bibs on this race (batch, auto, and manual).', '', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_tip_reset_all' 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 'bib_v4_tip_reset_all_locked', 'fr', 'Déverrouillez toutes les séquences (cadenas) avant de réinitialiser.', '', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_tip_reset_all_locked' 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 'bib_v4_tip_reset_all_locked', 'en', 'Unlock all sequences (padlocks) before resetting.', '', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_tip_reset_all_locked' 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 'bib_v4_js_reset_all_confirm', 'fr', 'Attention : tous les dossards de cette épreuve seront retirés.\n\nCela inclut les dossards assignés manuellement, en lot ou automatiquement.\n\nCette action est irréversible. Continuer ?', '', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_js_reset_all_confirm' 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 'bib_v4_js_reset_all_confirm', 'en', 'Warning: all bibs on this race will be removed.\n\nThis includes manually assigned, batch, and automatic bibs.\n\nThis cannot be undone. Continue?', '', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_js_reset_all_confirm' 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 'bib_v4_js_reset_all_locked', 'fr', 'Impossible : au moins une séquence est verrouillée.\n\nDéverrouillez tous les cadenas à droite avant de réinitialiser tous les dossards.', '', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_js_reset_all_locked' 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 'bib_v4_js_reset_all_locked', 'en', 'Cannot proceed: at least one sequence is locked.\n\nUnlock all padlocks on the right before resetting all bibs.', '', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_js_reset_all_locked' 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 'bib_v4_ajax_title_reset_all_done', 'fr', 'Réinitialisation totale terminée', '', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_title_reset_all_done' 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 'bib_v4_ajax_title_reset_all_done', 'en', 'Full reset completed', '', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_title_reset_all_done' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
Reference in New Issue
Block a user