import { auth } from "../lib/auth"; import { ownerFilter } from "../lib/authz"; import { getPipeline, getSystemUsers } from "../lib/queries"; import LoginPrompt from "../components/LoginPrompt"; import OwnerControl from "../components/OwnerControl"; import ErrorNotice from "../components/ErrorNotice"; import { DYN, ACT_COLOR, money, money2 } from "../lib/constants"; import { EJECUTIVOS_VENTA } from "../lib/derive"; export const dynamic = "force-dynamic"; export default async function TuberiaPage({ searchParams }) { const session = await auth(); if (!session?.email) return ; const { owner } = await searchParams; const scope = ownerFilter(session, owner); let rows, allUsers; try { [rows, allUsers] = await Promise.all([ getPipeline(session.accessToken, scope), session.isAdmin ? getSystemUsers(session.accessToken) : Promise.resolve([]), ]); } catch (error) { return ; } const owners = allUsers.filter((u) => EJECUTIVOS_VENTA.includes(u.name)); const sorted = [...rows].sort((a, b) => b.est - a.est); const totalEst = rows.reduce((a, r) => a + r.est, 0); const totalFc = rows.reduce((a, r) => a + r.fc, 0); const estancadas = rows.filter((r) => r.estanc).length; return (

Tubería Activa

{rows.length} Oportunidades activas
{money(totalEst)} Estimado total
{money(totalFc)} Forecast ponderado
{estancadas} Estancadas
{sorted.length === 0 ? (

No hay oportunidades activas para este filtro.

) : (
{!scope.locked && } {sorted.map((o) => ( {!scope.locked && } ))}
Cliente Oportunidad Seg. Plan cierre Línea de Negocio Fase actual Días en fase ActividadEjecutivoMRR est. Forecast Cierre est.
{o.cliente || "—"} {o.name} {o.segmento === "Cartera Activa" ? "CA" : "CN"} {(o.plan || "").replace(" - ", " ")} {o.linea || "—"} {o.faseActual || "—"} {o.diasEnFase == null ? "—" : o.diasEnFase} ● {o.actividad} {o.owner}{money2(o.est)} {money2(o.fc)} {o.close || "—"}
)}
); }