Diseño de un AuditoriaController con un patrón para añadir endpoints de historial para diferentes entidades.
Implementación de la lógica de servicio y repositorio para obtener datos de las tablas _H para:
Usuarios (gral_Usuarios_H)
Pagos de Distribuidores (cue_PagosDistribuidor_H)
Notas de Crédito/Débito (cue_CreditosDebitos_H)
Entradas/Salidas de Distribuidores (dist_EntradasSalidas_H)
Entradas/Salidas de Canillitas (dist_EntradasSalidasCanillas_H)
Novedades de Canillitas (dist_dtNovedadesCanillas_H)
Ajustes Manuales de Saldo (cue_SaldoAjustesHistorial)
Tipos de Pago (cue_dtTipopago_H)
Canillitas (Maestro) (dist_dtCanillas_H)
Distribuidores (Maestro) (dist_dtDistribuidores_H)
Empresas (Maestro) (dist_dtEmpresas_H)
DTOs específicos para cada tipo de historial, incluyendo NombreUsuarioModifico.
Frontend:
Servicio auditoriaService.ts con métodos para llamar a cada endpoint de historial.
Página AuditoriaGeneralPage.tsx con:
Selector de "Tipo de Entidad a Auditar".
Filtros comunes (Fechas, Usuario Modificador, Tipo de Modificación, ID Entidad).
Un DataGrid que muestra las columnas dinámicamente según el tipo de entidad seleccionada.
Lógica para cargar los datos correspondientes.
DTOs de historial en TypeScript.
Actualizaciones en AppRoutes.tsx y MainLayout.tsx para la nueva sección de Auditoría (restringida a SuperAdmin).
This commit is contained in:
2025-06-09 19:37:07 -03:00
parent 35e24ab7d2
commit 437b1e8864
98 changed files with 3683 additions and 325 deletions

View File

