feat: Permettre aux enseignants de dupliquer un devoir vers plusieurs classes
Un enseignant qui donne le même travail à plusieurs classes devait jusqu'ici recréer manuellement chaque devoir. La duplication permet de sélectionner les classes cibles, d'ajuster les dates d'échéance par classe, et de créer tous les devoirs en une seule opération atomique (transaction). La validation s'effectue par classe (affectation enseignant, date d'échéance) avec un rapport d'erreurs détaillé. L'infrastructure de warnings est prête pour les règles de timing de la Story 5.3. Le filtrage par classe dans la liste des devoirs passe côté serveur pour rester compatible avec la pagination.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Scolarite\Domain\Exception;
|
||||
|
||||
use App\Scolarite\Domain\ValueObject\ClassValidationResult;
|
||||
|
||||
use function array_filter;
|
||||
use function array_map;
|
||||
|
||||
use DomainException;
|
||||
|
||||
use function implode;
|
||||
|
||||
final class DuplicationValidationException extends DomainException
|
||||
{
|
||||
/** @param array<ClassValidationResult> $results */
|
||||
private function __construct(
|
||||
string $message,
|
||||
public readonly array $results,
|
||||
) {
|
||||
parent::__construct($message);
|
||||
}
|
||||
|
||||
/** @param array<ClassValidationResult> $results */
|
||||
public static function withResults(array $results): self
|
||||
{
|
||||
$failures = array_filter($results, static fn (ClassValidationResult $r): bool => !$r->valid);
|
||||
$messages = array_map(
|
||||
static fn (ClassValidationResult $r): string => "Classe {$r->classId} : {$r->error}",
|
||||
$failures,
|
||||
);
|
||||
|
||||
return new self(
|
||||
'Validation échouée pour certaines classes : ' . implode('; ', $messages),
|
||||
$results,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Scolarite\Domain\Repository;
|
||||
|
||||
use App\Scolarite\Domain\Model\Homework\HomeworkAttachment;
|
||||
use App\Scolarite\Domain\Model\Homework\HomeworkId;
|
||||
|
||||
interface HomeworkAttachmentRepository
|
||||
{
|
||||
/** @return array<HomeworkAttachment> */
|
||||
public function findByHomeworkId(HomeworkId $homeworkId): array;
|
||||
|
||||
public function save(HomeworkId $homeworkId, HomeworkAttachment $attachment): void;
|
||||
}
|
||||
44
backend/src/Scolarite/Domain/Service/HomeworkDuplicator.php
Normal file
44
backend/src/Scolarite/Domain/Service/HomeworkDuplicator.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Scolarite\Domain\Service;
|
||||
|
||||
use App\Administration\Domain\Model\SchoolClass\ClassId;
|
||||
use App\Scolarite\Domain\Model\Homework\Homework;
|
||||
use DateTimeImmutable;
|
||||
|
||||
final readonly class HomeworkDuplicator
|
||||
{
|
||||
/**
|
||||
* @param array<ClassId> $targetClassIds
|
||||
* @param array<DateTimeImmutable> $dueDates Dates indexées par position (même ordre que $targetClassIds)
|
||||
*
|
||||
* @return array<Homework>
|
||||
*/
|
||||
public function dupliquer(
|
||||
Homework $source,
|
||||
array $targetClassIds,
|
||||
array $dueDates,
|
||||
DateTimeImmutable $now,
|
||||
): array {
|
||||
$duplicates = [];
|
||||
|
||||
foreach ($targetClassIds as $index => $classId) {
|
||||
$dueDate = $dueDates[$index] ?? $source->dueDate;
|
||||
|
||||
$duplicates[] = Homework::creer(
|
||||
tenantId: $source->tenantId,
|
||||
classId: $classId,
|
||||
subjectId: $source->subjectId,
|
||||
teacherId: $source->teacherId,
|
||||
title: $source->title,
|
||||
description: $source->description,
|
||||
dueDate: $dueDate,
|
||||
now: $now,
|
||||
);
|
||||
}
|
||||
|
||||
return $duplicates;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Scolarite\Domain\ValueObject;
|
||||
|
||||
use App\Administration\Domain\Model\SchoolClass\ClassId;
|
||||
|
||||
final readonly class ClassValidationResult
|
||||
{
|
||||
private function __construct(
|
||||
public ClassId $classId,
|
||||
public bool $valid,
|
||||
public ?string $error,
|
||||
public ?string $warning,
|
||||
) {
|
||||
}
|
||||
|
||||
public static function success(ClassId $classId, ?string $warning = null): self
|
||||
{
|
||||
return new self($classId, true, null, $warning);
|
||||
}
|
||||
|
||||
public static function failure(ClassId $classId, string $error): self
|
||||
{
|
||||
return new self($classId, false, $error, null);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user