MSIN-4445 — Refine free assignment logic by enhancing duplicate bib number checks and improving feedback mechanisms for overlapping ranges. Update backend functions to ensure accurate detection of assigned bibs within specified ranges and adjust UI components to reflect these changes. Increment version code to 4.72.830.
This commit is contained in:
@ -714,10 +714,29 @@ if ($action == 'batch_global_free_analysis') {
|
|||||||
$eprIds = json_decode($_POST['epr_ids'] ?? '[]', true);
|
$eprIds = json_decode($_POST['epr_ids'] ?? '[]', true);
|
||||||
$tabEprIds = fxBibParseGlobalBatchGeneratedEprIds(is_array($eprIds) ? $eprIds : [], $int_eve_id);
|
$tabEprIds = fxBibParseGlobalBatchGeneratedEprIds(is_array($eprIds) ? $eprIds : [], $int_eve_id);
|
||||||
|
|
||||||
if ($int_eve_id <= 0 || $intStart <= 0 || $intEnd < $intStart || $strSort1 === '' || empty($tabEprIds)) {
|
if ($int_eve_id <= 0 || $intStart <= 0 || $intEnd < $intStart) {
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => fxBibMsg('bib_v4_global_batch_free_plan_invalid'),
|
'message' => fxBibMsg('bib_v4_global_batch_free_plan_invalid'),
|
||||||
|
'duplicates' => ['has' => false, 'count' => 0, 'message' => ''],
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MSIN-4445 — Doublons basés sur la plage entière (même si tri / épreuves incomplets).
|
||||||
|
$tabDupesOnly = fxBibFreeDuplicateRisk($int_eve_id, [], $intStart, $intEnd);
|
||||||
|
|
||||||
|
if ($strSort1 === '') {
|
||||||
|
$strSort1 = 'ba:2';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($tabEprIds)) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'info' => $tabDupesOnly['message'],
|
||||||
|
'stats' => ['nb_epreuves' => 0, 'nb_participants' => 0, 'nb_bibs' => 0],
|
||||||
|
'feedback' => fxBibFreeQtyFeedback($intEnd - $intStart + 1, 0),
|
||||||
|
'duplicates' => $tabDupesOnly,
|
||||||
]);
|
]);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1289,20 +1289,34 @@
|
|||||||
|
|
||||||
function bibSetGlobalFreeDupesWarn(section, blnShow, strMessage) {
|
function bibSetGlobalFreeDupesWarn(section, blnShow, strMessage) {
|
||||||
var fields = bibGetGlobalBatchFreeRangeFields(section);
|
var fields = bibGetGlobalBatchFreeRangeFields(section);
|
||||||
if (!fields || !fields.dupesEl) {
|
if (!fields) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!blnShow) {
|
var msg = strMessage
|
||||||
fields.dupesEl.textContent = '';
|
|
||||||
fields.dupesEl.classList.add('bib-ui-hidden');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fields.dupesEl.textContent = strMessage
|
|
||||||
|| bibJs('jsGlobalFreeDupesWarn')
|
|| bibJs('jsGlobalFreeDupesWarn')
|
||||||
|| 'Attention : vous êtes en train de créer des inscriptions avec des dossards en double.';
|
|| 'Attention : vous êtes en train de créer des inscriptions avec des dossards en double.';
|
||||||
fields.dupesEl.classList.remove('bib-ui-hidden');
|
|
||||||
|
if (fields.dupesEl) {
|
||||||
|
if (!blnShow) {
|
||||||
|
fields.dupesEl.textContent = '';
|
||||||
|
fields.dupesEl.classList.add('bib-ui-hidden');
|
||||||
|
} else {
|
||||||
|
fields.dupesEl.textContent = msg;
|
||||||
|
fields.dupesEl.classList.remove('bib-ui-hidden');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repli si l'ancien markup n'a pas la ligne dédiée.
|
||||||
|
if (fields.feedback && blnShow) {
|
||||||
|
var base = (fields.qtyEl && fields.qtyEl.textContent)
|
||||||
|
? fields.qtyEl.textContent
|
||||||
|
: (fields.feedback.textContent || '');
|
||||||
|
fields.feedback.textContent = base
|
||||||
|
? (base + ' — ' + msg)
|
||||||
|
: msg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function bibUpdateGlobalFreeQtyFeedback(section) {
|
function bibUpdateGlobalFreeQtyFeedback(section) {
|
||||||
@ -1551,6 +1565,7 @@
|
|||||||
data.message || bibJs('jsErrGeneric'),
|
data.message || bibJs('jsErrGeneric'),
|
||||||
'error'
|
'error'
|
||||||
);
|
);
|
||||||
|
bibSetGlobalFreeDupesWarn(section, false);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -61,68 +61,83 @@ function fxBibFreeQtyFeedbackMessage(array $tabFeedback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MSIN-4445 — Nombre de dossards de la plage déjà utilisés sur une autre épreuve.
|
* MSIN-4445 — Nombre de dossards déjà assignés dans [start, end] pour l'événement.
|
||||||
* Ces numéros seraient réassignés (doublon inter-épreuve) car le batch ne les saute pas.
|
* Jointure via épreuve : plus fiable que p.eve_id seul.
|
||||||
*/
|
*/
|
||||||
function fxBibCountBibsUsedOutsideEpr($int_eve_id, $intStart, $intEnd, $intEprId) {
|
function fxBibCountAssignedBibsInRange($int_eve_id, $intStart, $intEnd) {
|
||||||
global $objDatabase;
|
global $objDatabase;
|
||||||
|
|
||||||
$int_eve_id = (int)$int_eve_id;
|
$int_eve_id = (int)$int_eve_id;
|
||||||
$intStart = (int)$intStart;
|
$intStart = (int)$intStart;
|
||||||
$intEnd = (int)$intEnd;
|
$intEnd = (int)$intEnd;
|
||||||
$intEprId = (int)$intEprId;
|
|
||||||
|
|
||||||
if ($int_eve_id <= 0 || $intEprId <= 0 || $intStart <= 0 || $intEnd < $intStart) {
|
if ($int_eve_id <= 0 || $intStart <= 0 || $intEnd < $intStart) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sqlBib = fxBibSqlNoBibUnsigned('no_bib');
|
$sqlBib = fxBibSqlNoBibUnsigned('p.no_bib');
|
||||||
|
|
||||||
return (int)$objDatabase->fxGetVar("
|
return (int)$objDatabase->fxGetVar("
|
||||||
SELECT COUNT(DISTINCT $sqlBib)
|
SELECT COUNT(DISTINCT $sqlBib)
|
||||||
FROM resultats_participants
|
FROM resultats_participants p
|
||||||
WHERE eve_id = $int_eve_id
|
INNER JOIN inscriptions_epreuves e ON e.epr_id = p.epr_id
|
||||||
AND epr_id <> $intEprId
|
WHERE e.eve_id = $int_eve_id
|
||||||
AND is_cancelled = 0
|
AND IFNULL(p.is_cancelled, 0) = 0
|
||||||
AND no_bib IS NOT NULL
|
AND p.no_bib IS NOT NULL
|
||||||
AND TRIM(no_bib) <> ''
|
AND TRIM(p.no_bib) <> ''
|
||||||
AND $sqlBib BETWEEN $intStart AND $intEnd
|
AND $sqlBib BETWEEN $intStart AND $intEnd
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MSIN-4445 — Risque de doublons pour le plan libre (plages virtuelles vs dossards déjà pris ailleurs).
|
* MSIN-4445 — Risque de doublons pour une plage libre.
|
||||||
|
* Avertit si des dossards de la plage sont déjà portés, ou si une séquence
|
||||||
|
* existante chevauche la plage (même hors épreuves sélectionnées).
|
||||||
*
|
*
|
||||||
* @return array{has:bool, count:int, message:string}
|
* @return array{has:bool, count:int, message:string}
|
||||||
*/
|
*/
|
||||||
function fxBibFreeDuplicateRisk($int_eve_id, $tabPlan) {
|
function fxBibFreeDuplicateRisk($int_eve_id, $tabPlan, $intStart = 0, $intEnd = 0) {
|
||||||
$int_eve_id = (int)$int_eve_id;
|
$int_eve_id = (int)$int_eve_id;
|
||||||
$intCount = 0;
|
$intStart = (int)$intStart;
|
||||||
|
$intEnd = (int)$intEnd;
|
||||||
|
|
||||||
if (!is_array($tabPlan)) {
|
if ($intStart <= 0 || $intEnd < $intStart) {
|
||||||
|
// Repli : bornes du plan si Début/Fin absents.
|
||||||
|
foreach ((array)$tabPlan as $item) {
|
||||||
|
if (!empty($item['skip'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$intItemStart = (int)($item['start'] ?? 0);
|
||||||
|
$intItemEnd = (int)($item['end'] ?? 0);
|
||||||
|
if ($intItemStart <= 0 || $intItemEnd < $intItemStart) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($intStart <= 0 || $intItemStart < $intStart) {
|
||||||
|
$intStart = $intItemStart;
|
||||||
|
}
|
||||||
|
if ($intItemEnd > $intEnd) {
|
||||||
|
$intEnd = $intItemEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($int_eve_id <= 0 || $intStart <= 0 || $intEnd < $intStart) {
|
||||||
return ['has' => false, 'count' => 0, 'message' => ''];
|
return ['has' => false, 'count' => 0, 'message' => ''];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($tabPlan as $item) {
|
$intCount = fxBibCountAssignedBibsInRange($int_eve_id, $intStart, $intEnd);
|
||||||
if (!empty($item['skip'])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$intCount += fxBibCountBibsUsedOutsideEpr(
|
// Séquences déjà configurées qui chevauchent la plage (autre épreuve).
|
||||||
$int_eve_id,
|
$tabOverlaps = fxBibGetOverlappingRanges($int_eve_id, $intStart, $intEnd, 0, 0);
|
||||||
(int)($item['start'] ?? 0),
|
$intOverlapSeq = is_array($tabOverlaps) ? count($tabOverlaps) : 0;
|
||||||
(int)($item['end'] ?? 0),
|
|
||||||
(int)($item['epr_id'] ?? 0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($intCount <= 0) {
|
if ($intCount <= 0 && $intOverlapSeq <= 0) {
|
||||||
return ['has' => false, 'count' => 0, 'message' => ''];
|
return ['has' => false, 'count' => 0, 'message' => ''];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'has' => true,
|
'has' => true,
|
||||||
'count' => $intCount,
|
'count' => max($intCount, $intOverlapSeq),
|
||||||
'message' => fxBibMsg('bib_v4_global_batch_free_dupes_warn'),
|
'message' => fxBibMsg('bib_v4_global_batch_free_dupes_warn'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -262,7 +277,7 @@ function fxBibBuildGlobalBatchFreeAnalysis($int_eve_id, $tabPlan, $intStart, $in
|
|||||||
}
|
}
|
||||||
|
|
||||||
$tabFeedback = fxBibFreeQtyFeedback($intQty, $intPendingAll);
|
$tabFeedback = fxBibFreeQtyFeedback($intQty, $intPendingAll);
|
||||||
$tabDupes = fxBibFreeDuplicateRisk($int_eve_id, $tabPlan);
|
$tabDupes = fxBibFreeDuplicateRisk($int_eve_id, $tabPlan, $intStart, $intEnd);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'stats' => $tabStats,
|
'stats' => $tabStats,
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
* Constantes *
|
* Constantes *
|
||||||
*
|
*
|
||||||
**************/
|
**************/
|
||||||
define('_VERSION_CODE', '4.72.829');
|
define('_VERSION_CODE', '4.72.830');
|
||||||
define('_DATE_CODE', '2026-07-16');
|
define('_DATE_CODE', '2026-07-16');
|
||||||
//MSIN-4290
|
//MSIN-4290
|
||||||
define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe');
|
define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe');
|
||||||
|
|||||||
Reference in New Issue
Block a user