## Backend Changes - Add new API endpoints: combustible, pois, mantenimiento, video, configuracion - Fix vehiculos endpoint to return paginated response with items array - Add /vehiculos/all endpoint for non-paginated list - Add /geocercas/all endpoint - Add /alertas/configuracion GET/PUT endpoints - Add /viajes/activos and /viajes/iniciar endpoints - Add /reportes/stats, /reportes/templates, /reportes/preview endpoints - Add /conductores/all and /conductores/disponibles endpoints - Update router.py to include all new modules ## Frontend Changes - Fix authentication token handling (snake_case vs camelCase) - Update vehiculosApi.listAll to use /vehiculos/all - Fix FuelGauge component usage in Combustible page - Fix chart component exports (named + default exports) - Update API client for proper token refresh ## Infrastructure - Rename services from ADAN to ATLAS - Configure Cloudflare tunnel for atlas.consultoria-as.com - Update systemd service files - Configure PostgreSQL with TimescaleDB - Configure Redis, Mosquitto, Traccar, MediaMTX ## Documentation - Update installation guides - Update API reference - Rename all ADAN references to ATLAS Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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@atlas-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": '"Atlas 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",
|
|
},
|
|
]
|