94 lines
2.9 KiB
TypeScript
94 lines
2.9 KiB
TypeScript
// Matriz de módulos visibles por rol (definida con el cliente, sep-2026).
|
|
// Es la fuente de verdad del ecosistema: GET /auth/me la expone como
|
|
// `modulos` y las apps filtran su navegación con ella.
|
|
|
|
export const MODULOS = [
|
|
'mi-dia',
|
|
'alta-cliente',
|
|
'alta-afluencia',
|
|
'cotizador',
|
|
'mi-tablero',
|
|
'tablero-comercial',
|
|
'cobranza',
|
|
'contactos',
|
|
'chat',
|
|
'clientes-maestro',
|
|
'captura',
|
|
'soporte',
|
|
] as const
|
|
export type Modulo = (typeof MODULOS)[number]
|
|
|
|
export const ROLES = [
|
|
'vendedor',
|
|
'administracion_venta',
|
|
'director_ventas',
|
|
'escrituracion',
|
|
'direccion_general',
|
|
'manager',
|
|
'admin',
|
|
] as const
|
|
export type Rol = (typeof ROLES)[number]
|
|
|
|
// 'captura' y 'soporte' son transversales: todos los roles los ven
|
|
const MODULOS_VENDEDOR: readonly Modulo[] = [
|
|
'mi-dia',
|
|
'alta-cliente',
|
|
'alta-afluencia',
|
|
'cotizador',
|
|
'mi-tablero',
|
|
'contactos',
|
|
'chat',
|
|
'clientes-maestro',
|
|
'captura',
|
|
'soporte',
|
|
]
|
|
|
|
export const MATRIZ: Record<Rol, readonly Modulo[]> = {
|
|
vendedor: MODULOS_VENDEDOR,
|
|
administracion_venta: [...MODULOS_VENDEDOR, 'cobranza'],
|
|
director_ventas: [...MODULOS_VENDEDOR, 'cobranza', 'tablero-comercial'],
|
|
escrituracion: [...MODULOS_VENDEDOR, 'cobranza'],
|
|
direccion_general: ['mi-dia', 'tablero-comercial', 'cobranza', 'chat', 'clientes-maestro', 'captura', 'soporte'],
|
|
// manager: mismos módulos que admin, sin poder crear usuarios ni editar permisos
|
|
manager: MODULOS,
|
|
admin: MODULOS,
|
|
}
|
|
|
|
// Roles que ya existen en la BD pero no en la matriz nueva: se homologan a
|
|
// director_ventas (su equivalente funcional en la operación actual).
|
|
const ROLES_LEGACY: Record<string, Rol> = {
|
|
coordinador: 'director_ventas',
|
|
corporativo: 'director_ventas',
|
|
}
|
|
|
|
/**
|
|
* Módulos visibles para un rol. Intenta leer de RolConfiguracion (DB) y
|
|
* hace fallback a la MATRIZ estática si no existe registro.
|
|
*
|
|
* Roles legacy ('coordinador', 'corporativo') se tratan como director_ventas;
|
|
* un rol desconocido cae a vendedor (fallback seguro: es el conjunto más chico
|
|
* de módulos operativos).
|
|
*/
|
|
export async function modulosDeRol(rol: string): Promise<Modulo[]> {
|
|
const clave = rol.trim().toLowerCase()
|
|
const rolEfectivo: Rol =
|
|
(ROLES as readonly string[]).includes(clave) ? (clave as Rol) : (ROLES_LEGACY[clave] ?? 'vendedor')
|
|
|
|
try {
|
|
// Importación dinámica para evitar circular dependency con services
|
|
const { prisma } = await import('../services/prisma.js')
|
|
const row = await prisma.rolConfiguracion.findUnique({ where: { rol: clave } })
|
|
if (row) {
|
|
return JSON.parse(row.modulos) as Modulo[]
|
|
}
|
|
} catch {
|
|
// Si la tabla aún no existe o hay error de conexión, fallback silencioso
|
|
}
|
|
return [...MATRIZ[rolEfectivo]]
|
|
}
|
|
|
|
/** ¿Es un rol válido de la matriz nueva? (para PATCH /usuarios/:id/rol) */
|
|
export function esRolValido(rol: string): boolean {
|
|
return (ROLES as readonly string[]).includes(rol)
|
|
}
|