feat: Permettre aux enseignants de créer et gérer les devoirs
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

Les enseignants avaient besoin d'un outil pour créer des devoirs assignés
à leurs classes, avec filtrage automatique par matière selon la classe
sélectionnée. Le système valide que la date d'échéance tombe un jour
ouvrable (lundi-vendredi) et empêche les dates dans le passé.

Le domaine modélise le devoir comme un agrégat avec pièces jointes,
statut brouillon/publié, et événements métier (création, modification,
suppression). Les handlers de notification écoutent ces événements pour
les futurs envois aux parents et élèves.
This commit is contained in:
2026-03-12 10:11:06 +01:00
parent 56bc808d85
commit e9efb90f59
51 changed files with 4776 additions and 7 deletions

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace App\Scolarite\Application\Command\UploadHomeworkAttachment;
final readonly class UploadHomeworkAttachmentCommand
{
public function __construct(
public string $tenantId,
public string $homeworkId,
public string $filename,
public string $mimeType,
public int $fileSize,
public string $tempFilePath,
) {
}
}

View File

@@ -0,0 +1,59 @@
<?php
declare(strict_types=1);
namespace App\Scolarite\Application\Command\UploadHomeworkAttachment;
use App\Scolarite\Application\Port\FileStorage;
use App\Scolarite\Domain\Exception\PieceJointeInvalideException;
use App\Scolarite\Domain\Model\Homework\HomeworkAttachment;
use App\Scolarite\Domain\Model\Homework\HomeworkAttachmentId;
use App\Scolarite\Domain\Model\Homework\HomeworkId;
use App\Scolarite\Domain\Repository\HomeworkRepository;
use App\Shared\Domain\Clock;
use App\Shared\Domain\Tenant\TenantId;
use function file_get_contents;
use function sprintf;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
#[AsMessageHandler(bus: 'command.bus')]
final readonly class UploadHomeworkAttachmentHandler
{
public function __construct(
private HomeworkRepository $homeworkRepository,
private FileStorage $fileStorage,
private Clock $clock,
) {
}
public function __invoke(UploadHomeworkAttachmentCommand $command): HomeworkAttachment
{
$tenantId = TenantId::fromString($command->tenantId);
$homeworkId = HomeworkId::fromString($command->homeworkId);
// Valider que le devoir existe
$this->homeworkRepository->get($homeworkId, $tenantId);
$attachmentId = HomeworkAttachmentId::generate();
$storagePath = sprintf('homework/%s/%s/%s', $command->tenantId, $command->homeworkId, $command->filename);
$content = file_get_contents($command->tempFilePath);
if ($content === false) {
throw PieceJointeInvalideException::lectureFichierImpossible($command->filename);
}
$this->fileStorage->upload($storagePath, $content, $command->mimeType);
return new HomeworkAttachment(
id: $attachmentId,
filename: $command->filename,
filePath: $storagePath,
fileSize: $command->fileSize,
mimeType: $command->mimeType,
uploadedAt: $this->clock->now(),
);
}
}