diff --git a/php/chronotrack_api/fx_chronotrack_admin.php b/php/chronotrack_api/fx_chronotrack_admin.php index 221ad54..dcfbebd 100644 --- a/php/chronotrack_api/fx_chronotrack_admin.php +++ b/php/chronotrack_api/fx_chronotrack_admin.php @@ -223,9 +223,9 @@ function fxChronotrackApiAdminRenderPushPanel($intEveId, $blnClosed = false) { if ($blnClosed) { echo '
Lit resultats_participants (comme le rapport chrono). ';
- echo 'External ID = par_id_original. 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é.
Push manuel — pas de sync automatique. Lit resultats_participants ';
+ echo '(comme le rapport chrono). External ID = par_id_original. ';
+ echo 'Après une correction MS1 : Actualiser puis Pousser.
Avant le prochain push — lecture MS1 + ChronoTrack Live :
'; - html += 'État actuel (MS1 + ChronoTrack Live) :
'; - if (intTransfer > 0) { - html += 'Parmi les ' + intTransfer + ' envoyés : '; - html += '' + intWillCreate + ' création(s) · '; - html += '' + intAlreadyCt + ' mise(s) à jour.
'; + html += 'MS1 — ' + intMs1 + ' inscrits : '; + html += '' + intEligible + ' éligibles'; + if (intBlocked > 0) { + html += ' · ' + intBlocked + ' exclus'; } + html += ' (équipe, dossard, sexe, etc.)
'; + html += 'ChronoTrack — ' + intCtTotal + ' entries'; + if (intEligible > 0 || intOrphans > 0) { + html += ' ('; + 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 += ')'; + } + html += '
Un deuxième push renvoie les mêmes transférables : ChronoTrack fait une mise à jour (upsert par external_id), pas de doublon.
'; + html += 'Au prochain push — renvoie les ' + intEligible + + ' éligibles avec les données MS1 actuelles '; + html += '(' + intWillCreate + ' création · ' + intWillUpdate + ' mise à jour). '; + html += 'Ce n\'est pas une sync auto : corrigez dans MS1 → Actualiser → Pousser.
'; - if (intCtTotal > 0 && (res.ct_orphans || 0) > 0) { - html += '' + res.ct_orphans + ' entry(s) CT sans correspondant MS1 transférable.
'; + if (intOrphans > 0) { + html += '' + intOrphans + + ' entry(s) CT sans correspondant MS1 éligible (tests, anciennes données).
'; } if (intBlocked > 0) { html += ''; - html += 'Les ' + intBlocked + ' exclus ne seront pas envoyés tant que non corrigés dans MS1. '; + html += 'Les ' + intBlocked + ' exclus ne partent pas tant que non corrigés dans MS1. '; if (res.blocked_team > 0) { - html += '' + res.blocked_team + ' sont des inscriptions équipe (section dédiée). '; + html += '' + res.blocked_team + ' sont des inscriptions équipe. '; } - html += 'Détail dans la zone ci-dessous.
'; + html += 'Détail ci-dessous.'; } $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); diff --git a/php/chronotrack_api/fx_chronotrack_sync.php b/php/chronotrack_api/fx_chronotrack_sync.php index bd51c44..b755c99 100644 --- a/php/chronotrack_api/fx_chronotrack_sync.php +++ b/php/chronotrack_api/fx_chronotrack_sync.php @@ -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(