Enhance batch and auto selection UI with new prompts and visibility logic; increment version code to 4.72.688

This commit introduces a new prompt for sequence selection in batch and auto modes, improving user guidance. The visibility logic for various action groups is refined based on selection states, ensuring a clearer interface. Additionally, CSS styles are updated to support the new prompt, enhancing the overall user experience in the bib management system.
This commit is contained in:
2026-06-19 11:43:57 -04:00
parent 717f11e3d5
commit 6403f371fe
7 changed files with 436 additions and 29 deletions

View File

@ -1879,6 +1879,10 @@ a.ms1-trad-link.btn-aide-trad{
box-shadow:inset 0 0 0 1px #ffe082;
}
.bib-seq-pick-prompt{
margin-bottom:10px;
}
.batch-pick-prompt{
padding:12px 14px;
margin-bottom:0;

View File

@ -2410,6 +2410,7 @@ if ($strLangue == 'fr') {
});
updateAutoSelectionInfo(row);
syncBibUiState(row);
});
}
@ -2420,7 +2421,9 @@ if ($strLangue == 'fr') {
let avecBib = parseInt(bibQuery(row, '.bib-avec')?.textContent || '0', 10) || 0;
let hasSequences = bibHasSavedSequences(row);
let hasSelection = bibCountSelectedRanges(row) > 0;
let inAssignFlow = modes.batch || modes.reset;
let inBatchFlow = modes.batch || modes.reset;
let inAutoFlow = modes.auto;
let inPickFlow = inBatchFlow || inAutoFlow;
row.querySelectorAll('.team-mode-box input[type="radio"]').forEach(function (radio) {
if (!radio.closest('.team-mode-option.disabled')) {
@ -2436,27 +2439,32 @@ if ($strLangue == 'fr') {
bibSetVisible('.epr-action-reset-group', showReset, row);
bibSetVisible('.epr-action-auto-group',
hasSequences && !modes.reset && !modes.auto && !modes.batch, row);
bibSetVisible('.epr-action-desactiver-group',
hasSequences && row.dataset.autoActive === '1' && modes.auto, row);
if (hasSequences) {
syncAutoUiState(row, row.dataset.autoActive === '1');
}
bibSetVisible('.epr-add-range-row', !inAssignFlow && !modes.auto, row);
bibSetVisible('.batch-config-container', inAssignFlow, row);
bibSetVisible('.auto-config-container', modes.auto, row);
bibSetVisible('.epr-add-range-row', !inPickFlow, row);
bibSetVisible('.batch-config-container', inBatchFlow, row);
bibSetVisible('.auto-config-container', inAutoFlow, row);
let showBatchPick = inAssignFlow && !hasSelection;
let showBatchReady = inAssignFlow && hasSelection;
bibSetVisible('.batch-pick-prompt', showBatchPick, row);
let showPick = inPickFlow && !hasSelection;
let showBatchReady = inBatchFlow && hasSelection;
let showAutoReady = inAutoFlow && hasSelection;
bibSetVisible('.bib-seq-pick-prompt', showPick, row);
bibSetVisible('.batch-config-ready', showBatchReady, row);
bibSetVisible('.auto-config-ready', showAutoReady, row);
let bibContainer = getBibContainer(row);
if (bibContainer) {
bibContainer.classList.toggle('batch-awaiting-selection', showBatchPick);
bibContainer.classList.toggle('batch-awaiting-selection', showPick);
}
bibSetVisible('.epr-action-desactiver-group',
hasSequences && row.dataset.autoActive === '1' && inAutoFlow, row);
bibSetVisible('.epr-action-cancel-auto-group', inAutoFlow, row);
bibSetVisible('.epr-action-accept-auto-group', showAutoReady, row);
bibSetVisible('.epr-auto-info-group', showAutoReady, row);
bibSetVisible('.batch-reset-warning', showBatchReady && modes.reset, row);
bibSetVisible('.epr-batch-order-wrap', showBatchReady && !modes.reset, row);
bibSetVisible('.epr-action-sim-group', showBatchReady && !modes.reset, row);
@ -2584,9 +2592,10 @@ if ($strLangue == 'fr') {
let row = cb.closest('.epr-row');
if (!row) return;
// MSIN-4379 — En mode auto, pas de logique batch (refresh_ranges / GO).
// MSIN-4379 — Mode auto : même sélection de séquences que le batch, sans GO/simulation.
if (row.classList.contains('auto-mode')) {
updateAutoSelectionInfo(row);
syncBibUiState(row);
return;
}

View File

@ -2591,6 +2591,18 @@ function fxUpdateQuantites($intEpreuve, $intQuantite, $strLangue) {
}
// v2 — encart « choisissez vos séquences » (batch + auto)
function renderBibBatchPickPrompt() {
ob_start();
?>
<div class="bib-seq-pick-prompt batch-pick-prompt bib-ui-hidden">
<p class="batch-pick-prompt__title"><?php fxBibTexteTrad('bib_v4_batch_pick_title', 1); ?></p>
<p class="batch-pick-prompt__hint text-muted mb-0"><?php fxBibTexteTrad('bib_v4_batch_pick_hint', 1); ?></p>
</div>
<?php
return ob_get_clean();
}
// v2 — options d'ordre batch (table bib_assignements)
function renderBatchConfig($tabBibAssignments, $strLangue = 'fr', $isTeamEpreuve = false) {
@ -2599,11 +2611,6 @@ function renderBatchConfig($tabBibAssignments, $strLangue = 'fr', $isTeamEpreuve
<div class="batch-config">
<div class="batch-pick-prompt">
<p class="batch-pick-prompt__title"><?php fxBibTexteTrad('bib_v4_batch_pick_title', 1); ?></p>
<p class="batch-pick-prompt__hint text-muted mb-0"><?php fxBibTexteTrad('bib_v4_batch_pick_hint', 1); ?></p>
</div>
<div class="batch-config-ready bib-ui-hidden">
<!-- ORDRE -->
@ -3617,26 +3624,32 @@ function renderBibAssignActions($tabBibAssignments, $strLangue, $infoBib, $blnAu
<?php echo fxBibActionGroupClose(); ?>
</div>
<?php echo renderBibBatchPickPrompt(); ?>
<div class="auto-config-container bib-ui-hidden">
<?php echo fxBibActionGroupOpen('epr-auto-info-group text-muted small mb-2'); ?>
<span class="auto-info-text"><?php fxBibTexteTrad('bib_v4_auto_select_hint', 1); ?></span>
<?php echo fxBibAideButton('bib_v4_auto_select_hint', '', false); ?>
<?php echo fxBibActionGroupClose(); ?>
<div class="epr-action-row epr-action-row-auto-config">
<div class="epr-action-row-auto-left">
<?php echo fxBibActionGroupOpen('epr-action-accept-auto-group'); ?>
<?php echo fxBibBtnAideSegmentOpen(); ?>
<button type="button" class="btn btn-sm btn-success btn-accepter-auto"><?php fxBibTexte('bib_v4_auto_accept', 1); ?></button>
<?php echo fxBibAideButton('bib_v4_auto_accept', 'success', false); ?>
<?php echo fxBibBtnAideSegmentClose('bib_v4_auto_accept'); ?>
<div class="auto-config-ready bib-ui-hidden">
<?php echo fxBibActionGroupOpen('epr-auto-info-group text-muted small mb-2'); ?>
<span class="auto-info-text"><?php fxBibTexteTrad('bib_v4_auto_select_hint', 1); ?></span>
<?php echo fxBibAideButton('bib_v4_auto_select_hint', '', false); ?>
<?php echo fxBibActionGroupClose(); ?>
<div class="epr-action-row epr-action-row-auto-config">
<div class="epr-action-row-auto-left">
<?php echo fxBibActionGroupOpen('epr-action-accept-auto-group'); ?>
<?php echo fxBibBtnAideSegmentOpen(); ?>
<button type="button" class="btn btn-sm btn-success btn-accepter-auto"><?php fxBibTexte('bib_v4_auto_accept', 1); ?></button>
<?php echo fxBibAideButton('bib_v4_auto_accept', 'success', false); ?>
<?php echo fxBibBtnAideSegmentClose('bib_v4_auto_accept'); ?>
<?php echo fxBibActionGroupClose(); ?>
</div>
</div>
</div>
<div class="epr-action-row epr-action-row-auto-footer">
<?php echo fxBibActionGroupOpen('epr-action-cancel-auto-group'); ?>
<?php echo fxBibBtnAideSegmentOpen(); ?>
<button type="button" class="btn btn-sm btn-secondary btn-annuler-auto"><?php fxBibTexte('bib_v4_auto_cancel', 1); ?></button>
<?php echo fxBibAideButton('bib_v4_auto_cancel', 'secondary', false); ?>
<?php echo fxBibBtnAideSegmentClose('bib_v4_auto_cancel'); ?>
<?php echo fxBibActionGroupClose(); ?>
</div>
<?php echo fxBibActionGroupOpen('epr-action-desactiver-group', $blnAutoActive); ?>
<?php echo fxBibBtnAideSegmentOpen(); ?>
<button type="button" class="btn btn-sm btn-danger btn-desactiver-auto">

View File

@ -7,7 +7,7 @@
* Constantes *
*
**************/
define('_VERSION_CODE', '4.72.687');
define('_VERSION_CODE', '4.72.688');
define('_DATE_CODE', '2026-06-18');
//MSIN-4290
define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe');

View File

@ -0,0 +1,61 @@
/*
MSIN - Acces evenement v2 - Exemple pilote (MANUEL)
NE PAS executer tel quel : remplacer com_id et eve_id.
Executer UN bloc a la fois dans votre client SQL.
*/
/*
Etape A - Verifications
SELECT com_id, com_courriel FROM inscriptions_comptes WHERE com_courriel = 'pilote@example.com';
SELECT eve_id, eve_nom_fr FROM inscriptions_evenements WHERE eve_id = 1234;
SELECT role_id, role_code, role_label_fr FROM inscriptions_eve_roles WHERE role_actif = 1;
*/
/*
Etape B - Acces pilote mobile 30 jours
INSERT INTO inscriptions_eve_acces
(com_id, eve_id, role_id, ea_statut, ea_expires_at, ea_expire_days, ea_granted_by, ea_note)
SELECT
15464,
1234,
r.role_id,
'actif',
DATE_ADD(NOW(), INTERVAL 30 DAY),
30,
1,
'Pilote prod - API mobile v2'
FROM inscriptions_eve_roles r
WHERE r.role_code = 'mobile_ops'
LIMIT 1;
*/
/*
Etape C - Validation
SELECT * FROM v_eve_acces_actif WHERE com_id = 15464;
SELECT * FROM v_eve_acces_permissions WHERE com_id = 15464 AND eve_id = 1234;
SELECT com_id, com_eve_promoteur FROM inscriptions_comptes WHERE com_id = 15464;
*/
/*
Etape D - Revocation (sans toucher au legacy)
UPDATE inscriptions_eve_acces
SET ea_statut = 'revoke',
ea_revoked_at = NOW(),
ea_revoked_by = 1
WHERE com_id = 15464 AND eve_id = 1234;
INSERT INTO inscriptions_eve_acces_log
(ea_id, com_id, eve_id, role_id, log_action, log_detail, log_by_com_id)
SELECT ea_id, com_id, eve_id, role_id, 'revoke', 'Revoke manuel - fin pilote', 1
FROM inscriptions_eve_acces
WHERE com_id = 15464 AND eve_id = 1234;
*/

View File

@ -0,0 +1,159 @@
/*
MSIN - Acces evenement v2 (phase 1) - Seed
Executer APRES MSIN-eve-acces-v2-phase1-tables.sql
*/
SET NAMES utf8mb4;
INSERT INTO `inscriptions_eve_permissions`
(`perm_key`, `perm_group`, `perm_label_fr`, `perm_label_en`, `perm_description_fr`, `perm_description_en`, `perm_phase`, `perm_actif`, `perm_tri`)
VALUES
('events.list', 'api', 'Lister les evenements', 'List events',
'GET /v1/events', NULL, 1, 1, 10),
('events.view', 'api', 'Voir un evenement', 'View event',
'GET /v1/events/{id}', NULL, 1, 1, 20),
('registrations.view', 'api', 'Voir les inscriptions', 'View registrations',
'GET /v1/events/{id}/registrations', NULL, 1, 1, 30),
('registrations.scan', 'api', 'Scanner QR', 'Scan QR',
'Scan QR inscriptions mobile', NULL, 1, 1, 40),
('inscriptions.view', 'inscriptions', 'Inscriptions (lecture)', 'Registrations (read)',
'Tableau inscriptions web promoteur', NULL, 2, 1, 110),
('inscriptions.edit', 'inscriptions', 'Inscriptions (modification)', 'Registrations (edit)',
'Modifier ou annuler inscriptions', NULL, 2, 1, 120),
('inscriptions_mobile.view', 'inscriptions', 'Inscriptions mobile (web)', 'Mobile registrations (web)',
'Interface web inscriptions mobile', NULL, 2, 1, 130),
('dossards.view', 'dossards', 'Dossards (lecture)', 'Bibs (read)', NULL, NULL, 2, 1, 210),
('dossards.manage', 'dossards', 'Dossards (gestion)', 'Bibs (manage)', NULL, NULL, 2, 1, 220),
('epreuves.view', 'epreuves', 'Epreuves (lecture)', 'Races (read)', NULL, NULL, 2, 1, 310),
('epreuves.edit_qte', 'epreuves', 'Epreuves (quantites)', 'Races (quantities)', NULL, NULL, 2, 1, 320),
('rabais.view', 'rabais', 'Rabais (lecture)', 'Discounts (read)', NULL, NULL, 2, 1, 410),
('rabais.manage', 'rabais', 'Rabais (gestion)', 'Discounts (manage)', NULL, NULL, 2, 1, 420),
('emails.send', 'emails', 'Courriels', 'Emails', NULL, NULL, 2, 1, 510),
('reports.chrono', 'reports', 'Rapport chrono + questions', 'Chrono + questions report', NULL, NULL, 3, 1, 610),
('reports.finances', 'reports', 'Rapport finances', 'Finances report', NULL, NULL, 3, 1, 620),
('reports.finances_membership', 'reports', 'Finances adhesions', 'Membership finances', NULL, NULL, 3, 1, 625),
('reports.finances_events', 'reports', 'Finances evenements seul', 'Events-only finances', NULL, NULL, 3, 1, 626),
('reports.payments', 'reports', 'Rapport paiements', 'Payments report', NULL, NULL, 3, 1, 630),
('reports.adhesions', 'reports', 'Adhesions actives', 'Active memberships', NULL, NULL, 3, 1, 640),
('reports.adhesions_sales', 'reports', 'Ventes adhesions', 'Membership sales', NULL, NULL, 3, 1, 650),
('reports.finances_captains', 'reports', 'Finances capitaines', 'Captains finances', NULL, NULL, 3, 1, 660),
('reports.custom', 'reports', 'Rapports personnalises', 'Custom reports', NULL, NULL, 3, 1, 690),
('team.view', 'team', 'Voir l equipe', 'View team', NULL, NULL, 2, 1, 710),
('team.invite', 'team', 'Inviter des membres', 'Invite members', NULL, NULL, 2, 1, 720),
('team.manage', 'team', 'Gerer l equipe', 'Manage team', NULL, NULL, 2, 1, 730)
ON DUPLICATE KEY UPDATE
`perm_group` = VALUES(`perm_group`),
`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` = VALUES(`perm_actif`),
`perm_tri` = VALUES(`perm_tri`);
INSERT INTO `inscriptions_eve_roles`
(`role_code`, `role_label_fr`, `role_label_en`, `role_description_fr`, `role_description_en`, `role_icone`, `role_systeme`, `role_actif`, `role_tri`)
VALUES
('owner', 'Proprietaire', 'Owner',
'Acces complet sur l evenement',
'Full access to the event',
'fa-crown', 1, 1, 10),
('mobile_ops', 'Operations mobile', 'Mobile operations',
'API mobile : evenements, inscriptions, scan QR',
'Mobile API: events, registrations, QR scan',
'fa-mobile', 1, 1, 20),
('mobile_readonly', 'Mobile lecture seule', 'Mobile read-only',
'API mobile : consulter evenements et inscriptions',
'Mobile API: view events and registrations only',
'fa-eye', 1, 1, 30),
('reports_finance', 'Finances', 'Finance',
'Rapports finances et paiements uniquement',
'Finance and payments reports only',
'fa-money', 1, 1, 40),
('reports_ops', 'Operations + chrono', 'Operations + chrono',
'Rapports chrono et operationnels sans finances',
'Chrono and operational reports without finance',
'fa-bar-chart', 1, 1, 50)
ON DUPLICATE KEY UPDATE
`role_label_fr` = VALUES(`role_label_fr`),
`role_label_en` = VALUES(`role_label_en`),
`role_description_fr` = VALUES(`role_description_fr`),
`role_description_en` = VALUES(`role_description_en`),
`role_icone` = VALUES(`role_icone`),
`role_systeme` = VALUES(`role_systeme`),
`role_actif` = VALUES(`role_actif`),
`role_tri` = VALUES(`role_tri`);
DELETE erp FROM inscriptions_eve_role_permissions erp
INNER JOIN inscriptions_eve_roles r ON r.role_id = erp.role_id
WHERE r.role_code = 'owner';
INSERT INTO inscriptions_eve_role_permissions (role_id, perm_key)
SELECT r.role_id, p.perm_key
FROM inscriptions_eve_roles r
CROSS JOIN inscriptions_eve_permissions p
WHERE r.role_code = 'owner'
AND p.perm_actif = 1;
DELETE erp FROM inscriptions_eve_role_permissions erp
INNER JOIN inscriptions_eve_roles r ON r.role_id = erp.role_id
WHERE r.role_code = 'mobile_ops';
INSERT INTO inscriptions_eve_role_permissions (role_id, perm_key)
SELECT r.role_id, p.perm_key
FROM inscriptions_eve_roles r
INNER JOIN inscriptions_eve_permissions p
ON p.perm_key IN ('events.list', 'events.view', 'registrations.view', 'registrations.scan')
AND p.perm_actif = 1
WHERE r.role_code = 'mobile_ops';
DELETE erp FROM inscriptions_eve_role_permissions erp
INNER JOIN inscriptions_eve_roles r ON r.role_id = erp.role_id
WHERE r.role_code = 'mobile_readonly';
INSERT INTO inscriptions_eve_role_permissions (role_id, perm_key)
SELECT r.role_id, p.perm_key
FROM inscriptions_eve_roles r
INNER JOIN inscriptions_eve_permissions p
ON p.perm_key IN ('events.list', 'events.view', 'registrations.view')
AND p.perm_actif = 1
WHERE r.role_code = 'mobile_readonly';
DELETE erp FROM inscriptions_eve_role_permissions erp
INNER JOIN inscriptions_eve_roles r ON r.role_id = erp.role_id
WHERE r.role_code = 'reports_finance';
INSERT INTO inscriptions_eve_role_permissions (role_id, perm_key)
SELECT r.role_id, p.perm_key
FROM inscriptions_eve_roles r
INNER JOIN inscriptions_eve_permissions p
ON p.perm_key IN (
'events.list', 'events.view',
'reports.finances', 'reports.finances_membership', 'reports.finances_events',
'reports.payments', 'reports.finances_captains'
)
AND p.perm_actif = 1
WHERE r.role_code = 'reports_finance';
DELETE erp FROM inscriptions_eve_role_permissions erp
INNER JOIN inscriptions_eve_roles r ON r.role_id = erp.role_id
WHERE r.role_code = 'reports_ops';
INSERT INTO inscriptions_eve_role_permissions (role_id, perm_key)
SELECT r.role_id, p.perm_key
FROM inscriptions_eve_roles r
INNER JOIN inscriptions_eve_permissions p
ON p.perm_key IN (
'events.list', 'events.view',
'registrations.view', 'inscriptions.view', 'inscriptions_mobile.view',
'dossards.view', 'reports.chrono', 'reports.adhesions', 'reports.adhesions_sales', 'reports.custom'
)
AND p.perm_actif = 1
WHERE r.role_code = 'reports_ops';

View File

@ -0,0 +1,161 @@
/*
MSIN - Acces evenement v2 (phase 1)
Tables NEUVES uniquement. Aucune modification des tables legacy.
Legacy inchange :
inscriptions_comptes.com_eve_promoteur
inscriptions_comptes.com_rapports
inscriptions_comptes.com_eve_modifiable
Ordre :
1) Ce fichier
2) MSIN-eve-acces-v2-phase1-seed.sql
*/
SET NAMES utf8mb4;
/* 1. Catalogue des permissions */
CREATE TABLE IF NOT EXISTS `inscriptions_eve_permissions` (
`perm_key` varchar(64) NOT NULL,
`perm_group` varchar(32) NOT NULL DEFAULT 'general',
`perm_label_fr` varchar(100) NOT NULL,
`perm_label_en` varchar(100) NOT NULL,
`perm_description_fr` varchar(255) DEFAULT NULL,
`perm_description_en` varchar(255) DEFAULT NULL,
`perm_phase` tinyint(3) unsigned NOT NULL DEFAULT 1 COMMENT '1=mobile API, 2=web promoteur, 3=rapports',
`perm_actif` tinyint(1) unsigned NOT NULL DEFAULT 1,
`perm_tri` smallint(5) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`perm_key`),
KEY `idx_perm_group` (`perm_group`, `perm_actif`, `perm_tri`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='Catalogue permissions v2';
/* 2. Roles (super admin seulement) */
CREATE TABLE IF NOT EXISTS `inscriptions_eve_roles` (
`role_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`role_code` varchar(32) NOT NULL,
`role_label_fr` varchar(80) NOT NULL,
`role_label_en` varchar(80) NOT NULL,
`role_description_fr` varchar(255) DEFAULT NULL,
`role_description_en` varchar(255) DEFAULT NULL,
`role_icone` varchar(32) DEFAULT NULL,
`role_systeme` tinyint(1) unsigned NOT NULL DEFAULT 1,
`role_actif` tinyint(1) unsigned NOT NULL DEFAULT 1,
`role_tri` smallint(5) unsigned NOT NULL DEFAULT 0,
`role_created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`role_updated_at` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`role_id`),
UNIQUE KEY `uk_role_code` (`role_code`),
KEY `idx_role_actif` (`role_actif`, `role_tri`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='Roles v2';
/* 3. Permissions par role */
CREATE TABLE IF NOT EXISTS `inscriptions_eve_role_permissions` (
`role_id` int(10) unsigned NOT NULL,
`perm_key` varchar(64) NOT NULL,
PRIMARY KEY (`role_id`, `perm_key`),
KEY `idx_erp_perm` (`perm_key`),
CONSTRAINT `fk_erp_role`
FOREIGN KEY (`role_id`) REFERENCES `inscriptions_eve_roles` (`role_id`)
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_erp_perm`
FOREIGN KEY (`perm_key`) REFERENCES `inscriptions_eve_permissions` (`perm_key`)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='Matrice role-permission';
/* 4. Assignations compte x evenement */
CREATE TABLE IF NOT EXISTS `inscriptions_eve_acces` (
`ea_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`com_id` int(10) unsigned NOT NULL,
`eve_id` int(10) unsigned NOT NULL,
`role_id` int(10) unsigned NOT NULL,
`ea_statut` enum('actif','revoke','invite') NOT NULL DEFAULT 'actif',
`ea_expires_at` datetime DEFAULT NULL,
`ea_expire_days` smallint(5) unsigned DEFAULT NULL,
`ea_granted_by` int(10) unsigned DEFAULT NULL,
`ea_note` varchar(255) DEFAULT NULL,
`ea_created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ea_updated_at` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`ea_revoked_at` datetime DEFAULT NULL,
`ea_revoked_by` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`ea_id`),
UNIQUE KEY `uk_com_eve` (`com_id`, `eve_id`),
KEY `idx_eve_actif` (`eve_id`, `ea_statut`),
KEY `idx_com_actif` (`com_id`, `ea_statut`),
KEY `idx_expires` (`ea_expires_at`, `ea_statut`),
KEY `idx_role` (`role_id`),
CONSTRAINT `fk_ea_role`
FOREIGN KEY (`role_id`) REFERENCES `inscriptions_eve_roles` (`role_id`)
ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='Acces v2 par compte et evenement';
/* 5. Journal audit */
CREATE TABLE IF NOT EXISTS `inscriptions_eve_acces_log` (
`log_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ea_id` int(10) unsigned DEFAULT NULL,
`com_id` int(10) unsigned NOT NULL,
`eve_id` int(10) unsigned NOT NULL,
`role_id` int(10) unsigned DEFAULT NULL,
`log_action` varchar(32) NOT NULL,
`log_detail` text DEFAULT NULL,
`log_by_com_id` int(10) unsigned DEFAULT NULL,
`log_created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`log_id`),
KEY `idx_log_eve` (`eve_id`, `log_created_at`),
KEY `idx_log_com` (`com_id`, `log_created_at`),
KEY `idx_log_ea` (`ea_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='Audit acces v2';
/* 6. Vue acces actifs */
DROP VIEW IF EXISTS `v_eve_acces_actif`;
CREATE VIEW `v_eve_acces_actif` AS
SELECT
ea.ea_id,
ea.com_id,
ea.eve_id,
ea.role_id,
r.role_code,
r.role_label_fr,
r.role_label_en,
ea.ea_statut,
ea.ea_expires_at,
ea.ea_expire_days,
ea.ea_granted_by,
ea.ea_created_at
FROM inscriptions_eve_acces ea
INNER JOIN inscriptions_eve_roles r
ON r.role_id = ea.role_id
AND r.role_actif = 1
WHERE ea.ea_statut = 'actif'
AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW());
/* 7. Vue permissions effectives */
DROP VIEW IF EXISTS `v_eve_acces_permissions`;
CREATE VIEW `v_eve_acces_permissions` AS
SELECT
v.ea_id,
v.com_id,
v.eve_id,
v.role_id,
v.role_code,
erp.perm_key,
p.perm_group,
p.perm_label_fr,
p.perm_phase
FROM v_eve_acces_actif v
INNER JOIN inscriptions_eve_role_permissions erp
ON erp.role_id = v.role_id
INNER JOIN inscriptions_eve_permissions p
ON p.perm_key = erp.perm_key
AND p.perm_actif = 1;