using Dapper; using GestionIntegral.Api.Data.Repositories; using GestionIntegral.Api.Models; using Microsoft.Extensions.Logging; using System.Collections.Generic; using System.Data; using System.Threading.Tasks; namespace GestionIntegral.Api.Data.Repositories.Contables { public class SaldoRepository : ISaldoRepository { private readonly DbConnectionFactory _connectionFactory; private readonly ILogger _logger; public SaldoRepository(DbConnectionFactory connectionFactory, ILogger logger) { _connectionFactory = connectionFactory; _logger = logger; } public async Task> GetAllDistribuidorIdsAsync() { var sql = "SELECT Id_Distribuidor FROM dbo.dist_dtDistribuidores"; try { using (var connection = _connectionFactory.CreateConnection()) { return await connection.QueryAsync(sql); } } catch (Exception ex) { _logger.LogError(ex, "Error al obtener IDs de Distribuidores."); return Enumerable.Empty(); } } public async Task CreateSaldoInicialAsync(string destino, int idDestino, int idEmpresa, IDbTransaction transaction) { var sql = @" INSERT INTO dbo.cue_Saldos (Destino, Id_Destino, Monto, Id_Empresa) VALUES (@Destino, @IdDestino, 0.00, @IdEmpresa);"; try { int rowsAffected = await transaction.Connection!.ExecuteAsync(sql, // Añadir ! new { Destino = destino, IdDestino = idDestino, IdEmpresa = idEmpresa }, transaction: transaction); return rowsAffected == 1; } catch (Exception ex) { _logger.LogError(ex, "Error al insertar saldo inicial para {Destino} ID {IdDestino}, Empresa ID {IdEmpresa}.", destino, idDestino, idEmpresa); throw; } } public async Task DeleteSaldosByEmpresaAsync(int idEmpresa, IDbTransaction transaction) { var sql = "DELETE FROM dbo.cue_Saldos WHERE Id_Empresa = @IdEmpresa"; try { await transaction.Connection!.ExecuteAsync(sql, new { IdEmpresa = idEmpresa }, transaction: transaction); return true; // Asumir éxito si no hay excepción } catch (Exception ex) { _logger.LogError(ex, "Error al eliminar saldos para Empresa ID {IdEmpresa}.", idEmpresa); throw; } } public async Task ModificarSaldoAsync(string destino, int idDestino, int idEmpresa, decimal montoAAgregar, IDbTransaction? transaction = null) { var sql = @"UPDATE dbo.cue_Saldos SET Monto = Monto + @MontoAAgregar WHERE Destino = @Destino AND Id_Destino = @IdDestino AND Id_Empresa = @IdEmpresa;"; // Usar una variable para la conexión para poder aplicar el '!' si es necesario IDbConnection connection = transaction?.Connection ?? _connectionFactory.CreateConnection(); bool ownConnection = transaction == null; // Saber si necesitamos cerrar la conexión nosotros try { if (ownConnection) await (connection as System.Data.Common.DbConnection)!.OpenAsync(); // Abrir solo si no hay transacción externa var parameters = new { MontoAAgregar = montoAAgregar, Destino = destino, IdDestino = idDestino, IdEmpresa = idEmpresa }; // Aplicar '!' aquí también si viene de la transacción int rowsAffected = await connection.ExecuteAsync(sql, parameters, transaction: transaction); return rowsAffected == 1; } catch (Exception ex) { _logger.LogError(ex, "Error al modificar saldo para {Destino} ID {IdDestino}, Empresa ID {IdEmpresa}.", destino, idDestino, idEmpresa); if (transaction != null) throw; // Re-lanzar si estamos en una transacción externa return false; // Devolver false si fue una operación aislada que falló } finally { // Cerrar la conexión solo si la abrimos nosotros (no había transacción externa) if (ownConnection && connection.State == ConnectionState.Open) { await (connection as System.Data.Common.DbConnection)!.CloseAsync(); } // Disponer de la conexión si la creamos nosotros if(ownConnection) (connection as IDisposable)?.Dispose(); } } public async Task CheckIfSaldosExistForEmpresaAsync(int idEmpresa) { var sql = "SELECT COUNT(1) FROM dbo.cue_Saldos WHERE Id_Empresa = @IdEmpresa"; try { // Este método es de solo lectura, no necesita transacción externa normalmente using (var connection = _connectionFactory.CreateConnection()) { var count = await connection.ExecuteScalarAsync(sql, new { IdEmpresa = idEmpresa }); return count > 0; // Devuelve true si hay al menos un saldo } } catch (Exception ex) { _logger.LogError(ex, "Error en CheckIfSaldosExistForEmpresaAsync para Empresa ID {IdEmpresa}", idEmpresa); return false; // Asumir que no existen si hay error, para no bloquear la eliminación innecesariamente // O podrías devolver true para ser más conservador si la verificación es crítica. } } } }