""" Schemas Pydantic para Alerta y Tipo de Alerta. """ from datetime import datetime from typing import List, Optional from pydantic import Field from app.schemas.base import BaseSchema, TimestampSchema # ============================================================================ # Schemas de Tipo de Alerta # ============================================================================ class TipoAlertaBase(BaseSchema): """Schema base de tipo de alerta.""" codigo: str = Field(..., min_length=2, max_length=50) nombre: str = Field(..., min_length=2, max_length=100) descripcion: Optional[str] = None severidad_default: str = Field(default="media", pattern="^(baja|media|alta|critica)$") icono: Optional[str] = Field(None, max_length=50) color: str = Field(default="#EF4444", pattern=r"^#[0-9A-Fa-f]{6}$") class TipoAlertaCreate(TipoAlertaBase): """Schema para crear tipo de alerta.""" notificar_email: bool = False notificar_push: bool = True notificar_sms: bool = False prioridad: int = Field(default=50, ge=1, le=100) class TipoAlertaUpdate(BaseSchema): """Schema para actualizar tipo de alerta.""" nombre: Optional[str] = Field(None, min_length=2, max_length=100) descripcion: Optional[str] = None severidad_default: Optional[str] = Field(None, pattern="^(baja|media|alta|critica)$") icono: Optional[str] = Field(None, max_length=50) color: Optional[str] = Field(None, pattern=r"^#[0-9A-Fa-f]{6}$") notificar_email: Optional[bool] = None notificar_push: Optional[bool] = None notificar_sms: Optional[bool] = None prioridad: Optional[int] = Field(None, ge=1, le=100) activo: Optional[bool] = None class TipoAlertaResponse(TipoAlertaBase, TimestampSchema): """Schema de respuesta de tipo de alerta.""" id: int notificar_email: bool notificar_push: bool notificar_sms: bool prioridad: int activo: bool # ============================================================================ # Schemas de Alerta # ============================================================================ class AlertaBase(BaseSchema): """Schema base de alerta.""" tipo_alerta_id: int severidad: str = Field(default="media", pattern="^(baja|media|alta|critica)$") mensaje: str = Field(..., min_length=5, max_length=500) descripcion: Optional[str] = None class AlertaCreate(AlertaBase): """Schema para crear alerta manualmente.""" vehiculo_id: Optional[int] = None conductor_id: Optional[int] = None dispositivo_id: Optional[int] = None lat: Optional[float] = Field(None, ge=-90, le=90) lng: Optional[float] = Field(None, ge=-180, le=180) direccion: Optional[str] = Field(None, max_length=255) velocidad: Optional[float] = Field(None, ge=0) valor: Optional[float] = None umbral: Optional[float] = None datos_extra: Optional[str] = None # JSON class AlertaUpdate(BaseSchema): """Schema para actualizar alerta (marcar atendida).""" atendida: Optional[bool] = None notas_atencion: Optional[str] = None class AlertaResponse(AlertaBase, TimestampSchema): """Schema de respuesta de alerta.""" id: int vehiculo_id: Optional[int] = None conductor_id: Optional[int] = None dispositivo_id: Optional[int] = None lat: Optional[float] = None lng: Optional[float] = None direccion: Optional[str] = None velocidad: Optional[float] = None valor: Optional[float] = None umbral: Optional[float] = None datos_extra: Optional[str] = None atendida: bool atendida_por_id: Optional[int] = None atendida_en: Optional[datetime] = None notas_atencion: Optional[str] = None notificacion_email_enviada: bool notificacion_push_enviada: bool notificacion_sms_enviada: bool # Calculado es_critica: bool class AlertaConTipo(AlertaResponse): """Schema de alerta con información del tipo.""" tipo_alerta: TipoAlertaResponse class AlertaConRelaciones(AlertaResponse): """Schema de alerta con todas las relaciones.""" tipo_alerta: TipoAlertaResponse vehiculo_nombre: Optional[str] = None vehiculo_placa: Optional[str] = None conductor_nombre: Optional[str] = None class AlertaResumen(BaseSchema): """Schema resumido de alerta para listas.""" id: int tipo_codigo: str tipo_nombre: str severidad: str mensaje: str vehiculo_nombre: Optional[str] = None vehiculo_placa: Optional[str] = None creado_en: datetime atendida: bool class AlertasEstadisticas(BaseSchema): """Estadísticas de alertas.""" total: int pendientes: int atendidas: int criticas: int altas: int medias: int bajas: int por_tipo: List[dict] # [{codigo, nombre, cantidad}] por_vehiculo: List[dict] # [{vehiculo_id, nombre, cantidad}] class AlertaAtenderRequest(BaseSchema): """Schema para marcar alerta como atendida.""" notas_atencion: Optional[str] = None