194 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			194 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using GestionIntegral.Api.Data; // Para DbConnectionFactory
 | |
| using GestionIntegral.Api.Data.Repositories.Impresion;
 | |
| using GestionIntegral.Api.Dtos.Impresion;
 | |
| using GestionIntegral.Api.Models.Impresion; // Para Planta
 | |
| using Microsoft.Extensions.Logging;
 | |
| using System.Collections.Generic;
 | |
| using System.Data; // Para IsolationLevel
 | |
| using System.Linq;
 | |
| using System.Threading.Tasks; // Todavía usamos async para operaciones de BD
 | |
| 
 | |
| namespace GestionIntegral.Api.Services.Impresion
 | |
| {
 | |
|     public class PlantaService : IPlantaService
 | |
|     {
 | |
|         private readonly IPlantaRepository _plantaRepository;
 | |
|         private readonly DbConnectionFactory _connectionFactory; // Para manejar transacciones
 | |
|         private readonly ILogger<PlantaService> _logger;
 | |
| 
 | |
|         public PlantaService(IPlantaRepository plantaRepository, DbConnectionFactory connectionFactory, ILogger<PlantaService> logger)
 | |
|         {
 | |
|             _plantaRepository = plantaRepository;
 | |
|             _connectionFactory = connectionFactory;
 | |
|             _logger = logger;
 | |
|         }
 | |
| 
 | |
|         // Método para mapear Planta a PlantaDto
 | |
|         private PlantaDto MapToDto(Planta planta) => new PlantaDto
 | |
|         {
 | |
|             IdPlanta = planta.IdPlanta,
 | |
|             Nombre = planta.Nombre,
 | |
|             Detalle = planta.Detalle
 | |
|         };
 | |
| 
 | |
|         public async Task<IEnumerable<PlantaDto>> ObtenerTodasAsync(string? nombreFilter, string? detalleFilter)
 | |
|         {
 | |
|             // Las operaciones de lectura no suelen necesitar transacción explícita aquí
 | |
|             var plantas = await _plantaRepository.GetAllAsync(nombreFilter, detalleFilter);
 | |
|             return plantas.Select(MapToDto);
 | |
|         }
 | |
| 
 | |
|         public async Task<PlantaDto?> ObtenerPorIdAsync(int id)
 | |
|         {
 | |
|             var planta = await _plantaRepository.GetByIdAsync(id);
 | |
|             return planta == null ? null : MapToDto(planta);
 | |
|         }
 | |
| 
 | |
|         public async Task<(PlantaDto? Planta, string? Error)> CrearAsync(CreatePlantaDto createDto, int idUsuario)
 | |
|         {
 | |
|             if (await _plantaRepository.ExistsByNameAsync(createDto.Nombre))
 | |
|             {
 | |
|                 return (null, "El nombre de la planta ya existe.");
 | |
|             }
 | |
| 
 | |
|             var nuevaPlanta = new Planta
 | |
|             {
 | |
|                 Nombre = createDto.Nombre,
 | |
|                 Detalle = createDto.Detalle
 | |
|             };
 | |
| 
 | |
|             using var connection = _connectionFactory.CreateConnection();
 | |
|             // Abrir la conexión asíncronamente si es posible
 | |
|             if (connection is System.Data.Common.DbConnection dbConnection)
 | |
|             {
 | |
|                 await dbConnection.OpenAsync();
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 connection.Open(); // Fallback síncrono
 | |
|             }
 | |
| 
 | |
|             // Empezar transacción
 | |
|             using var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted);
 | |
| 
 | |
|             try
 | |
|             {
 | |
|                 var plantaCreada = await _plantaRepository.CreateAsync(nuevaPlanta, idUsuario, transaction);
 | |
|                 if (plantaCreada == null)
 | |
|                 {
 | |
|                     throw new DataException("La creación en el repositorio devolvió null.");
 | |
|                 }
 | |
| 
 | |
|                 transaction.Commit(); // <--- CORREGIDO: Commit síncrono
 | |
|                 _logger.LogInformation("Planta ID {IdPlanta} creada exitosamente por Usuario ID {IdUsuario}.", plantaCreada.IdPlanta, idUsuario);
 | |
|                 return (MapToDto(plantaCreada), null);
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 try
 | |
|                 {
 | |
|                     transaction.Rollback(); // <--- CORREGIDO: Rollback síncrono
 | |
|                 }
 | |
|                 catch (Exception rbEx)
 | |
|                 {
 | |
|                     _logger.LogError(rbEx, "Error adicional durante el rollback en CrearAsync Planta.");
 | |
|                 }
 | |
|                 _logger.LogError(ex, "Error en transacción CrearAsync para Planta. Nombre: {Nombre}", createDto.Nombre);
 | |
|                 return (null, $"Error interno al crear la planta: {ex.Message}"); // Devolver mensaje de error
 | |
|             }
 | |
|             // La conexión y transacción se disponen automáticamente al salir del 'using'
 | |
|         }
 | |
| 
 | |
|         public async Task<(bool Exito, string? Error)> ActualizarAsync(int id, UpdatePlantaDto updateDto, int idUsuario)
 | |
|         {
 | |
|             if (await _plantaRepository.ExistsByNameAsync(updateDto.Nombre, id))
 | |
|             {
 | |
|                 return (false, "El nombre de la planta ya existe para otro registro.");
 | |
|             }
 | |
| 
 | |
|             var plantaAActualizar = new Planta
 | |
|             {
 | |
|                 IdPlanta = id,
 | |
|                 Nombre = updateDto.Nombre,
 | |
|                 Detalle = updateDto.Detalle
 | |
|             };
 | |
| 
 | |
|             using var connection = _connectionFactory.CreateConnection();
 | |
|             if (connection is System.Data.Common.DbConnection dbConnection) { await dbConnection.OpenAsync(); } else { connection.Open(); }
 | |
|             using var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted);
 | |
| 
 | |
|             try
 | |
|             {
 | |
|                 var actualizado = await _plantaRepository.UpdateAsync(plantaAActualizar, idUsuario, transaction);
 | |
|                 if (!actualizado)
 | |
|                 {
 | |
|                     // La excepción KeyNotFoundException se manejará en el bloque catch
 | |
|                     // Aquí asumimos que si devuelve false es porque no afectó filas, lo cual podría ser un error lógico
 | |
|                     throw new DataException("La operación de actualización no afectó ninguna fila.");
 | |
|                 }
 | |
| 
 | |
|                 transaction.Commit(); // <--- CORREGIDO: Commit síncrono
 | |
|                 _logger.LogInformation("Planta ID {IdPlanta} actualizada exitosamente por Usuario ID {IdUsuario}.", id, idUsuario);
 | |
|                 return (true, null);
 | |
|             }
 | |
|             catch (KeyNotFoundException knfex) // Captura específica si el repo la lanza
 | |
|             {
 | |
|                 try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error adicional durante el rollback en ActualizarAsync Planta."); }
 | |
|                 _logger.LogWarning(knfex, "Intento de actualizar Planta ID: {Id} no encontrada.", id);
 | |
|                 return (false, "Planta no encontrada.");
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error adicional durante el rollback en ActualizarAsync Planta."); }
 | |
|                 _logger.LogError(ex, "Error en transacción ActualizarAsync para Planta ID: {Id}", id);
 | |
|                 return (false, $"Error interno al actualizar la planta: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public async Task<(bool Exito, string? Error)> EliminarAsync(int id, int idUsuario)
 | |
|         {
 | |
|             if (await _plantaRepository.IsInUseAsync(id))
 | |
|             {
 | |
|                 return (false, "No se puede eliminar. La planta está siendo utilizada.");
 | |
|             }
 | |
| 
 | |
|             using var connection = _connectionFactory.CreateConnection();
 | |
|             if (connection is System.Data.Common.DbConnection dbConnection) { await dbConnection.OpenAsync(); } else { connection.Open(); }
 | |
|             using var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted);
 | |
| 
 | |
|             try
 | |
|             {
 | |
|                 var eliminado = await _plantaRepository.DeleteAsync(id, idUsuario, transaction);
 | |
|                 if (!eliminado)
 | |
|                 {
 | |
|                     throw new DataException("La operación de eliminación no afectó ninguna fila.");
 | |
|                 }
 | |
| 
 | |
|                 transaction.Commit(); // <--- CORREGIDO: Commit síncrono
 | |
|                 _logger.LogInformation("Planta ID {IdPlanta} eliminada exitosamente por Usuario ID {IdUsuario}.", id, idUsuario);
 | |
|                 return (true, null);
 | |
|             }
 | |
|             catch (KeyNotFoundException knfex) // Captura específica si el repo la lanza
 | |
|             {
 | |
|                 try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error adicional durante el rollback en EliminarAsync Planta."); }
 | |
|                 _logger.LogWarning(knfex, "Intento de eliminar Planta ID: {Id} no encontrada.", id);
 | |
|                 return (false, "Planta no encontrada.");
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error adicional durante el rollback en EliminarAsync Planta."); }
 | |
|                 _logger.LogError(ex, "Error en transacción EliminarAsync para Planta ID: {Id}", id);
 | |
|                 return (false, $"Error interno al eliminar la planta: {ex.Message}");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public async Task<IEnumerable<PlantaDropdownDto>> ObtenerParaDropdownAsync()
 | |
|         {
 | |
|             var plantas = await _plantaRepository.GetAllAsync(null, null);
 | |
|             return plantas
 | |
|                 .OrderBy(p => p.Nombre)
 | |
|                 .Select(p => new PlantaDropdownDto { IdPlanta = p.IdPlanta, Nombre = p.Nombre })
 | |
|                 .ToList();
 | |
|         }
 | |
|     }
 | |
| } |