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

@@ -2,6 +2,7 @@
using GestionIntegral.Api.Data;
using GestionIntegral.Api.Data.Repositories.Contables;
using GestionIntegral.Api.Data.Repositories.Distribucion;
using GestionIntegral.Api.Dtos.Auditoria;
using GestionIntegral.Api.Dtos.Distribucion;
using GestionIntegral.Api.Models.Distribucion;
using Microsoft.Extensions.Logging;
@@ -85,7 +86,7 @@ namespace GestionIntegral.Api.Services.Distribucion
var data = await _distribuidorRepository.GetByIdAsync(id);
// MapToDto ahora devuelve DistribuidorDto?
return MapToDto(data);
}
}
public async Task<DistribuidorLookupDto?> ObtenerLookupPorIdAsync(int id)
{
@@ -104,9 +105,17 @@ namespace GestionIntegral.Api.Services.Distribucion
var nuevoDistribuidor = new Distribuidor
{
Nombre = createDto.Nombre, Contacto = createDto.Contacto, NroDoc = createDto.NroDoc, IdZona = createDto.IdZona,
Calle = createDto.Calle, Numero = createDto.Numero, Piso = createDto.Piso, Depto = createDto.Depto,
Telefono = createDto.Telefono, Email = createDto.Email, Localidad = createDto.Localidad
Nombre = createDto.Nombre,
Contacto = createDto.Contacto,
NroDoc = createDto.NroDoc,
IdZona = createDto.IdZona,
Calle = createDto.Calle,
Numero = createDto.Numero,
Piso = createDto.Piso,
Depto = createDto.Depto,
Telefono = createDto.Telefono,
Email = createDto.Email,
Localidad = createDto.Localidad
};
using var connection = _connectionFactory.CreateConnection();
@@ -136,7 +145,7 @@ namespace GestionIntegral.Api.Services.Distribucion
}
catch (Exception ex)
{
try { transaction.Rollback(); } catch {}
try { transaction.Rollback(); } catch { }
_logger.LogError(ex, "Error CrearAsync Distribuidor: {Nombre}", createDto.Nombre);
return (null, $"Error interno al crear el distribuidor: {ex.Message}");
}
@@ -173,10 +182,10 @@ namespace GestionIntegral.Api.Services.Distribucion
_logger.LogInformation("Distribuidor ID {IdDistribuidor} actualizado por Usuario ID {IdUsuario}.", id, idUsuario);
return (true, null);
}
catch (KeyNotFoundException) { try { transaction.Rollback(); } catch {} return (false, "Distribuidor no encontrado."); }
catch (KeyNotFoundException) { try { transaction.Rollback(); } catch { } return (false, "Distribuidor no encontrado."); }
catch (Exception ex)
{
try { transaction.Rollback(); } catch {}
try { transaction.Rollback(); } catch { }
_logger.LogError(ex, "Error ActualizarAsync Distribuidor ID: {IdDistribuidor}", id);
return (false, $"Error interno: {ex.Message}");
}
@@ -200,18 +209,47 @@ namespace GestionIntegral.Api.Services.Distribucion
// if (!saldosEliminados) throw new DataException("Error al eliminar saldos del distribuidor.");
var eliminado = await _distribuidorRepository.DeleteAsync(id, idUsuario, transaction);
if (!eliminado) throw new DataException("Error al eliminar.");
if (!eliminado) throw new DataException("Error al eliminar.");
transaction.Commit();
_logger.LogInformation("Distribuidor ID {IdDistribuidor} eliminado por Usuario ID {IdUsuario}.", id, idUsuario);
return (true, null);
}
catch (KeyNotFoundException) { try { transaction.Rollback(); } catch {} return (false, "Distribuidor no encontrado."); }
catch (KeyNotFoundException) { try { transaction.Rollback(); } catch { } return (false, "Distribuidor no encontrado."); }
catch (Exception ex)
{
try { transaction.Rollback(); } catch {}
try { transaction.Rollback(); } catch { }
_logger.LogError(ex, "Error EliminarAsync Distribuidor ID: {IdDistribuidor}", id);
return (false, $"Error interno: {ex.Message}");
}
}
public async Task<IEnumerable<DistribuidorHistorialDto>> ObtenerHistorialAsync(
DateTime? fechaDesde, DateTime? fechaHasta,
int? idUsuarioModifico, string? tipoModificacion,
int? idDistribuidorAfectado)
{
var historialData = await _distribuidorRepository.GetHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idDistribuidorAfectado);
// Si necesitas NombreZona, harías el JOIN en el repo o una llamada aquí a _zonaRepository
return historialData.Select(h => new DistribuidorHistorialDto
{
Id_Distribuidor = h.Historial.Id_Distribuidor,
Nombre = h.Historial.Nombre,
Contacto = h.Historial.Contacto,
NroDoc = h.Historial.NroDoc,
Id_Zona = h.Historial.Id_Zona,
Calle = h.Historial.Calle,
Numero = h.Historial.Numero,
Piso = h.Historial.Piso,
Depto = h.Historial.Depto,
Telefono = h.Historial.Telefono,
Email = h.Historial.Email,
Localidad = h.Historial.Localidad,
Id_Usuario = h.Historial.Id_Usuario,
NombreUsuarioModifico = h.NombreUsuarioModifico,
FechaMod = h.Historial.FechaMod,
TipoMod = h.Historial.TipoMod
}).ToList();
}
}
}