""" API Routes para gestión del Calendario de Contenido. """ from datetime import datetime, time from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from pydantic import BaseModel from app.core.database import get_db from app.models.content_calendar import ContentCalendar router = APIRouter() # =========================================== # SCHEMAS # =========================================== class CalendarEntryCreate(BaseModel): day_of_week: int # 0=Lunes, 6=Domingo time: str # Formato "HH:MM" content_type: str platforms: List[str] requires_approval: bool = False category_filter: Optional[str] = None priority: int = 0 description: Optional[str] = None class Config: from_attributes = True class CalendarEntryUpdate(BaseModel): day_of_week: Optional[int] = None time: Optional[str] = None content_type: Optional[str] = None platforms: Optional[List[str]] = None is_active: Optional[bool] = None requires_approval: Optional[bool] = None category_filter: Optional[str] = None priority: Optional[int] = None description: Optional[str] = None class Config: from_attributes = True # =========================================== # ENDPOINTS # =========================================== @router.get("/") async def list_calendar_entries( day_of_week: Optional[int] = Query(None), content_type: Optional[str] = Query(None), platform: Optional[str] = Query(None), is_active: Optional[bool] = Query(True), db: Session = Depends(get_db) ): """Listar entradas del calendario.""" query = db.query(ContentCalendar) if day_of_week is not None: query = query.filter(ContentCalendar.day_of_week == day_of_week) if content_type: query = query.filter(ContentCalendar.content_type == content_type) if is_active is not None: query = query.filter(ContentCalendar.is_active == is_active) if platform: query = query.filter(ContentCalendar.platforms.contains([platform])) entries = query.order_by( ContentCalendar.day_of_week, ContentCalendar.time ).all() return [e.to_dict() for e in entries] @router.get("/week") async def get_week_schedule(db: Session = Depends(get_db)): """Obtener el calendario semanal completo.""" entries = db.query(ContentCalendar).filter( ContentCalendar.is_active == True ).order_by( ContentCalendar.day_of_week, ContentCalendar.time ).all() # Organizar por día week = {i: [] for i in range(7)} for entry in entries: week[entry.day_of_week].append(entry.to_dict()) days = ["Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"] return { days[i]: week[i] for i in range(7) } @router.get("/today") async def get_today_schedule(db: Session = Depends(get_db)): """Obtener el calendario de hoy.""" today = datetime.now().weekday() entries = db.query(ContentCalendar).filter( ContentCalendar.day_of_week == today, ContentCalendar.is_active == True ).order_by(ContentCalendar.time).all() return [e.to_dict() for e in entries] @router.get("/{entry_id}") async def get_calendar_entry(entry_id: int, db: Session = Depends(get_db)): """Obtener una entrada del calendario por ID.""" entry = db.query(ContentCalendar).filter(ContentCalendar.id == entry_id).first() if not entry: raise HTTPException(status_code=404, detail="Entrada no encontrada") return entry.to_dict() @router.post("/") async def create_calendar_entry(entry_data: CalendarEntryCreate, db: Session = Depends(get_db)): """Crear una nueva entrada en el calendario.""" # Parsear hora hour, minute = map(int, entry_data.time.split(":")) entry_time = time(hour=hour, minute=minute) entry = ContentCalendar( day_of_week=entry_data.day_of_week, time=entry_time, content_type=entry_data.content_type, platforms=entry_data.platforms, requires_approval=entry_data.requires_approval, category_filter=entry_data.category_filter, priority=entry_data.priority, description=entry_data.description ) db.add(entry) db.commit() db.refresh(entry) return entry.to_dict() @router.put("/{entry_id}") async def update_calendar_entry( entry_id: int, entry_data: CalendarEntryUpdate, db: Session = Depends(get_db) ): """Actualizar una entrada del calendario.""" entry = db.query(ContentCalendar).filter(ContentCalendar.id == entry_id).first() if not entry: raise HTTPException(status_code=404, detail="Entrada no encontrada") update_data = entry_data.dict(exclude_unset=True) # Parsear hora si se proporciona if "time" in update_data and update_data["time"]: hour, minute = map(int, update_data["time"].split(":")) update_data["time"] = time(hour=hour, minute=minute) for field, value in update_data.items(): setattr(entry, field, value) entry.updated_at = datetime.utcnow() db.commit() db.refresh(entry) return entry.to_dict() @router.delete("/{entry_id}") async def delete_calendar_entry(entry_id: int, db: Session = Depends(get_db)): """Eliminar una entrada del calendario.""" entry = db.query(ContentCalendar).filter(ContentCalendar.id == entry_id).first() if not entry: raise HTTPException(status_code=404, detail="Entrada no encontrada") db.delete(entry) db.commit() return {"message": "Entrada eliminada", "entry_id": entry_id} @router.post("/{entry_id}/toggle") async def toggle_calendar_entry(entry_id: int, db: Session = Depends(get_db)): """Activar/desactivar una entrada del calendario.""" entry = db.query(ContentCalendar).filter(ContentCalendar.id == entry_id).first() if not entry: raise HTTPException(status_code=404, detail="Entrada no encontrada") entry.is_active = not entry.is_active db.commit() return { "message": f"Entrada {'activada' if entry.is_active else 'desactivada'}", "is_active": entry.is_active }