"""Génération des créneaux d'un poste à partir des créneaux types (DayPart).""" import datetime as dt from sqlmodel import Session, select from app.models import DayPart, Edition, Position, Shift from app.validation.engine import day_boundary def _dates(edition: Edition) -> list[dt.date]: span = (edition.end_date - edition.start_date).days return [edition.start_date + dt.timedelta(days=i) for i in range(span + 1)] def _window(day: dt.date, part: DayPart, boundary: dt.time) -> tuple[dt.datetime, dt.datetime]: actual_day = day + dt.timedelta(days=1) if part.start_time < boundary else day start = dt.datetime.combine(actual_day, part.start_time) end_day = ( actual_day if part.end_time > part.start_time else actual_day + dt.timedelta(days=1) ) return start, dt.datetime.combine(end_day, part.end_time) def generate_missing_shifts( session: Session, edition: Edition, position: Position ) -> int: """Crée, pour chaque jour de l'édition et chaque créneau type, un créneau à besoin 0/0 s'il n'existe pas déjà. Retourne le nombre créé.""" day_parts = list( session.exec(select(DayPart).where(DayPart.edition_id == edition.id)) ) boundary = day_boundary(day_parts) existing = { (s.day_part_id, s.starts_at.date()) for s in session.exec( select(Shift).where(Shift.position_id == position.id) ) } created = 0 for day in _dates(edition): for part in day_parts: start, end = _window(day, part, boundary) if (part.id, start.date()) in existing: continue session.add( Shift( edition_id=edition.id, position_id=position.id, day_part_id=part.id, starts_at=start, ends_at=end, min_staff=0, ideal_staff=0, ) ) created += 1 return created