""" Schemas Pydantic para Mantenimiento y Tipo de Mantenimiento. """ from datetime import date, datetime from typing import List, Optional from pydantic import Field from app.schemas.base import BaseSchema, TimestampSchema # ============================================================================ # Schemas de Tipo de Mantenimiento # ============================================================================ class TipoMantenimientoBase(BaseSchema): """Schema base de tipo de mantenimiento.""" nombre: str = Field(..., min_length=2, max_length=100) descripcion: Optional[str] = None codigo: Optional[str] = Field(None, max_length=20) categoria: str = Field(default="preventivo", pattern="^(preventivo|correctivo|predictivo)$") class TipoMantenimientoCreate(TipoMantenimientoBase): """Schema para crear tipo de mantenimiento.""" intervalo_km: Optional[int] = Field(None, gt=0) intervalo_dias: Optional[int] = Field(None, gt=0) costo_estimado: Optional[float] = Field(None, ge=0) duracion_estimada_horas: Optional[float] = Field(None, ge=0) prioridad: int = Field(default=50, ge=1, le=100) requiere_inmovilizacion: bool = False class TipoMantenimientoUpdate(BaseSchema): """Schema para actualizar tipo de mantenimiento.""" nombre: Optional[str] = Field(None, min_length=2, max_length=100) descripcion: Optional[str] = None codigo: Optional[str] = Field(None, max_length=20) categoria: Optional[str] = Field(None, pattern="^(preventivo|correctivo|predictivo)$") intervalo_km: Optional[int] = Field(None, gt=0) intervalo_dias: Optional[int] = Field(None, gt=0) costo_estimado: Optional[float] = Field(None, ge=0) duracion_estimada_horas: Optional[float] = Field(None, ge=0) prioridad: Optional[int] = Field(None, ge=1, le=100) requiere_inmovilizacion: Optional[bool] = None activo: Optional[bool] = None class TipoMantenimientoResponse(TipoMantenimientoBase, TimestampSchema): """Schema de respuesta de tipo de mantenimiento.""" id: int intervalo_km: Optional[int] = None intervalo_dias: Optional[int] = None costo_estimado: Optional[float] = None duracion_estimada_horas: Optional[float] = None prioridad: int requiere_inmovilizacion: bool activo: bool # ============================================================================ # Schemas de Mantenimiento # ============================================================================ class MantenimientoBase(BaseSchema): """Schema base de mantenimiento.""" vehiculo_id: int tipo_mantenimiento_id: int fecha_programada: date class MantenimientoCreate(MantenimientoBase): """Schema para crear/programar mantenimiento.""" odometro_programado: Optional[float] = Field(None, ge=0) costo_estimado: Optional[float] = Field(None, ge=0) proveedor: Optional[str] = Field(None, max_length=100) proveedor_direccion: Optional[str] = Field(None, max_length=255) proveedor_telefono: Optional[str] = Field(None, max_length=20) descripcion: Optional[str] = None notas: Optional[str] = None class MantenimientoUpdate(BaseSchema): """Schema para actualizar mantenimiento.""" estado: Optional[str] = Field(None, pattern="^(programado|en_proceso|completado|cancelado|vencido)$") fecha_programada: Optional[date] = None fecha_realizada: Optional[date] = None odometro_programado: Optional[float] = Field(None, ge=0) odometro_realizado: Optional[float] = Field(None, ge=0) costo_estimado: Optional[float] = Field(None, ge=0) costo_real: Optional[float] = Field(None, ge=0) costo_mano_obra: Optional[float] = Field(None, ge=0) costo_refacciones: Optional[float] = Field(None, ge=0) proveedor: Optional[str] = Field(None, max_length=100) proveedor_direccion: Optional[str] = Field(None, max_length=255) proveedor_telefono: Optional[str] = Field(None, max_length=20) numero_factura: Optional[str] = Field(None, max_length=50) numero_orden: Optional[str] = Field(None, max_length=50) descripcion: Optional[str] = None trabajos_realizados: Optional[str] = None refacciones_usadas: Optional[str] = None tecnico: Optional[str] = Field(None, max_length=100) proximo_km: Optional[float] = Field(None, ge=0) proxima_fecha: Optional[date] = None notas: Optional[str] = None class MantenimientoResponse(MantenimientoBase, TimestampSchema): """Schema de respuesta de mantenimiento.""" id: int estado: str fecha_realizada: Optional[date] = None odometro_programado: Optional[float] = None odometro_realizado: Optional[float] = None costo_estimado: Optional[float] = None costo_real: Optional[float] = None costo_mano_obra: Optional[float] = None costo_refacciones: Optional[float] = None proveedor: Optional[str] = None proveedor_direccion: Optional[str] = None proveedor_telefono: Optional[str] = None numero_factura: Optional[str] = None numero_orden: Optional[str] = None descripcion: Optional[str] = None trabajos_realizados: Optional[str] = None refacciones_usadas: Optional[str] = None tecnico: Optional[str] = None proximo_km: Optional[float] = None proxima_fecha: Optional[date] = None archivos_adjuntos: Optional[str] = None recordatorio_enviado: bool notas: Optional[str] = None # Calculados esta_vencido: bool dias_para_vencimiento: Optional[int] = None class MantenimientoConRelaciones(MantenimientoResponse): """Schema con información del vehículo y tipo.""" vehiculo_nombre: Optional[str] = None vehiculo_placa: Optional[str] = None tipo_mantenimiento_nombre: Optional[str] = None tipo_mantenimiento_categoria: Optional[str] = None class MantenimientoResumen(BaseSchema): """Schema resumido de mantenimiento.""" id: int vehiculo_id: int vehiculo_nombre: str vehiculo_placa: str tipo_mantenimiento_nombre: str estado: str fecha_programada: date dias_para_vencimiento: Optional[int] = None esta_vencido: bool class ProximosMantenimientos(BaseSchema): """Schema para próximos mantenimientos.""" vencidos: List[MantenimientoResumen] proximos_7_dias: List[MantenimientoResumen] proximos_30_dias: List[MantenimientoResumen] class CompletarMantenimientoRequest(BaseSchema): """Schema para completar un mantenimiento.""" fecha_realizada: date odometro_realizado: Optional[float] = Field(None, ge=0) costo_real: Optional[float] = Field(None, ge=0) costo_mano_obra: Optional[float] = Field(None, ge=0) costo_refacciones: Optional[float] = Field(None, ge=0) trabajos_realizados: Optional[str] = None refacciones_usadas: Optional[str] = None tecnico: Optional[str] = Field(None, max_length=100) numero_factura: Optional[str] = Field(None, max_length=50) notas: Optional[str] = None # Próximo mantenimiento programar_siguiente: bool = False proximo_km: Optional[float] = Field(None, ge=0) proxima_fecha: Optional[date] = None