diff --git a/ajax_inscr_gestion.php b/ajax_inscr_gestion.php index ef098dc..561ca1b 100644 --- a/ajax_inscr_gestion.php +++ b/ajax_inscr_gestion.php @@ -243,10 +243,9 @@ switch ($strAction) { break; } - // L'eve_id fait foi cote serveur (jamais le client). Acces = acces a la fiche : - // qui peut voir la transaction peut voir ses remboursements (decision produit). + // L'eve_id fait foi cote serveur (jamais le client). Droit granulaire transaction. $intEveId = intval($recCommandes['eve_id']); - if ($intEveId <= 0 || !fxInscrGestionCanAccess($intComId, $intEveId)) { + if ($intEveId <= 0 || !fxInscrGestionCanDo($intComId, $intEveId, 'inscriptions_gestion.transaction')) { $tabRetour = array('state' => 'error', 'message' => 'unauthorized'); break; } diff --git a/css/style.css b/css/style.css index 4ecccb2..748f10d 100644 --- a/css/style.css +++ b/css/style.css @@ -4137,12 +4137,31 @@ a.ms1-trad-link.btn-aide-trad{ flex-wrap:wrap; gap:8px; padding:0; + align-items:center; } .inscr-gestion-gestion-actions .btn{ margin:0; } +/* MSIN-4401 — Bouton + cadenas colle a droite (jamais orphelin a gauche). */ +.inscr-gestion-action-item{ + display:inline-flex; + flex-wrap:wrap; + align-items:center; + gap:4px 6px; + max-width:100%; +} + +.inscr-gestion-action-item .ms1-perm-inspect-badge, +.inscr-gestion-action-item .ms1-perm-inspect-slot{ + margin:0; +} + +.inscr-gestion-action-item--inspect-only{ + opacity:.92; +} + /* Remboursement PayPal — fiche gestion promoteur (formulaire + panneau doc) */ .ms1-refund-wrap{ width:100%; diff --git a/php/inc_fx_inscriptions_gestion.php b/php/inc_fx_inscriptions_gestion.php index 894e388..d974399 100644 --- a/php/inc_fx_inscriptions_gestion.php +++ b/php/inc_fx_inscriptions_gestion.php @@ -100,7 +100,7 @@ function fxInscrGestionPermInspectEcho($strPermKey) { return; } fxInscrGestionLoadEveAcces(); - echo ' ' . fxEveAccesPermInspectBadge($strPermKey, 'inscr_gestion'); + echo fxEveAccesPermInspectBadge($strPermKey, 'inscr_gestion'); } /** Badge + libelle pour un controle masque par les droits (mode inspecteur). */ @@ -112,7 +112,19 @@ function fxInscrGestionPermInspectEchoHidden($strPermKey, $strLabel) { echo ''; echo fxEveAccesPermInspectBadge($strPermKey, 'inscr_gestion'); echo ' ' . fxInscrGestionEsc($strLabel) . ''; - echo ' '; + echo ''; +} + +/** MSIN-4401 — Enveloppe action + cadenas (toujours a droite du controle). */ +function fxInscrGestionActionItemOpen($strExtraClass = '') { + $strExtra = trim((string)$strExtraClass); + echo ''; +} + +function fxInscrGestionActionItemClose() { + echo ''; } function fxInscrGestionLoadEveAcces() { @@ -2099,8 +2111,13 @@ function fxInscrGestionRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq, $blnCanRestore = fxInscrGestionCanDo($intComId, $intRowEveId, 'inscriptions_gestion.restore'); // Droit de remboursement PayPal (etape remboursement) : controle l'affichage du bouton + panneau. $blnCanRefund = fxInscrGestionCanDo($intComId, $intRowEveId, 'inscriptions_gestion.refund'); + // MSIN-4401 — granularite facture / transaction / renvoi (plus d'acces implicite sans droit). + $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); - $blnHasGestion = ($blnCanEdit || $blnCanCancel || $blnCanRestore || $blnCanRefund); + $blnHasGestion = ($blnCanEdit || $blnCanCancel || $blnCanRestore || $blnCanRefund + || $blnCanInvoice || $blnCanTransaction || $blnCanRenvoi); $blnInspect = function_exists('fxAdminPermInspectModeActive') && fxAdminPermInspectModeActive(); $strBackUrl = fxInscrGestionResolveBackUrl($strBaseUrl, $intEveId, $arrReq); @@ -2183,61 +2200,101 @@ function fxInscrGestionRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq, $blnForceSectionsOpen ); echo '
'; - // Libelle devant le bouton facture (numero de commande) — invite a afficher la facture. - echo '' . fxInscrGestionEsc(fxInscrGestionT('inscr_gestion_show_invoice')) . ''; - echo '' . fxInscrGestionEsc($arrRow['no_commande']) . ''; - // Bascule "Afficher la transaction" (MSIN) : place entre le numero de transaction et Modifier. - // Charge le resume de la commande en AJAX (action transaction_resume) dans le panneau ci-dessous. - echo ''; - if ($blnCanEdit) { - echo ''; - fxInscrGestionPermInspectEcho('inscriptions_gestion.edit'); + // MSIN-4401 — Chaque action = wrap [controle][cadenas a droite] (evite badge orphelin a gauche). + if ($blnCanInvoice) { + fxInscrGestionActionItemOpen(); + echo '' . fxInscrGestionEsc(fxInscrGestionT('inscr_gestion_show_invoice')) . ''; + echo '' . fxInscrGestionEsc($arrRow['no_commande']) . ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.invoice'); + fxInscrGestionActionItemClose(); } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); + fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.invoice', fxInscrGestionT('inscr_gestion_show_invoice')); + fxInscrGestionActionItemClose(); + } + if ($blnCanTransaction) { + fxInscrGestionActionItemOpen(); + echo ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.transaction'); + fxInscrGestionActionItemClose(); + } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); + fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.transaction', fxInscrGestionT('inscr_gestion_show_transaction')); + fxInscrGestionActionItemClose(); + } + if ($blnCanEdit) { + // d-none sur le wrap entier (pas seulement le bouton) pour ne pas laisser le cadenas orphelin. + fxInscrGestionActionItemOpen(trim($strStyleEdit)); + echo ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.edit'); + fxInscrGestionActionItemClose(); + } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.edit', fxInscrGestionT('inscr_gestion_modifier_participant')); + fxInscrGestionActionItemClose(); } if ($blnCanRefund) { - // Bouton bascule : ouvre/ferme le panneau de remboursement et declenche le chargement AJAX du formulaire. - echo ''; - fxInscrGestionPermInspectEcho('inscriptions_gestion.refund'); + fxInscrGestionActionItemOpen(); + echo ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.refund'); + fxInscrGestionActionItemClose(); } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.refund', fxInscrGestionT('inscr_gestion_remboursement')); + fxInscrGestionActionItemClose(); } if ($blnCanCancel) { - echo ''; - fxInscrGestionPermInspectEcho('inscriptions_gestion.cancel'); + fxInscrGestionActionItemOpen(trim($strStyleCancel)); + echo ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.cancel'); + fxInscrGestionActionItemClose(); } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.cancel', fxInscrGestionT('btn_annulerinscriptions')); + fxInscrGestionActionItemClose(); } if ($blnCanRestore) { - echo ''; - fxInscrGestionPermInspectEcho('inscriptions_gestion.restore'); + fxInscrGestionActionItemOpen(trim($strStyleRetablir)); + echo ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.restore'); + fxInscrGestionActionItemClose(); } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.restore', fxInscrGestionT('btn_retablirinscriptions')); + fxInscrGestionActionItemClose(); + } + if ($blnCanRenvoi) { + fxInscrGestionActionItemOpen(); + echo ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.renvoi'); + fxInscrGestionActionItemClose(); + } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); + fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.renvoi', $strRenvoi); + fxInscrGestionActionItemClose(); } - // RENVOI place en dernier (MSIN-4403) : retourne la confirmation au participant. - echo ''; echo '
'; if ($blnCanRefund) { // Panneau de remboursement : vide au depart, rempli en AJAX a la 1ere ouverture (action=refund_form). @@ -2249,9 +2306,11 @@ function fxInscrGestionRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq, } // Panneau de transaction : vide au depart, rempli en AJAX a la 1ere ouverture (action=transaction_resume). // Sous les boutons, repliable, accessible a tout moment (independant du remboursement). + if ($blnCanTransaction) { echo ''; + } fxInscrGestionRenderFicheSectionEnd(); } diff --git a/php/inc_settings.php b/php/inc_settings.php index 76055a2..038fd55 100644 --- a/php/inc_settings.php +++ b/php/inc_settings.php @@ -7,7 +7,7 @@ * Constantes * * **************/ -define('_VERSION_CODE', '4.72.815'); +define('_VERSION_CODE', '4.72.816'); define('_DATE_CODE', '2026-07-13'); //MSIN-4290 define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe'); diff --git a/sql/MSIN-4401-inscr-gestion-actions-perm.sql b/sql/MSIN-4401-inscr-gestion-actions-perm.sql new file mode 100644 index 0000000..6c14c0d --- /dev/null +++ b/sql/MSIN-4401-inscr-gestion-actions-perm.sql @@ -0,0 +1,59 @@ +-- MSIN-4401 — Droits granulaires fiche Gestion : facture, transaction, renvoi +-- Prérequis : MSIN-eve-acces-v2-phase2-multi-granular.sql (perms base) +-- Idempotent. Safe pilote. +-- +-- Note : kit propriétaire (role_grants_all) n'a PAS besoin de ces lignes. + +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.invoice', 'inscriptions', 'action', + 'Gestion inscription : facture', 'Registration mgmt: invoice', + 'Afficher la facture (numero de commande) depuis la fiche', + 'Show invoice (order number) from the sheet', + 2, 1, 138), + ('inscriptions_gestion.transaction', 'inscriptions', 'action', + 'Gestion inscription : transaction', 'Registration mgmt: transaction', + 'Afficher le resume de transaction depuis la fiche', + 'Show transaction summary from the sheet', + 2, 1, 139), + ('inscriptions_gestion.renvoi', 'inscriptions', 'action', + 'Gestion inscription : renvoyer confirmation', 'Registration mgmt: resend confirmation', + 'Renvoyer la confirmation au participant depuis la fiche', + 'Resend confirmation to the participant from the sheet', + 2, 1, 140) +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`); + +/* Kits terrain : ops = les 3 ; readonly = lecture facture+transaction */ +INSERT INTO inscriptions_eve_role_permissions (role_id, perm_key) +SELECT r.role_id, p.perm_key +FROM inscriptions_eve_roles r +CROSS JOIN ( + SELECT 'inscriptions_gestion.invoice' AS perm_key + UNION ALL SELECT 'inscriptions_gestion.transaction' + UNION ALL SELECT 'inscriptions_gestion.renvoi' +) p +WHERE r.role_code = 'gestion_ops' +ON DUPLICATE KEY UPDATE perm_key = VALUES(perm_key); + +INSERT INTO inscriptions_eve_role_permissions (role_id, perm_key) +SELECT r.role_id, p.perm_key +FROM inscriptions_eve_roles r +CROSS JOIN ( + SELECT 'inscriptions_gestion.invoice' AS perm_key + UNION ALL SELECT 'inscriptions_gestion.transaction' +) p +WHERE r.role_code IN ('gestion_readonly', 'gestion_statut') +ON DUPLICATE KEY UPDATE perm_key = VALUES(perm_key);