FlotillasGPS - Sistema completo de monitoreo de flotillas GPS

Sistema completo para monitoreo y gestion de flotas de vehiculos con:
- Backend FastAPI con PostgreSQL/TimescaleDB
- Frontend React con TypeScript y TailwindCSS
- App movil React Native con Expo
- Soporte para dispositivos GPS, Meshtastic y celulares
- Video streaming en vivo con MediaMTX
- Geocercas, alertas, viajes y reportes
- Autenticacion JWT y WebSockets en tiempo real

Documentacion completa y guias de usuario incluidas.
This commit is contained in:
FlotillasGPS Developer
2026-01-21 08:18:00 +00:00
commit 51d78bacf4
248 changed files with 50171 additions and 0 deletions

View File

@@ -0,0 +1,176 @@
"""
Schemas Pydantic para Vehículo.
"""
from datetime import datetime
from typing import List, Optional
from pydantic import Field
from app.schemas.base import BaseSchema, TimestampSchema
class VehiculoBase(BaseSchema):
"""Schema base de vehículo."""
nombre: str = Field(..., min_length=2, max_length=100)
placa: str = Field(..., min_length=2, max_length=20)
vin: Optional[str] = Field(None, max_length=17)
numero_economico: Optional[str] = Field(None, max_length=50)
marca: Optional[str] = Field(None, max_length=50)
modelo: Optional[str] = Field(None, max_length=50)
año: Optional[int] = Field(None, ge=1900, le=2100)
color: Optional[str] = Field(None, max_length=30)
tipo: Optional[str] = Field(None, max_length=50)
capacidad_carga_kg: Optional[float] = Field(None, ge=0)
capacidad_pasajeros: Optional[int] = Field(None, ge=0)
capacidad_combustible_litros: Optional[float] = Field(None, ge=0)
tipo_combustible: Optional[str] = Field(None, max_length=20)
odometro_inicial: float = Field(default=0.0, ge=0)
class VehiculoCreate(VehiculoBase):
"""Schema para crear vehículo."""
conductor_id: Optional[int] = None
grupo_id: Optional[int] = None
icono: Optional[str] = Field(None, max_length=50)
color_marcador: str = Field(default="#3B82F6", pattern=r"^#[0-9A-Fa-f]{6}$")
class VehiculoUpdate(BaseSchema):
"""Schema para actualizar vehículo."""
nombre: Optional[str] = Field(None, min_length=2, max_length=100)
placa: Optional[str] = Field(None, min_length=2, max_length=20)
vin: Optional[str] = Field(None, max_length=17)
numero_economico: Optional[str] = Field(None, max_length=50)
marca: Optional[str] = Field(None, max_length=50)
modelo: Optional[str] = Field(None, max_length=50)
año: Optional[int] = Field(None, ge=1900, le=2100)
color: Optional[str] = Field(None, max_length=30)
tipo: Optional[str] = Field(None, max_length=50)
capacidad_carga_kg: Optional[float] = Field(None, ge=0)
capacidad_pasajeros: Optional[int] = Field(None, ge=0)
capacidad_combustible_litros: Optional[float] = Field(None, ge=0)
tipo_combustible: Optional[str] = Field(None, max_length=20)
conductor_id: Optional[int] = None
grupo_id: Optional[int] = None
icono: Optional[str] = Field(None, max_length=50)
color_marcador: Optional[str] = Field(None, pattern=r"^#[0-9A-Fa-f]{6}$")
activo: Optional[bool] = None
en_servicio: Optional[bool] = None
notas: Optional[str] = None
class VehiculoResponse(VehiculoBase, TimestampSchema):
"""Schema de respuesta de vehículo."""
id: int
odometro_actual: float
icono: Optional[str] = None
color_marcador: str
conductor_id: Optional[int] = None
grupo_id: Optional[int] = None
activo: bool
en_servicio: bool
notas: Optional[str] = None
# Última ubicación
ultima_lat: Optional[float] = None
ultima_lng: Optional[float] = None
ultima_velocidad: Optional[float] = None
ultimo_rumbo: Optional[float] = None
ultima_ubicacion_tiempo: Optional[datetime] = None
motor_encendido: Optional[bool] = None
# Calculados
distancia_recorrida: float
class VehiculoResumen(BaseSchema):
"""Schema resumido de vehículo para listas."""
id: int
nombre: str
placa: str
marca: Optional[str] = None
modelo: Optional[str] = None
color_marcador: str
activo: bool
en_servicio: bool
# Estado actual
ultima_lat: Optional[float] = None
ultima_lng: Optional[float] = None
ultima_velocidad: Optional[float] = None
motor_encendido: Optional[bool] = None
ultima_ubicacion_tiempo: Optional[datetime] = None
class VehiculoConRelaciones(VehiculoResponse):
"""Schema de vehículo con relaciones expandidas."""
conductor: Optional["ConductorResumen"] = None
grupo: Optional["GrupoVehiculosResponse"] = None
dispositivos: List["DispositivoResumen"] = []
class VehiculoUbicacionActual(BaseSchema):
"""Schema para ubicación actual de vehículo (dashboard/mapa)."""
id: int
nombre: str
placa: str
color_marcador: str
icono: Optional[str] = None
# Ubicación
lat: Optional[float] = None
lng: Optional[float] = None
velocidad: Optional[float] = None
rumbo: Optional[float] = None
tiempo: Optional[datetime] = None
# Estado
motor_encendido: Optional[bool] = None
en_movimiento: bool = False
conductor_nombre: Optional[str] = None
class VehiculoEstadisticas(BaseSchema):
"""Estadísticas de un vehículo."""
vehiculo_id: int
nombre: str
placa: str
# Distancia
distancia_hoy_km: float
distancia_semana_km: float
distancia_mes_km: float
distancia_total_km: float
# Tiempo
tiempo_movimiento_hoy_min: int
tiempo_parado_hoy_min: int
# Combustible
consumo_mes_litros: Optional[float] = None
rendimiento_km_litro: Optional[float] = None
# Alertas
alertas_activas: int
alertas_mes: int
# Mantenimiento
proximo_mantenimiento: Optional[datetime] = None
mantenimientos_vencidos: int
# Import circular fix
from app.schemas.conductor import ConductorResumen # noqa: E402
from app.schemas.grupo_vehiculos import GrupoVehiculosResponse # noqa: E402
from app.schemas.dispositivo import DispositivoResumen # noqa: E402
VehiculoConRelaciones.model_rebuild()