feat(config): modulo Configuraciones admin + permisos por rol
- Tablas ConfiguracionSistema (7 configs) + RolConfiguracion (6 roles) - Endpoints: config/sistema GET/PATCH, config/roles GET/PATCH, config/usuarios GET/PATCH, config/reset-roles POST, config/acciones GET - modulosDeRol() async con fallback a MATRIZ estatica - auth/me devuelve acciones[] segun rol del usuario - saludMonday.estaDisponible() lee modo_local_forzado de DB (cache 30s) - Landing: vista Configuraciones con 4 tabs (Modo, Roles, Usuarios, Sistema) - Mi-dia: boton Descartar se deshabilita si !descartar_lead - 630 API tests + 24 landing tests + 20 mi-dia tests verdes Seed: npm run seed:config
This commit is contained in:
@@ -35,7 +35,7 @@ const MODULOS_VENDEDOR: readonly Modulo[] = [
|
||||
'chat',
|
||||
]
|
||||
|
||||
const MATRIZ: Record<Rol, readonly Modulo[]> = {
|
||||
export const MATRIZ: Record<Rol, readonly Modulo[]> = {
|
||||
vendedor: MODULOS_VENDEDOR,
|
||||
administracion_venta: [...MODULOS_VENDEDOR, 'cobranza'],
|
||||
director_ventas: [...MODULOS_VENDEDOR, 'cobranza', 'tablero-comercial'],
|
||||
@@ -52,14 +52,28 @@ const ROLES_LEGACY: Record<string, Rol> = {
|
||||
}
|
||||
|
||||
/**
|
||||
* Módulos visibles para un rol. 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).
|
||||
* 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 function modulosDeRol(rol: string): Modulo[] {
|
||||
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]]
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user