import { prisma } from './prisma.js' /** * Dashboard de mora: clientes con pagos vencidos (fechaVencimiento < hoy * y montoPagado < monto). Devuelve resumen + detalle por cliente. */ export interface ClienteMora { clienteNombre: string unidadCodigo: string proyecto: string pagoVencido: number monto: number diasAtraso: number telefono: string | null planId: string } export interface ResumenMora { clientesConMora: number montoTotalVencido: number diasPromedioAtraso: number clientes: ClienteMora[] } /** * Calcula días naturales de diferencia entre hoy y la fecha de vencimiento. */ function diasDesde(fechaVencimiento: Date, hoy: Date): number { const hv = new Date(hoy.getFullYear(), hoy.getMonth(), hoy.getDate()) const fv = new Date( fechaVencimiento.getFullYear(), fechaVencimiento.getMonth(), fechaVencimiento.getDate(), ) return Math.max(0, Math.round((hv.getTime() - fv.getTime()) / 86_400_000)) } /** * Resumen de mora: todos los pagos vencidos de planes activos. */ export async function resumenMora(): Promise { const hoy = new Date() const inicioHoy = new Date(hoy.getFullYear(), hoy.getMonth(), hoy.getDate()) const planes = await prisma.planPago.findMany({ where: { status: { not: 'CANCELADO' } }, include: { pagos: true }, }) const clientes: ClienteMora[] = [] for (const plan of planes) { for (const pago of plan.pagos) { const restante = pago.monto - pago.montoPagado if (restante <= 0) continue // ya pagado const fv = pago.fechaVencimiento if (fv >= inicioHoy) continue // aún no vence const dias = diasDesde(fv, hoy) clientes.push({ clienteNombre: plan.clienteNombre, unidadCodigo: plan.unidadCodigo, proyecto: plan.proyecto, pagoVencido: pago.numPago, monto: Math.round(restante * 100) / 100, diasAtraso: dias, telefono: plan.clienteTelefono, planId: plan.id, }) } } // Ordenar por días de atraso (mayor primero) clientes.sort((a, b) => b.diasAtraso - a.diasAtraso) const montoTotalVencido = Math.round(clientes.reduce((acc, c) => acc + c.monto, 0) * 100) / 100 const diasPromedioAtraso = clientes.length > 0 ? Math.round(clientes.reduce((acc, c) => acc + c.diasAtraso, 0) / clientes.length) : 0 return { clientesConMora: clientes.length, montoTotalVencido, diasPromedioAtraso, clientes, } }