1. Funcionalidad Principal: Auditoría General

Se creó una nueva sección de "Auditoría" en la aplicación, diseñada para ser accedida por SuperAdmins.
Se implementó una página AuditoriaGeneralPage.tsx que actúa como un visor centralizado para el historial de cambios de múltiples entidades del sistema.
2. Backend:
Nuevo Controlador (AuditoriaController.cs): Centraliza los endpoints para obtener datos de las tablas de historial (_H).
Servicios y Repositorios Extendidos:
Se añadieron métodos GetHistorialAsync y ObtenerHistorialAsync a las capas de repositorio y servicio para cada una de las siguientes entidades, permitiendo consultar sus tablas _H con filtros:
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)
Tipos de Pago (cue_dtTipopago_H)
Canillitas (Maestro) (dist_dtCanillas_H)
Distribuidores (Maestro) (dist_dtDistribuidores_H)
Empresas (Maestro) (dist_dtEmpresas_H)
Zonas (Maestro) (dist_dtZonas_H)
Otros Destinos (Maestro) (dist_dtOtrosDestinos_H)
Publicaciones (Maestro) (dist_dtPublicaciones_H)
Secciones de Publicación (dist_dtPubliSecciones_H)
Precios de Publicación (dist_Precios_H)
Recargos por Zona (dist_RecargoZona_H)
Porcentajes Pago Distribuidores (dist_PorcPago_H)
Porcentajes/Montos Canillita (dist_PorcMonPagoCanilla_H)
Control de Devoluciones (dist_dtCtrlDevoluciones_H)
Tipos de Bobina (bob_dtBobinas_H)
Estados de Bobina (bob_dtEstadosBobinas_H)
Plantas de Impresión (bob_dtPlantas_H)
Stock de Bobinas (bob_StockBobinas_H)
Tiradas (Registro Principal) (bob_RegTiradas_H)
Secciones de Tirada (bob_RegPublicaciones_H)
Cambios de Parada de Canillitas (dist_CambiosParadasCanillas_H)
Ajustes Manuales de Saldo (cue_SaldoAjustesHistorial)
DTOs de Historial: Se crearon DTOs específicos para cada tabla de historial (ej. UsuarioHistorialDto, PagoDistribuidorHistorialDto, etc.) para transferir los datos al frontend, incluyendo el nombre del usuario que realizó la modificación.
Corrección de Lógica de Saldos: Se revisó y corrigió la lógica de afectación de saldos en los servicios PagoDistribuidorService y NotaCreditoDebitoService para asegurar que los débitos y créditos se apliquen correctamente.
3. Frontend:
Nuevo Servicio (auditoriaService.ts): Contiene métodos para llamar a cada uno de los nuevos endpoints de auditoría del backend.
Nueva Página (AuditoriaGeneralPage.tsx):
Permite al SuperAdmin seleccionar el "Tipo de Entidad" a auditar desde un dropdown.
Ofrece filtros comunes (rango de fechas, usuario modificador, tipo de acción) y filtros específicos que aparecen dinámicamente según la entidad seleccionada.
Utiliza un DataGrid de Material-UI para mostrar el historial, con columnas que se adaptan dinámicamente al tipo de entidad consultada.
Nuevos DTOs en TypeScript: Se crearon las interfaces correspondientes a los DTOs de historial del backend.
Gestión de Permisos:
La sección de Auditoría en MainLayout.tsx y su ruta en AppRoutes.tsx están protegidas para ser visibles y accesibles solo por SuperAdmins.
Se añadió un permiso de ejemplo AU_GENERAL_VIEW para ser usado si se decide extender el acceso en el futuro.
Corrección de Errores Menores: Se solucionó el problema del "parpadeo" del selector de fecha en GestionarNovedadesCanillaPage al adoptar un patrón de carga de datos más controlado, similar a otras páginas funcionales.
This commit is contained in:
2025-06-12 19:36:21 -03:00
parent 437b1e8864
commit b04a3b99bf
145 changed files with 5033 additions and 1070 deletions

