feat: automatizaciones ronda 2 + app de dashboards /dash

- Escalado: lead asignado sin contactar >48h genera actividad URGENTE
  al coordinador (LEAD_ESCALADO_HORAS, MONDAY_COORDINADOR_USER_ID)
- Oportunidad en Aparto crea item en Apartado (fecha límite +7d);
  en Ganado crea la Venta; ambos con dedup
- GET /api/reportes/resumen: leads, funnel, unidades por desarrollo,
  cobranza y actividades en una respuesta (cache 60s)
- App dashboards (/dash): 8 KPIs + 3 gráficas Recharts, con auth
- Landing: tarjeta Tableros; docs/AUTOMATIZACIONES-MONDAY.md con las
  recetas nativas para activar en la UI
- Tests: api 158, dashboards 7, landing 5 — todo verde
This commit is contained in:
2026-08-27 09:05:09 +00:00
parent de11af985e
commit 04568a5603
34 changed files with 6279 additions and 8 deletions

View File

@@ -36,7 +36,14 @@ type PlanCompleto = PlanPago & {
notas: NotaPlan[]
}
function aDominio(plan: PlanCompleto): PlanPagoDominio {
/** Todos los planes en forma de dominio (lo que necesita el agregador de reportes) */
export async function cargarPlanesDominio(): Promise<PlanPagoDominio[]> {
const planes = await prisma.planPago.findMany({ include: includeCompleto })
return planes.map(aDominio)
}
// Exportado también para reportes.controller (agregador de cobranza)
export function aDominio(plan: PlanCompleto): PlanPagoDominio {
return {
id: plan.id,
ventaRef: plan.ventaRef,

View File

@@ -0,0 +1,12 @@
import type { Request, Response } from 'express'
import { mondayService } from '../services/monday.service.js'
import { ReportesService } from '../services/reportes.service.js'
import { cargarPlanesDominio } from './planes.controller.js'
/** Singleton del agregador (cache en memoria de 60 s; los tests instancian el suyo) */
export const reportesService = new ReportesService(mondayService, cargarPlanesDominio)
/** GET /api/reportes/resumen — todos los KPIs del dashboard en una sola respuesta */
export async function resumenReportes(_req: Request, res: Response): Promise<void> {
res.json(await reportesService.resumen())
}