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

@@ -16,6 +16,9 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
Task<NotaCreditoDebito?> CreateAsync(NotaCreditoDebito nuevaNota, int idUsuario, IDbTransaction transaction);
Task<bool> UpdateAsync(NotaCreditoDebito notaAActualizar, int idUsuario, IDbTransaction transaction);
Task<bool> DeleteAsync(int idNota, int idUsuario, IDbTransaction transaction);
// No se suele validar unicidad por referencia, ya que podría repetirse.
Task<IEnumerable<(NotaCreditoDebitoHistorico Historial, string NombreUsuarioModifico)>> GetHistorialAsync(
DateTime? fechaDesde, DateTime? fechaHasta,
int? idUsuarioModifico, string? tipoModificacion,
int? idNotaOriginal); // Para filtrar por una nota específica
}
}

View File

@@ -17,5 +17,9 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
Task<bool> UpdateAsync(PagoDistribuidor pagoAActualizar, int idUsuario, IDbTransaction transaction);
Task<bool> DeleteAsync(int idPago, int idUsuario, IDbTransaction transaction);
Task<bool> ExistsByReciboAndTipoMovimientoAsync(int recibo, string tipoMovimiento, int? excludeIdPago = null);
Task<IEnumerable<(PagoDistribuidorHistorico Historial, string NombreUsuarioModifico)>> GetHistorialAsync(
DateTime? fechaDesde, DateTime? fechaHasta,
int? idUsuarioModifico, string? tipoModificacion,
int? idPagoOriginal); // Para filtrar por un pago específico
}
}

View File

@@ -24,5 +24,9 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
Task<Saldo?> GetSaldoAsync(string destino, int idDestino, int idEmpresa, IDbTransaction? transaction = null);
// Para registrar el historial de ajuste
Task CreateSaldoAjusteHistorialAsync(SaldoAjusteHistorial historialEntry, IDbTransaction transaction);
Task<IEnumerable<(SaldoAjusteHistorial Historial, string NombreUsuarioModifico)>> GetHistorialAjustesAsync(
DateTime? fechaDesde, DateTime? fechaHasta,
int? idUsuarioModifico,
string? destino, int? idDestino, int? idEmpresa);
}
}

View File

@@ -13,5 +13,9 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
Task<bool> DeleteAsync(int id, int idUsuario); // Devuelve true si fue exitoso
Task<bool> ExistsByNameAsync(string nombre, int? excludeId = null);
Task<bool> IsInUseAsync(int id);
Task<IEnumerable<(TipoPagoHistorico Historial, string NombreUsuarioModifico)>> GetHistorialAsync(
DateTime? fechaDesde, DateTime? fechaHasta,
int? idUsuarioModifico, string? tipoModificacion,
int? idTipoPagoOriginal);
}
}

View File

