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."""
import requests
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
from app_new.extensions import db
from app_new.core.models import CollegeClosure
# 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):
@ -25,15 +26,15 @@ def fetch_vacances_scolaires(zone="A", annee=None):
# L'API du gouvernement filtre par zone et année
params = {
"where": f"zones='{zone}'",
"where": f"zones='Zone {zone}' AND annee_scolaire='{annee}-{annee + 1}'",
"order_by": "start_date",
"limit": 50
"limit": 100,
}
try:
response = requests.get(API_URL, params=params, timeout=30)
response.raise_for_status()
data = response.json()
data = response.json().get("results", [])
vacances = []
for item in data:
@ -43,13 +44,16 @@ def fetch_vacances_scolaires(zone="A", annee=None):
if start and end:
# 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:
raw_end_date = datetime.fromisoformat(end.replace("Z", "+00:00")).date()
end_date = raw_end_date - timedelta(days=1)
raw_end_date = datetime.fromisoformat(end.replace("Z", "+00:00")).astimezone(ZoneInfo("Europe/Paris")).date()
# 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
# (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
vacances.append({
"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),
# retenir la rentrée la plus tardive : la permanence reste possible
# 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:
max_end = max(item["end_date"] for item in grandes)
for item in grandes: