1. Re-captura: el dedup por telefono/email ya no considera etapas cerradas (Descartado, Perdido, Cancelo, Cancelacion Apartado). Los restos de la ultima limpieza (17 filas de APARTADO cancelados sin contraparte activa) bloqueaban a los vendedores al re-capturar; los registros activos siguen bloqueando con 409 como siempre. 2. Bitacora compartida: GET /recordatorios con leadId/clienteClave devuelve las notas de TODOS los usuarios de ese cliente (antes cada quien solo veia las suyas). Mi dia pide la bitacora con esos filtros; la lista personal sigue siendo propia. 3. Origen en oportunidades: el resumen de mi-dia ya devuelve origen y la card de cada oportunidad lo muestra (telefono · desarrollo · canal · modelo). 4. Privacidad del buscador: /leads/buscar y /buscar filtran por dueno cuando el rol es vendedor (leads por usuarioId, contactos por capturadoPorId, cotizaciones por vendedorId). Los roles de supervision siguen viendo todo. Ya no aparecen leads de otros asesores con nombre y telefono al teclear. Verificado en vivo contra el API: 10/10 comprobaciones (re-captura del telefono cancelado 201, duplicado activo 409, nota del admin visible para la vendedora, origen presente en 27/27 oportunidades, buscador del vendedor sin datos ajenos y del admin completo). 716 pruebas del API y 32 de mi-dia en verde. Los tests de roles ahora usan prisma mockeado (la BD viva cambia cuando el cliente edita permisos desde la UI).
91 lines
2.7 KiB
TypeScript
91 lines
2.7 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { MODULOS, esRolValido, modulosDeRol } from './roles.js'
|
|
|
|
// ---------- Prisma mockeado ----------
|
|
// modulosDeRol lee RolConfiguracion (BD) y cae a la MATRIZ estática cuando no
|
|
// hay fila para el rol. Los permisos reales se editan desde la UI, así que la
|
|
// BD viva cambia con el tiempo: estos tests fijan el contrato por defecto
|
|
// (sin override en BD), que es lo que recibe una instalación nueva.
|
|
const prismaMock = vi.hoisted(() => ({
|
|
rolConfiguracion: { findUnique: vi.fn() },
|
|
}))
|
|
vi.mock('../services/prisma.js', () => ({ prisma: prismaMock }))
|
|
|
|
beforeEach(() => {
|
|
prismaMock.rolConfiguracion.findUnique.mockResolvedValue(null)
|
|
})
|
|
|
|
const ESPERADOS: Record<string, string[]> = {
|
|
vendedor: ['mi-dia', 'alta-cliente', 'alta-afluencia', 'cotizador', 'mi-tablero', 'contactos', 'chat', 'clientes-maestro', 'captura', 'soporte'],
|
|
administracion_venta: [
|
|
'mi-dia',
|
|
'alta-cliente',
|
|
'alta-afluencia',
|
|
'cotizador',
|
|
'mi-tablero',
|
|
'contactos',
|
|
'chat',
|
|
'clientes-maestro',
|
|
'captura',
|
|
'soporte',
|
|
'cobranza',
|
|
],
|
|
director_ventas: [
|
|
'mi-dia',
|
|
'alta-cliente',
|
|
'alta-afluencia',
|
|
'cotizador',
|
|
'mi-tablero',
|
|
'contactos',
|
|
'chat',
|
|
'clientes-maestro',
|
|
'captura',
|
|
'soporte',
|
|
'cobranza',
|
|
'tablero-comercial',
|
|
],
|
|
escrituracion: [
|
|
'mi-dia',
|
|
'alta-cliente',
|
|
'alta-afluencia',
|
|
'cotizador',
|
|
'mi-tablero',
|
|
'contactos',
|
|
'chat',
|
|
'clientes-maestro',
|
|
'captura',
|
|
'soporte',
|
|
'cobranza',
|
|
],
|
|
direccion_general: ['mi-dia', 'tablero-comercial', 'cobranza', 'chat', 'clientes-maestro', 'captura', 'soporte'],
|
|
admin: [...MODULOS],
|
|
}
|
|
|
|
describe('modulosDeRol', () => {
|
|
it.each(Object.entries(ESPERADOS))('rol %s devuelve exactamente su lista', async (rol, esperados) => {
|
|
expect(await modulosDeRol(rol)).toEqual(esperados)
|
|
})
|
|
|
|
it('roles legacy (coordinador, corporativo) se tratan como director_ventas', async () => {
|
|
expect(await modulosDeRol('coordinador')).toEqual(ESPERADOS['director_ventas'])
|
|
expect(await modulosDeRol('corporativo')).toEqual(ESPERADOS['director_ventas'])
|
|
})
|
|
|
|
it('rol desconocido cae al fallback seguro (vendedor)', async () => {
|
|
expect(await modulosDeRol('otro')).toEqual(ESPERADOS['vendedor'])
|
|
expect(await modulosDeRol('')).toEqual(ESPERADOS['vendedor'])
|
|
})
|
|
|
|
it('tolera mayúsculas y espacios', async () => {
|
|
expect(await modulosDeRol(' Admin ')).toEqual([...MODULOS])
|
|
})
|
|
})
|
|
|
|
describe('esRolValido', () => {
|
|
it('acepta solo los roles de la matriz nueva', () => {
|
|
for (const rol of Object.keys(ESPERADOS)) expect(esRolValido(rol)).toBe(true)
|
|
expect(esRolValido('coordinador')).toBe(false)
|
|
expect(esRolValido('vendedorx')).toBe(false)
|
|
})
|
|
})
|