Files
FRASA-CAS/api-gateway/src/services/mora.service.test.ts
Consult AS Technology db18685872 feat(ux): 17 mejoras de experiencia de usuario
Backend (10 endpoints nuevos):
- Recordatorios personales (CRUD + tabla RecordatorioVendedor)
- Lead scoring 0-100 (etapa+recencia+datos)
- Dashboard mora (pagos vencidos, monto, días atraso)
- Timeline de pagos (pagado/vence/futuro)
- Perfil completo contacto (pagos+cotizaciones+docs+score)
- Exportar contactos a CSV

Frontend Mi día:
- Resumen matutino (saludo+KPIs)
- Historial visual lead (timeline)
- Score badge 0-100 (verde/amarillo/rojo)
- Vista kanban (drag & drop)

Frontend Cobranza:
- Dashboard mora (tabla+WhatsApp)
- Timeline pagos visual (nodos coloreados)

Frontend Alta Clientes:
- Checklist documentos visual
- Foto cliente (cámara)

Frontend Landing:
- Perfil contacto completo
- Exportar contactos CSV

Frontend Mi día (extras):
- Comparativa mensual
- KPIs dashboard (leads hoy, ventas, conversión)

806 tests, 5 apps construidas.
2026-09-08 07:42:54 +00:00

160 lines
4.3 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
const prismaMock = vi.hoisted(() => ({
planPago: {
findMany: vi.fn(),
},
}))
vi.mock('../services/prisma.js', () => ({ prisma: prismaMock }))
import { resumenMora } from './mora.service.js'
beforeEach(() => {
vi.clearAllMocks()
})
describe('resumenMora', () => {
it('devuelve 0 cuando no hay pagos vencidos', async () => {
prismaMock.planPago.findMany.mockResolvedValue([
{
clienteNombre: 'Juan',
unidadCodigo: 'U-101',
proyecto: 'SENDA',
clienteTelefono: '4771234567',
id: 'p1',
pagos: [
{ numPago: 1, fechaVencimiento: new Date('2026-12-01'), monto: 10000, montoPagado: 0 },
],
},
])
const result = await resumenMora()
expect(result.clientesConMora).toBe(0)
expect(result.montoTotalVencido).toBe(0)
expect(result.clientes).toHaveLength(0)
})
it('detecta pagos vencidos con monto restante', async () => {
prismaMock.planPago.findMany.mockResolvedValue([
{
clienteNombre: 'Juan Pérez',
unidadCodigo: 'SENDA-101',
proyecto: 'SENDA',
clienteTelefono: '4771234567',
id: 'plan1',
pagos: [
{
numPago: 1,
fechaVencimiento: new Date('2026-08-01'), // vencido
monto: 5000,
montoPagado: 2000, // parcial: restante = 3000
},
{
numPago: 2,
fechaVencimiento: new Date('2026-09-01'), // vencido
monto: 5000,
montoPagado: 0, // sin pagar
},
],
},
])
const result = await resumenMora()
expect(result.clientesConMora).toBe(2)
expect(result.montoTotalVencido).toBe(8000)
expect(result.diasPromedioAtraso).toBeGreaterThan(0)
expect(result.clientes[0]?.clienteNombre).toBe('Juan Pérez')
})
it('ordena por días de atraso (mayor primero)', async () => {
prismaMock.planPago.findMany.mockResolvedValue([
{
clienteNombre: 'Corto',
unidadCodigo: 'U-1',
proyecto: 'A',
clienteTelefono: null,
id: 'p1',
pagos: [
{ numPago: 1, fechaVencimiento: new Date('2026-08-25'), monto: 1000, montoPagado: 0 },
],
},
{
clienteNombre: 'Largo',
unidadCodigo: 'U-2',
proyecto: 'B',
clienteTelefono: null,
id: 'p2',
pagos: [
{ numPago: 1, fechaVencimiento: new Date('2026-07-01'), monto: 2000, montoPagado: 0 },
],
},
])
const result = await resumenMora()
expect(result.clientes[0]?.clienteNombre).toBe('Largo')
expect(result.clientes[0]?.diasAtraso).toBeGreaterThan(result.clientes[1]!.diasAtraso)
})
it('ignora pagos totalmente cubiertos', async () => {
prismaMock.planPago.findMany.mockResolvedValue([
{
clienteNombre: 'Cliente',
unidadCodigo: 'U-1',
proyecto: 'A',
clienteTelefono: null,
id: 'p1',
pagos: [
{ numPago: 1, fechaVencimiento: new Date('2026-08-01'), monto: 5000, montoPagado: 5000 },
],
},
])
const result = await resumenMora()
expect(result.clientesConMora).toBe(0)
})
it('ignora pagos cuyo vencimiento es futuro', async () => {
prismaMock.planPago.findMany.mockResolvedValue([
{
clienteNombre: 'Cliente',
unidadCodigo: 'U-1',
proyecto: 'A',
clienteTelefono: null,
id: 'p1',
pagos: [
{ numPago: 1, fechaVencimiento: new Date('2026-12-01'), monto: 5000, montoPagado: 0 },
],
},
])
const result = await resumenMora()
expect(result.clientesConMora).toBe(0)
})
it('excluye planes cancelados', async () => {
prismaMock.planPago.findMany.mockResolvedValue([
{
clienteNombre: 'Cancelado',
unidadCodigo: 'U-1',
proyecto: 'A',
clienteTelefono: null,
id: 'p1',
pagos: [
{ numPago: 1, fechaVencimiento: new Date('2026-08-01'), monto: 5000, montoPagado: 0 },
],
status: 'CANCELADO',
},
])
// The where clause filters out CANCELADO before they reach the loop
prismaMock.planPago.findMany.mockResolvedValue([])
const result = await resumenMora()
expect(result.clientesConMora).toBe(0)
})
})