feat: Avertir l'enseignant quand un devoir ne respecte pas les règles (mode soft)
Quand un établissement configure des règles de devoirs en mode "soft", l'enseignant est maintenant averti avant la création si la date d'échéance ne respecte pas les contraintes (délai minimum, pas de lundi après un certain créneau). Il peut alors choisir de continuer (avec traçabilité) ou de modifier la date vers une date conforme. Le mode "hard" (blocage) reste protégé : acknowledgeWarning ne permet pas de contourner les règles bloquantes, préparant la story 5.5.
This commit is contained in:
@@ -13,8 +13,12 @@ use App\Scolarite\Application\Command\CreateHomework\CreateHomeworkCommand;
|
||||
use App\Scolarite\Application\Command\CreateHomework\CreateHomeworkHandler;
|
||||
use App\Scolarite\Application\Port\CurrentCalendarProvider;
|
||||
use App\Scolarite\Application\Port\EnseignantAffectationChecker;
|
||||
use App\Scolarite\Application\Port\HomeworkRulesChecker;
|
||||
use App\Scolarite\Application\Port\HomeworkRulesCheckResult;
|
||||
use App\Scolarite\Application\Port\RuleWarning;
|
||||
use App\Scolarite\Domain\Exception\DateEcheanceInvalideException;
|
||||
use App\Scolarite\Domain\Exception\EnseignantNonAffecteException;
|
||||
use App\Scolarite\Domain\Exception\ReglesDevoirsNonRespecteesException;
|
||||
use App\Scolarite\Domain\Model\Homework\HomeworkId;
|
||||
use App\Scolarite\Domain\Model\Homework\HomeworkStatus;
|
||||
use App\Scolarite\Domain\Service\DueDateValidator;
|
||||
@@ -106,7 +110,103 @@ final class CreateHomeworkHandlerTest extends TestCase
|
||||
self::assertNull($homework->description);
|
||||
}
|
||||
|
||||
private function createHandler(bool $affecte): CreateHomeworkHandler
|
||||
#[Test]
|
||||
public function itThrowsWhenSoftRulesViolatedAndNotAcknowledged(): void
|
||||
{
|
||||
$warning = new RuleWarning(
|
||||
ruleType: 'minimum_delay',
|
||||
message: 'Le devoir doit être créé au moins 3 jours avant.',
|
||||
params: ['days' => 3],
|
||||
);
|
||||
$rulesResult = new HomeworkRulesCheckResult(warnings: [$warning], bloquant: false);
|
||||
$handler = $this->createHandler(affecte: true, rulesResult: $rulesResult);
|
||||
|
||||
$this->expectException(ReglesDevoirsNonRespecteesException::class);
|
||||
|
||||
$handler($this->createCommand(acknowledgeWarning: false));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itThrowsWhenHardRulesViolatedAndNotAcknowledged(): void
|
||||
{
|
||||
$warning = new RuleWarning(
|
||||
ruleType: 'minimum_delay',
|
||||
message: 'Le devoir doit être créé au moins 3 jours avant.',
|
||||
params: ['days' => 3],
|
||||
);
|
||||
$rulesResult = new HomeworkRulesCheckResult(warnings: [$warning], bloquant: true);
|
||||
$handler = $this->createHandler(affecte: true, rulesResult: $rulesResult);
|
||||
|
||||
$this->expectException(ReglesDevoirsNonRespecteesException::class);
|
||||
|
||||
$handler($this->createCommand(acknowledgeWarning: false));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itThrowsWhenHardRulesViolatedEvenWhenAcknowledged(): void
|
||||
{
|
||||
$warning = new RuleWarning(
|
||||
ruleType: 'minimum_delay',
|
||||
message: 'Le devoir doit être créé au moins 3 jours avant.',
|
||||
params: ['days' => 3],
|
||||
);
|
||||
$rulesResult = new HomeworkRulesCheckResult(warnings: [$warning], bloquant: true);
|
||||
$handler = $this->createHandler(affecte: true, rulesResult: $rulesResult);
|
||||
|
||||
$this->expectException(ReglesDevoirsNonRespecteesException::class);
|
||||
|
||||
$handler($this->createCommand(acknowledgeWarning: true));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itCreatesHomeworkWhenSoftRulesViolatedButAcknowledged(): void
|
||||
{
|
||||
$warning = new RuleWarning(
|
||||
ruleType: 'minimum_delay',
|
||||
message: 'Le devoir doit être créé au moins 3 jours avant.',
|
||||
params: ['days' => 3],
|
||||
);
|
||||
$rulesResult = new HomeworkRulesCheckResult(warnings: [$warning], bloquant: false);
|
||||
$handler = $this->createHandler(affecte: true, rulesResult: $rulesResult);
|
||||
|
||||
$homework = $handler($this->createCommand(acknowledgeWarning: true));
|
||||
|
||||
self::assertNotEmpty((string) $homework->id);
|
||||
self::assertSame(HomeworkStatus::PUBLISHED, $homework->status);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itRecordsRuleOverrideWhenAcknowledged(): void
|
||||
{
|
||||
$warning = new RuleWarning(
|
||||
ruleType: 'minimum_delay',
|
||||
message: 'Le devoir doit être créé au moins 3 jours avant.',
|
||||
params: ['days' => 3],
|
||||
);
|
||||
$rulesResult = new HomeworkRulesCheckResult(warnings: [$warning], bloquant: false);
|
||||
$handler = $this->createHandler(affecte: true, rulesResult: $rulesResult);
|
||||
|
||||
$homework = $handler($this->createCommand(acknowledgeWarning: true));
|
||||
|
||||
self::assertNotNull($homework->ruleOverride);
|
||||
self::assertArrayHasKey('warnings', $homework->ruleOverride);
|
||||
self::assertArrayHasKey('acknowledgedAt', $homework->ruleOverride);
|
||||
self::assertSame(['minimum_delay'], $homework->ruleOverride['warnings']);
|
||||
self::assertSame('2026-03-12T10:00:00+00:00', $homework->ruleOverride['acknowledgedAt']);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itCreatesHomeworkWithNoOverrideWhenRulesPass(): void
|
||||
{
|
||||
$rulesResult = HomeworkRulesCheckResult::ok();
|
||||
$handler = $this->createHandler(affecte: true, rulesResult: $rulesResult);
|
||||
|
||||
$homework = $handler($this->createCommand());
|
||||
|
||||
self::assertNull($homework->ruleOverride);
|
||||
}
|
||||
|
||||
private function createHandler(bool $affecte, ?HomeworkRulesCheckResult $rulesResult = null): CreateHomeworkHandler
|
||||
{
|
||||
$affectationChecker = new class($affecte) implements EnseignantAffectationChecker {
|
||||
public function __construct(private readonly bool $affecte)
|
||||
@@ -131,18 +231,31 @@ final class CreateHomeworkHandlerTest extends TestCase
|
||||
}
|
||||
};
|
||||
|
||||
$rulesChecker = new class($rulesResult ?? HomeworkRulesCheckResult::ok()) implements HomeworkRulesChecker {
|
||||
public function __construct(private readonly HomeworkRulesCheckResult $result)
|
||||
{
|
||||
}
|
||||
|
||||
public function verifier(TenantId $tenantId, DateTimeImmutable $dueDate, DateTimeImmutable $creationDate): HomeworkRulesCheckResult
|
||||
{
|
||||
return $this->result;
|
||||
}
|
||||
};
|
||||
|
||||
return new CreateHomeworkHandler(
|
||||
$this->homeworkRepository,
|
||||
$affectationChecker,
|
||||
$calendarProvider,
|
||||
new DueDateValidator(),
|
||||
$rulesChecker,
|
||||
$this->clock,
|
||||
);
|
||||
}
|
||||
|
||||
private function createCommand(
|
||||
?string $dueDate = null,
|
||||
mixed $description = 'Faire les exercices 1 à 10',
|
||||
?string $description = 'Faire les exercices 1 à 10',
|
||||
bool $acknowledgeWarning = false,
|
||||
): CreateHomeworkCommand {
|
||||
return new CreateHomeworkCommand(
|
||||
tenantId: self::TENANT_ID,
|
||||
@@ -152,6 +265,7 @@ final class CreateHomeworkHandlerTest extends TestCase
|
||||
title: 'Exercices chapitre 5',
|
||||
description: $description,
|
||||
dueDate: $dueDate ?? '2026-04-15',
|
||||
acknowledgeWarning: $acknowledgeWarning,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user