Corriger l'import des vacances scolaires officielles
Some checks are pending
CI - Tests et Syntax / lint-and-test (push) Waiting to run

This commit is contained in:
root 2026-08-20 21:11:50 +00:00
parent dfc182a8a9
commit 82cd35d4ae

View file

@ -1,12 +1,13 @@
"""Service d'import des vacances scolaires depuis l'API gouvernementale.""" """Service d'import des vacances scolaires depuis l'API gouvernementale."""
import requests import requests
from datetime import datetime, timedelta from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
from app_new.extensions import db from app_new.extensions import db
from app_new.core.models import CollegeClosure from app_new.core.models import CollegeClosure
# API du gouvernement pour les vacances scolaires # API du gouvernement pour les vacances scolaires
API_URL = "https://data.education.gouv.fr/api/v2/catalog/datasets/fr-en-calendrier-scolaire-scolaires/exports/json" API_URL = "https://data.education.gouv.fr/api/explore/v2.1/catalog/datasets/fr-en-calendrier-scolaire/records"
def fetch_vacances_scolaires(zone="A", annee=None): def fetch_vacances_scolaires(zone="A", annee=None):
@ -25,15 +26,15 @@ def fetch_vacances_scolaires(zone="A", annee=None):
# L'API du gouvernement filtre par zone et année # L'API du gouvernement filtre par zone et année
params = { params = {
"where": f"zones='{zone}'", "where": f"zones='Zone {zone}' AND annee_scolaire='{annee}-{annee + 1}'",
"order_by": "start_date", "order_by": "start_date",
"limit": 50 "limit": 100,
} }
try: try:
response = requests.get(API_URL, params=params, timeout=30) response = requests.get(API_URL, params=params, timeout=30)
response.raise_for_status() response.raise_for_status()
data = response.json() data = response.json().get("results", [])
vacances = [] vacances = []
for item in data: for item in data:
@ -43,13 +44,16 @@ def fetch_vacances_scolaires(zone="A", annee=None):
if start and end: if start and end:
# Filtrer pour l'année scolaire demandée # Filtrer pour l'année scolaire demandée
start_date = datetime.fromisoformat(start.replace("Z", "+00:00")) start_date = datetime.fromisoformat(start.replace("Z", "+00:00")).astimezone(ZoneInfo("Europe/Paris"))
if start_date.year >= annee - 1: if start_date.year >= annee - 1:
raw_end_date = datetime.fromisoformat(end.replace("Z", "+00:00")).date() raw_end_date = datetime.fromisoformat(end.replace("Z", "+00:00")).astimezone(ZoneInfo("Europe/Paris")).date()
end_date = raw_end_date - timedelta(days=1) # Les fermetures ponctuelles (ex. pont de l'Ascension)
# sont représentées par le même début et la même fin.
end_date = raw_end_date if raw_end_date == start_date.date() else raw_end_date - timedelta(days=1)
# Pour l'agent, le 31 août reste une journée de vacances # Pour l'agent, le 31 août reste une journée de vacances
# (la rentrée des enseignants ne déclenche pas la reprise). # (la rentrée des enseignants ne déclenche pas la reprise).
if "grandes vacances" in description.lower() and raw_end_date.month == 8: is_summer = "grandes vacances" in description.lower() or "vacances d'été" in description.lower()
if is_summer and raw_end_date.month == 8:
end_date = raw_end_date end_date = raw_end_date
vacances.append({ vacances.append({
"start_date": start_date.date(), "start_date": start_date.date(),
@ -63,7 +67,15 @@ def fetch_vacances_scolaires(zone="A", annee=None):
# Lorsque l'API fournit plusieurs calendriers (enseignants, élèves), # Lorsque l'API fournit plusieurs calendriers (enseignants, élèves),
# retenir la rentrée la plus tardive : la permanence reste possible # retenir la rentrée la plus tardive : la permanence reste possible
# jusqu'à la veille de la rentrée des élèves. # jusqu'à la veille de la rentrée des élèves.
grandes = [item for item in vacances if "grandes vacances" in item["description"].lower()] # Une ligne existe par académie et parfois par population. Dédupliquer
# en conservant la date de rentrée la plus tardive (élèves).
deduped = {}
for item in vacances:
key = (item["description"], item["start_date"])
if key not in deduped or item["end_date"] > deduped[key]["end_date"]:
deduped[key] = item
vacances = list(deduped.values())
grandes = [item for item in vacances if "grandes vacances" in item["description"].lower() or "vacances d'été" in item["description"].lower()]
if grandes: if grandes:
max_end = max(item["end_date"] for item in grandes) max_end = max(item["end_date"] for item in grandes)
for item in grandes: for item in grandes: