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:
160
backend/app/schemas/geocerca.py
Normal file
160
backend/app/schemas/geocerca.py
Normal file
@@ -0,0 +1,160 @@
|
||||
"""
|
||||
Schemas Pydantic para Geocerca.
|
||||
"""
|
||||
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import Field, field_validator
|
||||
|
||||
from app.schemas.base import BaseSchema, TimestampSchema
|
||||
|
||||
|
||||
class GeocercaBase(BaseSchema):
|
||||
"""Schema base de geocerca."""
|
||||
|
||||
nombre: str = Field(..., min_length=2, max_length=100)
|
||||
descripcion: Optional[str] = None
|
||||
tipo: str = Field(default="circular", pattern="^(circular|poligono)$")
|
||||
color: str = Field(default="#3B82F6", pattern=r"^#[0-9A-Fa-f]{6}$")
|
||||
opacidad: float = Field(default=0.3, ge=0, le=1)
|
||||
color_borde: str = Field(default="#1D4ED8", pattern=r"^#[0-9A-Fa-f]{6}$")
|
||||
categoria: Optional[str] = Field(None, max_length=50)
|
||||
|
||||
|
||||
class GeocercaCircularCreate(GeocercaBase):
|
||||
"""Schema para crear geocerca circular."""
|
||||
|
||||
tipo: str = "circular"
|
||||
centro_lat: float = Field(..., ge=-90, le=90)
|
||||
centro_lng: float = Field(..., ge=-180, le=180)
|
||||
radio_metros: float = Field(..., gt=0, le=100000)
|
||||
|
||||
# Configuración de alertas
|
||||
alerta_entrada: bool = True
|
||||
alerta_salida: bool = True
|
||||
velocidad_maxima: Optional[float] = Field(None, ge=0)
|
||||
|
||||
# Horario (opcional, JSON)
|
||||
horario_json: Optional[str] = None
|
||||
|
||||
# Vehículos asignados (opcional, vacío = todos)
|
||||
vehiculos_ids: Optional[List[int]] = None
|
||||
|
||||
|
||||
class GeocercaPoligonoCreate(GeocercaBase):
|
||||
"""Schema para crear geocerca poligonal."""
|
||||
|
||||
tipo: str = "poligono"
|
||||
coordenadas: List[List[float]] # [[lat, lng], [lat, lng], ...]
|
||||
|
||||
# Configuración de alertas
|
||||
alerta_entrada: bool = True
|
||||
alerta_salida: bool = True
|
||||
velocidad_maxima: Optional[float] = Field(None, ge=0)
|
||||
|
||||
# Horario (opcional, JSON)
|
||||
horario_json: Optional[str] = None
|
||||
|
||||
# Vehículos asignados (opcional, vacío = todos)
|
||||
vehiculos_ids: Optional[List[int]] = None
|
||||
|
||||
@field_validator("coordenadas")
|
||||
@classmethod
|
||||
def validate_coordenadas(cls, v: List[List[float]]) -> List[List[float]]:
|
||||
if len(v) < 3:
|
||||
raise ValueError("Un polígono debe tener al menos 3 puntos")
|
||||
for coord in v:
|
||||
if len(coord) != 2:
|
||||
raise ValueError("Cada coordenada debe tener [lat, lng]")
|
||||
if not (-90 <= coord[0] <= 90):
|
||||
raise ValueError("Latitud debe estar entre -90 y 90")
|
||||
if not (-180 <= coord[1] <= 180):
|
||||
raise ValueError("Longitud debe estar entre -180 y 180")
|
||||
return v
|
||||
|
||||
|
||||
class GeocercaUpdate(BaseSchema):
|
||||
"""Schema para actualizar geocerca."""
|
||||
|
||||
nombre: Optional[str] = Field(None, min_length=2, max_length=100)
|
||||
descripcion: Optional[str] = None
|
||||
color: Optional[str] = Field(None, pattern=r"^#[0-9A-Fa-f]{6}$")
|
||||
opacidad: Optional[float] = Field(None, ge=0, le=1)
|
||||
color_borde: Optional[str] = Field(None, pattern=r"^#[0-9A-Fa-f]{6}$")
|
||||
categoria: Optional[str] = Field(None, max_length=50)
|
||||
|
||||
# Para circular
|
||||
centro_lat: Optional[float] = Field(None, ge=-90, le=90)
|
||||
centro_lng: Optional[float] = Field(None, ge=-180, le=180)
|
||||
radio_metros: Optional[float] = Field(None, gt=0, le=100000)
|
||||
|
||||
# Para polígono
|
||||
coordenadas: Optional[List[List[float]]] = None
|
||||
|
||||
# Configuración
|
||||
alerta_entrada: Optional[bool] = None
|
||||
alerta_salida: Optional[bool] = None
|
||||
velocidad_maxima: Optional[float] = Field(None, ge=0)
|
||||
horario_json: Optional[str] = None
|
||||
activa: Optional[bool] = None
|
||||
|
||||
|
||||
class GeocercaResponse(GeocercaBase, TimestampSchema):
|
||||
"""Schema de respuesta de geocerca."""
|
||||
|
||||
id: int
|
||||
centro_lat: Optional[float] = None
|
||||
centro_lng: Optional[float] = None
|
||||
radio_metros: Optional[float] = None
|
||||
coordenadas_json: Optional[str] = None
|
||||
alerta_entrada: bool
|
||||
alerta_salida: bool
|
||||
velocidad_maxima: Optional[float] = None
|
||||
horario_json: Optional[str] = None
|
||||
activa: bool
|
||||
|
||||
# Calculado
|
||||
aplica_todos_vehiculos: bool
|
||||
|
||||
|
||||
class GeocercaConVehiculos(GeocercaResponse):
|
||||
"""Schema de geocerca con lista de vehículos asignados."""
|
||||
|
||||
vehiculos_asignados: List["VehiculoResumen"] = []
|
||||
|
||||
|
||||
class GeocercaGeoJSON(BaseSchema):
|
||||
"""Schema de geocerca en formato GeoJSON."""
|
||||
|
||||
type: str = "Feature"
|
||||
geometry: dict
|
||||
properties: dict
|
||||
|
||||
|
||||
class AsignarVehiculosRequest(BaseSchema):
|
||||
"""Schema para asignar vehículos a una geocerca."""
|
||||
|
||||
vehiculos_ids: List[int]
|
||||
reemplazar: bool = False # True = reemplaza todos, False = agrega a existentes
|
||||
|
||||
|
||||
class VerificarPuntoRequest(BaseSchema):
|
||||
"""Schema para verificar si un punto está dentro de una geocerca."""
|
||||
|
||||
lat: float = Field(..., ge=-90, le=90)
|
||||
lng: float = Field(..., ge=-180, le=180)
|
||||
|
||||
|
||||
class VerificarPuntoResponse(BaseSchema):
|
||||
"""Schema de respuesta de verificación de punto."""
|
||||
|
||||
dentro: bool
|
||||
geocerca_id: int
|
||||
geocerca_nombre: str
|
||||
distancia_metros: Optional[float] = None # Distancia al borde si está fuera
|
||||
|
||||
|
||||
# Import fix
|
||||
from app.schemas.vehiculo import VehiculoResumen # noqa: E402
|
||||
|
||||
GeocercaConVehiculos.model_rebuild()
|
||||
Reference in New Issue
Block a user