229 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			229 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using Dapper; | ||
|  | using GestionIntegral.Api.Models.Impresion; | ||
|  | using Microsoft.Extensions.Logging; | ||
|  | using System.Collections.Generic; | ||
|  | using System.Data; | ||
|  | using System.Text; // Para StringBuilder | ||
|  | using System.Threading.Tasks; | ||
|  | 
 | ||
|  | namespace GestionIntegral.Api.Data.Repositories.Impresion | ||
|  | { | ||
|  |     public class PlantaRepository : IPlantaRepository | ||
|  |     { | ||
|  |         private readonly DbConnectionFactory _connectionFactory; | ||
|  |         private readonly ILogger<PlantaRepository> _logger; | ||
|  | 
 | ||
|  |         public PlantaRepository(DbConnectionFactory connectionFactory, ILogger<PlantaRepository> logger) | ||
|  |         { | ||
|  |             _connectionFactory = connectionFactory; | ||
|  |             _logger = logger; | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<IEnumerable<Planta>> GetAllAsync(string? nombreFilter, string? detalleFilter) | ||
|  |         { | ||
|  |             var sqlBuilder = new StringBuilder("SELECT Id_Planta AS IdPlanta, Nombre, Detalle FROM dbo.bob_dtPlantas 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<Planta>(sqlBuilder.ToString(), parameters); | ||
|  |             } | ||
|  |             catch (Exception ex) | ||
|  |             { | ||
|  |                 _logger.LogError(ex, "Error al obtener todas las Plantas. Filtros: Nombre={Nombre}, Detalle={Detalle}", nombreFilter, detalleFilter); | ||
|  |                 return Enumerable.Empty<Planta>(); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<Planta?> GetByIdAsync(int id) | ||
|  |         { | ||
|  |             const string sql = "SELECT Id_Planta AS IdPlanta, Nombre, Detalle FROM dbo.bob_dtPlantas WHERE Id_Planta = @Id"; | ||
|  |             try | ||
|  |             { | ||
|  |                 using var connection = _connectionFactory.CreateConnection(); | ||
|  |                 return await connection.QuerySingleOrDefaultAsync<Planta>(sql, new { Id = id }); | ||
|  |             } | ||
|  |             catch (Exception ex) | ||
|  |             { | ||
|  |                 _logger.LogError(ex, "Error al obtener Planta por ID: {IdPlanta}", id); | ||
|  |                 return null; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<bool> ExistsByNameAsync(string nombre, int? excludeId = null) | ||
|  |         { | ||
|  |             var sqlBuilder = new StringBuilder("SELECT COUNT(1) FROM dbo.bob_dtPlantas WHERE Nombre = @Nombre"); | ||
|  |             var parameters = new DynamicParameters(); | ||
|  |             parameters.Add("Nombre", nombre); | ||
|  | 
 | ||
|  |             if (excludeId.HasValue) | ||
|  |             { | ||
|  |                 sqlBuilder.Append(" AND Id_Planta != @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 Planta con nombre: {Nombre}", nombre); | ||
|  |                 // Asumir que existe en caso de error para prevenir duplicados accidentales | ||
|  |                 return true; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<bool> IsInUseAsync(int id) | ||
|  |         { | ||
|  |             // Verificar si la planta está referenciada en bob_StockBobinas O bob_RegPublicaciones | ||
|  |             const string sqlCheckStock = "SELECT TOP 1 1 FROM dbo.bob_StockBobinas WHERE Id_Planta = @IdPlanta"; | ||
|  |             const string sqlCheckRegPubli = "SELECT TOP 1 1 FROM dbo.bob_RegPublicaciones WHERE Id_Planta = @IdPlanta"; | ||
|  | 
 | ||
|  |             try | ||
|  |             { | ||
|  |                 using var connection = _connectionFactory.CreateConnection(); | ||
|  |                 var inStock = await connection.ExecuteScalarAsync<int?>(sqlCheckStock, new { IdPlanta = id }); | ||
|  |                 if (inStock.HasValue && inStock.Value == 1) return true; | ||
|  | 
 | ||
|  |                 var inRegPubli = await connection.ExecuteScalarAsync<int?>(sqlCheckRegPubli, new { IdPlanta = id }); | ||
|  |                 return inRegPubli.HasValue && inRegPubli.Value == 1; | ||
|  |             } | ||
|  |             catch (Exception ex) | ||
|  |             { | ||
|  |                 _logger.LogError(ex, "Error en IsInUseAsync para Planta ID: {IdPlanta}", id); | ||
|  |                 // Asumir que está en uso si hay error para prevenir borrado incorrecto | ||
|  |                 return true; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         // --- Métodos de Escritura (USAN TRANSACCIÓN PASADA DESDE EL SERVICIO) --- | ||
|  | 
 | ||
|  |         public async Task<Planta?> CreateAsync(Planta nuevaPlanta, int idUsuario, IDbTransaction transaction) | ||
|  |         { | ||
|  |             const string sqlInsert = @"
 | ||
|  |                 INSERT INTO dbo.bob_dtPlantas (Nombre, Detalle) | ||
|  |                 OUTPUT INSERTED.Id_Planta AS IdPlanta, INSERTED.Nombre, INSERTED.Detalle | ||
|  |                 VALUES (@Nombre, @Detalle);";
 | ||
|  |             const string sqlInsertHistorico = @"
 | ||
|  |                 INSERT INTO dbo.bob_dtPlantas_H (Id_Planta, Nombre, Detalle, Id_Usuario, FechaMod, TipoMod) | ||
|  |                 VALUES (@IdPlanta, @Nombre, @Detalle, @IdUsuario, @FechaMod, @TipoMod);";
 | ||
|  | 
 | ||
|  |             // Dapper requiere que la conexión esté asociada a la transacción | ||
|  |             var connection = transaction.Connection ?? throw new InvalidOperationException("Transaction has no associated connection."); | ||
|  | 
 | ||
|  |             var insertedPlanta = await connection.QuerySingleAsync<Planta>( | ||
|  |                 sqlInsert, | ||
|  |                 new { nuevaPlanta.Nombre, nuevaPlanta.Detalle }, | ||
|  |                 transaction: transaction // Pasar la transacción | ||
|  |             ); | ||
|  | 
 | ||
|  |             if (insertedPlanta == null || insertedPlanta.IdPlanta <= 0) | ||
|  |             { | ||
|  |                 throw new DataException("No se pudo obtener el ID de la planta insertada."); // Usar DataException | ||
|  |             } | ||
|  | 
 | ||
|  |             // Insertar en historial | ||
|  |             await connection.ExecuteAsync(sqlInsertHistorico, new | ||
|  |             { | ||
|  |                 IdPlanta = insertedPlanta.IdPlanta, | ||
|  |                 insertedPlanta.Nombre, | ||
|  |                 insertedPlanta.Detalle, | ||
|  |                 IdUsuario = idUsuario, | ||
|  |                 FechaMod = DateTime.Now, | ||
|  |                 TipoMod = "Insertada" | ||
|  |             }, transaction: transaction); | ||
|  | 
 | ||
|  |             return insertedPlanta; // Devolver la entidad con el ID | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<bool> UpdateAsync(Planta plantaAActualizar, int idUsuario, IDbTransaction transaction) | ||
|  |         { | ||
|  |              // El servicio ya verificó que existe. Obtener estado actual para historial dentro de la transacción. | ||
|  |             var connection = transaction.Connection!; | ||
|  |             var plantaActual = await connection.QuerySingleOrDefaultAsync<Planta>( | ||
|  |                 "SELECT Id_Planta AS IdPlanta, Nombre, Detalle FROM dbo.bob_dtPlantas WHERE Id_Planta = @Id", | ||
|  |                  new { Id = plantaAActualizar.IdPlanta }, | ||
|  |                  transaction); | ||
|  | 
 | ||
|  |             if (plantaActual == null) throw new KeyNotFoundException($"No se encontró la planta con ID {plantaAActualizar.IdPlanta} para actualizar."); // Más específico | ||
|  | 
 | ||
|  |             const string sqlUpdate = @"
 | ||
|  |                 UPDATE dbo.bob_dtPlantas | ||
|  |                 SET Nombre = @Nombre, Detalle = @Detalle | ||
|  |                 WHERE Id_Planta = @IdPlanta;";
 | ||
|  |             const string sqlInsertHistorico = @"
 | ||
|  |                 INSERT INTO dbo.bob_dtPlantas_H (Id_Planta, Nombre, Detalle, Id_Usuario, FechaMod, TipoMod) | ||
|  |                 VALUES (@IdPlanta, @NombreActual, @DetalleActual, @IdUsuario, @FechaMod, @TipoMod);";
 | ||
|  | 
 | ||
|  |             // Insertar en historial (estado anterior) | ||
|  |             await connection.ExecuteAsync(sqlInsertHistorico, new | ||
|  |             { | ||
|  |                 IdPlanta = plantaActual.IdPlanta, | ||
|  |                 NombreActual = plantaActual.Nombre, | ||
|  |                 DetalleActual = plantaActual.Detalle, | ||
|  |                 IdUsuario = idUsuario, | ||
|  |                 FechaMod = DateTime.Now, | ||
|  |                 TipoMod = "Modificada" | ||
|  |             }, transaction: transaction); | ||
|  | 
 | ||
|  |             // Actualizar principal | ||
|  |             var rowsAffected = await connection.ExecuteAsync(sqlUpdate, new | ||
|  |             { | ||
|  |                 plantaAActualizar.Nombre, | ||
|  |                 plantaAActualizar.Detalle, | ||
|  |                 plantaAActualizar.IdPlanta | ||
|  |             }, transaction: transaction); | ||
|  | 
 | ||
|  |             return rowsAffected == 1; | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<bool> DeleteAsync(int id, int idUsuario, IDbTransaction transaction) | ||
|  |         { | ||
|  |             var connection = transaction.Connection!; | ||
|  |             // Obtener datos para historial ANTES de borrar | ||
|  |             var plantaActual = await connection.QuerySingleOrDefaultAsync<Planta>( | ||
|  |                  "SELECT Id_Planta AS IdPlanta, Nombre, Detalle FROM dbo.bob_dtPlantas WHERE Id_Planta = @Id", | ||
|  |                  new { Id = id }, | ||
|  |                  transaction); | ||
|  | 
 | ||
|  |             if (plantaActual == null) throw new KeyNotFoundException($"No se encontró la planta con ID {id} para eliminar."); | ||
|  | 
 | ||
|  |             const string sqlDelete = "DELETE FROM dbo.bob_dtPlantas WHERE Id_Planta = @Id"; | ||
|  |             const string sqlInsertHistorico = @"
 | ||
|  |                 INSERT INTO dbo.bob_dtPlantas_H (Id_Planta, Nombre, Detalle, Id_Usuario, FechaMod, TipoMod) | ||
|  |                 VALUES (@IdPlanta, @Nombre, @Detalle, @IdUsuario, @FechaMod, @TipoMod);";
 | ||
|  | 
 | ||
|  |             // Insertar en historial (estado antes de borrar) | ||
|  |             await connection.ExecuteAsync(sqlInsertHistorico, new | ||
|  |             { | ||
|  |                 IdPlanta = plantaActual.IdPlanta, | ||
|  |                 plantaActual.Nombre, | ||
|  |                 plantaActual.Detalle, | ||
|  |                 IdUsuario = idUsuario, | ||
|  |                 FechaMod = DateTime.Now, | ||
|  |                 TipoMod = "Eliminada" | ||
|  |             }, transaction: transaction); | ||
|  | 
 | ||
|  |             // Eliminar de la tabla principal | ||
|  |             var rowsAffected = await connection.ExecuteAsync(sqlDelete, new { Id = id }, transaction: transaction); | ||
|  | 
 | ||
|  |             return rowsAffected == 1; | ||
|  |         } | ||
|  |     } | ||
|  | } |