from __future__ import annotations from datetime import datetime from typing import Any, Dict, List, Optional from sqlalchemy import Boolean, DateTime, Integer, JSON, String, Text from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql import func from .database import Base class Schedule(Base): __tablename__ = "schedules" id: Mapped[str] = mapped_column(String, primary_key=True) name: Mapped[str] = mapped_column(String, nullable=False) description: Mapped[Optional[str]] = mapped_column(Text) playbook: Mapped[str] = mapped_column(String, nullable=False) target_type: Mapped[Optional[str]] = mapped_column(String, default="group") target: Mapped[str] = mapped_column(String, nullable=False) extra_vars: Mapped[Optional[Dict[str, Any]]] = mapped_column(JSON) schedule_type: Mapped[str] = mapped_column(String, nullable=False) schedule_time: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True)) recurrence_type: Mapped[Optional[str]] = mapped_column(String) recurrence_time: Mapped[Optional[str]] = mapped_column(String) recurrence_days: Mapped[Optional[str]] = mapped_column(Text) cron_expression: Mapped[Optional[str]] = mapped_column(String) timezone: Mapped[Optional[str]] = mapped_column(String, default="America/Montreal") start_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True)) end_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True)) enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) tags: Mapped[Optional[str]] = mapped_column(Text) next_run: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True)) last_run: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True)) last_status: Mapped[Optional[str]] = mapped_column(String, default="never") retry_on_failure: Mapped[Optional[int]] = mapped_column(Integer, default=0) timeout: Mapped[Optional[int]] = mapped_column(Integer, default=3600) # Type de notification: "none" (aucune), "all" (toujours), "errors" (erreurs seulement) notification_type: Mapped[Optional[str]] = mapped_column(String, default="all") run_count: Mapped[Optional[int]] = mapped_column(Integer, default=0) success_count: Mapped[Optional[int]] = mapped_column(Integer, default=0) failure_count: Mapped[Optional[int]] = mapped_column(Integer, default=0) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now()) updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now(), onupdate=func.now()) deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True)) runs: Mapped[List["ScheduleRun"]] = relationship( "ScheduleRun", back_populates="schedule", cascade="all, delete-orphan" ) logs: Mapped[List["Log"]] = relationship("Log", back_populates="schedule") def __repr__(self) -> str: # pragma: no cover - debug helper return f""