Files
pta/app/Models/VacationModel.php
Loic Masi 5fbf76868f pour prod
2026-08-07 16:13:43 +02:00

132 lines
4.4 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Models;
use DateTimeImmutable;
use PDO;
final class VacationModel extends BaseModel
{
public function all(?string $schoolYear = null): array
{
$sql = "SELECT id_periode, libelle, date_debut, date_fin, annee_scolaire,
academie, zone, source, date_creation
FROM periode_vacance
WHERE actif = TRUE";
$params = [];
if ($schoolYear !== null && $schoolYear !== '') {
$sql .= ' AND annee_scolaire = :annee_scolaire';
$params['annee_scolaire'] = $schoolYear;
}
$sql .= ' ORDER BY date_debut, libelle';
$stmt = $this->pdo->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
}
public function saveMany(array $periods): int
{
if ($periods === []) {
return 0;
}
$sql = "INSERT INTO periode_vacance
(libelle, date_debut, date_fin, annee_scolaire, academie, zone, source, actif)
VALUES
(:libelle, :date_debut, :date_fin, :annee_scolaire, :academie, :zone, :source, TRUE)
ON DUPLICATE KEY UPDATE
libelle = VALUES(libelle),
zone = VALUES(zone),
source = VALUES(source),
actif = TRUE";
$stmt = $this->pdo->prepare($sql);
$this->pdo->beginTransaction();
try {
foreach ($periods as $period) {
$stmt->execute([
'libelle' => $period['libelle'],
'date_debut' => $period['date_debut'],
'date_fin' => $period['date_fin'],
'annee_scolaire' => $period['annee_scolaire'],
'academie' => $period['academie'],
'zone' => $period['zone'],
'source' => $period['source'],
]);
}
$this->pdo->commit();
} catch (\Throwable $e) {
if ($this->pdo->inTransaction()) {
$this->pdo->rollBack();
}
throw $e;
}
return count($periods);
}
public function delete(int $id): bool
{
$stmt = $this->pdo->prepare('DELETE FROM periode_vacance WHERE id_periode = :id');
$stmt->execute(['id' => $id]);
return $stmt->rowCount() > 0;
}
public function periodsBetween(string $startDate, string $endDate): array
{
$stmt = $this->pdo->prepare(
"SELECT id_periode, libelle, date_debut, date_fin, annee_scolaire, academie, zone, source
FROM periode_vacance
WHERE actif = TRUE
AND date_debut <= :date_fin
AND date_fin >= :date_debut
ORDER BY date_debut"
);
$stmt->execute([
'date_debut' => $startDate,
'date_fin' => $endDate,
]);
return $stmt->fetchAll();
}
/**
* Retourne le type de période pour les cinq jours ouvrés d'une semaine ISO.
* Une date comprise dans une période de vacances confirmée est EXTRASCOLAIRE,
* sinon elle est PERISCOLAIRE.
*/
public function typesForIsoWeek(int $year, int $week): array
{
$monday = (new DateTimeImmutable())->setISODate($year, $week, 1)->setTime(0, 0);
$friday = $monday->modify('+4 days');
$periods = $this->periodsBetween($monday->format('Y-m-d'), $friday->format('Y-m-d'));
$days = [];
for ($offset = 0; $offset < 5; $offset++) {
$date = $monday->modify('+' . $offset . ' days')->format('Y-m-d');
$matchingPeriod = null;
foreach ($periods as $period) {
if ($date >= $period['date_debut'] && $date <= $period['date_fin']) {
$matchingPeriod = $period;
break;
}
}
$days[] = [
'date' => $date,
'type_affectation' => $matchingPeriod ? 'EXTRASCOLAIRE' : 'PERISCOLAIRE',
'vacances' => $matchingPeriod ? [
'id_periode' => (int) $matchingPeriod['id_periode'],
'libelle' => (string) $matchingPeriod['libelle'],
'annee_scolaire' => (string) $matchingPeriod['annee_scolaire'],
] : null,
];
}
return $days;
}
}