Ajout des commentaires dans le code

This commit is contained in:
PTA
2026-08-20 13:22:49 +02:00
parent 4201894e28
commit 5d8c0993a6
154 changed files with 5071 additions and 47 deletions

View File

@@ -20,6 +20,18 @@ use DateTimeImmutable;
use PDO;
use Throwable;
/**
* Fiche agent : consultation, référentiel des agents et documents PDF.
*
* Deux familles de méthodes cohabitent ici, avec des conventions d'erreur
* DIFFÉRENTES et qu'il ne faut pas mélanger :
* - les endpoints JSON, qui répondent via JsonResponse::send() ;
* - les endpoints PDF (pdf, timeSummaryPdf, hoursContractPdf), qui produisent
* un flux binaire. Leurs points d'entrée n'appellent PAS
* JsonResponse::bootstrap(), et ils signalent donc leurs erreurs par un
* http_response_code() suivi d'un `return` et d'un message en texte brut.
* Y écrire du JSON corromprait le document téléchargé.
*/
final class AgentController
{
private AgentModel $agentModel;
@@ -35,6 +47,13 @@ final class AgentController
$this->access = new Access($pdo);
}
/**
* GET api/agents.php — agents sélectionnables dans l'éditeur de planning.
*
* structure_id à 0 (ou absent) signifie « tous les lieux » : ce n'est licite
* que pour le Service Enfance, un responsable étant renvoyé en 403 par
* requireStructureEdit() dès qu'il vise un autre lieu que le sien.
*/
public function listForPlanning(): void
{
$this->access->requireDraftEditor();
@@ -45,6 +64,15 @@ final class AgentController
JsonResponse::send(200, ['agents' => $this->agentModel->listForLocation((int) $selectedLocation)]);
}
/**
* GET api/agent_overview.php — semaine d'un agent, tous lieux confondus.
*
* Vue transverse par agent (et non par lieu comme api/planning.php) : c'est
* la seule qui donne la charge réelle d'un agent planifié à plusieurs
* endroits. En lecture seule pour le rôle AGENT.
*
* Paramètres GET : agent_id, week (« 2026-W08 »).
*/
public function overview(): void
{
$agentId = filter_input(INPUT_GET, 'agent_id', FILTER_VALIDATE_INT);
@@ -73,6 +101,21 @@ final class AgentController
]);
}
/**
* GET api/agent_month_overview.php — grille mensuelle d'un agent.
*
* Construit un calendrier lundi→vendredi ALIGNÉ SUR LES SEMAINES ISO : la
* grille commence au lundi de la semaine du 1er du mois et finit au vendredi
* de la semaine du dernier jour. Elle déborde donc du mois, et le drapeau
* `in_month` de chaque jour permet à l'interface de griser les débordements.
* Sans cet alignement, une semaine serait coupée en deux et les cumuls
* hebdomadaires affichés seraient faux.
*
* Les créneaux sont chargés sur toute l'étendue de la grille, débordements
* compris, pour que les totaux de semaine restent justes.
*
* Paramètres GET : agent_id, month (« 2026-02 »).
*/
public function monthOverview(): void
{
$agentId = filter_input(INPUT_GET, 'agent_id', FILTER_VALIDATE_INT);
@@ -149,6 +192,16 @@ final class AgentController
]);
}
/**
* GET api/agent_time_summary_pdf.php — bilan annuel d'heures (PDF).
*
* La période couverte n'est pas choisie par l'appelant : elle est celle
* calculée par QuotaModel (année civile 01/01 → 31/12), d'où la lecture de
* date_debut_periode / date_fin_periode dans le quota. Le paramètre `year`
* n'est qu'un raccourci vers le 1er janvier correspondant.
*
* Paramètres GET : agent_id, puis date OU year.
*/
public function timeSummaryPdf(): void
{
$agentId = filter_input(INPUT_GET, 'agent_id', FILTER_VALIDATE_INT);
@@ -194,6 +247,15 @@ final class AgentController
);
}
/**
* GET api/agent_planning_pdf.php — planning d'un agent sur plusieurs semaines.
*
* `weeks` n'accepte que 6 ou 7 (7 par défaut) : au-delà, la grille ne tient
* plus sur une page A4 paysage et SimplePdf ne gère pas le report de tableau
* sur page suivante.
*
* Paramètres GET : agent_id, week (semaine de départ), weeks (6|7).
*/
public function pdf(): void
{
$agentId = filter_input(INPUT_GET, 'agent_id', FILTER_VALIDATE_INT);
@@ -257,6 +319,14 @@ final class AgentController
);
}
/**
* GET api/agent_hours_contract_pdf.php — contrat horaire annuel (PDF).
*
* Document contractuel : il n'affiche que le volume annualisé dû, sans le
* détail des créneaux planifiés.
*
* Paramètres GET : agent_id, puis date OU year.
*/
public function hoursContractPdf(): void
{
$agentId = filter_input(INPUT_GET, 'agent_id', FILTER_VALIDATE_INT);
@@ -296,6 +366,19 @@ final class AgentController
);
}
/**
* api/agent_assignments.php — rattachement principal d'un agent.
*
* Endpoint à double verbe, exception au reste de l'API : GET liste les
* agents, POST modifie un rattachement. Le GET sort par JsonResponse::send()
* qui termine le script, ce qui rend le `Request::requireMethod('POST')`
* suivant inatteignable en lecture — le flux tombe donc bien en séquence.
*
* Un structure_id nul est VALIDE : il détache l'agent de tout lieu par
* défaut, sans l'empêcher d'être planifié ponctuellement ailleurs.
*
* Charge utile (POST) : agent_id, structure_id (nullable), csrf_token.
*/
public function assignments(): void
{
$this->access->requireService();
@@ -338,6 +421,19 @@ final class AgentController
]);
}
/**
* POST api/create_agent.php — création d'un agent.
*
* Réservé au Service Enfance. Les contrôles vont au-delà du « non vide » :
* poste existant en base, type de contrat dans l'énumération, dates
* cohérentes entre elles, quotité dans ]0;100], longueurs alignées sur les
* colonnes SQL (une chaîne trop longue serait sinon tronquée silencieusement
* par MariaDB), et unicité du matricule (409, pas 422 : c'est un conflit
* avec l'existant, pas une saisie malformée).
*
* La réponse renvoie l'agent complet reconstitué, pour que l'interface
* l'insère dans sa liste sans avoir à recharger toute la page.
*/
public function create(): void
{
$this->access->requireService();
@@ -411,6 +507,10 @@ final class AgentController
'commentaire_pta' => $ptaComment !== '' ? $ptaComment : null,
]);
} catch (Throwable $e) {
// Seul endroit du projet qui utilise correctement
// Security::debugEnabled() (fermé par défaut). Les autres blocs
// catch testent `getenv('PTA_DEBUG') ?: '1'`, dont le défaut est
// OUVERT — voir la note dans PlanningController::save().
JsonResponse::send(500, [
'error' => 'Impossible de créer l’agent.',
'details' => Security::debugEnabled() ? $e->getMessage() : null,
@@ -444,6 +544,16 @@ final class AgentController
]);
}
/**
* POST api/update_agent.php — modification de la fiche d'un agent.
*
* Mêmes contrôles que create(), matricule excepté : celui-ci n'est jamais
* modifiable, c'est la clé de rapprochement avec les outils RH.
*
* La quotité de travail n'est pas modifiable ici non plus : elle détermine
* le quota annuel déjà consommé, et la changer en cours d'année fausserait
* rétroactivement tous les suivis.
*/
public function updateProfile(): void
{
$this->access->requireService();
@@ -523,6 +633,12 @@ final class AgentController
]);
}
/**
* Décode « AAAA-Www ». Dupliqué dans plusieurs contrôleurs, chacun n'ayant
* pas de base commune ; toute correction doit être reportée partout.
*
* @return array{0: int, 1: int}|null [année ISO, semaine], ou null.
*/
private function parseWeek(string $value): ?array
{
if (!preg_match('/^(\d{4})-W(\d{2})$/', $value, $matches)) {