Lorsqu'un super-admin crée un établissement via l'interface, le système doit automatiquement créer la base tenant, exécuter les migrations, créer le premier utilisateur admin et envoyer l'invitation — le tout de manière asynchrone pour ne pas bloquer la réponse HTTP. Ce mécanisme rend chaque établissement opérationnel dès sa création sans intervention manuelle sur l'infrastructure.
83 lines
2.9 KiB
PHP
83 lines
2.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Scolarite\Application\Query\GetBlockedDates;
|
|
|
|
use App\Administration\Domain\Model\SchoolCalendar\SchoolCalendarRepository;
|
|
use App\Administration\Domain\Model\SchoolClass\AcademicYearId;
|
|
use App\Scolarite\Application\Port\HomeworkRulesChecker;
|
|
use App\Shared\Domain\Clock;
|
|
use App\Shared\Domain\Tenant\TenantId;
|
|
use DateInterval;
|
|
use DateTimeImmutable;
|
|
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
|
|
|
|
/**
|
|
* Retourne les dates bloquées (jours fériés, vacances, journées pédagogiques, weekends,
|
|
* et dates non conformes aux règles de devoirs) pour une plage de dates donnée.
|
|
*
|
|
* Utilisé par le frontend pour griser les jours non disponibles dans le calendrier.
|
|
*/
|
|
#[AsMessageHandler(bus: 'query.bus')]
|
|
final readonly class GetBlockedDatesHandler
|
|
{
|
|
public function __construct(
|
|
private SchoolCalendarRepository $calendarRepository,
|
|
private HomeworkRulesChecker $rulesChecker,
|
|
private Clock $clock,
|
|
) {
|
|
}
|
|
|
|
/** @return array<BlockedDateDto> */
|
|
public function __invoke(GetBlockedDatesQuery $query): array
|
|
{
|
|
$tenantId = TenantId::fromString($query->tenantId);
|
|
$academicYearId = AcademicYearId::fromString($query->academicYearId);
|
|
|
|
$calendar = $this->calendarRepository->findByTenantAndYear($tenantId, $academicYearId);
|
|
|
|
$startDate = new DateTimeImmutable($query->startDate);
|
|
$endDate = new DateTimeImmutable($query->endDate);
|
|
$oneDay = new DateInterval('P1D');
|
|
|
|
$now = $this->clock->now();
|
|
$blockedDates = [];
|
|
$current = $startDate;
|
|
|
|
while ($current <= $endDate) {
|
|
$dayOfWeek = (int) $current->format('N');
|
|
$dateStr = $current->format('Y-m-d');
|
|
|
|
if ($dayOfWeek >= 6) {
|
|
$blockedDates[] = new BlockedDateDto(
|
|
date: $dateStr,
|
|
reason: $dayOfWeek === 6 ? 'Samedi' : 'Dimanche',
|
|
type: 'weekend',
|
|
);
|
|
} elseif ($calendar !== null && ($entry = $calendar->trouverEntreePourDate($current)) !== null) {
|
|
$blockedDates[] = new BlockedDateDto(
|
|
date: $dateStr,
|
|
reason: $entry->label,
|
|
type: $entry->type->value,
|
|
);
|
|
} else {
|
|
$dueDate = new DateTimeImmutable($dateStr);
|
|
$result = $this->rulesChecker->verifier($tenantId, $dueDate, $now);
|
|
|
|
if (!$result->estValide()) {
|
|
$blockedDates[] = new BlockedDateDto(
|
|
date: $dateStr,
|
|
reason: $result->messages()[0] ?? 'Règle de devoirs',
|
|
type: $result->estBloquant() ? 'rule_hard' : 'rule_soft',
|
|
);
|
|
}
|
|
}
|
|
|
|
$current = $current->add($oneDay);
|
|
}
|
|
|
|
return $blockedDates;
|
|
}
|
|
}
|