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

@@ -28,6 +28,16 @@ final class QuotaModel extends BaseModel
*/
public const REFERENCE_MINUTES = 1607 * 60;
/**
* Crée la ligne de quota annuel d'un agent, proratisée par sa quotité.
*
* Appelé à la création d'un agent (AgentModel::createWithDefaults()). Le
* quota cible est FIGÉ à ce moment-là : modifier ensuite la quotité de
* l'agent ne recalcule pas rétroactivement l'année en cours, ce qui
* fausserait un suivi déjà entamé.
*
* @param float $rate Quotité en pourcentage (100 = temps plein).
*/
public function createForAgent(int $agentId, int $year, float $rate): void
{
$target = (int) round(self::REFERENCE_MINUTES * ($rate / 100));
@@ -53,6 +63,19 @@ final class QuotaModel extends BaseModel
*
* Exemple : une date de contexte au 15/09/2026 renvoie toujours la période
* 01/01/2026 -> 31/12/2026, quelle que soit la date de début du contrat.
*
* Les minutes VALIDÉES et les minutes en BROUILLON sont comptées
* séparément mais s'additionnent toutes deux dans `minutes_affectees` :
* un brouillon consomme déjà le quota du point de vue de la planification,
* la distinction ne sert qu'à indiquer ce qui est acquis.
*
* Le filtre `m.compte_dans_quota = TRUE` est le point de bascule métier :
* CONGE, AUTRE_ABSENCE et JNT sont ainsi exclus (voir REFERENCE_MINUTES).
*
* `minutes_restantes` peut être NÉGATIF — c'est un dépassement, signalé en
* ALERTE à la validation, jamais bloqué.
*
* @return array<string, mixed> Période de référence enrichie des compteurs.
*/
public function forDate(int $agentId, string $contextDate): array
{
@@ -100,16 +123,33 @@ final class QuotaModel extends BaseModel
]);
}
/**
* Idem forDate(), avec les libellés lisibles ajoutés par enrich().
* C'est cette variante que consomment tous les endpoints JSON.
*
* @return array<string, mixed>
*/
public function forDateForApi(int $agentId, string $contextDate): array
{
return $this->enrich($this->forDate($agentId, $contextDate));
}
/**
* Quota d'une année entière. Le 1er janvier suffit comme point d'entrée,
* la période étant de toute façon l'année civile complète.
*
* @return array<string, mixed>
*/
public function annual(int $agentId, int $year): array
{
return $this->forDate($agentId, sprintf('%04d-01-01', $year));
}
/**
* Idem annual(), enrichi des libellés.
*
* @return array<string, mixed>
*/
public function annualForApi(int $agentId, int $year): array
{
return $this->forDateForApi($agentId, sprintf('%04d-01-01', $year));
@@ -118,6 +158,16 @@ final class QuotaModel extends BaseModel
/**
* Période de référence PTA : toujours l'année civile.
* La date de contrat est retournée uniquement à titre informatif.
*
* Les clés `periode_contractuelle`, `periode_civile` et
* `date_contrat_manquante` sont des VESTIGES d'une version où la période
* pouvait être ancrée sur la date de contrat. Elles sont figées
* (false / true / false) et conservées pour ne pas casser les écrans qui les
* lisent encore. Ne pas construire de nouvelle logique dessus.
*
* @return array<string, mixed>
*
* @throws InvalidArgumentException Si la date de contexte est malformée.
*/
public function referencePeriod(int $agentId, string $contextDate): array
{
@@ -151,6 +201,16 @@ final class QuotaModel extends BaseModel
];
}
/**
* Ajoute les versions lisibles des compteurs à un quota brut.
*
* Les clés en minutes restent présentes : le JavaScript calcule sur les
* minutes et n'affiche que les libellés.
*
* @param array<string, mixed> $quota
*
* @return array<string, mixed>
*/
public function enrich(array $quota): array
{
return array_merge($quota, [
@@ -162,6 +222,16 @@ final class QuotaModel extends BaseModel
]);
}
/**
* Met en forme une durée en minutes sous ses trois représentations.
*
* Gère les valeurs NÉGATIVES (dépassement de quota) : le signe est extrait
* avant la division, sans quoi intdiv() et le modulo produiraient un libellé
* incohérent du type « -1 h -30 ».
*
* @return array{minutes: int, heures_decimales: float, libelle: string}
* Ex. : 90 → « 1 h 30 » ; -90 → « -1 h 30 ».
*/
public function formatMinutes(int $minutes): array
{
$sign = $minutes < 0 ? -1 : 1;
@@ -176,6 +246,24 @@ final class QuotaModel extends BaseModel
];
}
/**
* Retrouve la ligne de quota la plus pertinente pour une année donnée.
*
* Le tri du ORDER BY applique une règle de repli en trois temps :
* 1. l'année demandée exactement ;
* 2. sinon l'année ANTÉRIEURE la plus proche (la quotité connue la plus
* récente reste la meilleure estimation) ;
* 3. sinon l'année POSTÉRIEURE la plus proche.
*
* Sans aucune ligne — agent créé avant la mise en place des quotas — on
* retombe sur un temps plein théorique plutôt que sur un quota nul, qui
* afficherait un dépassement à la première heure planifiée.
*
* `quota_source_annee` indique quelle année a réellement servi, pour que
* l'interface puisse signaler un quota emprunté à une autre année.
*
* @return array{quotite_travail: float, quota_reference_minutes: int, quota_cible_minutes: int, quota_source_annee: int}
*/
private function quotaProfile(int $agentId, int $year): array
{
$stmt = $this->pdo->prepare(