Ajout des commentaires dans le code
This commit is contained in:
@@ -6,8 +6,38 @@ namespace App\Models;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Équipes des mercredis et des vacances, et leurs contrôles d'encadrement.
|
||||
*
|
||||
* Le NOMBRE D'AGENTS REQUIS est calculé en SQL, au plus contraignant des deux
|
||||
* règles :
|
||||
* GREATEST(minimum_agents,
|
||||
* CEIL(enfants_moins_6 / ratio_moins_6)
|
||||
* + CEIL(enfants_6_plus / ratio_6_plus))
|
||||
* Chaque tranche d'âge est arrondie au SUPÉRIEUR séparément avant d'être
|
||||
* additionnée : un demi-agent n'existe pas, et sommer avant d'arrondir
|
||||
* sous-estimerait l'encadrement.
|
||||
*
|
||||
* Les contrôles suivent la forme commune {niveau, code, message}. Aucun n'est
|
||||
* bloquant : ils signalent, l'arbitrage restant humain.
|
||||
*
|
||||
* Cycle de vie propre aux équipes : BROUILLON → A_CONTROLER → VALIDEE, sans
|
||||
* transition imposée.
|
||||
*/
|
||||
final class TeamModel extends BaseModel
|
||||
{
|
||||
/**
|
||||
* Toutes les équipes, avec leurs membres et leurs contrôles.
|
||||
*
|
||||
* Le filtre de dates cherche les équipes qui INTERSECTENT l'intervalle
|
||||
* (fin >= début demandé ET début <= fin demandée) et non celles qui y sont
|
||||
* incluses : une équipe à cheval sur les bornes doit remonter.
|
||||
*
|
||||
* ATTENTION AU COÛT : deux requêtes supplémentaires par équipe (membres puis
|
||||
* contrôles). Acceptable sur quelques dizaines d'équipes, à revoir au-delà.
|
||||
*
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
public function all(?string $startDate = null, ?string $endDate = null): array
|
||||
{
|
||||
$sql = "SELECT e.id_equipe, e.id_structure, s.nom AS structure_nom,
|
||||
@@ -56,6 +86,15 @@ final class TeamModel extends BaseModel
|
||||
return $teams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Une équipe par identifiant.
|
||||
*
|
||||
* Passe par all() plutôt que par une requête dédiée, afin de bénéficier des
|
||||
* mêmes agrégats et contrôles. Coûteux, mais cette méthode n'est pas sur un
|
||||
* chemin critique.
|
||||
*
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
public function find(int $teamId): ?array
|
||||
{
|
||||
foreach ($this->all() as $team) {
|
||||
@@ -66,6 +105,17 @@ final class TeamModel extends BaseModel
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une équipe, toujours en BROUILLON.
|
||||
*
|
||||
* $data est passé tel quel à execute() : ses clés doivent correspondre
|
||||
* exactement aux paramètres nommés. La validation est faite par
|
||||
* TeamController::index().
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
*
|
||||
* @return int Identifiant créé.
|
||||
*/
|
||||
public function create(array $data): int
|
||||
{
|
||||
$stmt = $this->pdo->prepare(
|
||||
@@ -85,6 +135,20 @@ final class TeamModel extends BaseModel
|
||||
return (int) $this->pdo->lastInsertId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute un agent à une équipe, ou met à jour sa fonction s'il y est déjà.
|
||||
*
|
||||
* Un seul refus est automatique : une INTERDICTION active de l'agent pour ce
|
||||
* lieu (agent_structure_souhait). Tout le reste — contraintes médicales,
|
||||
* temps partiel thérapeutique — est signalé dans les contrôles de l'équipe
|
||||
* et laissé à l'appréciation humaine, ces situations pouvant être compatibles
|
||||
* avec certaines affectations.
|
||||
*
|
||||
* Les RuntimeException levées ici portent un message destiné à l'utilisateur
|
||||
* final, que le contrôleur renvoie tel quel en 422.
|
||||
*
|
||||
* @throws \RuntimeException Équipe introuvable ou interdiction active.
|
||||
*/
|
||||
public function addMember(int $teamId, int $agentId, string $function, ?string $comment): void
|
||||
{
|
||||
$team = $this->teamDates($teamId);
|
||||
@@ -125,6 +189,11 @@ final class TeamModel extends BaseModel
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retire un agent d'une équipe.
|
||||
*
|
||||
* @return bool false s'il n'en faisait pas partie.
|
||||
*/
|
||||
public function removeMember(int $teamId, int $agentId): bool
|
||||
{
|
||||
$stmt = $this->pdo->prepare(
|
||||
@@ -134,12 +203,27 @@ final class TeamModel extends BaseModel
|
||||
return $stmt->rowCount() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change le statut d'une équipe. La valeur est contrôlée par le contrôleur ;
|
||||
* aucune transition n'est imposée, y compris un retour en arrière.
|
||||
*/
|
||||
public function setStatus(int $teamId, string $status): void
|
||||
{
|
||||
$stmt = $this->pdo->prepare('UPDATE equipe_pta SET statut = :statut WHERE id_equipe = :id');
|
||||
$stmt->execute(['statut' => $status, 'id' => $teamId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Membres d'une équipe, enrichis de tout ce dont les contrôles ont besoin :
|
||||
* diplôme, poste, lieu de rattachement, souhait exprimé pour ce lieu, et
|
||||
* nombre de contraintes actives sur la période de l'équipe (sous-requête
|
||||
* corrélée, calculée pour la seule fenêtre de dates de l'équipe).
|
||||
*
|
||||
* Le FIELD() ordonne par fonction — responsable, animation, restauration —
|
||||
* plutôt qu'alphabétiquement : c'est l'ordre de lecture d'un trombinoscope.
|
||||
*
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private function members(int $teamId): array
|
||||
{
|
||||
$stmt = $this->pdo->prepare(
|
||||
@@ -171,6 +255,23 @@ final class TeamModel extends BaseModel
|
||||
return $stmt->fetchAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Contrôles d'une équipe.
|
||||
*
|
||||
* Deux ERREUR (effectif insuffisant, taux de diplômés sous le seuil), deux
|
||||
* ALERTE (aucun responsable identifié, membre sous contrainte médicale) et
|
||||
* une INFO signalant qu'une préférence de l'agent est satisfaite. Un INFO
|
||||
* « conforme » est ajouté si rien n'a été relevé, pour distinguer l'absence
|
||||
* d'anomalie d'une absence de contrôle.
|
||||
*
|
||||
* Le taux de diplômés est calculé sur les agents AFFECTÉS, pas sur les
|
||||
* agents requis : c'est la composition réelle de l'équipe qui compte.
|
||||
*
|
||||
* @param array<string, mixed> $team
|
||||
* @param array<int, array<string, mixed>> $members
|
||||
*
|
||||
* @return array<int, array<string, string>>
|
||||
*/
|
||||
private function controls(array $team, array $members): array
|
||||
{
|
||||
$controls = [];
|
||||
@@ -225,6 +326,11 @@ final class TeamModel extends BaseModel
|
||||
return $controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lieu et dates d'une équipe — lecture légère, sans les agrégats de all().
|
||||
*
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
private function teamDates(int $teamId): ?array
|
||||
{
|
||||
$stmt = $this->pdo->prepare(
|
||||
|
||||
Reference in New Issue
Block a user