@@ -0,0 +1,278 @@
using GestionIntegral.Api.Services.Usuarios;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Security.Claims; // Para ClaimTypes
using GestionIntegral.Api.Services.Contables; // Para IPagoDistribuidorService, etc.
using GestionIntegral.Api.Dtos.Contables; // Para PagoDistribuidorHistorialDto, etc.
using GestionIntegral.Api.Services.Distribucion;
using GestionIntegral.Api.Dtos.Distribucion;
using GestionIntegral.Api.Dtos.Usuarios.Auditoria;
using GestionIntegral.Api.Dtos.Auditoria;
namespace GestionIntegral.Api.Controllers
{
[Route("api/auditoria")]
[ApiController]
[Authorize]
public class AuditoriaController : ControllerBase
{
private readonly IUsuarioService _usuarioService;
private readonly IPagoDistribuidorService _pagoDistribuidorService;
private readonly INotaCreditoDebitoService _notaCreditoDebitoService;
private readonly IEntradaSalidaDistService _esDistService;
private readonly IDistribuidorService _distribuidorService;
private readonly IEntradaSalidaCanillaService _esCanillaService;
private readonly INovedadCanillaService _novedadCanillaService;
private readonly ICanillaService _canillaService;
private readonly ISaldoService _saldoService;
private readonly ITipoPagoService _tipoPagoService;
private readonly IEmpresaService _empresaService;
private readonly ILogger<AuditoriaController> _logger;
// Permiso general para ver cualquier auditoría.
// Podrías tener permisos más granulares por tipo de auditoría si es necesario.
private const string PermisoVerAuditoria = "AU_GENERAL_VIEW"; // Define este permiso
public AuditoriaController(
IUsuarioService usuarioService,
IPagoDistribuidorService pagoDistribuidorService,
INotaCreditoDebitoService notaCreditoDebitoService,
IEntradaSalidaDistService esDistService,
IDistribuidorService distribuidorService,
IEntradaSalidaCanillaService esCanillaService,
INovedadCanillaService novedadCanillaService,
ICanillaService canillaService,
ISaldoService saldoService,
ITipoPagoService tipoPagoService,
IEmpresaService empresaService,
ILogger<AuditoriaController> logger)
{
_usuarioService = usuarioService;
_pagoDistribuidorService = pagoDistribuidorService;
_notaCreditoDebitoService = notaCreditoDebitoService;
_esDistService = esDistService;
_distribuidorService = distribuidorService;
_esCanillaService = esCanillaService;
_novedadCanillaService = novedadCanillaService;
_canillaService = canillaService;
_saldoService = saldoService;
_tipoPagoService = tipoPagoService;
_empresaService = empresaService;
_logger = logger;
}
private bool TienePermiso(string codAcc) => User.IsInRole("SuperAdmin") || User.HasClaim(c => c.Type == "permission" && c.Value == codAcc);
private int? GetCurrentUserId() // Podría no ser necesario aquí si solo filtramos por usuario modificador
{
if (int.TryParse(User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub"), out int userId)) return userId;
return null;
}
[HttpGet("pagos-distribuidores")]
[ProducesResponseType(typeof(IEnumerable<PagoDistribuidorHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialPagosDistribuidor(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idPagoAfectado) // Parámetro para filtrar por un ID de pago específico
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid(); // O un permiso más específico si lo creas
try
{
var historial = await _pagoDistribuidorService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPagoAfectado);
return Ok(historial ?? Enumerable.Empty<PagoDistribuidorHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de pagos de distribuidores.");
return StatusCode(500, "Error interno al obtener historial de pagos.");
}
}
[HttpGet("notas-credito-debito")]
[ProducesResponseType(typeof(IEnumerable<NotaCreditoDebitoHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialNotasCD(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idNotaAfectada) // ID de la nota original
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _notaCreditoDebitoService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idNotaAfectada);
return Ok(historial ?? Enumerable.Empty<NotaCreditoDebitoHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de notas C/D.");
return StatusCode(500, "Error interno al obtener historial de notas C/D.");
}
}
[HttpGet("entradas-salidas-dist")]
[ProducesResponseType(typeof(IEnumerable<EntradaSalidaDistHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialEntradasSalidasDist(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idParteAfectada) // ID del movimiento original
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _esDistService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idParteAfectada);
return Ok(historial ?? Enumerable.Empty<EntradaSalidaDistHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de E/S Distribuidores.");
return StatusCode(500, "Error interno al obtener historial de E/S Distribuidores.");
}
}
[HttpGet("entradas-salidas-canilla")]
[ProducesResponseType(typeof(IEnumerable<EntradaSalidaCanillaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialEntradasSalidasCanilla(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idParteAfectada)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _esCanillaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idParteAfectada);
return Ok(historial ?? Enumerable.Empty<EntradaSalidaCanillaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de E/S Canillitas.");
return StatusCode(500, "Error interno al obtener historial de E/S Canillitas.");
}
}
[HttpGet("novedades-canilla")] // Endpoint consistente con el servicio frontend
[ProducesResponseType(typeof(IEnumerable<NovedadCanillaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialNovedadesCanilla(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idNovedadAfectada) // ID de la novedad original
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _novedadCanillaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idNovedadAfectada);
return Ok(historial ?? Enumerable.Empty<NovedadCanillaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Novedades de Canillitas.");
return StatusCode(500, "Error interno al obtener historial de Novedades de Canillitas.");
}
}
[HttpGet("ajustes-saldo")]
[ProducesResponseType(typeof(IEnumerable<SaldoAjusteHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialAjustesSaldo(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico,
[FromQuery] string? destino, [FromQuery] int? idDestino, [FromQuery] int? idEmpresa)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid(); // O un permiso más específico si lo creas
try
{
var historial = await _saldoService.ObtenerHistorialAjustesAsync(fechaDesde, fechaHasta, idUsuarioModifico, destino, idDestino, idEmpresa);
return Ok(historial ?? Enumerable.Empty<SaldoAjusteHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de ajustes de saldo.");
return StatusCode(500, "Error interno al obtener historial de ajustes de saldo.");
}
}
[HttpGet("tipos-pago")]
[ProducesResponseType(typeof(IEnumerable<TipoPagoHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialTiposPago(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idTipoPagoAfectado)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
// Asumiendo que _tipoPagoService está inyectado
var historial = await _tipoPagoService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idTipoPagoAfectado);
return Ok(historial ?? Enumerable.Empty<TipoPagoHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Tipos de Pago.");
return StatusCode(500, "Error interno al obtener historial de Tipos de Pago.");
}
}
[HttpGet("canillitas-maestro")] // Endpoint para el historial del maestro de canillitas
[ProducesResponseType(typeof(IEnumerable<CanillaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialCanillitasMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idCanillaAfectado) // ID del canillita original
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _canillaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idCanillaAfectado);
return Ok(historial ?? Enumerable.Empty<CanillaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Canillitas (Maestro).");
return StatusCode(500, "Error interno al obtener historial de Canillitas (Maestro).");
}
}
[HttpGet("distribuidores-maestro")]
[ProducesResponseType(typeof(IEnumerable<DistribuidorHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialDistribuidoresMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idDistribuidorAfectado)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _distribuidorService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idDistribuidorAfectado);
return Ok(historial ?? Enumerable.Empty<DistribuidorHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Distribuidores (Maestro).");
return StatusCode(500, "Error interno al obtener historial de Distribuidores (Maestro).");
}
}
[HttpGet("empresas-maestro")]
[ProducesResponseType(typeof(IEnumerable<EmpresaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialEmpresasMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idEmpresaAfectada)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
// Asumiendo que _empresaService está inyectado
var historial = await _empresaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idEmpresaAfectada);
return Ok(historial ?? Enumerable.Empty<EmpresaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Empresas (Maestro).");
return StatusCode(500, "Error interno al obtener historial de Empresas (Maestro).");
}
}
}
}