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.
250 lines
7.2 KiB
Python
250 lines
7.2 KiB
Python
"""
|
|
Modelo de Configuración para almacenar settings del sistema.
|
|
"""
|
|
|
|
from sqlalchemy import String, Text
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from app.core.database import Base
|
|
from app.models.base import TimestampMixin
|
|
|
|
|
|
class Configuracion(Base, TimestampMixin):
|
|
"""
|
|
Modelo para almacenar configuraciones del sistema.
|
|
|
|
Permite guardar configuraciones dinámicas sin necesidad
|
|
de reiniciar la aplicación.
|
|
"""
|
|
|
|
__tablename__ = "configuraciones"
|
|
|
|
clave: Mapped[str] = mapped_column(String(100), primary_key=True)
|
|
valor_json: Mapped[str] = mapped_column(Text, nullable=False) # Valor en formato JSON
|
|
categoria: Mapped[str] = mapped_column(
|
|
String(50),
|
|
default="general",
|
|
nullable=False,
|
|
index=True,
|
|
)
|
|
descripcion: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
|
|
# Tipo de dato para validación
|
|
tipo_dato: Mapped[str] = mapped_column(
|
|
String(20),
|
|
default="string",
|
|
nullable=False,
|
|
) # string, number, boolean, json, array
|
|
|
|
# Si la configuración es sensible (no mostrar en logs)
|
|
sensible: Mapped[bool] = mapped_column(default=False, nullable=False)
|
|
|
|
# Si puede ser modificada desde la UI
|
|
editable: Mapped[bool] = mapped_column(default=True, nullable=False)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Configuracion(clave='{self.clave}', categoria='{self.categoria}')>"
|
|
|
|
def get_value(self):
|
|
"""Parsea y retorna el valor según su tipo."""
|
|
import json
|
|
if self.tipo_dato == "string":
|
|
return json.loads(self.valor_json)
|
|
elif self.tipo_dato == "number":
|
|
return float(json.loads(self.valor_json))
|
|
elif self.tipo_dato == "boolean":
|
|
return bool(json.loads(self.valor_json))
|
|
else:
|
|
return json.loads(self.valor_json)
|
|
|
|
|
|
# Configuraciones por defecto del sistema
|
|
CONFIGURACIONES_DEFAULT = [
|
|
# Alertas
|
|
{
|
|
"clave": "alerta_velocidad_maxima",
|
|
"valor_json": "120",
|
|
"categoria": "alertas",
|
|
"descripcion": "Velocidad máxima permitida (km/h) antes de generar alerta",
|
|
"tipo_dato": "number",
|
|
},
|
|
{
|
|
"clave": "alerta_parada_minutos",
|
|
"valor_json": "15",
|
|
"categoria": "alertas",
|
|
"descripcion": "Minutos de parada para considerar como parada prolongada",
|
|
"tipo_dato": "number",
|
|
},
|
|
{
|
|
"clave": "alerta_bateria_minima",
|
|
"valor_json": "20",
|
|
"categoria": "alertas",
|
|
"descripcion": "Porcentaje mínimo de batería antes de alertar",
|
|
"tipo_dato": "number",
|
|
},
|
|
{
|
|
"clave": "alerta_sin_señal_minutos",
|
|
"valor_json": "30",
|
|
"categoria": "alertas",
|
|
"descripcion": "Minutos sin señal para generar alerta",
|
|
"tipo_dato": "number",
|
|
},
|
|
{
|
|
"clave": "alerta_motor_encendido_minutos",
|
|
"valor_json": "10",
|
|
"categoria": "alertas",
|
|
"descripcion": "Minutos con motor encendido sin movimiento para alertar",
|
|
"tipo_dato": "number",
|
|
},
|
|
|
|
# Viajes
|
|
{
|
|
"clave": "viaje_velocidad_minima",
|
|
"valor_json": "5",
|
|
"categoria": "viajes",
|
|
"descripcion": "Velocidad mínima (km/h) para considerar movimiento",
|
|
"tipo_dato": "number",
|
|
},
|
|
{
|
|
"clave": "viaje_parada_minutos",
|
|
"valor_json": "5",
|
|
"categoria": "viajes",
|
|
"descripcion": "Minutos de parada para finalizar un viaje automáticamente",
|
|
"tipo_dato": "number",
|
|
},
|
|
|
|
# Paradas
|
|
{
|
|
"clave": "parada_duracion_minima",
|
|
"valor_json": "120",
|
|
"categoria": "paradas",
|
|
"descripcion": "Segundos mínimos para registrar una parada",
|
|
"tipo_dato": "number",
|
|
},
|
|
|
|
# Combustible
|
|
{
|
|
"clave": "combustible_precio_gasolina",
|
|
"valor_json": "22.50",
|
|
"categoria": "combustible",
|
|
"descripcion": "Precio por defecto del litro de gasolina",
|
|
"tipo_dato": "number",
|
|
},
|
|
{
|
|
"clave": "combustible_precio_diesel",
|
|
"valor_json": "23.80",
|
|
"categoria": "combustible",
|
|
"descripcion": "Precio por defecto del litro de diesel",
|
|
"tipo_dato": "number",
|
|
},
|
|
|
|
# Mantenimiento
|
|
{
|
|
"clave": "mantenimiento_recordatorio_dias",
|
|
"valor_json": "7",
|
|
"categoria": "mantenimiento",
|
|
"descripcion": "Días de anticipación para recordatorio de mantenimiento",
|
|
"tipo_dato": "number",
|
|
},
|
|
{
|
|
"clave": "mantenimiento_recordatorio_km",
|
|
"valor_json": "500",
|
|
"categoria": "mantenimiento",
|
|
"descripcion": "Km de anticipación para recordatorio de mantenimiento",
|
|
"tipo_dato": "number",
|
|
},
|
|
|
|
# Notificaciones
|
|
{
|
|
"clave": "notificaciones_email_habilitado",
|
|
"valor_json": "true",
|
|
"categoria": "notificaciones",
|
|
"descripcion": "Habilitar notificaciones por email",
|
|
"tipo_dato": "boolean",
|
|
},
|
|
{
|
|
"clave": "notificaciones_push_habilitado",
|
|
"valor_json": "true",
|
|
"categoria": "notificaciones",
|
|
"descripcion": "Habilitar notificaciones push",
|
|
"tipo_dato": "boolean",
|
|
},
|
|
{
|
|
"clave": "notificaciones_destinatarios",
|
|
"valor_json": '["admin@adan-fleet.com"]',
|
|
"categoria": "notificaciones",
|
|
"descripcion": "Lista de emails para notificaciones críticas",
|
|
"tipo_dato": "array",
|
|
"sensible": True,
|
|
},
|
|
|
|
# Mapas
|
|
{
|
|
"clave": "mapa_centro_lat",
|
|
"valor_json": "19.4326",
|
|
"categoria": "mapas",
|
|
"descripcion": "Latitud del centro del mapa por defecto",
|
|
"tipo_dato": "number",
|
|
},
|
|
{
|
|
"clave": "mapa_centro_lng",
|
|
"valor_json": "-99.1332",
|
|
"categoria": "mapas",
|
|
"descripcion": "Longitud del centro del mapa por defecto",
|
|
"tipo_dato": "number",
|
|
},
|
|
{
|
|
"clave": "mapa_zoom_default",
|
|
"valor_json": "12",
|
|
"categoria": "mapas",
|
|
"descripcion": "Nivel de zoom inicial del mapa",
|
|
"tipo_dato": "number",
|
|
},
|
|
|
|
# Retención de datos
|
|
{
|
|
"clave": "retencion_ubicaciones_dias",
|
|
"valor_json": "365",
|
|
"categoria": "retencion",
|
|
"descripcion": "Días de retención de ubicaciones GPS",
|
|
"tipo_dato": "number",
|
|
},
|
|
{
|
|
"clave": "retencion_alertas_dias",
|
|
"valor_json": "180",
|
|
"categoria": "retencion",
|
|
"descripcion": "Días de retención de alertas",
|
|
"tipo_dato": "number",
|
|
},
|
|
{
|
|
"clave": "retencion_videos_dias",
|
|
"valor_json": "30",
|
|
"categoria": "retencion",
|
|
"descripcion": "Días de retención de videos",
|
|
"tipo_dato": "number",
|
|
},
|
|
|
|
# General
|
|
{
|
|
"clave": "empresa_nombre",
|
|
"valor_json": '"Adan Fleet"',
|
|
"categoria": "general",
|
|
"descripcion": "Nombre de la empresa",
|
|
"tipo_dato": "string",
|
|
},
|
|
{
|
|
"clave": "empresa_logo_url",
|
|
"valor_json": '""',
|
|
"categoria": "general",
|
|
"descripcion": "URL del logo de la empresa",
|
|
"tipo_dato": "string",
|
|
},
|
|
{
|
|
"clave": "zona_horaria",
|
|
"valor_json": '"America/Mexico_City"',
|
|
"categoria": "general",
|
|
"descripcion": "Zona horaria del sistema",
|
|
"tipo_dato": "string",
|
|
},
|
|
]
|