-- ============================================================ -- PTA - Quotas annuels et vues de pilotage -- À exécuter APRÈS : -- 1. pta_mysql_test.sql -- 2. migration_planning_motifs.sql -- Compatible MySQL 8+ -- ============================================================ USE pta_test; -- ------------------------------------------------------------ -- 1. Quota annuel d'un agent -- 1607 h = 96 420 minutes à 100 %. -- La quotité permet de proratiser automatiquement le quota cible. -- ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS quota_agent_annuel ( id_quota INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, id_agent INT UNSIGNED NOT NULL, annee SMALLINT UNSIGNED NOT NULL, quotite_travail DECIMAL(5,2) NOT NULL DEFAULT 100.00, quota_reference_minutes INT UNSIGNED NOT NULL DEFAULT 96420, quota_cible_minutes INT UNSIGNED NOT NULL, commentaire VARCHAR(255) NULL, CONSTRAINT fk_quota_annuel_agent FOREIGN KEY (id_agent) REFERENCES agent(id_agent), CONSTRAINT chk_quotite_travail CHECK (quotite_travail > 0 AND quotite_travail <= 100), CONSTRAINT chk_quota_annuel_positif CHECK (quota_cible_minutes > 0), UNIQUE KEY uk_quota_agent_annee (id_agent, annee) ) ENGINE = InnoDB; -- Jeu d'essai 2026 : tous les agents existants à 100 %, soit 1607 h. INSERT INTO quota_agent_annuel ( id_agent, annee, quotite_travail, quota_reference_minutes, quota_cible_minutes, commentaire ) SELECT a.id_agent, 2026, 100.00, 96420, 96420, 'Quota annuel de référence à 100 %' FROM agent a WHERE NOT EXISTS ( SELECT 1 FROM quota_agent_annuel q WHERE q.id_agent = a.id_agent AND q.annee = 2026 ); -- Exemple de modification pour un agent à 80 % : -- UPDATE quota_agent_annuel -- SET quotite_travail = 80.00, -- quota_cible_minutes = ROUND(96420 * 0.80) -- WHERE id_agent = 2 AND annee = 2026; -- ------------------------------------------------------------ -- 2. Règle de décompte des motifs -- L'application reste paramétrable : le booléen compte_dans_quota -- indique si le motif consomme le quota annuel. -- Selon le besoin exprimé, les motifs principaux ci-dessous sont -- comptés par défaut. Il est possible de changer cette règle ensuite. -- ------------------------------------------------------------ UPDATE motif_planning SET compte_dans_quota = TRUE WHERE code IN ('TRAVAIL', 'FORMATION', 'CONGE', 'MALADIE'); -- ------------------------------------------------------------ -- 3. Vue annuelle de suivi des quotas -- Les brouillons et les plannings validés sont distingués. -- ------------------------------------------------------------ CREATE OR REPLACE VIEW v_suivi_quota_annuel AS SELECT q.id_agent, a.matricule, a.nom, a.prenom, q.annee, q.quotite_travail, q.quota_reference_minutes, q.quota_cible_minutes, ROUND(q.quota_cible_minutes / 60, 2) AS quota_cible_heures, COALESCE(SUM( CASE WHEN p.statut = 'VALIDE' AND m.compte_dans_quota = TRUE THEN TIMESTAMPDIFF( MINUTE, CONCAT(c.date_jour, ' ', c.heure_debut), CONCAT(c.date_jour, ' ', c.heure_fin) ) ELSE 0 END ), 0) AS minutes_valides, COALESCE(SUM( CASE WHEN p.statut = 'BROUILLON' AND m.compte_dans_quota = TRUE THEN TIMESTAMPDIFF( MINUTE, CONCAT(c.date_jour, ' ', c.heure_debut), CONCAT(c.date_jour, ' ', c.heure_fin) ) ELSE 0 END ), 0) AS minutes_brouillon, q.quota_cible_minutes - COALESCE(SUM( CASE WHEN m.compte_dans_quota = TRUE THEN TIMESTAMPDIFF( MINUTE, CONCAT(c.date_jour, ' ', c.heure_debut), CONCAT(c.date_jour, ' ', c.heure_fin) ) ELSE 0 END ), 0) AS minutes_restantes FROM quota_agent_annuel q INNER JOIN agent a ON a.id_agent = q.id_agent LEFT JOIN planning p ON p.id_agent = q.id_agent LEFT JOIN creneau_horaire c ON c.id_planning = p.id_planning AND YEAR(c.date_jour) = q.annee LEFT JOIN motif_planning m ON m.id_motif = c.id_motif GROUP BY q.id_agent, a.matricule, a.nom, a.prenom, q.annee, q.quotite_travail, q.quota_reference_minutes, q.quota_cible_minutes;