feat: roles con modulos por rol + mejoras Mi dia y descarte
- Matriz de roles (vendedor, administracion_venta, director_ventas, escrituracion, direccion_general, admin) con modulos visibles por rol; auth/me y login incluyen 'modulos'; PATCH /usuarios/:id/rol (admin). - Landing: Cobranza -> Clientes, Chat IA -> Chat Hermes, nuevo modulo Contactos (vista interna leyendo el tablero Contactos), grid filtrado por rol, rol visible en Configuracion de cuenta. - Dashboards: tab 'Tablero comercial' y tabs filtrados por rol. - Boton '<- Menu' en el header de todas las apps. - Mi dia: cada lead muestra el ultimo cambio (que, quien, cuando) desde el activity log de Monday (normalizacion de created_at 100ns/us/ms). - Descarte: el motivo se crea en el grupo de su categoria en el tablero Motivos No Compra.
This commit is contained in:
67
api-gateway/src/config/roles.test.ts
Normal file
67
api-gateway/src/config/roles.test.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { MODULOS, esRolValido, modulosDeRol } from './roles.js'
|
||||
|
||||
const ESPERADOS: Record<string, string[]> = {
|
||||
vendedor: ['mi-dia', 'alta-cliente', 'alta-afluencia', 'cotizador', 'mi-tablero', 'contactos', 'chat'],
|
||||
administracion_venta: [
|
||||
'mi-dia',
|
||||
'alta-cliente',
|
||||
'alta-afluencia',
|
||||
'cotizador',
|
||||
'mi-tablero',
|
||||
'contactos',
|
||||
'chat',
|
||||
'cobranza',
|
||||
],
|
||||
director_ventas: [
|
||||
'mi-dia',
|
||||
'alta-cliente',
|
||||
'alta-afluencia',
|
||||
'cotizador',
|
||||
'mi-tablero',
|
||||
'contactos',
|
||||
'chat',
|
||||
'cobranza',
|
||||
'tablero-comercial',
|
||||
],
|
||||
escrituracion: [
|
||||
'mi-dia',
|
||||
'alta-cliente',
|
||||
'alta-afluencia',
|
||||
'cotizador',
|
||||
'mi-tablero',
|
||||
'contactos',
|
||||
'chat',
|
||||
'cobranza',
|
||||
],
|
||||
direccion_general: ['mi-dia', 'tablero-comercial', 'cobranza', 'chat'],
|
||||
admin: [...MODULOS],
|
||||
}
|
||||
|
||||
describe('modulosDeRol', () => {
|
||||
it.each(Object.entries(ESPERADOS))('rol %s devuelve exactamente su lista', (rol, esperados) => {
|
||||
expect(modulosDeRol(rol)).toEqual(esperados)
|
||||
})
|
||||
|
||||
it('roles legacy (coordinador, corporativo) se tratan como director_ventas', () => {
|
||||
expect(modulosDeRol('coordinador')).toEqual(ESPERADOS['director_ventas'])
|
||||
expect(modulosDeRol('corporativo')).toEqual(ESPERADOS['director_ventas'])
|
||||
})
|
||||
|
||||
it('rol desconocido cae al fallback seguro (vendedor)', () => {
|
||||
expect(modulosDeRol('otro')).toEqual(ESPERADOS['vendedor'])
|
||||
expect(modulosDeRol('')).toEqual(ESPERADOS['vendedor'])
|
||||
})
|
||||
|
||||
it('tolera mayúsculas y espacios', () => {
|
||||
expect(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)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user