""" 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"" 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", }, ]