Files
GestionIntegralWeb/Backend/GestionIntegral.Api/Data/Repositories/Contables/PagoDistribuidorRepository.cs
eldiadmolinari 437b1e8864 Backend:
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).
2025-06-09 19:37:07 -03:00

245 lines
13 KiB
C#

using Dapper;
using GestionIntegral.Api.Models.Contables;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GestionIntegral.Api.Data.Repositories.Contables
{
public class PagoDistribuidorRepository : IPagoDistribuidorRepository
{
private readonly DbConnectionFactory _cf;
private readonly ILogger<PagoDistribuidorRepository> _log;
public PagoDistribuidorRepository(DbConnectionFactory cf, ILogger<PagoDistribuidorRepository> log)
{
_cf = cf;
_log = log;
}
private string SelectQueryBase() => @"
SELECT
Id_Pago AS IdPago, Id_Distribuidor AS IdDistribuidor, Fecha, TipoMovimiento, Recibo, Monto,
Id_TipoPago AS IdTipoPago, Detalle, Id_Empresa AS IdEmpresa
FROM dbo.cue_PagosDistribuidor";
public async Task<IEnumerable<PagoDistribuidor>> GetAllAsync(
DateTime? fechaDesde, DateTime? fechaHasta,
int? idDistribuidor, int? idEmpresa, string? tipoMovimiento)
{
var sqlBuilder = new StringBuilder(SelectQueryBase());
sqlBuilder.Append(" WHERE 1=1");
var parameters = new DynamicParameters();
if (fechaDesde.HasValue) { sqlBuilder.Append(" AND Fecha >= @FechaDesdeParam"); parameters.Add("FechaDesdeParam", fechaDesde.Value.Date); }
if (fechaHasta.HasValue) { sqlBuilder.Append(" AND Fecha <= @FechaHastaParam"); parameters.Add("FechaHastaParam", fechaHasta.Value.Date); }
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
{
using var connection = _cf.CreateConnection();
return await connection.QueryAsync<PagoDistribuidor>(sqlBuilder.ToString(), parameters);
}
catch (Exception ex)
{
_log.LogError(ex, "Error al obtener todos los Pagos de Distribuidores.");
return Enumerable.Empty<PagoDistribuidor>();
}
}
public async Task<PagoDistribuidor?> GetByIdAsync(int idPago)
{
var sql = SelectQueryBase() + " WHERE Id_Pago = @IdPagoParam";
try
{
using var connection = _cf.CreateConnection();
return await connection.QuerySingleOrDefaultAsync<PagoDistribuidor>(sql, new { IdPagoParam = idPago });
}
catch (Exception ex)
{
_log.LogError(ex, "Error al obtener PagoDistribuidor por ID: {IdPago}", idPago);
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");
var parameters = new DynamicParameters();
parameters.Add("ReciboParam", recibo);
parameters.Add("TipoMovParam", tipoMovimiento);
if (excludeIdPago.HasValue)
{
sqlBuilder.Append(" AND Id_Pago != @ExcludeIdPagoParam");
parameters.Add("ExcludeIdPagoParam", excludeIdPago.Value);
}
try
{
using var connection = _cf.CreateConnection();
return await connection.ExecuteScalarAsync<bool>(sqlBuilder.ToString(), parameters);
}
catch (Exception ex)
{
_log.LogError(ex, "Error en ExistsByReciboAndTipoMovimientoAsync. Recibo: {Recibo}, Tipo: {Tipo}", recibo, tipoMovimiento);
return true; // Asumir que existe en caso de error para prevenir duplicados
}
}
public async Task<PagoDistribuidor?> CreateAsync(PagoDistribuidor nuevoPago, int idUsuario, IDbTransaction transaction)
{
const string sqlInsert = @"
INSERT INTO dbo.cue_PagosDistribuidor (Id_Distribuidor, Fecha, TipoMovimiento, Recibo, Monto, Id_TipoPago, Detalle, Id_Empresa)
OUTPUT INSERTED.Id_Pago AS IdPago, INSERTED.Id_Distribuidor AS IdDistribuidor, INSERTED.Fecha, INSERTED.TipoMovimiento,
INSERTED.Recibo, INSERTED.Monto, INSERTED.Id_TipoPago AS IdTipoPago, INSERTED.Detalle, INSERTED.Id_Empresa AS IdEmpresa
VALUES (@IdDistribuidor, @Fecha, @TipoMovimiento, @Recibo, @Monto, @IdTipoPago, @Detalle, @IdEmpresa);";
const string sqlHistorico = @"
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);";
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"
}, transaction);
return inserted;
}
public async Task<bool> UpdateAsync(PagoDistribuidor pagoAActualizar, int idUsuario, IDbTransaction transaction)
{
var actual = await transaction.Connection!.QuerySingleOrDefaultAsync<PagoDistribuidor>(
SelectQueryBase() + " WHERE Id_Pago = @IdPagoParam",
new { IdPagoParam = pagoAActualizar.IdPago }, transaction);
if (actual == null) throw new KeyNotFoundException("Pago no encontrado.");
// Campos que se permiten actualizar: Monto, Id_TipoPago, Detalle
// Otros campos como IdDistribuidor, Fecha, TipoMovimiento, Recibo, IdEmpresa no deberían cambiar
// para un pago ya registrado. Si necesitan cambiar, se debería anular/eliminar y crear uno nuevo.
const string sqlUpdate = @"
UPDATE dbo.cue_PagosDistribuidor SET
Monto = @Monto, Id_TipoPago = @IdTipoPago, Detalle = @Detalle
WHERE Id_Pago = @IdPago;";
const string sqlHistorico = @"
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"
}, transaction);
var rowsAffected = await transaction.Connection!.ExecuteAsync(sqlUpdate, pagoAActualizar, transaction);
return rowsAffected == 1;
}
public async Task<bool> DeleteAsync(int idPago, int idUsuario, IDbTransaction transaction)
{
var actual = await transaction.Connection!.QuerySingleOrDefaultAsync<PagoDistribuidor>(
SelectQueryBase() + " WHERE Id_Pago = @IdPagoParam",
new { IdPagoParam = idPago }, transaction);
if (actual == null) throw new KeyNotFoundException("Pago no encontrado para eliminar.");
const string sqlDelete = "DELETE FROM dbo.cue_PagosDistribuidor WHERE Id_Pago = @IdPagoParam";
const string sqlHistorico = @"
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,
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)>();
}
}
}
}