Actualizar backend/services.py

This commit is contained in:
2026-09-11 15:37:21 -05:00
parent 2d38e7e06d
commit 6c6c563fd4

View File

@@ -1033,12 +1033,66 @@ def usuarios_actualizar_rol(user_id, rol):
sb.table("perfiles").update({"rol": rol}).eq("id", user_id).execute() sb.table("perfiles").update({"rol": rol}).eq("id", user_id).execute()
return {"status": "ok"} return {"status": "ok"}
def usuarios_actualizar_email(user_id, email):
"""Cambia el correo de un usuario existente (Supabase Auth)."""
sb = _sb()
sb.auth.admin.update_user_by_id(user_id, {"email": email, "email_confirm": True})
return {"status": "ok"}
def usuarios_actualizar_password(user_id, password):
"""Cambia la contraseña de un usuario existente (Supabase Auth)."""
sb = _sb()
sb.auth.admin.update_user_by_id(user_id, {"password": password})
return {"status": "ok"}
def usuarios_eliminar(user_id): def usuarios_eliminar(user_id):
sb = _sb() sb = _sb()
sb.auth.admin.delete_user(user_id) sb.auth.admin.delete_user(user_id)
return {"status": "ok"} return {"status": "ok"}
# ── ROLES Y PERMISOS (tabla 'permisos': rol, modulo, puede_ver) ────────────
def roles_modulos_disponibles():
"""Lista de módulos existentes (todos los que aparecen en la tabla permisos)."""
sb = _sb()
res = sb.table("permisos").select("modulo").execute()
mods = sorted({str(r.get("modulo", "")).strip() for r in (res.data or []) if r.get("modulo")})
return {"modulos": mods}
def roles_listar():
"""Devuelve todos los roles con la lista de módulos que puede ver cada uno."""
sb = _sb()
res = sb.table("permisos").select("rol,modulo,puede_ver").execute()
por_rol = {}
for r in (res.data or []):
rol = str(r.get("rol", "")).strip()
if not rol:
continue
por_rol.setdefault(rol, [])
if r.get("puede_ver"):
por_rol[rol].append(str(r.get("modulo", "")).strip())
return {"roles": [{"rol": k, "modulos": sorted(v)} for k, v in sorted(por_rol.items())]}
def rol_guardar(rol, modulos):
"""Crea o actualiza un rol: borra sus filas y reinserta una por módulo marcado."""
sb = _sb()
rol = str(rol or "").strip().upper()
if not rol:
return {"status": "error", "msg": "Nombre de rol vacío"}
sb.table("permisos").delete().eq("rol", rol).execute()
registros = [{"rol": rol, "modulo": str(m).strip(), "puede_ver": True}
for m in (modulos or []) if str(m).strip()]
if registros:
sb.table("permisos").insert(registros).execute()
return {"status": "ok", "rol": rol, "modulos": len(registros)}
def rol_eliminar(rol):
"""Borra un rol y todos sus permisos."""
sb = _sb()
sb.table("permisos").delete().eq("rol", str(rol or "").strip().upper()).execute()
return {"status": "ok"}
# ── VENDEDORES MANUALES (Comisiones, en Supabase) ────────────────────────── # ── VENDEDORES MANUALES (Comisiones, en Supabase) ──────────────────────────
# ── CONFIG MENSUAL COMISIONES (IMP_TC, META, COMISIÓN por tipo de programa) ── # ── CONFIG MENSUAL COMISIONES (IMP_TC, META, COMISIÓN por tipo de programa) ──
def comisiones_config_listar(ano, mes): def comisiones_config_listar(ano, mes):
@@ -1158,3 +1212,73 @@ def comisiones_override_restaurar(num_matricula):
cache_invalidate("ventas") cache_invalidate("ventas")
cache_invalidate("comisiones_det_todos") cache_invalidate("comisiones_det_todos")
return {"status": "ok"} return {"status": "ok"}
# ── HISTORIAL DE ESTADO DE ASESORES (Chatwoot -> historial_estado_asesor) ──
def registrar_estado_asesores():
"""Lee el estado actual de cada agente en Chatwoot (account_users) y, si cambió
respecto a lo último guardado, inserta una fila en historial_estado_asesor.
availability: 0 = ON (conectado), 1 = OFF (desconectado)."""
dm = get_dm()
conn = dm.get_pg_connection()
if conn is None:
return {"status": "error", "msg": "sin conexion postgre"}
try:
cur = conn.cursor()
cur.execute("""
SELECT u.name, u.uid, au.availability, au.updated_at
FROM account_users au
JOIN users u ON au.user_id = u.id
WHERE u.uid LIKE '%@escueladerefrigeracion.edu.pe'
""")
actuales = cur.fetchall()
cur.execute("""
SELECT DISTINCT ON (email) email, accion
FROM historial_estado_asesor
ORDER BY email, fecha_hora DESC
""")
ultimo = {r[0]: r[1] for r in cur.fetchall()}
nuevos = 0
for (name, email, avail, updated_at) in actuales:
accion = "ON" if int(avail) == 0 else "OFF"
if ultimo.get(email) == accion:
continue
cur.execute("""
INSERT INTO historial_estado_asesor (asesor, email, accion, origen, quien, fecha_hora)
VALUES (%s, %s, %s, %s, %s, %s)
""", (name, email, accion, "CHATWOOT", name, updated_at))
nuevos += 1
conn.commit()
return {"status": "ok", "nuevos": nuevos}
except Exception as e:
print(f"[historial asesores] {e}")
return {"status": "error", "msg": str(e)}
finally:
conn.close()
def historial_asesor(email, limite=100):
"""Devuelve el historial de estados de un asesor (por email), más reciente primero."""
dm = get_dm()
conn = dm.get_pg_connection()
if conn is None:
return {"historial": []}
try:
cur = conn.cursor()
cur.execute("""
SELECT accion, origen, quien, fecha_hora
FROM historial_estado_asesor
WHERE email = %s
ORDER BY fecha_hora DESC
LIMIT %s
""", (email, int(limite)))
filas = [{"accion": r[0], "origen": r[1], "quien": r[2],
"fecha_hora": r[3].isoformat() if r[3] else None} for r in cur.fetchall()]
return {"historial": filas}
except Exception as e:
print(f"[historial_asesor] {e}")
return {"historial": []}
finally:
conn.close()