feat: Permettre aux administrateurs de configurer les règles de devoirs
Les établissements ont besoin de protéger les élèves et familles des devoirs de dernière minute. Cette configuration au niveau tenant permet de définir des règles de timing (délai minimum, pas de devoir pour lundi après une heure limite) et un mode d'application (avertissement, blocage ou désactivé). Le service de validation est prêt pour être branché dans le flux de création de devoirs (Stories 5.4/5.5). L'historique des changements assure la traçabilité des modifications de configuration.
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Administration\Application\Command\UpdateHomeworkRules;
|
||||
|
||||
use App\Administration\Application\Command\UpdateHomeworkRules\UpdateHomeworkRulesCommand;
|
||||
use App\Administration\Application\Command\UpdateHomeworkRules\UpdateHomeworkRulesHandler;
|
||||
use App\Administration\Domain\Model\HomeworkRules\EnforcementMode;
|
||||
use App\Administration\Domain\Model\HomeworkRules\HomeworkRule;
|
||||
use App\Administration\Domain\Model\HomeworkRules\HomeworkRules;
|
||||
use App\Administration\Domain\Model\HomeworkRules\RuleType;
|
||||
use App\Administration\Infrastructure\Persistence\InMemory\InMemoryHomeworkRulesHistoryRepository;
|
||||
use App\Administration\Infrastructure\Persistence\InMemory\InMemoryHomeworkRulesRepository;
|
||||
use App\Shared\Domain\Clock;
|
||||
use App\Shared\Domain\Tenant\TenantId;
|
||||
use DateTimeImmutable;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class UpdateHomeworkRulesHandlerTest extends TestCase
|
||||
{
|
||||
private const string TENANT_ID = '550e8400-e29b-41d4-a716-446655440001';
|
||||
private const string USER_ID = '550e8400-e29b-41d4-a716-446655440099';
|
||||
|
||||
private InMemoryHomeworkRulesRepository $rulesRepository;
|
||||
private InMemoryHomeworkRulesHistoryRepository $historyRepository;
|
||||
private Clock $clock;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->rulesRepository = new InMemoryHomeworkRulesRepository();
|
||||
$this->historyRepository = new InMemoryHomeworkRulesHistoryRepository();
|
||||
$this->clock = new class implements Clock {
|
||||
public function now(): DateTimeImmutable
|
||||
{
|
||||
return new DateTimeImmutable('2026-03-17 10:00:00');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itCreatesRulesWhenNoneExist(): void
|
||||
{
|
||||
$handler = $this->handler();
|
||||
|
||||
$result = $handler($this->commandAvecDelai(3));
|
||||
|
||||
self::assertCount(1, $result->rules);
|
||||
self::assertSame(RuleType::MINIMUM_DELAY, $result->rules[0]->type);
|
||||
self::assertSame(EnforcementMode::SOFT, $result->enforcementMode);
|
||||
self::assertTrue($result->enabled);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itUpdatesExistingRules(): void
|
||||
{
|
||||
$this->seedRules();
|
||||
|
||||
$handler = $this->handler();
|
||||
$result = $handler($this->commandAvecDelai(5, 'hard'));
|
||||
|
||||
self::assertCount(1, $result->rules);
|
||||
self::assertSame(5, $result->rules[0]->params['days']);
|
||||
self::assertSame(EnforcementMode::HARD, $result->enforcementMode);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itRecordsHistory(): void
|
||||
{
|
||||
$handler = $this->handler();
|
||||
$handler($this->commandAvecDelai(3));
|
||||
|
||||
$history = $this->historyRepository->findByTenant(TenantId::fromString(self::TENANT_ID));
|
||||
|
||||
self::assertCount(1, $history);
|
||||
self::assertSame('soft', $history[0]['enforcement_mode']);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itSavesToRepository(): void
|
||||
{
|
||||
$handler = $this->handler();
|
||||
$handler($this->commandAvecDelai(3));
|
||||
|
||||
$saved = $this->rulesRepository->findByTenantId(TenantId::fromString(self::TENANT_ID));
|
||||
self::assertNotNull($saved);
|
||||
self::assertCount(1, $saved->rules);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itDisablesRules(): void
|
||||
{
|
||||
$this->seedRules();
|
||||
|
||||
$handler = $this->handler();
|
||||
$result = $handler(new UpdateHomeworkRulesCommand(
|
||||
tenantId: self::TENANT_ID,
|
||||
rules: [],
|
||||
enforcementMode: 'disabled',
|
||||
enabled: false,
|
||||
changedBy: self::USER_ID,
|
||||
));
|
||||
|
||||
self::assertFalse($result->enabled);
|
||||
self::assertSame(EnforcementMode::DISABLED, $result->enforcementMode);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itHandlesMultipleRules(): void
|
||||
{
|
||||
$handler = $this->handler();
|
||||
$result = $handler(new UpdateHomeworkRulesCommand(
|
||||
tenantId: self::TENANT_ID,
|
||||
rules: [
|
||||
['type' => 'minimum_delay', 'params' => ['days' => 3]],
|
||||
['type' => 'no_monday_after', 'params' => ['day' => 'friday', 'time' => '12:00']],
|
||||
],
|
||||
enforcementMode: 'soft',
|
||||
enabled: true,
|
||||
changedBy: self::USER_ID,
|
||||
));
|
||||
|
||||
self::assertCount(2, $result->rules);
|
||||
}
|
||||
|
||||
private function handler(): UpdateHomeworkRulesHandler
|
||||
{
|
||||
return new UpdateHomeworkRulesHandler(
|
||||
$this->rulesRepository,
|
||||
$this->historyRepository,
|
||||
$this->clock,
|
||||
);
|
||||
}
|
||||
|
||||
private function commandAvecDelai(int $days, string $mode = 'soft'): UpdateHomeworkRulesCommand
|
||||
{
|
||||
return new UpdateHomeworkRulesCommand(
|
||||
tenantId: self::TENANT_ID,
|
||||
rules: [['type' => 'minimum_delay', 'params' => ['days' => $days]]],
|
||||
enforcementMode: $mode,
|
||||
enabled: true,
|
||||
changedBy: self::USER_ID,
|
||||
);
|
||||
}
|
||||
|
||||
private function seedRules(): void
|
||||
{
|
||||
$rules = HomeworkRules::creer(
|
||||
tenantId: TenantId::fromString(self::TENANT_ID),
|
||||
now: new DateTimeImmutable('2026-03-01'),
|
||||
);
|
||||
|
||||
$rules->mettreAJour(
|
||||
rules: [new HomeworkRule(RuleType::MINIMUM_DELAY, ['days' => 3])],
|
||||
enforcementMode: EnforcementMode::SOFT,
|
||||
enabled: true,
|
||||
now: new DateTimeImmutable('2026-03-01'),
|
||||
);
|
||||
|
||||
$this->rulesRepository->save($rules);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user