Enhance ChronoTrack API push functionality and improve user feedback

This commit updates the ChronoTrack API push process by refining the user interface messaging for manual pushes, clarifying the status of participants, and improving the confirmation prompts. Key changes include the introduction of new variables for tracking eligible participants and orphans, as well as enhanced HTML output for better clarity on the current state of entries. These improvements aim to streamline the push process and enhance the overall user experience in managing participant data.
This commit is contained in:
2026-07-03 20:35:43 -04:00
parent 8c7f3e13ed
commit f2519dc987
2 changed files with 72 additions and 28 deletions

View File

@ -223,9 +223,9 @@ function fxChronotrackApiAdminRenderPushPanel($intEveId, $blnClosed = false) {
if ($blnClosed) {
echo '<div class="alert alert-warning py-2 small mb-2">Événement fermé — push manuel autorisé pour tests ou rattrapage.</div>';
}
echo '<p class="small text-muted mb-2">Lit <code>resultats_participants</code> (comme le rapport chrono). ';
echo 'External ID = <code>par_id_original</code>. Dossard obligatoire ; sexe vide ou « n » (non défini) → NOT SPECIFIED côté CT ; ';
echo 'doublon de dossard MS1 = aucun des inscrits concernés n\'est transféré.</p>';
echo '<p class="small text-muted mb-2">Push <strong>manuel</strong> — pas de sync automatique. Lit <code>resultats_participants</code> ';
echo '(comme le rapport chrono). External ID = <code>par_id_original</code>. ';
echo 'Après une correction MS1 : <strong>Actualiser</strong> puis <strong>Pousser</strong>.</p>';
echo '<div id="ct_api_push_summary" class="mb-3 text-muted small">'
. 'Cliquez sur <strong>Actualiser</strong> pour calculer le diff MS1 ↔ ChronoTrack.</div>';
echo '<div id="ct_api_push_blocked_wrap" class="mb-3 d-none"></div>';
@ -754,46 +754,60 @@ function fxChronotrackApiAdminRenderPageScript($intEveId, $arrConfig, $blnClosed
}
var intBlocked = res.blocked_count || 0;
var intTransfer = res.transferable || 0;
var intEligible = res.transferable || 0;
var intMs1 = res.ms1_total || 0;
var intAlreadyCt = res.already_in_ct || 0;
var intWillUpdate = res.will_update || res.already_in_ct || 0;
var intWillCreate = res.will_create || res.to_create || 0;
var intCtTotal = res.ct_total || 0;
var intOrphans = res.ct_orphans || 0;
var html = '<p class="small text-muted mb-2">Avant le prochain push — lecture MS1 + ChronoTrack Live :</p>';
html += '<div class="ct-api-stat-row mb-2">';
html += '<div class="ct-api-stat"><strong>' + intMs1 + '</strong><span class="text-muted small">inscrits MS1</span></div>';
html += '<div class="ct-api-stat text-primary"><strong>' + intTransfer + '</strong><span class="small">seront envoyés</span></div>';
html += '<div class="ct-api-stat ' + (intBlocked > 0 ? 'text-danger' : 'text-muted') + '">';
html += '<strong>' + intBlocked + '</strong><span class="small">exclus</span></div>';
html += '<div class="ct-api-stat text-info"><strong>' + intAlreadyCt + '</strong><span class="small">déjà sur CT Live</span></div>';
html += '<div class="ct-api-stat text-secondary"><strong>' + intCtTotal + '</strong><span class="small">entries CT (total)</span></div>';
html += '</div>';
var html = '<p class="small text-muted mb-2">État actuel (MS1 + ChronoTrack Live) :</p>';
if (intTransfer > 0) {
html += '<p class="small mb-1">Parmi les <strong>' + intTransfer + '</strong> envoyés : ';
html += '<strong>' + intWillCreate + '</strong> création(s) · ';
html += '<strong>' + intAlreadyCt + '</strong> mise(s) à jour.</p>';
html += '<div class="border rounded p-2 mb-2 bg-light">';
html += '<p class="small mb-1"><strong>MS1</strong> — <strong>' + intMs1 + '</strong> inscrits : ';
html += '<span class="text-primary">' + intEligible + ' éligibles</span>';
if (intBlocked > 0) {
html += ' · <span class="text-danger">' + intBlocked + ' exclus</span>';
}
html += ' <span class="text-muted">(équipe, dossard, sexe, etc.)</span></p>';
html += '<p class="small mb-0"><strong>ChronoTrack</strong> — <strong>' + intCtTotal + '</strong> entries';
if (intEligible > 0 || intOrphans > 0) {
html += ' <span class="text-muted">(';
if (intWillUpdate > 0 || intWillCreate > 0) {
html += intWillUpdate + ' déjà liées à un éligible MS1';
if (intWillCreate > 0) {
html += ', ' + intWillCreate + ' éligible(s) pas encore sur CT';
}
}
if (intOrphans > 0) {
html += (intWillUpdate > 0 || intWillCreate > 0 ? ', ' : '') + intOrphans + ' sans correspondant MS1';
}
html += ')</span>';
}
html += '</p></div>';
html += '<p class="small text-muted mb-1">Un <strong>deuxième push</strong> renvoie les mêmes transférables : ChronoTrack fait une <em>mise à jour</em> (upsert par external_id), pas de doublon.</p>';
html += '<p class="small mb-2"><strong>Au prochain push</strong> renvoie les <strong>' + intEligible
+ '</strong> éligibles avec les données MS1 <em>actuelles</em> ';
html += '(<strong>' + intWillCreate + '</strong> création · <strong>' + intWillUpdate + '</strong> mise à jour). ';
html += 'Ce n\'est pas une sync auto : corrigez dans MS1 → <strong>Actualiser</strong> → <strong>Pousser</strong>.</p>';
if (intCtTotal > 0 && (res.ct_orphans || 0) > 0) {
html += '<p class="small text-warning mb-1">' + res.ct_orphans + ' entry(s) CT sans correspondant MS1 transférable.</p>';
if (intOrphans > 0) {
html += '<p class="small text-warning mb-1">' + intOrphans
+ ' entry(s) CT sans correspondant MS1 éligible (tests, anciennes données).</p>';
}
if (intBlocked > 0) {
html += '<p class="small text-danger mb-0"><i class="fa fa-info-circle" aria-hidden="true"></i> ';
html += 'Les <strong>' + intBlocked + '</strong> exclus ne seront <em>pas</em> envoyés tant que non corrigés dans MS1. ';
html += 'Les <strong>' + intBlocked + '</strong> exclus ne partent pas tant que non corrigés dans MS1. ';
if (res.blocked_team > 0) {
html += '<strong>' + res.blocked_team + '</strong> sont des <span class="text-warning">inscriptions équipe</span> (section dédiée). ';
html += '<strong>' + res.blocked_team + '</strong> sont des <span class="text-warning">inscriptions équipe</span>. ';
}
html += 'Détail dans la zone ci-dessous.</p>';
html += 'Détail ci-dessous.</p>';
}
$sum.html(html);
renderBlockedPanel(res);
$btn.prop('disabled', intTransfer <= 0);
$btn.prop('disabled', intEligible <= 0);
}
function renderPushResult(res, strTitle) {
@ -904,7 +918,11 @@ function fxChronotrackApiAdminRenderPageScript($intEveId, $arrConfig, $blnClosed
});
$('#ct_api_btn_push').on('click', function () {
if (!window.confirm('Envoyer les participants éligibles vers ChronoTrack ?\n\nMS1 ne sera pas modifié.')) {
var intEligible = (objPushPreview && objPushPreview.transferable) ? objPushPreview.transferable : 0;
var strConfirm = 'Push manuel — renvoyer les ' + intEligible + ' participants éligibles vers ChronoTrack ?\n\n';
strConfirm += 'Données MS1 actuelles (upsert par external_id). Pas de sync automatique.\n';
strConfirm += 'MS1 ne sera pas modifié.';
if (!window.confirm(strConfirm)) {
return;
}
var $btn = $(this);

View File

@ -485,9 +485,25 @@ function fxChronotrackApiSyncBuildEntryPayload(array $arrRow, array $arrRaceMap,
$arrEntry['country_code'] = $strCountry;
}
$arrEntry['entry_status'] = fxChronotrackApiSyncMapEntryStatus(
$arrRow['par_statut_course'] ?? 'CONF',
intval($arrRow['is_cancelled'] ?? 0) === 1
);
return $arrEntry;
}
function fxChronotrackApiSyncEnrichPayloadWithCtEntry(array $arrPayload, $arrCtEntity) {
if (!is_array($arrCtEntity)) {
return $arrPayload;
}
$strEntryId = fxChronotrackApiEntityId($arrCtEntity);
if ($strEntryId !== '') {
$arrPayload['entry_id'] = $strEntryId;
}
return $arrPayload;
}
function fxChronotrackApiSyncPostEntries($intCtEventId, array $tabEntries) {
$intCtEventId = intval($intCtEventId);
if ($intCtEventId <= 0 || count($tabEntries) === 0) {
@ -770,10 +786,20 @@ function fxChronotrackApiSyncPushEvent($intEveId) {
);
}
$tabCtEntries = array();
$arrCtFetch = fxChronotrackApiSyncFetchCtEntriesIndexed($intCtEventId);
if ($arrCtFetch['state'] === 'ok') {
$tabCtEntries = $arrCtFetch['entries'];
}
$tabBatch = array();
$tabMeta = array();
foreach ($arrClass['transferable'] as $arrItem) {
$tabBatch[] = $arrItem['payload'];
$arrPayload = fxChronotrackApiSyncEnrichPayloadWithCtEntry(
$arrItem['payload'],
$tabCtEntries[$arrItem['payload']['external_id']] ?? null
);
$tabBatch[] = $arrPayload;
$tabMeta[] = array(
'par_id' => intval($arrItem['row']['par_id'] ?? 0),
'external_id' => $arrItem['payload']['external_id'],
@ -860,7 +886,7 @@ function fxChronotrackApiSyncPushEvent($intEveId) {
$intBlockedCount = $arrClass['blocked_count'];
$strMessage = ($intErr === 0)
? ($intOk . ' participant(s) envoyé(s) vers ChronoTrack.')
? ($intOk . ' éligible(s) (re)envoyé(s) vers ChronoTrack (données MS1 actuelles, upsert par external_id).')
: ($intOk . ' OK, ' . $intErr . ' erreur(s) API.');
return array(