Files
Classeo/backend/src/Scolarite/Infrastructure/Persistence/Doctrine/DoctrineHomeworkRuleExceptionRepository.php
Mathias STRASSER 3446cbf04b
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 aux enseignants de contourner les règles de devoirs avec justification
Akeneo permet de configurer des règles de devoirs en mode Hard qui bloquent
totalement la création. Or certains cas légitimes (sorties scolaires, événements
exceptionnels) nécessitent de passer outre ces règles. Sans mécanisme d'exception,
l'enseignant est bloqué et doit contacter manuellement la direction.

Cette implémentation ajoute un flux complet d'exception : l'enseignant justifie
sa demande (min 20 caractères), le devoir est créé immédiatement, et la direction
est notifiée par email. Le handler vérifie côté serveur que les règles sont
réellement bloquantes avant d'accepter l'exception, empêchant toute fabrication
de fausses exceptions via l'API. La direction dispose d'un rapport filtrable
par période, enseignant et type de règle.
2026-03-19 22:02:48 +01:00

124 lines
4.2 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Scolarite\Infrastructure\Persistence\Doctrine;
use App\Administration\Domain\Model\User\UserId;
use App\Scolarite\Domain\Model\Homework\HomeworkId;
use App\Scolarite\Domain\Model\Homework\HomeworkRuleException;
use App\Scolarite\Domain\Model\Homework\HomeworkRuleExceptionId;
use App\Scolarite\Domain\Repository\HomeworkRuleExceptionRepository;
use App\Shared\Domain\Tenant\TenantId;
use function array_map;
use DateTimeImmutable;
use Doctrine\DBAL\Connection;
use Override;
final readonly class DoctrineHomeworkRuleExceptionRepository implements HomeworkRuleExceptionRepository
{
public function __construct(
private Connection $connection,
) {
}
#[Override]
public function save(HomeworkRuleException $exception): void
{
$this->connection->executeStatement(
'INSERT INTO homework_rule_exceptions (id, tenant_id, homework_id, rule_type, justification, created_by, created_at)
VALUES (:id, :tenant_id, :homework_id, :rule_type, :justification, :created_by, :created_at)
ON CONFLICT (id) DO NOTHING',
[
'id' => (string) $exception->id,
'tenant_id' => (string) $exception->tenantId,
'homework_id' => (string) $exception->homeworkId,
'rule_type' => $exception->ruleType,
'justification' => $exception->justification,
'created_by' => (string) $exception->createdBy,
'created_at' => $exception->createdAt->format(DateTimeImmutable::ATOM),
],
);
}
#[Override]
public function findByHomework(HomeworkId $homeworkId, TenantId $tenantId): array
{
$rows = $this->connection->fetchAllAssociative(
'SELECT * FROM homework_rule_exceptions
WHERE homework_id = :homework_id AND tenant_id = :tenant_id
ORDER BY created_at DESC',
[
'homework_id' => (string) $homeworkId,
'tenant_id' => (string) $tenantId,
],
);
return array_map($this->hydrate(...), $rows);
}
#[Override]
public function findByTenant(TenantId $tenantId): array
{
$rows = $this->connection->fetchAllAssociative(
'SELECT * FROM homework_rule_exceptions
WHERE tenant_id = :tenant_id
ORDER BY created_at DESC',
['tenant_id' => (string) $tenantId],
);
return array_map($this->hydrate(...), $rows);
}
#[Override]
public function homeworkIdsWithExceptions(TenantId $tenantId): array
{
$rows = $this->connection->fetchAllAssociative(
'SELECT DISTINCT homework_id FROM homework_rule_exceptions WHERE tenant_id = :tenant_id',
['tenant_id' => (string) $tenantId],
);
return array_map(
/** @param array<string, mixed> $row */
static function (array $row): string {
/** @var string $homeworkId */
$homeworkId = $row['homework_id'];
return $homeworkId;
},
$rows,
);
}
/** @param array<string, mixed> $row */
private function hydrate(array $row): HomeworkRuleException
{
/** @var string $id */
$id = $row['id'];
/** @var string $tenantId */
$tenantId = $row['tenant_id'];
/** @var string $homeworkId */
$homeworkId = $row['homework_id'];
/** @var string $ruleType */
$ruleType = $row['rule_type'];
/** @var string $justification */
$justification = $row['justification'];
/** @var string $createdBy */
$createdBy = $row['created_by'];
/** @var string $createdAt */
$createdAt = $row['created_at'];
return HomeworkRuleException::reconstitute(
id: HomeworkRuleExceptionId::fromString($id),
tenantId: TenantId::fromString($tenantId),
homeworkId: HomeworkId::fromString($homeworkId),
ruleType: $ruleType,
justification: $justification,
createdBy: UserId::fromString($createdBy),
createdAt: new DateTimeImmutable($createdAt),
);
}
}