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,111 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Administration\Infrastructure\Api\Resource;
|
||||
|
||||
use ApiPlatform\Metadata\ApiProperty;
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use ApiPlatform\Metadata\Put;
|
||||
use App\Administration\Domain\Model\SchoolCalendar\SchoolCalendar;
|
||||
use App\Administration\Infrastructure\Api\Processor\AddPedagogicalDayProcessor;
|
||||
use App\Administration\Infrastructure\Api\Processor\ConfigureCalendarProcessor;
|
||||
use App\Administration\Infrastructure\Api\Provider\CalendarProvider;
|
||||
use App\Administration\Infrastructure\Api\Provider\IsSchoolDayProvider;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* API Resource pour la gestion du calendrier scolaire.
|
||||
*
|
||||
* @see FR80 - Configurer jours fériés et vacances scolaires
|
||||
*/
|
||||
#[ApiResource(
|
||||
shortName: 'Calendar',
|
||||
operations: [
|
||||
new Get(
|
||||
uriTemplate: '/academic-years/{academicYearId}/calendar',
|
||||
provider: CalendarProvider::class,
|
||||
name: 'get_calendar',
|
||||
),
|
||||
new Put(
|
||||
uriTemplate: '/academic-years/{academicYearId}/calendar',
|
||||
read: false,
|
||||
processor: ConfigureCalendarProcessor::class,
|
||||
name: 'configure_calendar',
|
||||
),
|
||||
new Post(
|
||||
uriTemplate: '/academic-years/{academicYearId}/calendar/import-official',
|
||||
read: false,
|
||||
processor: ConfigureCalendarProcessor::class,
|
||||
name: 'import_official_holidays',
|
||||
),
|
||||
new Post(
|
||||
uriTemplate: '/academic-years/{academicYearId}/calendar/pedagogical-day',
|
||||
read: false,
|
||||
processor: AddPedagogicalDayProcessor::class,
|
||||
name: 'add_pedagogical_day',
|
||||
),
|
||||
new Get(
|
||||
uriTemplate: '/academic-years/{academicYearId}/calendar/is-school-day/{date}',
|
||||
provider: IsSchoolDayProvider::class,
|
||||
name: 'is_school_day',
|
||||
),
|
||||
],
|
||||
)]
|
||||
final class CalendarResource
|
||||
{
|
||||
#[ApiProperty(identifier: true)]
|
||||
public ?string $academicYearId = null;
|
||||
|
||||
#[Assert\Choice(choices: ['A', 'B', 'C'], message: 'La zone scolaire doit être A, B ou C.')]
|
||||
public ?string $zone = null;
|
||||
|
||||
/** @var CalendarEntryItem[]|null */
|
||||
public ?array $entries = null;
|
||||
|
||||
// Write-only for import-official
|
||||
#[ApiProperty(readable: false)]
|
||||
public ?string $importZone = null;
|
||||
|
||||
// Write-only for pedagogical-day
|
||||
#[ApiProperty(readable: false)]
|
||||
#[Assert\Date(message: 'La date doit être au format YYYY-MM-DD.')]
|
||||
public ?string $date = null;
|
||||
|
||||
#[ApiProperty(readable: false)]
|
||||
#[Assert\Length(min: 2, max: 100)]
|
||||
public ?string $label = null;
|
||||
|
||||
#[ApiProperty(readable: false)]
|
||||
public ?string $description = null;
|
||||
|
||||
// Read-only for is-school-day
|
||||
#[ApiProperty(writable: false)]
|
||||
public ?bool $isSchoolDay = null;
|
||||
|
||||
#[ApiProperty(writable: false)]
|
||||
public ?string $reason = null;
|
||||
|
||||
public static function fromCalendar(SchoolCalendar $calendar, string $academicYearId): self
|
||||
{
|
||||
$resource = new self();
|
||||
$resource->academicYearId = $academicYearId;
|
||||
$resource->zone = $calendar->zone?->value;
|
||||
$resource->entries = [];
|
||||
|
||||
foreach ($calendar->entries() as $entry) {
|
||||
$item = new CalendarEntryItem();
|
||||
$item->id = (string) $entry->id;
|
||||
$item->type = $entry->type->value;
|
||||
$item->startDate = $entry->startDate->format('Y-m-d');
|
||||
$item->endDate = $entry->endDate->format('Y-m-d');
|
||||
$item->label = $entry->label;
|
||||
$item->description = $entry->description;
|
||||
$resource->entries[] = $item;
|
||||
}
|
||||
|
||||
return $resource;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user