MSIN-4464 — Implement audit history feature for participant fields. Add functionality to retrieve and display recent changes for specific fields, enhancing traceability of modifications. Introduce a new button in the UI to access the audit history, along with corresponding styles and JavaScript logic for improved user interaction. Update relevant backend functions to support this feature, ensuring proper access control and data retrieval.

This commit is contained in:
2026-07-15 13:18:44 -04:00
parent 3ac01a6f00
commit d23d471de4
9 changed files with 421 additions and 9 deletions

View File

@ -280,6 +280,43 @@ switch ($strAction) {
$tabRetour = array('state' => 'ok', 'html' => $strHtml);
break;
case 'fiche_audit_history':
// MSIN-4464 — derniers changements d'un champ whitelist (popup « ! » fiche).
require_once 'php/inc_fx_fiche_audit.php';
$intParId = intval($_REQUEST['par_id'] ?? 0);
$strField = preg_replace('/[^a-z0-9_]/i', '', (string)($_REQUEST['field'] ?? ''));
$intEveId = fxEveAccesResolveEveIdFromParId($intParId);
if ($intParId <= 0 || $strField === '' || $intEveId <= 0
|| !fxInscrGestionCanDo($intComId, $intEveId, 'inscriptions_gestion.audit_view')) {
$tabRetour = array('state' => 'error', 'message' => 'unauthorized');
break;
}
$arrItems = fxFicheAuditGetRecentForField($intParId, $strField);
$arrOut = array();
if (is_array($arrItems)) {
foreach ($arrItems as $row) {
if (!is_array($row)) {
continue;
}
$arrOut[] = array(
'when' => (string)($row['created_at'] ?? ''),
'who' => (string)($row['changed_by_label'] ?? ''),
'old' => (string)($row['old_value'] ?? ''),
'new' => (string)($row['new_value'] ?? ''),
'source' => (string)($row['source'] ?? ''),
);
}
}
$tabRetour = array(
'state' => 'success',
'field' => $strField,
'items' => $arrOut,
);
break;
default:
$tabRetour = array('state' => 'error', 'message' => 'invalid_action');
break;

View File

@ -4468,6 +4468,36 @@ button.inscr-gestion-list-remis:hover{
margin-bottom:8px;
}
/* MSIN-4464 — historique champ ( ! ) sur la fiche */
.inscr-gestion-audit-bang{
display:inline-block;
margin-left:6px;
padding:0 7px;
min-width:22px;
height:22px;
line-height:20px;
border:1px solid #c0392b;
border-radius:4px;
background:#fff5f5;
color:#c0392b;
font-weight:800;
font-size:14px;
vertical-align:middle;
cursor:pointer;
}
.inscr-gestion-audit-bang:hover,
.inscr-gestion-audit-bang:focus{
background:#c0392b;
color:#fff;
outline:none;
}
.inscr-gestion-audit-inline{
display:inline-flex;
align-items:center;
font-size:13px;
color:#495057;
}
.inscr-gestion-order-row{
display:flex;
flex-wrap:wrap;

View File

@ -255,6 +255,103 @@
});
})();
// MSIN-4464 — « ! » historique champ (fiche seulement).
(function () {
function auditFieldLabel(fieldKey) {
var map = {
par_statut_course: t('auditFieldStatut'),
no_bib: t('auditFieldBib'),
no_bib_remis: t('auditFieldRemis'),
is_cancelled: t('auditFieldCancel')
};
return map[fieldKey] || fieldKey;
}
function escHtml(str) {
return String(str == null ? '' : str)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
}
function renderAuditTable(items) {
if (!items || !items.length) {
return '<p class="mb-0">' + escHtml(t('auditPopupEmpty') || '') + '</p>';
}
var html = '<div class="table-responsive"><table class="table table-sm table-striped mb-0 small">';
html += '<thead><tr>'
+ '<th>' + escHtml(t('auditColWhen') || '') + '</th>'
+ '<th>' + escHtml(t('auditColWho') || '') + '</th>'
+ '<th>' + escHtml(t('auditColFrom') || '') + '</th>'
+ '<th>' + escHtml(t('auditColTo') || '') + '</th>'
+ '</tr></thead><tbody>';
for (var i = 0; i < items.length; i++) {
var row = items[i] || {};
html += '<tr>'
+ '<td class="text-nowrap">' + escHtml(row.when || '') + '</td>'
+ '<td>' + escHtml(row.who || '') + '</td>'
+ '<td>' + escHtml(row.old || '') + '</td>'
+ '<td>' + escHtml(row.new || '') + '</td>'
+ '</tr>';
}
html += '</tbody></table></div>';
return html;
}
$body.on('click', '.inscr-gestion-audit-bang', function (e) {
e.preventDefault();
var $btn = $(this);
var intParId = parseInt($btn.data('par_id'), 10) || 0;
var strField = String($btn.data('field') || '');
if (!intParId || !strField) {
return;
}
var strTitle = (t('auditPopupTitle') || '') + ' — ' + auditFieldLabel(strField);
function showDialog(htmlBody) {
if (typeof window.bootbox !== 'undefined') {
window.bootbox.dialog({
title: strTitle,
message: htmlBody,
size: 'large',
buttons: {
close: {
label: t('auditPopupClose') || 'OK',
className: 'btn btn-secondary rounded-0'
}
}
});
return;
}
window.alert(strTitle);
}
$preloader_text.html(cfg.preloaderWait || '');
$preloader.show();
$.post((cfg.domain || '') + '/ajax_inscr_gestion.php', {
a: 'fiche_audit_history',
par_id: intParId,
field: strField,
lang: cfg.lang || 'fr'
}, function (result) {
$preloader.fadeOut('slow');
if (fxInscrRedirectIfSessionExpired(result)) {
return;
}
if (!result || result.state !== 'success') {
showDialog('<p class="mb-0 text-danger">' + escHtml(t('errLoad') || '') + '</p>');
return;
}
showDialog(renderAuditTable(result.items || []));
}, 'json').fail(function () {
$preloader.fadeOut('slow');
showDialog('<p class="mb-0 text-danger">' + escHtml(t('errNetwork') || '') + '</p>');
});
});
})();
(function () {
var pendingStatutXhr = null;
var lastStatutParId = null;

View File

@ -419,6 +419,70 @@ function fxFicheAuditAdminListEvents()
return is_array($arrRows) ? $arrRows : array();
}
/**
* Champs (hors last_touch) qui ont au moins 1 log pour ce participant.
*
* @return array<string,true>
*/
function fxFicheAuditFieldsWithLogsForPar($intParId)
{
global $objDatabase;
$intParId = intval($intParId);
$arrOut = array();
if ($intParId <= 0 || !isset($objDatabase) || !fxFicheAuditTablesReady()) {
return $arrOut;
}
$sql = 'SELECT field_key FROM inscriptions_fiche_audit_log'
. ' WHERE par_id = ' . $intParId
. " AND field_key <> 'last_touch'"
. ' GROUP BY field_key';
$arrRows = $objDatabase->fxGetResults($sql);
if (is_array($arrRows)) {
foreach ($arrRows as $row) {
if (!empty($row['field_key'])) {
$arrOut[(string)$row['field_key']] = true;
}
}
}
return $arrOut;
}
/**
* Historique détail d'un champ (fiche / AJAX), limité par la config.
*
* @return array[]
*/
function fxFicheAuditGetRecentForField($intParId, $strFieldKey, $intLimit = 0)
{
global $objDatabase;
$intParId = intval($intParId);
$strFieldKey = preg_replace('/[^a-z0-9_]/i', '', (string)$strFieldKey);
if ($intParId <= 0 || $strFieldKey === '' || $strFieldKey === 'last_touch'
|| !isset($objDatabase) || !fxFicheAuditTablesReady()) {
return array();
}
if ($intLimit <= 0) {
$arrSettings = fxFicheAuditGetSettings();
$intLimit = max(1, intval($arrSettings['retention_max_per_field']));
}
$intLimit = min(100, max(1, intval($intLimit)));
$sql = 'SELECT fal_id, field_key, old_value, new_value, changed_by_label, source, created_at'
. ' FROM inscriptions_fiche_audit_log'
. ' WHERE par_id = ' . $intParId
. " AND field_key = '" . $objDatabase->fxEscape($strFieldKey) . "'"
. ' ORDER BY created_at DESC, fal_id DESC'
. ' LIMIT ' . $intLimit;
$arrRows = $objDatabase->fxGetResults($sql);
return is_array($arrRows) ? $arrRows : array();
}
/**
* Derniers logs d'un événement (contrôle admin).
*

View File

@ -121,6 +121,28 @@ function fxInscrGestionPermInspectEchoHidden($strPermKey, $strLabel) {
}
/** MSIN-4401 — Enveloppe action + cadenas (toujours a droite du controle). */
/**
* MSIN-4464 — Bouton « ! » historique (seulement s'il y a au moins 1 log pour le champ).
*
* @param array<string,true> $arrFieldsWithLogs
*/
function fxInscrGestionRenderAuditBang($intParId, $strFieldKey, $blnCanAudit, $arrFieldsWithLogs)
{
$intParId = intval($intParId);
$strFieldKey = preg_replace('/[^a-z0-9_]/i', '', (string)$strFieldKey);
if (!$blnCanAudit || $intParId <= 0 || $strFieldKey === '' || empty($arrFieldsWithLogs[$strFieldKey])) {
return;
}
$strTitle = fxInscrGestionT('inscr_gestion_audit_bang_title');
$strAria = fxInscrGestionT('inscr_gestion_audit_bang_aria');
echo ' <button type="button" class="inscr-gestion-audit-bang"'
. ' data-par_id="' . $intParId . '"'
. ' data-field="' . fxInscrGestionEsc($strFieldKey) . '"'
. ' title="' . fxInscrGestionEsc($strTitle) . '"'
. ' aria-label="' . fxInscrGestionEsc($strAria) . '">!</button>';
}
function fxInscrGestionActionItemOpen($strExtraClass = '') {
$strExtra = trim((string)$strExtraClass);
echo '<span class="inscr-gestion-action-item'
@ -492,6 +514,20 @@ function fxInscrGestionFallbackTexte($strClef, $strLangue) {
: 'Are you sure you want to remove the "bib retrieved" status for this participant?',
'inscr_gestion_remis_confirm_ok' => $blnFr ? 'Retirer' : 'Remove',
'inscr_gestion_remis_confirm_cancel' => $blnFr ? 'Annuler' : 'Cancel',
// MSIN-4464 — historique fiche ( ! )
'inscr_gestion_audit_bang_title' => $blnFr ? 'Voir les derniers changements' : 'View recent changes',
'inscr_gestion_audit_bang_aria' => $blnFr ? 'Historique des modifications' : 'Change history',
'inscr_gestion_audit_popup_title' => $blnFr ? 'Derniers changements' : 'Recent changes',
'inscr_gestion_audit_popup_empty' => $blnFr ? 'Aucun historique pour ce champ.' : 'No history for this field.',
'inscr_gestion_audit_popup_close' => $blnFr ? 'Fermer' : 'Close',
'inscr_gestion_audit_col_when' => $blnFr ? 'Quand' : 'When',
'inscr_gestion_audit_col_who' => $blnFr ? 'Par' : 'By',
'inscr_gestion_audit_col_from' => $blnFr ? 'Avant' : 'From',
'inscr_gestion_audit_col_to' => $blnFr ? 'Après' : 'To',
'inscr_gestion_audit_field_par_statut_course' => $blnFr ? 'Statut de course' : 'Race status',
'inscr_gestion_audit_field_no_bib' => $blnFr ? 'Numéro de dossard' : 'Bib number',
'inscr_gestion_audit_field_no_bib_remis' => $blnFr ? 'Dossard remis' : 'Bib handed out',
'inscr_gestion_audit_field_is_cancelled' => $blnFr ? 'Annulation' : 'Cancellation',
// MSIN-4328 — bouton superadmin vers fiche ChronoTrack
'inscr_gestion_btn_chronotrack' => $blnFr ? 'Voir dans ChronoTrack' : 'View in ChronoTrack',
'inscr_gestion_list_count_one' => $blnFr ? '%d inscription' : '%d registration',
@ -2243,9 +2279,24 @@ function fxInscrGestionRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq,
$blnCanInvoice = fxInscrGestionCanDo($intComId, $intRowEveId, 'inscriptions_gestion.invoice');
$blnCanTransaction = fxInscrGestionCanDo($intComId, $intRowEveId, 'inscriptions_gestion.transaction');
$blnCanRenvoi = fxInscrGestionCanDo($intComId, $intRowEveId, 'inscriptions_gestion.renvoi');
$blnHasEditable = ($blnCanStatut || $blnCanBib || $blnCanRemis);
// MSIN-4464 — historique ( ! ) sur champs whitelist avec au moins 1 log.
$blnCanAudit = fxInscrGestionCanDo($intComId, $intRowEveId, 'inscriptions_gestion.audit_view');
$arrAuditFieldsWithLogs = array();
if ($blnCanAudit) {
if (!function_exists('fxFicheAuditFieldsWithLogsForPar')) {
require_once dirname(__FILE__) . '/inc_fx_fiche_audit.php';
}
$arrAuditFieldsWithLogs = fxFicheAuditFieldsWithLogsForPar(intval($arrRow['par_id']));
}
$blnHasAuditEditable = $blnCanAudit && (
!empty($arrAuditFieldsWithLogs['no_bib'])
|| !empty($arrAuditFieldsWithLogs['par_statut_course'])
|| !empty($arrAuditFieldsWithLogs['no_bib_remis'])
);
$blnHasEditable = ($blnCanStatut || $blnCanBib || $blnCanRemis || $blnHasAuditEditable);
$blnHasGestion = ($blnCanEdit || $blnCanCancel || $blnCanRestore || $blnCanRefund
|| $blnCanInvoice || $blnCanTransaction || $blnCanRenvoi);
|| $blnCanInvoice || $blnCanTransaction || $blnCanRenvoi
|| ($blnCanAudit && !empty($arrAuditFieldsWithLogs['is_cancelled'])));
$blnInspect = function_exists('fxAdminPermInspectModeActive') && fxAdminPermInspectModeActive();
$strBackUrl = fxInscrGestionResolveBackUrl($strBaseUrl, $intEveId, $arrReq);
@ -2317,10 +2368,16 @@ function fxInscrGestionRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq,
if ($blnCancelled) {
// MSIN-4405 — Detail de l'annulation (transferee / annulee) derive en lecture seule.
$strCause = fxGetAnnulationCause($arrRow['pec_id_original'], $arrRow['pec_actif']);
$strCancelVal = '<span class="inscr-gestion-cancel-badge inscr-gestion-cancel-badge--' . $strCause . '">'
. fxInscrGestionEsc(fxInscrGestionT('inscr_gestion_statut_' . $strCause)) . '</span>';
if ($blnCanAudit && !empty($arrAuditFieldsWithLogs['is_cancelled'])) {
ob_start();
fxInscrGestionRenderAuditBang($intParId, 'is_cancelled', $blnCanAudit, $arrAuditFieldsWithLogs);
$strCancelVal .= ob_get_clean();
}
fxInscrGestionRenderKvRow(
fxInscrGestionT('inscr_gestion_annulation_titre'),
'<span class="inscr-gestion-cancel-badge inscr-gestion-cancel-badge--' . $strCause . '">'
. fxInscrGestionEsc(fxInscrGestionT('inscr_gestion_statut_' . $strCause)) . '</span>',
$strCancelVal,
true
);
}
@ -2429,6 +2486,18 @@ function fxInscrGestionRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq,
fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.restore', fxInscrGestionT('btn_retablirinscriptions'));
fxInscrGestionActionItemClose();
}
// MSIN-4464 — historique annulation si pas deja affiche a cote du badge (fiche active).
if ($blnCanAudit && !empty($arrAuditFieldsWithLogs['is_cancelled']) && !$blnCancelled) {
fxInscrGestionActionItemOpen();
echo '<span class="inscr-gestion-audit-inline">'
. fxInscrGestionEsc(fxInscrGestionT('inscr_gestion_audit_field_is_cancelled'));
fxInscrGestionRenderAuditBang($intParId, 'is_cancelled', $blnCanAudit, $arrAuditFieldsWithLogs);
echo '</span>';
fxInscrGestionActionItemClose();
}
if ($blnInspect) {
fxInscrGestionPermInspectEcho('inscriptions_gestion.audit_view');
}
if ($blnCanRenvoi) {
fxInscrGestionActionItemOpen();
echo '<button class="btn btn-primary btn-sm rounded-0 link_confirmation" type="button"'
@ -2477,7 +2546,9 @@ function fxInscrGestionRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq,
// cote client (Tesseract.js) et ne touche aucun endpoint serveur protege.
$blnCanBibScan = true;
echo '<div class="inscr-gestion-field-block" data-inscr-field="bib">';
echo '<div class="inscr-gestion-field-block__label">' . fxInscrGestionEsc(fxInscrGestionT('promoteur_bib_number')) . '</div>';
echo '<div class="inscr-gestion-field-block__label">' . fxInscrGestionEsc(fxInscrGestionT('promoteur_bib_number'));
fxInscrGestionRenderAuditBang($intParId, 'no_bib', $blnCanAudit, $arrAuditFieldsWithLogs);
echo '</div>';
if ($blnCanBibScan) {
fxInscrGestionRenderBibScanBlock($strFullBibInputId, $strLangue);
}
@ -2499,16 +2570,33 @@ function fxInscrGestionRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq,
fxInscrGestionPermInspectEcho('inscriptions_gestion.bib_edit');
echo '</div>';
echo '</div>';
} elseif ($blnCanAudit && !empty($arrAuditFieldsWithLogs['no_bib'])) {
echo '<div class="inscr-gestion-field-block" data-inscr-field="bib">';
echo '<div class="inscr-gestion-field-block__label">' . fxInscrGestionEsc(fxInscrGestionT('promoteur_bib_number'));
fxInscrGestionRenderAuditBang($intParId, 'no_bib', $blnCanAudit, $arrAuditFieldsWithLogs);
echo '</div>';
echo '<div class="inscr-gestion-muted">' . fxInscrGestionEsc($strBib) . '</div>';
echo '</div>';
} elseif ($blnInspect) {
fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.bib_edit', fxInscrGestionT('promoteur_bib_number'));
}
if ($blnCanStatut) {
echo '<div class="inscr-gestion-field-block inscr-gestion-field-block--statut" data-inscr-field="statut">';
echo '<div class="inscr-gestion-field-block__label">' . fxInscrGestionEsc(fxInscrGestionT('inscr_gestion_statut_label')) . '</div>';
echo '<div class="inscr-gestion-field-block__label">' . fxInscrGestionEsc(fxInscrGestionT('inscr_gestion_statut_label'));
fxInscrGestionRenderAuditBang($intParId, 'par_statut_course', $blnCanAudit, $arrAuditFieldsWithLogs);
echo '</div>';
fxInscrGestionRenderStatutField($intParId, $arrRow['par_statut_course'] ?? '', $arrRow['eve_id'], $strLangue);
fxInscrGestionPermInspectEcho('inscriptions_gestion.statut_edit');
echo '</div>';
} elseif ($blnCanAudit && !empty($arrAuditFieldsWithLogs['par_statut_course'])) {
echo '<div class="inscr-gestion-field-block inscr-gestion-field-block--statut" data-inscr-field="statut">';
echo '<div class="inscr-gestion-field-block__label">' . fxInscrGestionEsc(fxInscrGestionT('inscr_gestion_statut_label'));
fxInscrGestionRenderAuditBang($intParId, 'par_statut_course', $blnCanAudit, $arrAuditFieldsWithLogs);
echo '</div>';
$strStatutDisp = trim((string)($arrRow['par_statut_course'] ?? ''));
echo '<div class="inscr-gestion-muted">' . fxInscrGestionEsc($strStatutDisp !== '' ? $strStatutDisp : '—') . '</div>';
echo '</div>';
} elseif ($blnInspect) {
fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.statut_edit', fxInscrGestionT('inscr_gestion_statut_label'));
}
@ -2523,7 +2611,10 @@ function fxInscrGestionRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq,
echo '<div class="inscr-gestion-field-block" data-inscr-field="remis">';
echo '<div class="inscr-gestion-remis-row">';
echo '<div class="inscr-gestion-remis-row__left">';
echo '<div class="inscr-gestion-field-block__label inscr-gestion-field-block__label--inline">' . fxInscrGestionEsc(fxInscrGestionT('promoteur_bib_enregistre')) . '</div>';
echo '<div class="inscr-gestion-field-block__label inscr-gestion-field-block__label--inline">'
. fxInscrGestionEsc(fxInscrGestionT('promoteur_bib_enregistre'));
fxInscrGestionRenderAuditBang($intParId, 'no_bib_remis', $blnCanAudit, $arrAuditFieldsWithLogs);
echo '</div>';
echo '<span id="' . (int)$intParId . '">';
echo '<a class="btn btn-sm rounded-0 btn_remis ' . $strRemisClass . '" href="#" data-action="remis"'
. ' data-table="' . rawurlencode(base64_encode('resultats_participants')) . '"'
@ -2539,6 +2630,13 @@ function fxInscrGestionRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq,
echo '<span id="par_' . (int)$intParId . '">' . fxInscrGestionEsc($strRemisPar) . '</span>';
echo '</div></div></div>';
fxInscrGestionPermInspectEcho('inscriptions_gestion.bib_remis');
} elseif ($blnCanAudit && !empty($arrAuditFieldsWithLogs['no_bib_remis'])) {
echo '<div class="inscr-gestion-field-block" data-inscr-field="remis">';
echo '<div class="inscr-gestion-field-block__label">'
. fxInscrGestionEsc(fxInscrGestionT('promoteur_bib_enregistre'));
fxInscrGestionRenderAuditBang($intParId, 'no_bib_remis', $blnCanAudit, $arrAuditFieldsWithLogs);
echo '</div>';
echo '</div>';
} elseif ($blnInspect) {
fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.bib_remis', fxInscrGestionT('promoteur_bib_enregistre'));
}

