220 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			220 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using Dapper; | ||
|  | using GestionIntegral.Api.Data.Repositories; | ||
|  | using GestionIntegral.Api.Models.Distribucion; | ||
|  | using System.Collections.Generic; | ||
|  | using System.Data; | ||
|  | using System.Text; | ||
|  | using System.Threading.Tasks; | ||
|  | 
 | ||
|  | namespace GestionIntegral.Api.Data.Repositories.Distribucion | ||
|  | { | ||
|  |   public class EmpresaRepository : IEmpresaRepository | ||
|  |   { | ||
|  |     private readonly DbConnectionFactory _connectionFactory; | ||
|  |     private readonly ILogger<EmpresaRepository> _logger; | ||
|  | 
 | ||
|  |     public EmpresaRepository(DbConnectionFactory connectionFactory, ILogger<EmpresaRepository> logger) | ||
|  |     { | ||
|  |       _connectionFactory = connectionFactory; | ||
|  |       _logger = logger; | ||
|  |     } | ||
|  | 
 | ||
|  |     // --- Métodos de Lectura (no necesitan transacción explícita aquí) --- | ||
|  | 
 | ||
|  |     public async Task<IEnumerable<Empresa>> GetAllAsync(string? nombreFilter, string? detalleFilter) | ||
|  |     { | ||
|  |       var sqlBuilder = new StringBuilder("SELECT Id_Empresa AS IdEmpresa, Nombre, Detalle FROM dbo.dist_dtEmpresas WHERE 1=1"); | ||
|  |       var parameters = new DynamicParameters(); | ||
|  | 
 | ||
|  |       if (!string.IsNullOrWhiteSpace(nombreFilter)) | ||
|  |       { | ||
|  |         sqlBuilder.Append(" AND Nombre LIKE @NombreFilter"); | ||
|  |         parameters.Add("NombreFilter", $"%{nombreFilter}%"); | ||
|  |       } | ||
|  |       if (!string.IsNullOrWhiteSpace(detalleFilter)) | ||
|  |       { | ||
|  |         sqlBuilder.Append(" AND Detalle LIKE @DetalleFilter"); | ||
|  |         parameters.Add("DetalleFilter", $"%{detalleFilter}%"); | ||
|  |       } | ||
|  |       sqlBuilder.Append(" ORDER BY Nombre;"); | ||
|  | 
 | ||
|  |       try | ||
|  |       { | ||
|  |         using (var connection = _connectionFactory.CreateConnection()) | ||
|  |         { | ||
|  |           return await connection.QueryAsync<Empresa>(sqlBuilder.ToString(), parameters); | ||
|  |         } | ||
|  |       } | ||
|  |       catch (Exception ex) | ||
|  |       { | ||
|  |         _logger.LogError(ex, "Error al obtener todas las Empresas."); | ||
|  |         return Enumerable.Empty<Empresa>(); | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     public async Task<Empresa?> GetByIdAsync(int id) | ||
|  |     { | ||
|  |       var sql = "SELECT Id_Empresa AS IdEmpresa, Nombre, Detalle FROM dbo.dist_dtEmpresas WHERE Id_Empresa = @Id"; | ||
|  |       try | ||
|  |       { | ||
|  |         using (var connection = _connectionFactory.CreateConnection()) | ||
|  |         { | ||
|  |           return await connection.QuerySingleOrDefaultAsync<Empresa>(sql, new { Id = id }); | ||
|  |         } | ||
|  |       } | ||
|  |       catch (Exception ex) | ||
|  |       { | ||
|  |         _logger.LogError(ex, "Error al obtener Empresa por ID: {IdEmpresa}", id); | ||
|  |         return null; | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     public async Task<bool> ExistsByNameAsync(string nombre, int? excludeId = null) | ||
|  |     { | ||
|  |       var sqlBuilder = new StringBuilder("SELECT COUNT(1) FROM dbo.dist_dtEmpresas WHERE Nombre = @Nombre"); | ||
|  |       var parameters = new DynamicParameters(); | ||
|  |       parameters.Add("Nombre", nombre); | ||
|  | 
 | ||
|  |       if (excludeId.HasValue) | ||
|  |       { | ||
|  |         sqlBuilder.Append(" AND Id_Empresa != @ExcludeId"); | ||
|  |         parameters.Add("ExcludeId", excludeId.Value); | ||
|  |       } | ||
|  | 
 | ||
|  |       try | ||
|  |       { | ||
|  |         using (var connection = _connectionFactory.CreateConnection()) | ||
|  |         { | ||
|  |           var count = await connection.ExecuteScalarAsync<int>(sqlBuilder.ToString(), parameters); | ||
|  |           return count > 0; | ||
|  |         } | ||
|  |       } | ||
|  |       catch (Exception ex) | ||
|  |       { | ||
|  |         _logger.LogError(ex, "Error en ExistsByNameAsync para Empresa con nombre: {Nombre}", nombre); | ||
|  |         return true; // Asumir que existe si hay error | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     public async Task<bool> IsInUseAsync(int id) | ||
|  |     { | ||
|  |       // Verifica si la empresa está referenciada en dist_dtPublicaciones | ||
|  |       var sql = "SELECT COUNT(1) FROM dbo.dist_dtPublicaciones WHERE Id_Empresa = @IdEmpresa"; | ||
|  |       try | ||
|  |       { | ||
|  |         using (var connection = _connectionFactory.CreateConnection()) | ||
|  |         { | ||
|  |           var count = await connection.ExecuteScalarAsync<int>(sql, new { IdEmpresa = id }); | ||
|  |           return count > 0; | ||
|  |         } | ||
|  |       } | ||
|  |       catch (Exception ex) | ||
|  |       { | ||
|  |         _logger.LogError(ex, "Error en IsInUseAsync para Empresa ID: {IdEmpresa}", id); | ||
|  |         return true; // Asumir en uso si hay error | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     // --- Métodos de Escritura (USAN TRANSACCIÓN PASADA DESDE EL SERVICIO) --- | ||
|  | 
 | ||
|  |     public async Task<Empresa?> CreateAsync(Empresa nuevaEmpresa, int idUsuario, IDbTransaction transaction) | ||
|  |     { | ||
|  |       var sqlInsert = @"
 | ||
|  |                 INSERT INTO dbo.dist_dtEmpresas (Nombre, Detalle) | ||
|  |                 OUTPUT INSERTED.Id_Empresa AS IdEmpresa, INSERTED.Nombre, INSERTED.Detalle | ||
|  |                 VALUES (@Nombre, @Detalle);";
 | ||
|  | 
 | ||
|  |       var sqlInsertHistorico = @"
 | ||
|  |                 INSERT INTO dbo.dist_dtEmpresas_H (Id_Empresa, Nombre, Detalle, Id_Usuario, FechaMod, TipoMod) | ||
|  |                 VALUES (@IdEmpresa, @Nombre, @Detalle, @IdUsuario, @FechaMod, @TipoMod);";
 | ||
|  | 
 | ||
|  |       // La ejecución y manejo de errores/commit/rollback se hará en el SERVICIO | ||
|  |       // Aquí solo ejecutamos los comandos DENTRO de la transacción existente. | ||
|  | 
 | ||
|  |       // Obtener el ID y datos insertados | ||
|  |       var insertedEmpresa = await transaction.Connection!.QuerySingleAsync<Empresa>( | ||
|  |         sqlInsert, | ||
|  |         new { nuevaEmpresa.Nombre, nuevaEmpresa.Detalle }, | ||
|  |         transaction: transaction | ||
|  |       ); | ||
|  | 
 | ||
|  |       if (insertedEmpresa == null || insertedEmpresa.IdEmpresa <= 0) | ||
|  |       { | ||
|  |         throw new Exception("No se pudo obtener el ID de la empresa insertada."); | ||
|  |       } | ||
|  | 
 | ||
|  |       // Insertar en historial | ||
|  |       await transaction.Connection!.ExecuteAsync(sqlInsertHistorico, new { | ||
|  |         IdEmpresa = insertedEmpresa.IdEmpresa, | ||
|  |         insertedEmpresa.Nombre, | ||
|  |         insertedEmpresa.Detalle, | ||
|  |         IdUsuario = idUsuario, | ||
|  |         FechaMod = DateTime.Now, | ||
|  |         TipoMod = "Insertada" | ||
|  |       }, transaction: transaction); | ||
|  | 
 | ||
|  |       return insertedEmpresa; // Devolver la entidad con el ID | ||
|  |     } | ||
|  | 
 | ||
|  |     public async Task<bool> UpdateAsync(Empresa empresaAActualizar, int idUsuario, IDbTransaction transaction) | ||
|  |     { | ||
|  |       // El servicio ya verificó que existe. Obtenemos estado actual para historial. | ||
|  |       var empresaActual = await GetByIdAsync(empresaAActualizar.IdEmpresa); // Podría fallar si ya no existe, controlar en servicio | ||
|  |       if (empresaActual == null) throw new InvalidOperationException("No se encontró la empresa para obtener datos para el historial de actualización."); | ||
|  | 
 | ||
|  |       var sqlUpdate = @"
 | ||
|  |                 UPDATE dbo.dist_dtEmpresas | ||
|  |                 SET Nombre = @Nombre, Detalle = @Detalle | ||
|  |                 WHERE Id_Empresa = @IdEmpresa;";
 | ||
|  | 
 | ||
|  |       var sqlInsertHistorico = @"
 | ||
|  |                 INSERT INTO dbo.dist_dtEmpresas_H (Id_Empresa, Nombre, Detalle, Id_Usuario, FechaMod, TipoMod) | ||
|  |                 VALUES (@IdEmpresa, @NombreActual, @DetalleActual, @IdUsuario, @FechaMod, @TipoMod);";
 | ||
|  | 
 | ||
|  |       // Insertar en historial (estado anterior) | ||
|  |       await transaction.Connection!.ExecuteAsync(sqlInsertHistorico, new { | ||
|  |         IdEmpresa = empresaActual.IdEmpresa, | ||
|  |         NombreActual = empresaActual.Nombre, | ||
|  |         DetalleActual = empresaActual.Detalle, | ||
|  |         IdUsuario = idUsuario, | ||
|  |         FechaMod = DateTime.Now, | ||
|  |         TipoMod = "Modificada" | ||
|  |       }, transaction: transaction); | ||
|  | 
 | ||
|  |       // Actualizar principal | ||
|  |       var rowsAffected = await transaction.Connection!.ExecuteAsync(sqlUpdate, new { | ||
|  |         empresaAActualizar.Nombre, | ||
|  |         empresaAActualizar.Detalle, | ||
|  |         empresaAActualizar.IdEmpresa | ||
|  |       }, transaction: transaction); | ||
|  | 
 | ||
|  |       return rowsAffected == 1; | ||
|  |     } | ||
|  | 
 | ||
|  |     public async Task<bool> DeleteAsync(int id, int idUsuario, IDbTransaction transaction) | ||
|  |     { | ||
|  |       var empresaActual = await GetByIdAsync(id); // Obtener datos para historial | ||
|  |       if (empresaActual == null) throw new InvalidOperationException("No se encontró la empresa para obtener datos para el historial de eliminación."); | ||
|  | 
 | ||
|  |       var sqlDelete = "DELETE FROM dbo.dist_dtEmpresas WHERE Id_Empresa = @Id"; | ||
|  |       var sqlInsertHistorico = @"
 | ||
|  |                 INSERT INTO dbo.dist_dtEmpresas_H (Id_Empresa, Nombre, Detalle, Id_Usuario, FechaMod, TipoMod) | ||
|  |                 VALUES (@IdEmpresa, @Nombre, @Detalle, @IdUsuario, @FechaMod, @TipoMod);";
 | ||
|  | 
 | ||
|  |       // Insertar en historial (estado antes de borrar) | ||
|  |       await transaction.Connection!.ExecuteAsync(sqlInsertHistorico, new { | ||
|  |         IdEmpresa = empresaActual.IdEmpresa, | ||
|  |         empresaActual.Nombre, | ||
|  |         empresaActual.Detalle, | ||
|  |         IdUsuario = idUsuario, | ||
|  |         FechaMod = DateTime.Now, | ||
|  |         TipoMod = "Eliminada" | ||
|  |       }, transaction: transaction); | ||
|  | 
 | ||
|  |       // Eliminar de la tabla principal | ||
|  |       var rowsAffected = await transaction.Connection!.ExecuteAsync(sqlDelete, new { Id = id }, transaction: transaction); | ||
|  | 
 | ||
|  |       return rowsAffected == 1; | ||
|  |     } | ||
|  |   } | ||
|  | } |