feat: Gestion des classes scolaires
Permet aux administrateurs de créer, modifier et supprimer des classes pour organiser les élèves par niveau. L'archivage soft-delete préserve l'historique tout en masquant les classes obsolètes. Inclut la validation des noms (2-50 caractères), les niveaux scolaires du CP à la Terminale, et les contrôles d'accès par rôle.
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Administration\Domain\Model\SchoolClass;
|
||||
|
||||
use App\Administration\Domain\Event\ClasseArchivee;
|
||||
use App\Administration\Domain\Event\ClasseCreee;
|
||||
use App\Administration\Domain\Event\ClasseModifiee;
|
||||
use App\Shared\Domain\AggregateRoot;
|
||||
use App\Shared\Domain\Tenant\TenantId;
|
||||
use DateTimeImmutable;
|
||||
|
||||
/**
|
||||
* Aggregate Root représentant une classe scolaire.
|
||||
*
|
||||
* Une classe appartient à un établissement (tenant), une école et une année scolaire.
|
||||
* Elle peut recevoir des élèves et est organisée par niveau scolaire.
|
||||
*
|
||||
* @see FR73: Organiser les élèves par groupes pédagogiques
|
||||
*/
|
||||
final class SchoolClass extends AggregateRoot
|
||||
{
|
||||
public private(set) ?string $description = null;
|
||||
public private(set) DateTimeImmutable $updatedAt;
|
||||
public private(set) ?DateTimeImmutable $deletedAt = null;
|
||||
|
||||
private function __construct(
|
||||
public private(set) ClassId $id,
|
||||
public private(set) TenantId $tenantId,
|
||||
public private(set) SchoolId $schoolId,
|
||||
public private(set) AcademicYearId $academicYearId,
|
||||
public private(set) ClassName $name,
|
||||
public private(set) ?SchoolLevel $level,
|
||||
public private(set) ?int $capacity,
|
||||
public private(set) ClassStatus $status,
|
||||
public private(set) DateTimeImmutable $createdAt,
|
||||
) {
|
||||
$this->updatedAt = $createdAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une nouvelle classe scolaire.
|
||||
*/
|
||||
public static function creer(
|
||||
TenantId $tenantId,
|
||||
SchoolId $schoolId,
|
||||
AcademicYearId $academicYearId,
|
||||
ClassName $name,
|
||||
?SchoolLevel $level,
|
||||
?int $capacity,
|
||||
DateTimeImmutable $createdAt,
|
||||
): self {
|
||||
$class = new self(
|
||||
id: ClassId::generate(),
|
||||
tenantId: $tenantId,
|
||||
schoolId: $schoolId,
|
||||
academicYearId: $academicYearId,
|
||||
name: $name,
|
||||
level: $level,
|
||||
capacity: $capacity,
|
||||
status: ClassStatus::ACTIVE,
|
||||
createdAt: $createdAt,
|
||||
);
|
||||
|
||||
$class->recordEvent(new ClasseCreee(
|
||||
classId: $class->id,
|
||||
tenantId: $class->tenantId,
|
||||
name: $class->name,
|
||||
level: $class->level,
|
||||
occurredOn: $createdAt,
|
||||
));
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renomme la classe.
|
||||
*/
|
||||
public function renommer(ClassName $nouveauNom, DateTimeImmutable $at): void
|
||||
{
|
||||
if ($this->name->equals($nouveauNom)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ancienNom = $this->name;
|
||||
$this->name = $nouveauNom;
|
||||
$this->updatedAt = $at;
|
||||
|
||||
$this->recordEvent(new ClasseModifiee(
|
||||
classId: $this->id,
|
||||
tenantId: $this->tenantId,
|
||||
ancienNom: $ancienNom,
|
||||
nouveauNom: $nouveauNom,
|
||||
occurredOn: $at,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifie le niveau scolaire de la classe.
|
||||
*/
|
||||
public function changerNiveau(?SchoolLevel $niveau, DateTimeImmutable $at): void
|
||||
{
|
||||
if ($this->level === $niveau) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->level = $niveau;
|
||||
$this->updatedAt = $at;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifie la capacité maximale de la classe.
|
||||
*/
|
||||
public function changerCapacite(?int $capacity, DateTimeImmutable $at): void
|
||||
{
|
||||
if ($this->capacity === $capacity) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->capacity = $capacity;
|
||||
$this->updatedAt = $at;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute ou modifie la description de la classe.
|
||||
*/
|
||||
public function decrire(?string $description, DateTimeImmutable $at): void
|
||||
{
|
||||
$this->description = $description;
|
||||
$this->updatedAt = $at;
|
||||
}
|
||||
|
||||
/**
|
||||
* Archive la classe (soft delete).
|
||||
*
|
||||
* Note: La vérification des élèves affectés doit être faite par l'Application Layer
|
||||
* via une Query avant d'appeler cette méthode.
|
||||
*/
|
||||
public function archiver(DateTimeImmutable $at): void
|
||||
{
|
||||
if ($this->status === ClassStatus::ARCHIVED) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->status = ClassStatus::ARCHIVED;
|
||||
$this->deletedAt = $at;
|
||||
$this->updatedAt = $at;
|
||||
|
||||
$this->recordEvent(new ClasseArchivee(
|
||||
classId: $this->id,
|
||||
tenantId: $this->tenantId,
|
||||
occurredOn: $at,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la classe est active.
|
||||
*/
|
||||
public function estActive(): bool
|
||||
{
|
||||
return $this->status === ClassStatus::ACTIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la classe peut recevoir des élèves.
|
||||
*/
|
||||
public function peutRecevoirEleves(): bool
|
||||
{
|
||||
return $this->status->peutRecevoirEleves();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstitue une SchoolClass depuis le stockage.
|
||||
*
|
||||
* @internal Pour usage Infrastructure uniquement
|
||||
*/
|
||||
public static function reconstitute(
|
||||
ClassId $id,
|
||||
TenantId $tenantId,
|
||||
SchoolId $schoolId,
|
||||
AcademicYearId $academicYearId,
|
||||
ClassName $name,
|
||||
?SchoolLevel $level,
|
||||
?int $capacity,
|
||||
ClassStatus $status,
|
||||
?string $description,
|
||||
DateTimeImmutable $createdAt,
|
||||
DateTimeImmutable $updatedAt,
|
||||
?DateTimeImmutable $deletedAt,
|
||||
): self {
|
||||
$class = new self(
|
||||
id: $id,
|
||||
tenantId: $tenantId,
|
||||
schoolId: $schoolId,
|
||||
academicYearId: $academicYearId,
|
||||
name: $name,
|
||||
level: $level,
|
||||
capacity: $capacity,
|
||||
status: $status,
|
||||
createdAt: $createdAt,
|
||||
);
|
||||
|
||||
$class->description = $description;
|
||||
$class->updatedAt = $updatedAt;
|
||||
$class->deletedAt = $deletedAt;
|
||||
|
||||
return $class;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user