feat(auditoria): mostrar el nombre del usuario en lugar del id (tabla y filtro)

This commit is contained in:
2026-09-17 08:54:56 +00:00
parent 9643f866cc
commit 84582ce6a2
6 changed files with 66 additions and 19 deletions

View File

@@ -8,6 +8,9 @@ const prismaMock = vi.hoisted(() => ({
auditoriaLog: {
findMany: vi.fn(),
},
usuario: {
findMany: vi.fn(),
},
}))
vi.mock('../services/prisma.js', () => ({ prisma: prismaMock }))
@@ -29,13 +32,14 @@ beforeEach(() => {
})
describe('listarAuditoriaEndpoint (GET /api/auditoria)', () => {
it('retorna logs de auditoría para admin', async () => {
it('retorna logs de auditoría para admin (con el nombre del usuario)', async () => {
const logsFake = [{ id: 'log-1', usuarioId: 'u1', accion: 'CREAR_LEAD', entidad: 'lead', entidadId: 'l1', detalle: null, createdAt: new Date() }]
prismaMock.auditoriaLog.findMany.mockResolvedValue(logsFake)
prismaMock.usuario.findMany.mockResolvedValue([{ id: 'u1', nombre: 'Martin Zavala' }])
const { res, json } = resFake()
await listarAuditoriaEndpoint(reqFake({}, { sub: 'admin1', rol: 'admin' }), res)
expect(json).toHaveBeenCalledWith(logsFake)
expect(json).toHaveBeenCalledWith([{ ...logsFake[0], usuarioNombre: 'Martin Zavala' }])
})
it('aplica filtros de entidad y usuarioId', async () => {

View File

@@ -7,6 +7,9 @@ const prismaMock = vi.hoisted(() => ({
create: vi.fn(),
findMany: vi.fn(),
},
usuario: {
findMany: vi.fn(),
},
}))
vi.mock('./prisma.js', () => ({ prisma: prismaMock }))
@@ -48,9 +51,10 @@ describe('registrar', () => {
})
describe('buscar', () => {
it('sin filtros: retorna todos los logs ordenados por createdAt desc', async () => {
const logsFake = [{ id: 'log-1' }]
it('sin filtros: retorna los logs con el nombre del usuario resuelto', async () => {
const logsFake = [{ id: 'log-1', usuarioId: 'u1' }]
prismaMock.auditoriaLog.findMany.mockResolvedValue(logsFake)
prismaMock.usuario.findMany.mockResolvedValue([{ id: 'u1', nombre: 'Martin Zavala' }])
const resultado = await buscar({})
expect(prismaMock.auditoriaLog.findMany).toHaveBeenCalledWith({
@@ -58,11 +62,23 @@ describe('buscar', () => {
orderBy: { createdAt: 'desc' },
take: 100,
})
expect(resultado).toEqual(logsFake)
expect(resultado).toEqual([{ id: 'log-1', usuarioId: 'u1', usuarioNombre: 'Martin Zavala' }])
})
it('si el usuario ya no existe usa el id; "sistema" se muestra como Sistema', async () => {
prismaMock.auditoriaLog.findMany.mockResolvedValue([
{ id: 'log-2', usuarioId: 'fantasma' },
{ id: 'log-3', usuarioId: 'sistema' },
])
prismaMock.usuario.findMany.mockResolvedValue([])
const resultado = await buscar({})
expect(resultado.map((r) => r.usuarioNombre)).toEqual(['fantasma', 'Sistema'])
})
it('con filtros de entidad y usuarioId', async () => {
prismaMock.auditoriaLog.findMany.mockResolvedValue([])
prismaMock.usuario.findMany.mockResolvedValue([])
await buscar({ entidad: 'lead', usuarioId: 'u1' })
expect(prismaMock.auditoriaLog.findMany).toHaveBeenCalledWith({
where: { entidad: 'lead', usuarioId: 'u1' },
@@ -75,6 +91,7 @@ describe('buscar', () => {
const desde = new Date('2026-09-01')
const hasta = new Date('2026-09-07')
prismaMock.auditoriaLog.findMany.mockResolvedValue([])
prismaMock.usuario.findMany.mockResolvedValue([])
await buscar({ desde, hasta })
expect(prismaMock.auditoriaLog.findMany).toHaveBeenCalledWith({
where: { createdAt: { gte: desde, lte: hasta } },
@@ -85,6 +102,7 @@ describe('buscar', () => {
it('respeta el límite personalizado', async () => {
prismaMock.auditoriaLog.findMany.mockResolvedValue([])
prismaMock.usuario.findMany.mockResolvedValue([])
await buscar({ entidad: 'lead' }, 10)
expect(prismaMock.auditoriaLog.findMany).toHaveBeenCalledWith({
where: { entidad: 'lead' },

View File

@@ -30,6 +30,11 @@ export function registrar(
})
}
/**
* Lista registros de auditoría con el NOMBRE del usuario resuelto (la UI
* muestra nombres, no ids). Si el usuario ya no existe se devuelve el id como
* respaldo ('sistema' se muestra como 'Sistema').
*/
export async function buscar(filtros: FiltrosAuditoria, limite = 100) {
const where: Record<string, unknown> = {}
if (filtros.entidad !== undefined) where['entidad'] = filtros.entidad
@@ -41,9 +46,22 @@ export async function buscar(filtros: FiltrosAuditoria, limite = 100) {
...(filtros.hasta !== undefined ? { lte: filtros.hasta } : {}),
}
}
return prisma.auditoriaLog.findMany({
const logs = await prisma.auditoriaLog.findMany({
where,
orderBy: { createdAt: 'desc' },
take: limite,
})
const ids = [...new Set(logs.map((l) => l.usuarioId))]
const usuarios = ids.length > 0
? await prisma.usuario.findMany({ where: { id: { in: ids } }, select: { id: true, nombre: true } })
: []
const nombrePorId = new Map(usuarios.map((u) => [u.id, u.nombre]))
return logs.map((l) => ({
...l,
usuarioNombre:
nombrePorId.get(l.usuarioId) ??
(l.usuarioId === 'sistema' || l.usuarioId === 'desconocido' ? 'Sistema' : l.usuarioId),
}))
}