Files
pta/app/Models/SchemaModel.php
PTA 4201894e28 V7.10 — Tableau de bord, guide, semaine type et enveloppe de formation
Reprise dans le répertoire de production du travail mené dans le worktree
ux-service-enfance :

- tableau de bord Service Enfance (dashboard.php) et navigation regroupée ;
- guide d'utilisation (faq.php) accessible depuis toute la navigation ;
- éditeur de semaine type mis en avant sur l'écran de saisie ;
- droit à l'enveloppe de formation par agent, en remplacement de la case
  « formation déjà prévue dans la répartition annuelle » ;
- correctif de « [object Object] » sur les cartes de quota du PTA ;
- motif de travail par défaut à la saisie, heures travaillées complètes
  dans les PDF.

Le docker-compose.yml de production est conservé : celui du worktree décrit
une pile de test (conteneurs et volume suffixés « test », ports 9080/9081),
qui aurait fait redémarrer l'application sur un volume MariaDB vide.

Les migrations database/migration_v7_9*.sql sont obligatoires ; le service
db-migrate les applique au déploiement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 16:53:04 +02:00

121 lines
4.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace App\Models;
final class SchemaModel extends BaseModel
{
public function assertCurrent(): void
{
$requiredTables = [
'agent',
'structure',
'agent_structure',
'motif_planning',
'semaine',
'planning',
'creneau_horaire',
'quota_agent_annuel',
'modele_semaine_agent',
'modele_semaine_creneau',
'structure_couverture_horaire',
'periode_vacance',
'poste_agent',
'pta_annuel',
'agent_structure_souhait',
'agent_contrainte',
'equipe_pta',
'equipe_pta_membre',
'structure_creneau_reference',
];
$placeholders = implode(',', array_fill(0, count($requiredTables), '?'));
$stmt = $this->pdo->prepare(
"SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME IN ($placeholders)"
);
$stmt->execute($requiredTables);
$existing = $stmt->fetchAll(\PDO::FETCH_COLUMN);
$missingTables = array_values(array_diff($requiredTables, $existing));
if ($missingTables) {
throw new \RuntimeException(
'Base PTA incomplète : table(s) manquante(s) : '
. implode(', ', $missingTables)
. '. Exécutez database/install_complet.sql ou les migrations nécessaires.'
);
}
$requiredColumns = [
'creneau_horaire' => ['id_motif'],
'planning' => ['date_validation'],
'agent' => ['email', 'telephone', 'adresse', 'est_diplome', 'diplome_libelle', 'id_structure', 'id_poste', 'type_contrat', 'date_debut_contrat', 'date_fin_contrat', 'droit_enveloppe_formation', 'commentaire_pta'],
'structure' => ['type_affectation'],
];
foreach ($requiredColumns as $table => $columns) {
$columnPlaceholders = implode(',', array_fill(0, count($columns), '?'));
$params = array_merge([$table], $columns);
$columnStmt = $this->pdo->prepare(
"SELECT COLUMN_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = ?
AND COLUMN_NAME IN ($columnPlaceholders)"
);
$columnStmt->execute($params);
$existingColumns = $columnStmt->fetchAll(\PDO::FETCH_COLUMN);
$missingColumns = array_values(array_diff($columns, $existingColumns));
if ($missingColumns) {
throw new \RuntimeException(sprintf(
'Base PTA incomplète : colonne(s) manquante(s) dans %s : %s.',
$table,
implode(', ', $missingColumns)
));
}
}
$this->assertAccessViews();
}
/**
* Les vues d'accès portent l'intégralité des règles de droits. Si elles
* manquent, l'application doit refuser de démarrer plutôt que de tourner
* sans contrôle de périmètre.
*/
private function assertAccessViews(): void
{
$requiredViews = [
'v_acces_role_page',
'v_acces_role_permission',
'v_acces_identite_agent',
'v_acces_identite_structure',
'v_acces_agent_par_structure',
'v_acces_perimetre_creneau',
'v_acces_perimetre_planning',
];
$placeholders = implode(',', array_fill(0, count($requiredViews), '?'));
$stmt = $this->pdo->prepare(
"SELECT TABLE_NAME
FROM information_schema.VIEWS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME IN ($placeholders)"
);
$stmt->execute($requiredViews);
$missing = array_values(array_diff($requiredViews, $stmt->fetchAll(\PDO::FETCH_COLUMN)));
if ($missing) {
throw new \RuntimeException(
'Contrôle d’accès indisponible : vue(s) manquante(s) : '
. implode(', ', $missing)
. '. Exécutez database/migration_v7_8_securite_acces.sql.'
);
}
}
}