import { auth } from "./lib/auth"; import { ownerFilter } from "./lib/authz"; import { getClosed, getSystemUsers } from "./lib/queries"; import { TIPOS_META, EJECUTIVOS_VENTA } from "./lib/derive"; import { getMetas, getMetaGlobal } from "./lib/metas"; import LoginPrompt from "./components/LoginPrompt"; import OwnerControl from "./components/OwnerControl"; import ErrorNotice from "./components/ErrorNotice"; import { money2 } from "./lib/constants"; export const dynamic = "force-dynamic"; function currentMonth() { const d = new Date(); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`; } export default async function Home({ searchParams }) { const session = await auth(); if (!session?.email) return ; const { owner } = await searchParams; const scope = ownerFilter(session, owner); const mes = currentMonth(); let won, lost, allUsers; try { [won, lost, allUsers] = await Promise.all([ getClosed(session.accessToken, scope, 1, mes), getClosed(session.accessToken, scope, 2, mes), getSystemUsers(session.accessToken), ]); } catch (error) { return ; } const owners = allUsers.filter((u) => EJECUTIVOS_VENTA.includes(u.name)); const sumW = won.reduce((a, o) => a + (o.actual || 0), 0); const sumWMeta = won .filter((o) => TIPOS_META.includes(o.tipo)) .reduce((a, o) => a + (o.actual || 0), 0); const arpu = won.length ? sumW / won.length : 0; const conv = won.length + lost.length ? Math.round((won.length / (won.length + lost.length)) * 100) : 0; const metas = getMetas(); const viewedEmail = scope.locked ? session.email : scope.email; const metaDen = viewedEmail ? metas[viewedEmail.toLowerCase()] || null : getMetaGlobal(); const cumpl = metaDen ? Math.round((sumWMeta / metaDen) * 100) : null; return (

Resumen — {mes}

{money2(sumW)} Ingresos reales (ganadas)
{won.length} Oportunidades ganadas
{money2(arpu)} ARPU logrado
{lost.length} Oportunidades perdidas
{conv}% % Conversión (ganadas/total)
{cumpl != null ? cumpl + "%" : "n/d"} Cumplimiento de meta{metaDen ? ` (${money2(metaDen)})` : " (sin meta asignada)"}

Cumplimiento de meta cuenta solo Venta - Cliente Nuevo, Up-Selling, Cross-Selling y Plan de Cuenta (se excluyen renovaciones y SAC).

); }