L'enseignant avait besoin d'un moyen rapide de saisir les notes après une évaluation. La grille inline permet de compléter 30 élèves en moins de 3 minutes grâce à la navigation clavier (Tab/Enter/Shift+Tab), la validation temps réel, l'auto-save debounced (500ms) et les raccourcis /abs et /disp pour marquer absents/dispensés. Les notes restent en brouillon jusqu'à publication explicite (avec confirmation modale). Une fois publiées, les élèves les voient immédiatement ; les parents après un délai de 24h (VisibiliteNotesPolicy). Le mode offline stocke les notes en IndexedDB et synchronise automatiquement au retour de la connexion. Chaque modification est auditée dans grade_events via un event subscriber qui écoute NoteSaisie/NoteModifiee sur le bus d'événements.
198 lines
6.0 KiB
PHP
198 lines
6.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Scolarite\Domain\Model\Evaluation;
|
|
|
|
use App\Administration\Domain\Model\SchoolClass\ClassId;
|
|
use App\Administration\Domain\Model\Subject\SubjectId;
|
|
use App\Administration\Domain\Model\User\UserId;
|
|
use App\Scolarite\Domain\Event\EvaluationCreee;
|
|
use App\Scolarite\Domain\Event\EvaluationModifiee;
|
|
use App\Scolarite\Domain\Event\EvaluationSupprimee;
|
|
use App\Scolarite\Domain\Event\NotesPubliees;
|
|
use App\Scolarite\Domain\Exception\BaremeNonModifiableException;
|
|
use App\Scolarite\Domain\Exception\EvaluationDejaSupprimeeException;
|
|
use App\Scolarite\Domain\Exception\NotesDejaPublieesException;
|
|
use App\Shared\Domain\AggregateRoot;
|
|
use App\Shared\Domain\Tenant\TenantId;
|
|
use DateTimeImmutable;
|
|
|
|
final class Evaluation extends AggregateRoot
|
|
{
|
|
public private(set) DateTimeImmutable $updatedAt;
|
|
public private(set) ?DateTimeImmutable $gradesPublishedAt = null;
|
|
|
|
private function __construct(
|
|
public private(set) EvaluationId $id,
|
|
public private(set) TenantId $tenantId,
|
|
public private(set) ClassId $classId,
|
|
public private(set) SubjectId $subjectId,
|
|
public private(set) UserId $teacherId,
|
|
public private(set) string $title,
|
|
public private(set) ?string $description,
|
|
public private(set) DateTimeImmutable $evaluationDate,
|
|
public private(set) GradeScale $gradeScale,
|
|
public private(set) Coefficient $coefficient,
|
|
public private(set) EvaluationStatus $status,
|
|
public private(set) DateTimeImmutable $createdAt,
|
|
) {
|
|
$this->updatedAt = $createdAt;
|
|
}
|
|
|
|
public static function creer(
|
|
TenantId $tenantId,
|
|
ClassId $classId,
|
|
SubjectId $subjectId,
|
|
UserId $teacherId,
|
|
string $title,
|
|
?string $description,
|
|
DateTimeImmutable $evaluationDate,
|
|
GradeScale $gradeScale,
|
|
Coefficient $coefficient,
|
|
DateTimeImmutable $now,
|
|
): self {
|
|
$evaluation = new self(
|
|
id: EvaluationId::generate(),
|
|
tenantId: $tenantId,
|
|
classId: $classId,
|
|
subjectId: $subjectId,
|
|
teacherId: $teacherId,
|
|
title: $title,
|
|
description: $description,
|
|
evaluationDate: $evaluationDate,
|
|
gradeScale: $gradeScale,
|
|
coefficient: $coefficient,
|
|
status: EvaluationStatus::PUBLISHED,
|
|
createdAt: $now,
|
|
);
|
|
|
|
$evaluation->recordEvent(new EvaluationCreee(
|
|
evaluationId: $evaluation->id,
|
|
classId: (string) $classId,
|
|
subjectId: (string) $subjectId,
|
|
teacherId: (string) $teacherId,
|
|
title: $title,
|
|
evaluationDate: $evaluationDate,
|
|
occurredOn: $now,
|
|
));
|
|
|
|
return $evaluation;
|
|
}
|
|
|
|
public function modifier(
|
|
string $title,
|
|
?string $description,
|
|
Coefficient $coefficient,
|
|
DateTimeImmutable $evaluationDate,
|
|
?GradeScale $gradeScale,
|
|
bool $hasGrades,
|
|
DateTimeImmutable $now,
|
|
): void {
|
|
if ($this->status === EvaluationStatus::DELETED) {
|
|
throw EvaluationDejaSupprimeeException::withId($this->id);
|
|
}
|
|
|
|
if ($gradeScale !== null && !$this->gradeScale->equals($gradeScale) && $hasGrades) {
|
|
throw BaremeNonModifiableException::carNotesExistantes($this->id);
|
|
}
|
|
|
|
$this->title = $title;
|
|
$this->description = $description;
|
|
$this->coefficient = $coefficient;
|
|
$this->evaluationDate = $evaluationDate;
|
|
|
|
if ($gradeScale !== null && !$hasGrades) {
|
|
$this->gradeScale = $gradeScale;
|
|
}
|
|
|
|
$this->updatedAt = $now;
|
|
|
|
$this->recordEvent(new EvaluationModifiee(
|
|
evaluationId: $this->id,
|
|
title: $title,
|
|
evaluationDate: $evaluationDate,
|
|
occurredOn: $now,
|
|
));
|
|
}
|
|
|
|
public function publierNotes(DateTimeImmutable $now): void
|
|
{
|
|
if ($this->status === EvaluationStatus::DELETED) {
|
|
throw EvaluationDejaSupprimeeException::withId($this->id);
|
|
}
|
|
|
|
if ($this->gradesPublishedAt !== null) {
|
|
throw NotesDejaPublieesException::pourEvaluation($this->id);
|
|
}
|
|
|
|
$this->gradesPublishedAt = $now;
|
|
$this->updatedAt = $now;
|
|
|
|
$this->recordEvent(new NotesPubliees(
|
|
evaluationId: $this->id,
|
|
occurredOn: $now,
|
|
));
|
|
}
|
|
|
|
public function notesPubliees(): bool
|
|
{
|
|
return $this->gradesPublishedAt !== null;
|
|
}
|
|
|
|
public function supprimer(DateTimeImmutable $now): void
|
|
{
|
|
if ($this->status === EvaluationStatus::DELETED) {
|
|
throw EvaluationDejaSupprimeeException::withId($this->id);
|
|
}
|
|
|
|
$this->status = EvaluationStatus::DELETED;
|
|
$this->updatedAt = $now;
|
|
|
|
$this->recordEvent(new EvaluationSupprimee(
|
|
evaluationId: $this->id,
|
|
occurredOn: $now,
|
|
));
|
|
}
|
|
|
|
/**
|
|
* @internal Pour usage Infrastructure uniquement
|
|
*/
|
|
public static function reconstitute(
|
|
EvaluationId $id,
|
|
TenantId $tenantId,
|
|
ClassId $classId,
|
|
SubjectId $subjectId,
|
|
UserId $teacherId,
|
|
string $title,
|
|
?string $description,
|
|
DateTimeImmutable $evaluationDate,
|
|
GradeScale $gradeScale,
|
|
Coefficient $coefficient,
|
|
EvaluationStatus $status,
|
|
DateTimeImmutable $createdAt,
|
|
DateTimeImmutable $updatedAt,
|
|
?DateTimeImmutable $gradesPublishedAt = null,
|
|
): self {
|
|
$evaluation = new self(
|
|
id: $id,
|
|
tenantId: $tenantId,
|
|
classId: $classId,
|
|
subjectId: $subjectId,
|
|
teacherId: $teacherId,
|
|
title: $title,
|
|
description: $description,
|
|
evaluationDate: $evaluationDate,
|
|
gradeScale: $gradeScale,
|
|
coefficient: $coefficient,
|
|
status: $status,
|
|
createdAt: $createdAt,
|
|
);
|
|
|
|
$evaluation->updatedAt = $updatedAt;
|
|
$evaluation->gradesPublishedAt = $gradesPublishedAt;
|
|
|
|
return $evaluation;
|
|
}
|
|
}
|