using Dapper; using GestionIntegral.Api.Models.Distribucion; 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.Distribucion { public class ControlDevolucionesRepository : IControlDevolucionesRepository { private readonly DbConnectionFactory _cf; private readonly ILogger _log; public ControlDevolucionesRepository(DbConnectionFactory cf, ILogger log) { _cf = cf; _log = log; } private string SelectQueryBase() => @" SELECT Id_Control AS IdControl, Id_Empresa AS IdEmpresa, Fecha, Entrada, Sobrantes, Detalle, SinCargo FROM dbo.dist_dtCtrlDevoluciones"; public async Task> GetAllAsync(DateTime? fechaDesde, DateTime? fechaHasta, int? idEmpresa) { 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 (idEmpresa.HasValue) { sqlBuilder.Append(" AND Id_Empresa = @IdEmpresaParam"); parameters.Add("IdEmpresaParam", idEmpresa.Value); } sqlBuilder.Append(" ORDER BY Fecha DESC, Id_Empresa;"); try { using var connection = _cf.CreateConnection(); return await connection.QueryAsync(sqlBuilder.ToString(), parameters); } catch (Exception ex) { _log.LogError(ex, "Error al obtener todos los Controles de Devoluciones."); return Enumerable.Empty(); } } public async Task GetByIdAsync(int idControl) { var sql = SelectQueryBase() + " WHERE Id_Control = @IdControlParam"; try { using var connection = _cf.CreateConnection(); return await connection.QuerySingleOrDefaultAsync(sql, new { IdControlParam = idControl }); } catch (Exception ex) { _log.LogError(ex, "Error al obtener ControlDevoluciones por ID: {IdControl}", idControl); return null; } } public async Task GetByEmpresaAndFechaAsync(int idEmpresa, DateTime fecha, IDbTransaction? transaction = null) { var sql = SelectQueryBase() + " WHERE Id_Empresa = @IdEmpresaParam AND Fecha = @FechaParam"; var cn = transaction?.Connection ?? _cf.CreateConnection(); bool ownConnection = transaction == null; ControlDevoluciones? result = null; try { if (ownConnection && cn.State == ConnectionState.Closed && cn is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); result = await cn.QuerySingleOrDefaultAsync(sql, new { IdEmpresaParam = idEmpresa, FechaParam = fecha.Date }, transaction); } finally { if (ownConnection && cn.State == ConnectionState.Open && cn is System.Data.Common.DbConnection dbConnClose) await dbConnClose.CloseAsync(); if (ownConnection) (cn as IDisposable)?.Dispose(); } return result; } public async Task CreateAsync(ControlDevoluciones nuevoControl, int idUsuario, IDbTransaction transaction) { const string sqlInsert = @" INSERT INTO dbo.dist_dtCtrlDevoluciones (Id_Empresa, Fecha, Entrada, Sobrantes, Detalle, SinCargo) OUTPUT INSERTED.Id_Control AS IdControl, INSERTED.Id_Empresa AS IdEmpresa, INSERTED.Fecha, INSERTED.Entrada, INSERTED.Sobrantes, INSERTED.Detalle, INSERTED.SinCargo VALUES (@IdEmpresa, @Fecha, @Entrada, @Sobrantes, @Detalle, @SinCargo);"; const string sqlHistorico = @" INSERT INTO dbo.dist_dtCtrlDevoluciones_H (Id_Control, Id_Empresa, Fecha, Entrada, Sobrantes, Detalle, SinCargo, Id_Usuario, FechaMod, TipoMod) VALUES (@IdControlParam, @IdEmpresaParam, @FechaParam, @EntradaParam, @SobrantesParam, @DetalleParam, @SinCargoParam, @IdUsuarioParam, @FechaModParam, @TipoModParam);"; var inserted = await transaction.Connection!.QuerySingleAsync(sqlInsert, nuevoControl, transaction); if (inserted == null || inserted.IdControl == 0) throw new DataException("Error al crear control de devoluciones o ID no generado."); await transaction.Connection!.ExecuteAsync(sqlHistorico, new { IdControlParam = inserted.IdControl, IdEmpresaParam = inserted.IdEmpresa, FechaParam = inserted.Fecha, EntradaParam = inserted.Entrada, SobrantesParam = inserted.Sobrantes, DetalleParam = inserted.Detalle, SinCargoParam = inserted.SinCargo, IdUsuarioParam = idUsuario, FechaModParam = DateTime.Now, TipoModParam = "Creado" }, transaction); return inserted; } public async Task UpdateAsync(ControlDevoluciones controlAActualizar, int idUsuario, IDbTransaction transaction) { var actual = await transaction.Connection!.QuerySingleOrDefaultAsync( SelectQueryBase() + " WHERE Id_Control = @IdControlParam", new { IdControlParam = controlAActualizar.IdControl }, transaction); if (actual == null) throw new KeyNotFoundException("Control de devoluciones no encontrado."); // En este caso, Id_Empresa y Fecha no deberían cambiar para un registro existente const string sqlUpdate = @" UPDATE dbo.dist_dtCtrlDevoluciones SET Entrada = @Entrada, Sobrantes = @Sobrantes, Detalle = @Detalle, SinCargo = @SinCargo WHERE Id_Control = @IdControl;"; const string sqlHistorico = @" INSERT INTO dbo.dist_dtCtrlDevoluciones_H (Id_Control, Id_Empresa, Fecha, Entrada, Sobrantes, Detalle, SinCargo, Id_Usuario, FechaMod, TipoMod) VALUES (@IdControlParam, @IdEmpresaParam, @FechaParam, @EntradaParam, @SobrantesParam, @DetalleParam, @SinCargoParam, @IdUsuarioParam, @FechaModParam, @TipoModParam);"; await transaction.Connection!.ExecuteAsync(sqlHistorico, new { IdControlParam = actual.IdControl, IdEmpresaParam = actual.IdEmpresa, FechaParam = actual.Fecha, // Datos originales EntradaParam = actual.Entrada, SobrantesParam = actual.Sobrantes, DetalleParam = actual.Detalle, SinCargoParam = actual.SinCargo, // Valores ANTERIORES IdUsuarioParam = idUsuario, FechaModParam = DateTime.Now, TipoModParam = "Actualizado" }, transaction); var rowsAffected = await transaction.Connection!.ExecuteAsync(sqlUpdate, controlAActualizar, transaction); return rowsAffected == 1; } public async Task DeleteAsync(int idControl, int idUsuario, IDbTransaction transaction) { var actual = await transaction.Connection!.QuerySingleOrDefaultAsync( SelectQueryBase() + " WHERE Id_Control = @IdControlParam", new { IdControlParam = idControl }, transaction); if (actual == null) throw new KeyNotFoundException("Control de devoluciones no encontrado para eliminar."); const string sqlDelete = "DELETE FROM dbo.dist_dtCtrlDevoluciones WHERE Id_Control = @IdControlParam"; const string sqlHistorico = @" INSERT INTO dbo.dist_dtCtrlDevoluciones_H (Id_Control, Id_Empresa, Fecha, Entrada, Sobrantes, Detalle, SinCargo, Id_Usuario, FechaMod, TipoMod) VALUES (@IdControlParam, @IdEmpresaParam, @FechaParam, @EntradaParam, @SobrantesParam, @DetalleParam, @SinCargoParam, @IdUsuarioParam, @FechaModParam, @TipoModParam);"; await transaction.Connection!.ExecuteAsync(sqlHistorico, new { IdControlParam = actual.IdControl, IdEmpresaParam = actual.IdEmpresa, FechaParam = actual.Fecha, EntradaParam = actual.Entrada, SobrantesParam = actual.Sobrantes, DetalleParam = actual.Detalle, SinCargoParam = actual.SinCargo, IdUsuarioParam = idUsuario, FechaModParam = DateTime.Now, TipoModParam = "Eliminado" }, transaction); var rowsAffected = await transaction.Connection!.ExecuteAsync(sqlDelete, new { IdControlParam = idControl }, transaction); return rowsAffected == 1; } } }