feat: Configurer les jours fériés et vacances du calendrier scolaire
Les administrateurs d'établissement avaient besoin de gérer le calendrier scolaire (FR80) pour que l'EDT et les devoirs respectent automatiquement les jours non travaillés. Sans cette configuration centralisée, chaque module devait gérer indépendamment les contraintes de dates. Le calendrier s'appuie sur l'API data.education.gouv.fr pour importer les vacances officielles par zone (A/B/C) et calcule les 11 jours fériés français (dont les fêtes mobiles liées à Pâques). Les enseignants sont notifiés par email lors de l'ajout d'une journée pédagogique. Un query IsSchoolDay et une validation des dates d'échéance de devoirs permettent aux autres modules de s'intégrer sans couplage direct.
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Administration\Domain\Model\SchoolCalendar;
|
||||
|
||||
use App\Administration\Domain\Exception\CalendrierDatesInvalidesException;
|
||||
use App\Administration\Domain\Exception\CalendrierLabelInvalideException;
|
||||
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntry;
|
||||
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntryId;
|
||||
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntryType;
|
||||
use DateTimeImmutable;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class CalendarEntryTest extends TestCase
|
||||
{
|
||||
#[Test]
|
||||
public function creationValide(): void
|
||||
{
|
||||
$entry = $this->createHoliday();
|
||||
|
||||
self::assertSame(CalendarEntryType::HOLIDAY, $entry->type);
|
||||
self::assertSame('Toussaint', $entry->label);
|
||||
self::assertSame('2024-11-01', $entry->startDate->format('Y-m-d'));
|
||||
self::assertSame('2024-11-01', $entry->endDate->format('Y-m-d'));
|
||||
self::assertNull($entry->description);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function creationAvecDescription(): void
|
||||
{
|
||||
$entry = new CalendarEntry(
|
||||
id: CalendarEntryId::generate(),
|
||||
type: CalendarEntryType::PEDAGOGICAL_DAY,
|
||||
startDate: new DateTimeImmutable('2025-03-14'),
|
||||
endDate: new DateTimeImmutable('2025-03-14'),
|
||||
label: 'Formation enseignants',
|
||||
description: 'Journée de formation continue',
|
||||
);
|
||||
|
||||
self::assertSame('Journée de formation continue', $entry->description);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function creationPeriodeVacances(): void
|
||||
{
|
||||
$entry = new CalendarEntry(
|
||||
id: CalendarEntryId::generate(),
|
||||
type: CalendarEntryType::VACATION,
|
||||
startDate: new DateTimeImmutable('2024-10-19'),
|
||||
endDate: new DateTimeImmutable('2024-11-03'),
|
||||
label: 'Vacances de la Toussaint',
|
||||
);
|
||||
|
||||
self::assertSame(CalendarEntryType::VACATION, $entry->type);
|
||||
self::assertSame('2024-10-19', $entry->startDate->format('Y-m-d'));
|
||||
self::assertSame('2024-11-03', $entry->endDate->format('Y-m-d'));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function labelEstTrimme(): void
|
||||
{
|
||||
$entry = new CalendarEntry(
|
||||
id: CalendarEntryId::generate(),
|
||||
type: CalendarEntryType::HOLIDAY,
|
||||
startDate: new DateTimeImmutable('2024-11-01'),
|
||||
endDate: new DateTimeImmutable('2024-11-01'),
|
||||
label: ' Toussaint ',
|
||||
);
|
||||
|
||||
self::assertSame('Toussaint', $entry->label);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function dateFinAvantDebutLeveException(): void
|
||||
{
|
||||
$this->expectException(CalendrierDatesInvalidesException::class);
|
||||
|
||||
new CalendarEntry(
|
||||
id: CalendarEntryId::generate(),
|
||||
type: CalendarEntryType::HOLIDAY,
|
||||
startDate: new DateTimeImmutable('2024-11-02'),
|
||||
endDate: new DateTimeImmutable('2024-11-01'),
|
||||
label: 'Invalid',
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function labelVideLeveException(): void
|
||||
{
|
||||
$this->expectException(CalendrierLabelInvalideException::class);
|
||||
|
||||
new CalendarEntry(
|
||||
id: CalendarEntryId::generate(),
|
||||
type: CalendarEntryType::HOLIDAY,
|
||||
startDate: new DateTimeImmutable('2024-11-01'),
|
||||
endDate: new DateTimeImmutable('2024-11-01'),
|
||||
label: '',
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function labelTropCourtLeveException(): void
|
||||
{
|
||||
$this->expectException(CalendrierLabelInvalideException::class);
|
||||
|
||||
new CalendarEntry(
|
||||
id: CalendarEntryId::generate(),
|
||||
type: CalendarEntryType::HOLIDAY,
|
||||
startDate: new DateTimeImmutable('2024-11-01'),
|
||||
endDate: new DateTimeImmutable('2024-11-01'),
|
||||
label: 'A',
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function labelTropLongLeveException(): void
|
||||
{
|
||||
$this->expectException(CalendrierLabelInvalideException::class);
|
||||
|
||||
new CalendarEntry(
|
||||
id: CalendarEntryId::generate(),
|
||||
type: CalendarEntryType::HOLIDAY,
|
||||
startDate: new DateTimeImmutable('2024-11-01'),
|
||||
endDate: new DateTimeImmutable('2024-11-01'),
|
||||
label: str_repeat('A', 101),
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function couvreRetourneTruePourDateDansLaPeriode(): void
|
||||
{
|
||||
$entry = new CalendarEntry(
|
||||
id: CalendarEntryId::generate(),
|
||||
type: CalendarEntryType::VACATION,
|
||||
startDate: new DateTimeImmutable('2024-10-19'),
|
||||
endDate: new DateTimeImmutable('2024-11-03'),
|
||||
label: 'Vacances Toussaint',
|
||||
);
|
||||
|
||||
self::assertTrue($entry->couvre(new DateTimeImmutable('2024-10-19')));
|
||||
self::assertTrue($entry->couvre(new DateTimeImmutable('2024-10-25')));
|
||||
self::assertTrue($entry->couvre(new DateTimeImmutable('2024-11-03')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function couvreRetourneFalsePourDateHorsPeriode(): void
|
||||
{
|
||||
$entry = new CalendarEntry(
|
||||
id: CalendarEntryId::generate(),
|
||||
type: CalendarEntryType::VACATION,
|
||||
startDate: new DateTimeImmutable('2024-10-19'),
|
||||
endDate: new DateTimeImmutable('2024-11-03'),
|
||||
label: 'Vacances Toussaint',
|
||||
);
|
||||
|
||||
self::assertFalse($entry->couvre(new DateTimeImmutable('2024-10-18')));
|
||||
self::assertFalse($entry->couvre(new DateTimeImmutable('2024-11-04')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function couvreJourUnique(): void
|
||||
{
|
||||
$entry = $this->createHoliday();
|
||||
|
||||
self::assertTrue($entry->couvre(new DateTimeImmutable('2024-11-01')));
|
||||
self::assertFalse($entry->couvre(new DateTimeImmutable('2024-10-31')));
|
||||
self::assertFalse($entry->couvre(new DateTimeImmutable('2024-11-02')));
|
||||
}
|
||||
|
||||
private function createHoliday(): CalendarEntry
|
||||
{
|
||||
return new CalendarEntry(
|
||||
id: CalendarEntryId::generate(),
|
||||
type: CalendarEntryType::HOLIDAY,
|
||||
startDate: new DateTimeImmutable('2024-11-01'),
|
||||
endDate: new DateTimeImmutable('2024-11-01'),
|
||||
label: 'Toussaint',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Administration\Domain\Model\SchoolCalendar;
|
||||
|
||||
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntryType;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class CalendarEntryTypeTest extends TestCase
|
||||
{
|
||||
#[Test]
|
||||
public function chaqueTypeAUnLabel(): void
|
||||
{
|
||||
foreach (CalendarEntryType::cases() as $type) {
|
||||
self::assertNotEmpty($type->label());
|
||||
}
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function labelsAttendus(): void
|
||||
{
|
||||
self::assertSame('Jour férié', CalendarEntryType::HOLIDAY->label());
|
||||
self::assertSame('Vacances scolaires', CalendarEntryType::VACATION->label());
|
||||
self::assertSame('Journée pédagogique', CalendarEntryType::PEDAGOGICAL_DAY->label());
|
||||
self::assertSame('Pont', CalendarEntryType::BRIDGE->label());
|
||||
self::assertSame('Fermeture exceptionnelle', CalendarEntryType::EXCEPTIONAL_CLOSURE->label());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function backedValuesConsistantes(): void
|
||||
{
|
||||
self::assertSame('holiday', CalendarEntryType::HOLIDAY->value);
|
||||
self::assertSame('vacation', CalendarEntryType::VACATION->value);
|
||||
self::assertSame('pedagogical', CalendarEntryType::PEDAGOGICAL_DAY->value);
|
||||
self::assertSame('bridge', CalendarEntryType::BRIDGE->value);
|
||||
self::assertSame('closure', CalendarEntryType::EXCEPTIONAL_CLOSURE->value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,420 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Administration\Domain\Model\SchoolCalendar;
|
||||
|
||||
use App\Administration\Domain\Event\CalendrierConfigure;
|
||||
use App\Administration\Domain\Event\JourneePedagogiqueAjoutee;
|
||||
use App\Administration\Domain\Exception\CalendrierEntreeNonTrouveeException;
|
||||
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntry;
|
||||
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntryId;
|
||||
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntryType;
|
||||
use App\Administration\Domain\Model\SchoolCalendar\SchoolCalendar;
|
||||
use App\Administration\Domain\Model\SchoolCalendar\SchoolZone;
|
||||
use App\Administration\Domain\Model\SchoolClass\AcademicYearId;
|
||||
use App\Shared\Domain\Tenant\TenantId;
|
||||
use DateTimeImmutable;
|
||||
use InvalidArgumentException;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
final class SchoolCalendarTest extends TestCase
|
||||
{
|
||||
private const string TENANT_ID = '550e8400-e29b-41d4-a716-446655440001';
|
||||
private const string ACADEMIC_YEAR_ID = '550e8400-e29b-41d4-a716-446655440010';
|
||||
|
||||
#[Test]
|
||||
public function initialiserCreeCalendrierVide(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
|
||||
self::assertTrue($calendar->tenantId->equals(TenantId::fromString(self::TENANT_ID)));
|
||||
self::assertTrue($calendar->academicYearId->equals(AcademicYearId::fromString(self::ACADEMIC_YEAR_ID)));
|
||||
self::assertNull($calendar->zone);
|
||||
self::assertEmpty($calendar->entries());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function configurerZoneDefInitLaZone(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
|
||||
$calendar->configurerZone(SchoolZone::A);
|
||||
|
||||
self::assertSame(SchoolZone::A, $calendar->zone);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function configurerZonePeutEtreChangee(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
|
||||
$calendar->configurerZone(SchoolZone::A);
|
||||
$calendar->configurerZone(SchoolZone::C);
|
||||
|
||||
self::assertSame(SchoolZone::C, $calendar->zone);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function ajouterEntreeAjouteAuCalendrier(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$entry = $this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-01', '2024-11-01', 'Toussaint');
|
||||
|
||||
$calendar->ajouterEntree($entry);
|
||||
|
||||
self::assertCount(1, $calendar->entries());
|
||||
self::assertSame($entry, $calendar->entries()[0]);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function ajouterPlusieursEntrees(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
|
||||
$calendar->ajouterEntree($this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-01', '2024-11-01', 'Toussaint'));
|
||||
$calendar->ajouterEntree($this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-11', '2024-11-11', 'Armistice'));
|
||||
$calendar->ajouterEntree($this->createEntry(CalendarEntryType::VACATION, '2024-12-21', '2025-01-05', 'Vacances de Noël'));
|
||||
|
||||
self::assertCount(3, $calendar->entries());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function supprimerEntreeRetireEntreeExistante(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$entry = $this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-01', '2024-11-01', 'Toussaint');
|
||||
|
||||
$calendar->ajouterEntree($entry);
|
||||
$calendar->supprimerEntree($entry->id);
|
||||
|
||||
self::assertEmpty($calendar->entries());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function supprimerEntreeInexistanteLeveException(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
|
||||
$this->expectException(CalendrierEntreeNonTrouveeException::class);
|
||||
|
||||
$calendar->supprimerEntree(CalendarEntryId::generate());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function viderEntreesSupprimeTout(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$calendar->ajouterEntree($this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-01', '2024-11-01', 'Toussaint'));
|
||||
$calendar->ajouterEntree($this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-11', '2024-11-11', 'Armistice'));
|
||||
|
||||
$calendar->viderEntrees();
|
||||
|
||||
self::assertEmpty($calendar->entries());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function estJourOuvreRetourneTruePourJourSemaine(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
|
||||
// Lundi 4 novembre 2024
|
||||
self::assertTrue($calendar->estJourOuvre(new DateTimeImmutable('2024-11-04')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function estJourOuvreRetourneFalsePourSamedi(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
|
||||
// Samedi 2 novembre 2024
|
||||
self::assertFalse($calendar->estJourOuvre(new DateTimeImmutable('2024-11-02')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function estJourOuvreRetourneFalsePourDimanche(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
|
||||
// Dimanche 3 novembre 2024
|
||||
self::assertFalse($calendar->estJourOuvre(new DateTimeImmutable('2024-11-03')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function estJourOuvreRetourneFalsePourJourFerie(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$calendar->ajouterEntree(
|
||||
$this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-01', '2024-11-01', 'Toussaint'),
|
||||
);
|
||||
|
||||
// Vendredi 1er novembre 2024 (Toussaint)
|
||||
self::assertFalse($calendar->estJourOuvre(new DateTimeImmutable('2024-11-01')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function estJourOuvreRetourneFalsePendantVacances(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$calendar->ajouterEntree(
|
||||
$this->createEntry(CalendarEntryType::VACATION, '2024-10-19', '2024-11-03', 'Vacances Toussaint'),
|
||||
);
|
||||
|
||||
// Mercredi 23 octobre 2024 (en plein dans les vacances)
|
||||
self::assertFalse($calendar->estJourOuvre(new DateTimeImmutable('2024-10-23')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function estJourOuvreRetourneFalsePourJourneePedagogique(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$calendar->ajouterEntree(
|
||||
$this->createEntry(CalendarEntryType::PEDAGOGICAL_DAY, '2025-03-14', '2025-03-14', 'Formation'),
|
||||
);
|
||||
|
||||
// Vendredi 14 mars 2025
|
||||
self::assertFalse($calendar->estJourOuvre(new DateTimeImmutable('2025-03-14')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function estJourOuvreRetourneTrueApresVacances(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$calendar->ajouterEntree(
|
||||
$this->createEntry(CalendarEntryType::VACATION, '2024-10-19', '2024-11-03', 'Vacances Toussaint'),
|
||||
);
|
||||
|
||||
// Lundi 4 novembre 2024 (jour de reprise)
|
||||
self::assertTrue($calendar->estJourOuvre(new DateTimeImmutable('2024-11-04')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function trouverEntreePourDateRetourneEntreeCorrespondante(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$holiday = $this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-01', '2024-11-01', 'Toussaint');
|
||||
$calendar->ajouterEntree($holiday);
|
||||
|
||||
$found = $calendar->trouverEntreePourDate(new DateTimeImmutable('2024-11-01'));
|
||||
|
||||
self::assertNotNull($found);
|
||||
self::assertSame('Toussaint', $found->label);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function trouverEntreePourDateRetourneNullSiAucune(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
|
||||
$found = $calendar->trouverEntreePourDate(new DateTimeImmutable('2024-11-01'));
|
||||
|
||||
self::assertNull($found);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function estEnVacancesRetourneTruePendantVacances(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$calendar->ajouterEntree(
|
||||
$this->createEntry(CalendarEntryType::VACATION, '2024-10-19', '2024-11-03', 'Vacances Toussaint'),
|
||||
);
|
||||
|
||||
self::assertTrue($calendar->estEnVacances(new DateTimeImmutable('2024-10-25')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function estEnVacancesRetourneFalseHorsVacances(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$calendar->ajouterEntree(
|
||||
$this->createEntry(CalendarEntryType::VACATION, '2024-10-19', '2024-11-03', 'Vacances Toussaint'),
|
||||
);
|
||||
|
||||
self::assertFalse($calendar->estEnVacances(new DateTimeImmutable('2024-11-04')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function estEnVacancesRetourneFalsePourJourFerie(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$calendar->ajouterEntree(
|
||||
$this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-01', '2024-11-01', 'Toussaint'),
|
||||
);
|
||||
|
||||
self::assertFalse($calendar->estEnVacances(new DateTimeImmutable('2024-11-01')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function estJourRetourVacancesRetourneTruePourJourApresFinVacances(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$calendar->ajouterEntree(
|
||||
$this->createEntry(CalendarEntryType::VACATION, '2024-10-19', '2024-11-03', 'Vacances Toussaint'),
|
||||
);
|
||||
|
||||
// 4 novembre = lendemain de la fin des vacances (3 novembre)
|
||||
self::assertTrue($calendar->estJourRetourVacances(new DateTimeImmutable('2024-11-04')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function estJourRetourVacancesRetourneFalsePourJourNormal(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$calendar->ajouterEntree(
|
||||
$this->createEntry(CalendarEntryType::VACATION, '2024-10-19', '2024-11-03', 'Vacances Toussaint'),
|
||||
);
|
||||
|
||||
self::assertFalse($calendar->estJourRetourVacances(new DateTimeImmutable('2024-11-05')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function configurerDefinitZoneEtImporteEntreesAvecEvenement(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$entries = [
|
||||
$this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-01', '2024-11-01', 'Toussaint'),
|
||||
$this->createEntry(CalendarEntryType::VACATION, '2024-10-19', '2024-11-03', 'Vacances Toussaint'),
|
||||
];
|
||||
$at = new DateTimeImmutable('2026-02-17 10:00:00');
|
||||
|
||||
$calendar->configurer(SchoolZone::A, $entries, $at);
|
||||
|
||||
self::assertSame(SchoolZone::A, $calendar->zone);
|
||||
self::assertCount(2, $calendar->entries());
|
||||
|
||||
$events = $calendar->pullDomainEvents();
|
||||
self::assertCount(1, $events);
|
||||
self::assertInstanceOf(CalendrierConfigure::class, $events[0]);
|
||||
self::assertSame(SchoolZone::A, $events[0]->zone);
|
||||
self::assertSame(2, $events[0]->nombreEntrees);
|
||||
|
||||
$expectedAggregateId = Uuid::uuid5(
|
||||
Uuid::NAMESPACE_DNS,
|
||||
sprintf('school-calendar:%s:%s', self::TENANT_ID, self::ACADEMIC_YEAR_ID),
|
||||
);
|
||||
self::assertTrue($events[0]->aggregateId()->equals($expectedAggregateId));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function configurerPreserveJourneesPedagogiques(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$pedaEntry = $this->createEntry(CalendarEntryType::PEDAGOGICAL_DAY, '2025-03-14', '2025-03-14', 'Formation');
|
||||
$calendar->ajouterEntree($pedaEntry);
|
||||
$calendar->ajouterEntree($this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-01', '2024-11-01', 'Toussaint'));
|
||||
|
||||
$entries = [
|
||||
$this->createEntry(CalendarEntryType::VACATION, '2024-12-21', '2025-01-05', 'Vacances de Noël'),
|
||||
];
|
||||
|
||||
$calendar->configurer(SchoolZone::A, $entries, new DateTimeImmutable());
|
||||
|
||||
// 1 preserved pedagogical day + 1 new vacation = 2
|
||||
self::assertCount(2, $calendar->entries());
|
||||
|
||||
$types = array_map(static fn (CalendarEntry $e) => $e->type, $calendar->entries());
|
||||
self::assertContains(CalendarEntryType::PEDAGOGICAL_DAY, $types);
|
||||
self::assertContains(CalendarEntryType::VACATION, $types);
|
||||
self::assertNotContains(CalendarEntryType::HOLIDAY, $types);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function configurerReemplaceEntreesExistantes(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$calendar->ajouterEntree($this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-01', '2024-11-01', 'Ancienne'));
|
||||
|
||||
$entries = [
|
||||
$this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-11', '2024-11-11', 'Armistice'),
|
||||
];
|
||||
|
||||
$calendar->configurer(SchoolZone::B, $entries, new DateTimeImmutable());
|
||||
|
||||
self::assertCount(1, $calendar->entries());
|
||||
self::assertSame('Armistice', $calendar->entries()[0]->label);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function ajouterJourneePedagogiqueEmetEvenement(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$entry = $this->createEntry(CalendarEntryType::PEDAGOGICAL_DAY, '2025-03-14', '2025-03-14', 'Formation enseignants');
|
||||
$at = new DateTimeImmutable('2026-02-17 10:00:00');
|
||||
|
||||
$calendar->ajouterJourneePedagogique($entry, $at);
|
||||
|
||||
self::assertCount(1, $calendar->entries());
|
||||
|
||||
$events = $calendar->pullDomainEvents();
|
||||
self::assertCount(1, $events);
|
||||
self::assertInstanceOf(JourneePedagogiqueAjoutee::class, $events[0]);
|
||||
self::assertSame('Formation enseignants', $events[0]->label);
|
||||
self::assertSame('2025-03-14', $events[0]->date->format('Y-m-d'));
|
||||
|
||||
$expectedAggregateId = Uuid::uuid5(
|
||||
Uuid::NAMESPACE_DNS,
|
||||
sprintf('school-calendar:%s:%s', self::TENANT_ID, self::ACADEMIC_YEAR_ID),
|
||||
);
|
||||
self::assertTrue($events[0]->aggregateId()->equals($expectedAggregateId));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function ajouterJourneePedagogiqueRefuseTypeDifferent(): void
|
||||
{
|
||||
$calendar = $this->createCalendar();
|
||||
$entry = $this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-01', '2024-11-01', 'Toussaint');
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$calendar->ajouterJourneePedagogique($entry, new DateTimeImmutable());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function reconstituteRestaureLEtat(): void
|
||||
{
|
||||
$tenantId = TenantId::fromString(self::TENANT_ID);
|
||||
$yearId = AcademicYearId::fromString(self::ACADEMIC_YEAR_ID);
|
||||
$entry1 = $this->createEntry(CalendarEntryType::HOLIDAY, '2024-11-01', '2024-11-01', 'Toussaint');
|
||||
$entry2 = $this->createEntry(CalendarEntryType::VACATION, '2024-12-21', '2025-01-05', 'Noël');
|
||||
|
||||
$calendar = SchoolCalendar::reconstitute(
|
||||
tenantId: $tenantId,
|
||||
academicYearId: $yearId,
|
||||
zone: SchoolZone::B,
|
||||
entries: [$entry1, $entry2],
|
||||
);
|
||||
|
||||
self::assertTrue($calendar->tenantId->equals($tenantId));
|
||||
self::assertTrue($calendar->academicYearId->equals($yearId));
|
||||
self::assertSame(SchoolZone::B, $calendar->zone);
|
||||
self::assertCount(2, $calendar->entries());
|
||||
self::assertEmpty($calendar->pullDomainEvents());
|
||||
}
|
||||
|
||||
private function createCalendar(): SchoolCalendar
|
||||
{
|
||||
return SchoolCalendar::initialiser(
|
||||
tenantId: TenantId::fromString(self::TENANT_ID),
|
||||
academicYearId: AcademicYearId::fromString(self::ACADEMIC_YEAR_ID),
|
||||
);
|
||||
}
|
||||
|
||||
private function createEntry(
|
||||
CalendarEntryType $type,
|
||||
string $startDate,
|
||||
string $endDate,
|
||||
string $label,
|
||||
): CalendarEntry {
|
||||
return new CalendarEntry(
|
||||
id: CalendarEntryId::generate(),
|
||||
type: $type,
|
||||
startDate: new DateTimeImmutable($startDate),
|
||||
endDate: new DateTimeImmutable($endDate),
|
||||
label: $label,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Administration\Domain\Model\SchoolCalendar;
|
||||
|
||||
use App\Administration\Domain\Model\SchoolCalendar\SchoolZone;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class SchoolZoneTest extends TestCase
|
||||
{
|
||||
#[Test]
|
||||
public function zoneAContientLyonEtBordeaux(): void
|
||||
{
|
||||
$academies = SchoolZone::A->academies();
|
||||
|
||||
self::assertContains('Lyon', $academies);
|
||||
self::assertContains('Bordeaux', $academies);
|
||||
self::assertContains('Grenoble', $academies);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function zoneBContientLilleEtNantes(): void
|
||||
{
|
||||
$academies = SchoolZone::B->academies();
|
||||
|
||||
self::assertContains('Lille', $academies);
|
||||
self::assertContains('Nantes', $academies);
|
||||
self::assertContains('Strasbourg', $academies);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function zoneCContientParisEtToulouse(): void
|
||||
{
|
||||
$academies = SchoolZone::C->academies();
|
||||
|
||||
self::assertContains('Paris', $academies);
|
||||
self::assertContains('Toulouse', $academies);
|
||||
self::assertContains('Versailles', $academies);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function backedValues(): void
|
||||
{
|
||||
self::assertSame('A', SchoolZone::A->value);
|
||||
self::assertSame('B', SchoolZone::B->value);
|
||||
self::assertSame('C', SchoolZone::C->value);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function chaqueZoneADesAcademies(): void
|
||||
{
|
||||
foreach (SchoolZone::cases() as $zone) {
|
||||
self::assertNotEmpty($zone->academies());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user