View File

@@ -7,11 +7,13 @@ 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;
using GestionIntegral.Api.Dtos.Zonas;
using GestionIntegral.Api.Dtos.Distribucion;
using GestionIntegral.Api.Services.Impresion;
using GestionIntegral.Api.Dtos.Impresion;
using GestionIntegral.Api.Dtos.Usuarios;
namespace GestionIntegral.Api.Controllers
@@ -32,6 +34,23 @@ namespace GestionIntegral.Api.Controllers
private readonly ISaldoService _saldoService;
private readonly ITipoPagoService _tipoPagoService;
private readonly IEmpresaService _empresaService;
private readonly IZonaService _zonaService;
private readonly IOtroDestinoService _otroDestinoService;
private readonly IPublicacionService _publicacionService;
private readonly IPubliSeccionService _publiSeccionService;
private readonly IPrecioService _precioService;
private readonly IRecargoZonaService _recargoZonaService;
private readonly IPorcPagoService _porcPagoService;
private readonly IPorcMonCanillaService _porcMonCanillaService;
private readonly IControlDevolucionesService _controlDevolucionesService;
private readonly ITipoBobinaService _tipoBobinaService;
private readonly IEstadoBobinaService _estadoBobinaService;
private readonly IPlantaService _plantaService;
private readonly IStockBobinaService _stockBobinaService;
private readonly ITiradaService _tiradaService;
private readonly IPerfilService _perfilService;
private readonly IPermisoService _permisoService;
private readonly ICambioParadaService _cambioParadaService;
private readonly ILogger<AuditoriaController> _logger;
// Permiso general para ver cualquier auditoría.
@@ -50,6 +69,23 @@ namespace GestionIntegral.Api.Controllers
ISaldoService saldoService,
ITipoPagoService tipoPagoService,
IEmpresaService empresaService,
IZonaService zonaService,
IOtroDestinoService otroDestinoService,
IPublicacionService publicacionService,
IPubliSeccionService publiSeccionService,
IPrecioService precioService,
IRecargoZonaService recargoZonaService,
IPorcPagoService porcPagoService,
IPorcMonCanillaService porcMonCanillaService,
IControlDevolucionesService controlDevolucionesService,
ITipoBobinaService tipoBobinaService,
IEstadoBobinaService estadoBobinaService,
IPlantaService plantaService,
IStockBobinaService stockBobinaService,
ITiradaService tiradaService,
IPerfilService perfilService,
IPermisoService permisoService,
ICambioParadaService cambioParadaService,
ILogger<AuditoriaController> logger)
{
_usuarioService = usuarioService;
@@ -63,6 +99,23 @@ namespace GestionIntegral.Api.Controllers
_saldoService = saldoService;
_tipoPagoService = tipoPagoService;
_empresaService = empresaService;
_zonaService = zonaService;
_otroDestinoService = otroDestinoService;
_publicacionService = publicacionService;
_publiSeccionService = publiSeccionService;
_precioService = precioService;
_recargoZonaService = recargoZonaService;
_porcPagoService = porcPagoService;
_porcMonCanillaService = porcMonCanillaService;
_controlDevolucionesService = controlDevolucionesService;
_tipoBobinaService = tipoBobinaService;
_estadoBobinaService = estadoBobinaService;
_plantaService = plantaService;
_stockBobinaService = stockBobinaService;
_tiradaService = tiradaService;
_perfilService = perfilService;
_cambioParadaService = cambioParadaService;
_permisoService = permisoService;
_logger = logger;
}
@@ -274,5 +327,389 @@ namespace GestionIntegral.Api.Controllers
return StatusCode(500, "Error interno al obtener historial de Empresas (Maestro).");
}
}
[HttpGet("zonas-maestro")]
[ProducesResponseType(typeof(IEnumerable<ZonaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialZonasMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idZonaAfectada)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
// Asumiendo que _zonaService está inyectado
var historial = await _zonaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idZonaAfectada);
return Ok(historial ?? Enumerable.Empty<ZonaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Zonas (Maestro).");
return StatusCode(500, "Error interno al obtener historial de Zonas (Maestro).");
}
}
[HttpGet("otros-destinos-maestro")]
[ProducesResponseType(typeof(IEnumerable<OtroDestinoHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialOtrosDestinosMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idOtroDestinoAfectado)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _otroDestinoService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idOtroDestinoAfectado);
return Ok(historial ?? Enumerable.Empty<OtroDestinoHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Otros Destinos (Maestro).");
return StatusCode(500, "Error interno al obtener historial de Otros Destinos (Maestro).");
}
}
[HttpGet("publicaciones-maestro")]
[ProducesResponseType(typeof(IEnumerable<PublicacionHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialPublicacionesMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idPublicacionAfectada)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _publicacionService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPublicacionAfectada);
return Ok(historial ?? Enumerable.Empty<PublicacionHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Publicaciones (Maestro).");
return StatusCode(500, "Error interno al obtener historial de Publicaciones (Maestro).");
}
}
[HttpGet("publi-secciones-maestro")]
[ProducesResponseType(typeof(IEnumerable<PubliSeccionHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialPubliSeccionesMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idSeccionAfectada, [FromQuery] int? idPublicacionAfectada) // Nuevos filtros
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _publiSeccionService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idSeccionAfectada, idPublicacionAfectada);
return Ok(historial ?? Enumerable.Empty<PubliSeccionHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Secciones de Publicación.");
return StatusCode(500, "Error interno al obtener historial de Secciones de Publicación.");
}
}
[HttpGet("precios-publicacion-maestro")]
[ProducesResponseType(typeof(IEnumerable<PrecioHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialPreciosMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idPrecioAfectado, [FromQuery] int? idPublicacionAfectada)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _precioService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPrecioAfectado, idPublicacionAfectada);
return Ok(historial ?? Enumerable.Empty<PrecioHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Precios de Publicación.");
return StatusCode(500, "Error interno al obtener historial de Precios de Publicación.");
}
}
[HttpGet("recargos-zona-maestro")]
[ProducesResponseType(typeof(IEnumerable<RecargoZonaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialRecargosZonaMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idRecargoAfectado, [FromQuery] int? idPublicacionAfectada, [FromQuery] int? idZonaAfectada)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _recargoZonaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idRecargoAfectado, idPublicacionAfectada, idZonaAfectada);
return Ok(historial ?? Enumerable.Empty<RecargoZonaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Recargos por Zona.");
return StatusCode(500, "Error interno al obtener historial de Recargos por Zona.");
}
}
[HttpGet("porc-pago-dist-maestro")]
[ProducesResponseType(typeof(IEnumerable<PorcPagoHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialPorcPagoDistMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idPorcentajeAfectado, [FromQuery] int? idPublicacionAfectada, [FromQuery] int? idDistribuidorAfectado)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _porcPagoService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPorcentajeAfectado, idPublicacionAfectada, idDistribuidorAfectado);
return Ok(historial ?? Enumerable.Empty<PorcPagoHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Porcentajes de Pago (Dist).");
return StatusCode(500, "Error interno al obtener historial de Porcentajes de Pago (Dist).");
}
}
[HttpGet("porc-mon-canilla-maestro")]
[ProducesResponseType(typeof(IEnumerable<PorcMonCanillaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialPorcMonCanillaMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idPorcMonAfectado, [FromQuery] int? idPublicacionAfectada, [FromQuery] int? idCanillaAfectado)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _porcMonCanillaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPorcMonAfectado, idPublicacionAfectada, idCanillaAfectado);
return Ok(historial ?? Enumerable.Empty<PorcMonCanillaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Porc/Mon Canillita.");
return StatusCode(500, "Error interno al obtener historial de Porc/Mon Canillita.");
}
}
[HttpGet("control-devoluciones-maestro")]
[ProducesResponseType(typeof(IEnumerable<ControlDevolucionesHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialControlDevolucionesMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idControlAfectado, [FromQuery] int? idEmpresaAfectada, [FromQuery] DateTime? fechaAfectada)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _controlDevolucionesService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idControlAfectado, idEmpresaAfectada, fechaAfectada);
return Ok(historial ?? Enumerable.Empty<ControlDevolucionesHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Control de Devoluciones.");
return StatusCode(500, "Error interno al obtener historial de Control de Devoluciones.");
}
}
[HttpGet("tipos-bobina-maestro")]
[ProducesResponseType(typeof(IEnumerable<TipoBobinaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialTiposBobinaMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idTipoBobinaAfectado)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _tipoBobinaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idTipoBobinaAfectado);
return Ok(historial ?? Enumerable.Empty<TipoBobinaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Tipos de Bobina.");
return StatusCode(500, "Error interno al obtener historial de Tipos de Bobina.");
}
}
[HttpGet("estados-bobina-maestro")]
[ProducesResponseType(typeof(IEnumerable<EstadoBobinaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialEstadosBobinaMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idEstadoBobinaAfectado)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _estadoBobinaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idEstadoBobinaAfectado);
return Ok(historial ?? Enumerable.Empty<EstadoBobinaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Estados de Bobina.");
return StatusCode(500, "Error interno al obtener historial de Estados de Bobina.");
}
}
[HttpGet("plantas-impresion-maestro")]
[ProducesResponseType(typeof(IEnumerable<PlantaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialPlantasMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idPlantaAfectada)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _plantaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPlantaAfectada);
return Ok(historial ?? Enumerable.Empty<PlantaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Plantas de Impresión.");
return StatusCode(500, "Error interno al obtener historial de Plantas de Impresión.");
}
}
[HttpGet("stock-bobinas-maestro")]
[ProducesResponseType(typeof(IEnumerable<StockBobinaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialStockBobinasMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idBobinaAfectada, [FromQuery] int? idTipoBobinaFiltro,
[FromQuery] int? idPlantaFiltro, [FromQuery] int? idEstadoBobinaFiltro)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _stockBobinaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idBobinaAfectada, idTipoBobinaFiltro, idPlantaFiltro, idEstadoBobinaFiltro);
return Ok(historial ?? Enumerable.Empty<StockBobinaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Stock de Bobinas.");
return StatusCode(500, "Error interno al obtener historial de Stock de Bobinas.");
}
}
[HttpGet("reg-tiradas-maestro")]
[ProducesResponseType(typeof(IEnumerable<RegTiradaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialRegTiradasMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idRegistroAfectado, [FromQuery] int? idPublicacionFiltro,
[FromQuery] int? idPlantaFiltro, [FromQuery] DateTime? fechaTiradaFiltro)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _tiradaService.ObtenerRegTiradasHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idRegistroAfectado, idPublicacionFiltro, idPlantaFiltro, fechaTiradaFiltro);
return Ok(historial ?? Enumerable.Empty<RegTiradaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Registro de Tiradas.");
return StatusCode(500, "Error interno al obtener historial de Registro de Tiradas.");
}
}
[HttpGet("reg-secciones-tirada-maestro")]
[ProducesResponseType(typeof(IEnumerable<RegSeccionTiradaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialRegSeccionesTiradaMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idTiradaAfectada, [FromQuery] int? idPublicacionFiltro,
[FromQuery] int? idSeccionFiltro, [FromQuery] int? idPlantaFiltro, [FromQuery] DateTime? fechaTiradaFiltro)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _tiradaService.ObtenerRegSeccionesTiradaHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idTiradaAfectada, idPublicacionFiltro, idSeccionFiltro, idPlantaFiltro, fechaTiradaFiltro);
return Ok(historial ?? Enumerable.Empty<RegSeccionTiradaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Secciones de Tirada.");
return StatusCode(500, "Error interno al obtener historial de Secciones de Tirada.");
}
}
[HttpGet("perfiles-maestro")]
[ProducesResponseType(typeof(IEnumerable<PerfilHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialPerfilesMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idPerfilAfectado)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _perfilService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPerfilAfectado);
return Ok(historial ?? Enumerable.Empty<PerfilHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Perfiles (Maestro).");
return StatusCode(500, "Error interno al obtener historial de Perfiles (Maestro).");
}
}
[HttpGet("permisos-maestro")]
[ProducesResponseType(typeof(IEnumerable<PermisoHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialPermisosMaestro(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idPermisoAfectado)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _permisoService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPermisoAfectado);
return Ok(historial ?? Enumerable.Empty<PermisoHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Permisos (Maestro).");
return StatusCode(500, "Error interno al obtener historial de Permisos (Maestro).");
}
}
[HttpGet("permisos-perfiles-historial")]
[ProducesResponseType(typeof(IEnumerable<PermisosPerfilesHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialPermisosPerfiles(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idPerfilAfectado, [FromQuery] int? idPermisoAfectado)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _perfilService.ObtenerPermisosAsignadosHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPerfilAfectado, idPermisoAfectado);
return Ok(historial ?? Enumerable.Empty<PermisosPerfilesHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Asignación de Permisos.");
return StatusCode(500, "Error interno al obtener historial de Asignación de Permisos.");
}
}
[HttpGet("cambios-parada-canilla")]
[ProducesResponseType(typeof(IEnumerable<CambioParadaHistorialDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetHistorialCambiosParada(
[FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
[FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
[FromQuery] int? idCanillaAfectado)
{
if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
try
{
var historial = await _cambioParadaService.ObtenerCambiosParadaHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idCanillaAfectado);
return Ok(historial ?? Enumerable.Empty<CambioParadaHistorialDto>());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error obteniendo historial de Cambios de Parada.");
return StatusCode(500, "Error interno al obtener historial de Cambios de Parada.");
}
}
}
}

View File

@@ -124,11 +124,15 @@ namespace GestionIntegral.Api.Controllers.Impresion
public async Task<IActionResult> CambiarEstadoBobina(int idBobina, [FromBody] CambiarEstadoBobinaDto cambiarEstadoDto)
{
if (!TienePermiso(PermisoCambiarEstado)) return Forbid();
if (!ModelState.IsValid) return BadRequest(ModelState);
if (!ModelState.IsValid) return BadRequest(ModelState); // Validaciones de DTO (Required, Range, etc.)
var userId = GetCurrentUserId();
if (userId == null) return Unauthorized();
// Validación adicional en el controlador para el caso "En Uso"
// La validación de que IdPublicacion/IdSeccion son requeridos para estado "En Uso"
// ahora está más robusta en el servicio. Se puede quitar del controlador
// si se prefiere que el servicio sea la única fuente de verdad para esa lógica.
// Si la mantenés acá, es una validación temprana.
/*
if (cambiarEstadoDto.NuevoEstadoId == 2) // Asumiendo 2 = En Uso
{
if (!cambiarEstadoDto.IdPublicacion.HasValue || cambiarEstadoDto.IdPublicacion.Value <= 0)
@@ -136,12 +140,13 @@ namespace GestionIntegral.Api.Controllers.Impresion
if (!cambiarEstadoDto.IdSeccion.HasValue || cambiarEstadoDto.IdSeccion.Value <=0)
return BadRequest(new { message = "Se requiere IdSeccion para el estado 'En Uso'."});
}
*/
var (exito, error) = await _stockBobinaService.CambiarEstadoBobinaAsync(idBobina, cambiarEstadoDto, userId.Value);
if (!exito)
{
if (error == "Bobina no encontrada.") return NotFound(new { message = error });
// Otros errores específicos del servicio (ej. flujo de estado no permitido) vienen como BadRequest
return BadRequest(new { message = error });
}
return NoContent();