Files
Classeo/backend/src/Scolarite/Infrastructure/Api/Resource/EvaluationResource.php
Mathias STRASSER b70d5ec2ad
Some checks failed
CI / Backend Tests (push) Has been cancelled
CI / Frontend Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Naming Conventions (push) Has been cancelled
CI / Build Check (push) Has been cancelled
feat: Permettre à l'enseignant de saisir les notes dans une grille inline
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.
2026-03-29 10:02:03 +02:00

124 lines
4.6 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Scolarite\Infrastructure\Api\Resource;
use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Post;
use App\Scolarite\Domain\Model\Evaluation\Evaluation;
use App\Scolarite\Infrastructure\Api\Processor\CreateEvaluationProcessor;
use App\Scolarite\Infrastructure\Api\Processor\DeleteEvaluationProcessor;
use App\Scolarite\Infrastructure\Api\Processor\UpdateEvaluationProcessor;
use App\Scolarite\Infrastructure\Api\Provider\EvaluationCollectionProvider;
use App\Scolarite\Infrastructure\Api\Provider\EvaluationItemProvider;
use DateTimeImmutable;
use Symfony\Component\Validator\Constraints as Assert;
#[ApiResource(
shortName: 'Evaluation',
operations: [
new GetCollection(
uriTemplate: '/evaluations',
provider: EvaluationCollectionProvider::class,
name: 'get_evaluation_list',
),
new Get(
uriTemplate: '/evaluations/{id}',
provider: EvaluationItemProvider::class,
name: 'get_evaluation',
),
new Post(
uriTemplate: '/evaluations',
processor: CreateEvaluationProcessor::class,
validationContext: ['groups' => ['Default', 'create']],
name: 'create_evaluation',
),
new Patch(
uriTemplate: '/evaluations/{id}',
provider: EvaluationItemProvider::class,
processor: UpdateEvaluationProcessor::class,
validationContext: ['groups' => ['Default', 'update']],
name: 'update_evaluation',
),
new Delete(
uriTemplate: '/evaluations/{id}',
provider: EvaluationItemProvider::class,
processor: DeleteEvaluationProcessor::class,
name: 'delete_evaluation',
),
],
)]
final class EvaluationResource
{
#[ApiProperty(identifier: true)]
public ?string $id = null;
#[Assert\NotBlank(message: 'La classe est requise.', groups: ['create'])]
#[Assert\Uuid(message: 'L\'identifiant de la classe doit être un UUID valide.', groups: ['create'])]
public ?string $classId = null;
#[Assert\NotBlank(message: 'La matière est requise.', groups: ['create'])]
#[Assert\Uuid(message: 'L\'identifiant de la matière doit être un UUID valide.', groups: ['create'])]
public ?string $subjectId = null;
public ?string $teacherId = null;
#[Assert\NotBlank(message: 'Le titre est requis.', groups: ['create', 'update'])]
#[Assert\Length(max: 255, maxMessage: 'Le titre ne peut pas dépasser 255 caractères.')]
public ?string $title = null;
public ?string $description = null;
#[Assert\NotBlank(message: 'La date d\'évaluation est requise.', groups: ['create', 'update'])]
public ?string $evaluationDate = null;
#[Assert\Range(min: 1, max: 100, notInRangeMessage: 'Le barème doit être compris entre 1 et 100.')]
public ?int $gradeScale = null;
#[Assert\Range(min: 0.1, max: 10, notInRangeMessage: 'Le coefficient doit être compris entre 0.1 et 10.')]
public ?float $coefficient = null;
public ?string $status = null;
public ?string $className = null;
public ?string $subjectName = null;
public ?DateTimeImmutable $createdAt = null;
public ?DateTimeImmutable $updatedAt = null;
public ?DateTimeImmutable $gradesPublishedAt = null;
public static function fromDomain(
Evaluation $evaluation,
?string $className = null,
?string $subjectName = null,
): self {
$resource = new self();
$resource->id = (string) $evaluation->id;
$resource->classId = (string) $evaluation->classId;
$resource->subjectId = (string) $evaluation->subjectId;
$resource->teacherId = (string) $evaluation->teacherId;
$resource->title = $evaluation->title;
$resource->description = $evaluation->description;
$resource->evaluationDate = $evaluation->evaluationDate->format('Y-m-d');
$resource->gradeScale = $evaluation->gradeScale->maxValue;
$resource->coefficient = $evaluation->coefficient->value;
$resource->status = $evaluation->status->value;
$resource->className = $className;
$resource->subjectName = $subjectName;
$resource->createdAt = $evaluation->createdAt;
$resource->updatedAt = $evaluation->updatedAt;
$resource->gradesPublishedAt = $evaluation->gradesPublishedAt;
return $resource;
}
}