View File

@ -7,7 +7,7 @@
* Constantes *
*
**************/
define('_VERSION_CODE', '4.72.825');
define('_VERSION_CODE', '4.72.826');
define('_DATE_CODE', '2026-07-15');
//MSIN-4290
define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe');

View File

@ -119,6 +119,18 @@ if (!function_exists('fxV2RegisterScript')) {
'remisConfirmMsg' => fxInscrGestionT('inscr_gestion_remis_confirm_msg'),
'remisConfirmOk' => fxInscrGestionT('inscr_gestion_remis_confirm_ok'),
'remisConfirmCancel' => fxInscrGestionT('inscr_gestion_remis_confirm_cancel'),
// MSIN-4464 — historique fiche (!).
'auditPopupTitle' => fxInscrGestionT('inscr_gestion_audit_popup_title'),
'auditPopupEmpty' => fxInscrGestionT('inscr_gestion_audit_popup_empty'),
'auditPopupClose' => fxInscrGestionT('inscr_gestion_audit_popup_close'),
'auditColWhen' => fxInscrGestionT('inscr_gestion_audit_col_when'),
'auditColWho' => fxInscrGestionT('inscr_gestion_audit_col_who'),
'auditColFrom' => fxInscrGestionT('inscr_gestion_audit_col_from'),
'auditColTo' => fxInscrGestionT('inscr_gestion_audit_col_to'),
'auditFieldStatut' => fxInscrGestionT('inscr_gestion_audit_field_par_statut_course'),
'auditFieldBib' => fxInscrGestionT('inscr_gestion_audit_field_no_bib'),
'auditFieldRemis' => fxInscrGestionT('inscr_gestion_audit_field_no_bib_remis'),
'auditFieldCancel' => fxInscrGestionT('inscr_gestion_audit_field_is_cancelled'),
] : [],
// MSIN-4448 — Operateur pour no_bib_remis_par (chemin superadm / usa_id).
'remisOperator' => [

View File

@ -0,0 +1,73 @@
-- MSIN-4464 — Droit kit « voir historique fiche » + libellés Info (popup !)
-- Prérequis : sql/MSIN-4464-fiche-audit-config.sql
-- Notes prod : idempotent. Kit owner (role_grants_all) obtient le droit auto.
-- Les autres kits : cocher manuellement dans la matrice.
SET NAMES utf8mb4;
INSERT INTO `inscriptions_eve_permissions`
(`perm_key`, `perm_group`, `perm_scope`, `perm_label_fr`, `perm_label_en`,
`perm_description_fr`, `perm_description_en`, `perm_phase`, `perm_actif`, `perm_tri`)
VALUES
('inscriptions_gestion.audit_view', 'inscriptions', 'action',
'Gestion inscription : voir historique ( ! )',
'Registration mgmt: view change history (!)',
'Affiche un ! a cote des champs audites sur la fiche ; pop-up des derniers changements',
'Shows a ! next to audited fields on the sheet; popup of recent changes',
2, 1, 118)
ON DUPLICATE KEY UPDATE
`perm_group` = VALUES(`perm_group`),
`perm_scope` = VALUES(`perm_scope`),
`perm_label_fr` = VALUES(`perm_label_fr`),
`perm_label_en` = VALUES(`perm_label_en`),
`perm_description_fr` = VALUES(`perm_description_fr`),
`perm_description_en` = VALUES(`perm_description_en`),
`perm_phase` = VALUES(`perm_phase`),
`perm_actif` = 1,
`perm_tri` = VALUES(`perm_tri`);
DELETE FROM info
WHERE info_prg = 'compte.php'
AND info_clef IN (
'inscr_gestion_audit_bang_title',
'inscr_gestion_audit_bang_aria',
'inscr_gestion_audit_popup_title',
'inscr_gestion_audit_popup_empty',
'inscr_gestion_audit_popup_close',
'inscr_gestion_audit_col_when',
'inscr_gestion_audit_col_who',
'inscr_gestion_audit_col_from',
'inscr_gestion_audit_col_to',
'inscr_gestion_audit_field_par_statut_course',
'inscr_gestion_audit_field_no_bib',
'inscr_gestion_audit_field_no_bib_remis',
'inscr_gestion_audit_field_is_cancelled'
);
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) VALUES
('inscr_gestion_audit_bang_title', 'fr', 'Voir les derniers changements', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_bang_title', 'en', 'View recent changes', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_bang_aria', 'fr', 'Historique des modifications', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_bang_aria', 'en', 'Change history', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_popup_title', 'fr', 'Derniers changements', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_popup_title', 'en', 'Recent changes', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_popup_empty', 'fr', 'Aucun historique pour ce champ.', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_popup_empty', 'en', 'No history for this field.', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_popup_close', 'fr', 'Fermer', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_popup_close', 'en', 'Close', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_col_when', 'fr', 'Quand', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_col_when', 'en', 'When', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_col_who', 'fr', 'Par', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_col_who', 'en', 'By', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_col_from', 'fr', 'Avant', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_col_from', 'en', 'From', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_col_to', 'fr', 'Après', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_col_to', 'en', 'To', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_field_par_statut_course', 'fr', 'Statut de course', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_field_par_statut_course', 'en', 'Race status', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_field_no_bib', 'fr', 'Numéro de dossard', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_field_no_bib', 'en', 'Bib number', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_field_no_bib_remis', 'fr', 'Dossard remis', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_field_no_bib_remis', 'en', 'Bib handed out', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_field_is_cancelled', 'fr', 'Annulation', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW()),
('inscr_gestion_audit_field_is_cancelled', 'en', 'Cancellation', '', 'compte.php', 'MSIN-4464', 0, 1, '', '', '', NOW());

View File

@ -57,7 +57,8 @@ function fxFicheAuditAdminRenderPage($strFlash = '', $strError = '')
<p class="mb-0 text-muted">
Points branchés : statut, dossard manuel, dossard remis, annulation/rétablissement, édition fiche,
batch dossards, surplus changement d'épreuve, transfert/upgrade.
L'affichage « ? » sur la fiche et le droit promoteur associé viennent ensuite.
Sur la fiche : droit kit <code>inscriptions_gestion.audit_view</code> → « ! » si au moins 1 log
(pop-up limité au N de la rétention).
</p>
</div>
</div>