@@ -41,7 +41,7 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
if (idDestino.HasValue) { sqlBuilder.Append(" AND Id_Destino = @IdDestinoParam"); parameters.Add("IdDestinoParam", idDestino.Value); }
if (idEmpresa.HasValue) { sqlBuilder.Append(" AND Id_Empresa = @IdEmpresaParam"); parameters.Add("IdEmpresaParam", idEmpresa.Value); }
if (!string.IsNullOrWhiteSpace(tipoNota)) { sqlBuilder.Append(" AND Tipo = @TipoParam"); parameters.Add("TipoParam", tipoNota); }
sqlBuilder.Append(" ORDER BY Fecha DESC, Id_Nota DESC;");
try
@@ -86,11 +86,20 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
var inserted = await transaction.Connection!.QuerySingleAsync<NotaCreditoDebito>(sqlInsert, nuevaNota, transaction);
if (inserted == null || inserted.IdNota == 0) throw new DataException("Error al crear la nota o ID no generado.");
await transaction.Connection!.ExecuteAsync(sqlHistorico, new {
IdNotaHist = inserted.IdNota, DestinoHist = inserted.Destino, IdDestinoHist = inserted.IdDestino,
ReferenciaHist = inserted.Referencia, TipoHist = inserted.Tipo, FechaHist = inserted.Fecha, MontoHist = inserted.Monto,
ObservacionesHist = inserted.Observaciones, IdEmpresaHist = inserted.IdEmpresa,
IdUsuarioHist = idUsuario, FechaModHist = DateTime.Now, TipoModHist = "Creada"
await transaction.Connection!.ExecuteAsync(sqlHistorico, new
{
IdNotaHist = inserted.IdNota,
DestinoHist = inserted.Destino,
IdDestinoHist = inserted.IdDestino,
ReferenciaHist = inserted.Referencia,
TipoHist = inserted.Tipo,
FechaHist = inserted.Fecha,
MontoHist = inserted.Monto,
ObservacionesHist = inserted.Observaciones,
IdEmpresaHist = inserted.IdEmpresa,
IdUsuarioHist = idUsuario,
FechaModHist = DateTime.Now,
TipoModHist = "Creada"
}, transaction);
return inserted;
}
@@ -107,23 +116,33 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
UPDATE dbo.cue_CreditosDebitos SET
Monto = @Monto, Observaciones = @Observaciones
WHERE Id_Nota = @IdNota;";
const string sqlHistorico = @"
const string sqlHistorico = @"
INSERT INTO dbo.cue_CreditosDebitos_H
(Id_Nota, Destino, Id_Destino, Referencia, Tipo, Fecha, Monto, Observaciones, Id_Empresa, Id_Usuario, FechaMod, TipoMod)
VALUES (@IdNotaHist, @DestinoHist, @IdDestinoHist, @ReferenciaHist, @TipoHist, @FechaHist, @MontoHist, @ObservacionesHist, @IdEmpresaHist, @IdUsuarioHist, @FechaModHist, @TipoModHist);";
await transaction.Connection!.ExecuteAsync(sqlHistorico, new {
IdNotaHist = actual.IdNota, DestinoHist = actual.Destino, IdDestinoHist = actual.IdDestino, ReferenciaHist = actual.Referencia,
TipoHist = actual.Tipo, FechaHist = actual.Fecha, MontoHist = actual.Monto, // Valor ANTERIOR
ObservacionesHist = actual.Observaciones, IdEmpresaHist = actual.IdEmpresa, // Valor ANTERIOR
IdUsuarioHist = idUsuario, FechaModHist = DateTime.Now, TipoModHist = "Actualizada"
await transaction.Connection!.ExecuteAsync(sqlHistorico, new
{
IdNotaHist = actual.IdNota,
DestinoHist = actual.Destino,
IdDestinoHist = actual.IdDestino,
ReferenciaHist = actual.Referencia,
TipoHist = actual.Tipo,
FechaHist = actual.Fecha,
MontoHist = actual.Monto, // Valor ANTERIOR
ObservacionesHist = actual.Observaciones,
IdEmpresaHist = actual.IdEmpresa, // Valor ANTERIOR
IdUsuarioHist = idUsuario,
FechaModHist = DateTime.Now,
TipoModHist = "Actualizada"
}, transaction);
var rowsAffected = await transaction.Connection!.ExecuteAsync(sqlUpdate, new {
var rowsAffected = await transaction.Connection!.ExecuteAsync(sqlUpdate, new
{
notaAActualizar.Monto,
notaAActualizar.Observaciones,
notaAActualizar.IdNota
} , transaction);
}, transaction);
return rowsAffected == 1;
}
@@ -140,14 +159,67 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
(Id_Nota, Destino, Id_Destino, Referencia, Tipo, Fecha, Monto, Observaciones, Id_Empresa, Id_Usuario, FechaMod, TipoMod)
VALUES (@IdNotaHist, @DestinoHist, @IdDestinoHist, @ReferenciaHist, @TipoHist, @FechaHist, @MontoHist, @ObservacionesHist, @IdEmpresaHist, @IdUsuarioHist, @FechaModHist, @TipoModHist);";
await transaction.Connection!.ExecuteAsync(sqlHistorico, new {
IdNotaHist = actual.IdNota, DestinoHist = actual.Destino, IdDestinoHist = actual.IdDestino, ReferenciaHist = actual.Referencia,
TipoHist = actual.Tipo, FechaHist = actual.Fecha, MontoHist = actual.Monto, ObservacionesHist = actual.Observaciones, IdEmpresaHist = actual.IdEmpresa,
IdUsuarioHist = idUsuario, FechaModHist = DateTime.Now, TipoModHist = "Eliminada"
await transaction.Connection!.ExecuteAsync(sqlHistorico, new
{
IdNotaHist = actual.IdNota,
DestinoHist = actual.Destino,
IdDestinoHist = actual.IdDestino,
ReferenciaHist = actual.Referencia,
TipoHist = actual.Tipo,
FechaHist = actual.Fecha,
MontoHist = actual.Monto,
ObservacionesHist = actual.Observaciones,
IdEmpresaHist = actual.IdEmpresa,
IdUsuarioHist = idUsuario,
FechaModHist = DateTime.Now,
TipoModHist = "Eliminada"
}, transaction);
var rowsAffected = await transaction.Connection!.ExecuteAsync(sqlDelete, new { IdNotaParam = idNota }, transaction);
return rowsAffected == 1;
}
public async Task<IEnumerable<(NotaCreditoDebitoHistorico Historial, string NombreUsuarioModifico)>> GetHistorialAsync(
DateTime? fechaDesde, DateTime? fechaHasta,
int? idUsuarioModifico, string? tipoModificacion,
int? idNotaOriginal)
{
using var connection = _cf.CreateConnection();
var sqlBuilder = new StringBuilder(@"
SELECT
h.Id_Nota, h.Destino, h.Id_Destino, h.Referencia, h.Tipo, h.Fecha, h.Monto,
h.Observaciones, h.Id_Empresa,
h.Id_Usuario, h.FechaMod, h.TipoMod,
u.Nombre + ' ' + u.Apellido AS NombreUsuarioModifico
FROM dbo.cue_CreditosDebitos_H h
JOIN dbo.gral_Usuarios u ON h.Id_Usuario = u.Id
WHERE 1=1");
var parameters = new DynamicParameters();
if (fechaDesde.HasValue) { sqlBuilder.Append(" AND h.FechaMod >= @FechaDesdeParam"); parameters.Add("FechaDesdeParam", fechaDesde.Value.Date); }
if (fechaHasta.HasValue) { sqlBuilder.Append(" AND h.FechaMod <= @FechaHastaParam"); parameters.Add("FechaHastaParam", fechaHasta.Value.Date.AddDays(1).AddTicks(-1)); }
if (idUsuarioModifico.HasValue) { sqlBuilder.Append(" AND h.Id_Usuario = @IdUsuarioModificoParam"); parameters.Add("IdUsuarioModificoParam", idUsuarioModifico.Value); }
if (!string.IsNullOrWhiteSpace(tipoModificacion)) { sqlBuilder.Append(" AND h.TipoMod = @TipoModParam"); parameters.Add("TipoModParam", tipoModificacion); }
if (idNotaOriginal.HasValue) { sqlBuilder.Append(" AND h.Id_Nota = @IdNotaOriginalParam"); parameters.Add("IdNotaOriginalParam", idNotaOriginal.Value); }
sqlBuilder.Append(" ORDER BY h.FechaMod DESC;");
try
{
var result = await connection.QueryAsync<NotaCreditoDebitoHistorico, string, (NotaCreditoDebitoHistorico, string)>(
sqlBuilder.ToString(),
(hist, userName) => (hist, userName),
parameters,
splitOn: "NombreUsuarioModifico"
);
return result;
}
catch (Exception ex)
{
_log.LogError(ex, "Error al obtener historial de Notas C/D.");
return Enumerable.Empty<(NotaCreditoDebitoHistorico, string)>();
}
}
}
}

View File

@@ -40,7 +40,7 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
if (idDistribuidor.HasValue) { sqlBuilder.Append(" AND Id_Distribuidor = @IdDistribuidorParam"); parameters.Add("IdDistribuidorParam", idDistribuidor.Value); }
if (idEmpresa.HasValue) { sqlBuilder.Append(" AND Id_Empresa = @IdEmpresaParam"); parameters.Add("IdEmpresaParam", idEmpresa.Value); }
if (!string.IsNullOrWhiteSpace(tipoMovimiento)) { sqlBuilder.Append(" AND TipoMovimiento = @TipoMovParam"); parameters.Add("TipoMovParam", tipoMovimiento); }
sqlBuilder.Append(" ORDER BY Fecha DESC, Id_Pago DESC;");
try
@@ -69,7 +69,7 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
return null;
}
}
public async Task<bool> ExistsByReciboAndTipoMovimientoAsync(int recibo, string tipoMovimiento, int? excludeIdPago = null)
{
var sqlBuilder = new StringBuilder("SELECT COUNT(1) FROM dbo.cue_PagosDistribuidor WHERE Recibo = @ReciboParam AND TipoMovimiento = @TipoMovParam");
@@ -109,11 +109,20 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
var inserted = await transaction.Connection!.QuerySingleAsync<PagoDistribuidor>(sqlInsert, nuevoPago, transaction);
if (inserted == null || inserted.IdPago == 0) throw new DataException("Error al crear pago o ID no generado.");
await transaction.Connection!.ExecuteAsync(sqlHistorico, new {
IdPagoHist = inserted.IdPago, IdDistribuidorHist = inserted.IdDistribuidor, FechaHist = inserted.Fecha,
TipoMovimientoHist = inserted.TipoMovimiento, ReciboHist = inserted.Recibo, MontoHist = inserted.Monto,
IdTipoPagoHist = inserted.IdTipoPago, DetalleHist = inserted.Detalle, IdEmpresaHist = inserted.IdEmpresa,
IdUsuarioHist = idUsuario, FechaModHist = DateTime.Now, TipoModHist = "Creado"
await transaction.Connection!.ExecuteAsync(sqlHistorico, new
{
IdPagoHist = inserted.IdPago,
IdDistribuidorHist = inserted.IdDistribuidor,
FechaHist = inserted.Fecha,
TipoMovimientoHist = inserted.TipoMovimiento,
ReciboHist = inserted.Recibo,
MontoHist = inserted.Monto,
IdTipoPagoHist = inserted.IdTipoPago,
DetalleHist = inserted.Detalle,
IdEmpresaHist = inserted.IdEmpresa,
IdUsuarioHist = idUsuario,
FechaModHist = DateTime.Now,
TipoModHist = "Creado"
}, transaction);
return inserted;
}
@@ -136,12 +145,21 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
INSERT INTO dbo.cue_PagosDistribuidor_H
(Id_Pago, Id_Distribuidor, Fecha, TipoMovimiento, Recibo, Monto, Id_TipoPago, Detalle, Id_Empresa, Id_Usuario, FechaMod, TipoMod)
VALUES (@IdPagoHist, @IdDistribuidorHist, @FechaHist, @TipoMovimientoHist, @ReciboHist, @MontoHist, @IdTipoPagoHist, @DetalleHist, @IdEmpresaHist, @IdUsuarioHist, @FechaModHist, @TipoModHist);";
await transaction.Connection!.ExecuteAsync(sqlHistorico, new {
IdPagoHist = actual.IdPago, IdDistribuidorHist = actual.IdDistribuidor, FechaHist = actual.Fecha,
TipoMovimientoHist = actual.TipoMovimiento, ReciboHist = actual.Recibo, MontoHist = actual.Monto, // Valor ANTERIOR
IdTipoPagoHist = actual.IdTipoPago, DetalleHist = actual.Detalle, IdEmpresaHist = actual.IdEmpresa, // Valores ANTERIORES
IdUsuarioHist = idUsuario, FechaModHist = DateTime.Now, TipoModHist = "Actualizado"
await transaction.Connection!.ExecuteAsync(sqlHistorico, new
{
IdPagoHist = actual.IdPago,
IdDistribuidorHist = actual.IdDistribuidor,
FechaHist = actual.Fecha,
TipoMovimientoHist = actual.TipoMovimiento,
ReciboHist = actual.Recibo,
MontoHist = actual.Monto, // Valor ANTERIOR
IdTipoPagoHist = actual.IdTipoPago,
DetalleHist = actual.Detalle,
IdEmpresaHist = actual.IdEmpresa, // Valores ANTERIORES
IdUsuarioHist = idUsuario,
FechaModHist = DateTime.Now,
TipoModHist = "Actualizado"
}, transaction);
var rowsAffected = await transaction.Connection!.ExecuteAsync(sqlUpdate, pagoAActualizar, transaction);
@@ -161,15 +179,67 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
(Id_Pago, Id_Distribuidor, Fecha, TipoMovimiento, Recibo, Monto, Id_TipoPago, Detalle, Id_Empresa, Id_Usuario, FechaMod, TipoMod)
VALUES (@IdPagoHist, @IdDistribuidorHist, @FechaHist, @TipoMovimientoHist, @ReciboHist, @MontoHist, @IdTipoPagoHist, @DetalleHist, @IdEmpresaHist, @IdUsuarioHist, @FechaModHist, @TipoModHist);";
await transaction.Connection!.ExecuteAsync(sqlHistorico, new {
IdPagoHist = actual.IdPago, IdDistribuidorHist = actual.IdDistribuidor, FechaHist = actual.Fecha,
TipoMovimientoHist = actual.TipoMovimiento, ReciboHist = actual.Recibo, MontoHist = actual.Monto,
IdTipoPagoHist = actual.IdTipoPago, DetalleHist = actual.Detalle, IdEmpresaHist = actual.IdEmpresa,
IdUsuarioHist = idUsuario, FechaModHist = DateTime.Now, TipoModHist = "Eliminado"
await transaction.Connection!.ExecuteAsync(sqlHistorico, new
{
IdPagoHist = actual.IdPago,
IdDistribuidorHist = actual.IdDistribuidor,
FechaHist = actual.Fecha,
TipoMovimientoHist = actual.TipoMovimiento,
ReciboHist = actual.Recibo,
MontoHist = actual.Monto,
IdTipoPagoHist = actual.IdTipoPago,
DetalleHist = actual.Detalle,
IdEmpresaHist = actual.IdEmpresa,
IdUsuarioHist = idUsuario,
FechaModHist = DateTime.Now,
TipoModHist = "Eliminado"
}, transaction);
var rowsAffected = await transaction.Connection!.ExecuteAsync(sqlDelete, new { IdPagoParam = idPago }, transaction);
return rowsAffected == 1;
}
public async Task<IEnumerable<(PagoDistribuidorHistorico Historial, string NombreUsuarioModifico)>> GetHistorialAsync(
DateTime? fechaDesde, DateTime? fechaHasta,
int? idUsuarioModifico, string? tipoModificacion,
int? idPagoOriginal)
{
using var connection = _cf.CreateConnection();
var sqlBuilder = new StringBuilder(@"
SELECT
h.Id_Pago, h.Id_Distribuidor, h.Fecha, h.TipoMovimiento, h.Recibo, h.Monto,
h.Id_TipoPago, h.Detalle, h.Id_Empresa,
h.Id_Usuario, h.FechaMod, h.TipoMod,
u.Nombre + ' ' + u.Apellido AS NombreUsuarioModifico
FROM dbo.cue_PagosDistribuidor_H h
JOIN dbo.gral_Usuarios u ON h.Id_Usuario = u.Id
WHERE 1=1");
var parameters = new DynamicParameters();
if (fechaDesde.HasValue) { sqlBuilder.Append(" AND h.FechaMod >= @FechaDesdeParam"); parameters.Add("FechaDesdeParam", fechaDesde.Value.Date); }
if (fechaHasta.HasValue) { sqlBuilder.Append(" AND h.FechaMod <= @FechaHastaParam"); parameters.Add("FechaHastaParam", fechaHasta.Value.Date.AddDays(1).AddTicks(-1)); }
if (idUsuarioModifico.HasValue) { sqlBuilder.Append(" AND h.Id_Usuario = @IdUsuarioModificoParam"); parameters.Add("IdUsuarioModificoParam", idUsuarioModifico.Value); }
if (!string.IsNullOrWhiteSpace(tipoModificacion)) { sqlBuilder.Append(" AND h.TipoMod = @TipoModParam"); parameters.Add("TipoModParam", tipoModificacion); }
if (idPagoOriginal.HasValue) { sqlBuilder.Append(" AND h.Id_Pago = @IdPagoOriginalParam"); parameters.Add("IdPagoOriginalParam", idPagoOriginal.Value); }
sqlBuilder.Append(" ORDER BY h.FechaMod DESC;");
try
{
var result = await connection.QueryAsync<PagoDistribuidorHistorico, string, (PagoDistribuidorHistorico, string)>(
sqlBuilder.ToString(),
(hist, userName) => (hist, userName),
parameters,
splitOn: "NombreUsuarioModifico"
);
return result;
}
catch (Exception ex)
{
_log.LogError(ex, "Error al obtener historial de Pagos de Distribuidores.");
return Enumerable.Empty<(PagoDistribuidorHistorico, string)>();
}
}
}
}

View File

@@ -188,5 +188,49 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
await transaction.Connection!.ExecuteAsync(sql, historialEntry, transaction);
}
public async Task<IEnumerable<(SaldoAjusteHistorial Historial, string NombreUsuarioModifico)>> GetHistorialAjustesAsync(
DateTime? fechaDesde, DateTime? fechaHasta,
int? idUsuarioModifico,
string? destino, int? idDestino, int? idEmpresa)
{
using var connection = _connectionFactory.CreateConnection();
var sqlBuilder = new StringBuilder(@"
SELECT
h.IdSaldoAjusteHist, h.Destino, h.Id_Destino, h.Id_Empresa,
h.MontoAjuste, h.SaldoAnterior, h.SaldoNuevo, h.Justificacion,
h.FechaAjuste, h.Id_UsuarioAjuste,
u.Nombre + ' ' + u.Apellido AS NombreUsuarioModifico
FROM dbo.cue_SaldoAjustesHistorial h
JOIN dbo.gral_Usuarios u ON h.Id_UsuarioAjuste = u.Id
WHERE 1=1");
var parameters = new DynamicParameters();
if (fechaDesde.HasValue) { sqlBuilder.Append(" AND h.FechaAjuste >= @FechaDesdeParam"); parameters.Add("FechaDesdeParam", fechaDesde.Value.Date); }
if (fechaHasta.HasValue) { sqlBuilder.Append(" AND h.FechaAjuste <= @FechaHastaParam"); parameters.Add("FechaHastaParam", fechaHasta.Value.Date.AddDays(1).AddTicks(-1)); }
if (idUsuarioModifico.HasValue) { sqlBuilder.Append(" AND h.Id_UsuarioAjuste = @IdUsuarioModificoParam"); parameters.Add("IdUsuarioModificoParam", idUsuarioModifico.Value); }
if (!string.IsNullOrWhiteSpace(destino)) { sqlBuilder.Append(" AND h.Destino = @DestinoParam"); parameters.Add("DestinoParam", destino); }
if (idDestino.HasValue) { sqlBuilder.Append(" AND h.Id_Destino = @IdDestinoParam"); parameters.Add("IdDestinoParam", idDestino.Value); }
if (idEmpresa.HasValue) { sqlBuilder.Append(" AND h.Id_Empresa = @IdEmpresaParam"); parameters.Add("IdEmpresaParam", idEmpresa.Value); }
sqlBuilder.Append(" ORDER BY h.FechaAjuste DESC;");
try
{
var result = await connection.QueryAsync<SaldoAjusteHistorial, string, (SaldoAjusteHistorial, string)>(
sqlBuilder.ToString(),
(hist, userName) => (hist, userName),
parameters,
splitOn: "NombreUsuarioModifico"
);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error al obtener historial de Ajustes de Saldo.");
return Enumerable.Empty<(SaldoAjusteHistorial, string)>();
}
}
}
}

View File

@@ -2,6 +2,7 @@ using Dapper;
using GestionIntegral.Api.Models.Contables;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading.Tasks;
namespace GestionIntegral.Api.Data.Repositories.Contables
@@ -284,5 +285,47 @@ namespace GestionIntegral.Api.Data.Repositories.Contables
return true; // Asumir que está en uso si hay error para prevenir borrado incorrecto
}
}
public async Task<IEnumerable<(TipoPagoHistorico Historial, string NombreUsuarioModifico)>> GetHistorialAsync(
DateTime? fechaDesde, DateTime? fechaHasta,
int? idUsuarioModifico, string? tipoModificacion,
int? idTipoPagoOriginal)
{
using var connection = _connectionFactory.CreateConnection(); // Asumiendo _cf es tu DbConnectionFactory
var sqlBuilder = new StringBuilder(@"
SELECT
h.Id_TipoPago, h.Nombre, h.Detalle,
h.Id_Usuario, h.FechaMod, h.TipoMod,
u.Nombre + ' ' + u.Apellido AS NombreUsuarioModifico
FROM dbo.cue_dtTipopago_H h
JOIN dbo.gral_Usuarios u ON h.Id_Usuario = u.Id
WHERE 1=1");
var parameters = new DynamicParameters();
if (fechaDesde.HasValue) { sqlBuilder.Append(" AND h.FechaMod >= @FechaDesdeParam"); parameters.Add("FechaDesdeParam", fechaDesde.Value.Date); }
if (fechaHasta.HasValue) { sqlBuilder.Append(" AND h.FechaMod <= @FechaHastaParam"); parameters.Add("FechaHastaParam", fechaHasta.Value.Date.AddDays(1).AddTicks(-1)); }
if (idUsuarioModifico.HasValue) { sqlBuilder.Append(" AND h.Id_Usuario = @IdUsuarioModificoParam"); parameters.Add("IdUsuarioModificoParam", idUsuarioModifico.Value); }
if (!string.IsNullOrWhiteSpace(tipoModificacion)) { sqlBuilder.Append(" AND h.TipoMod = @TipoModParam"); parameters.Add("TipoModParam", tipoModificacion); }
if (idTipoPagoOriginal.HasValue) { sqlBuilder.Append(" AND h.Id_TipoPago = @IdTipoPagoOriginalParam"); parameters.Add("IdTipoPagoOriginalParam", idTipoPagoOriginal.Value); }
sqlBuilder.Append(" ORDER BY h.FechaMod DESC;");
try
{
var result = await connection.QueryAsync<TipoPagoHistorico, string, (TipoPagoHistorico, string)>(
sqlBuilder.ToString(),
(hist, userName) => (hist, userName),
parameters,
splitOn: "NombreUsuarioModifico"
);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error al obtener historial de Tipos de Pago."); // Asumiendo _log
return Enumerable.Empty<(TipoPagoHistorico, string)>();
}
}
}
}