255 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			255 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using GestionIntegral.Api.Data; | ||
|  | using GestionIntegral.Api.Data.Repositories.Distribucion; | ||
|  | using GestionIntegral.Api.Dtos.Distribucion; | ||
|  | using GestionIntegral.Api.Models.Distribucion; | ||
|  | using Microsoft.Extensions.Logging; | ||
|  | using System.Collections.Generic; | ||
|  | using System.Data; | ||
|  | using System.Linq; | ||
|  | using System.Threading.Tasks; | ||
|  | 
 | ||
|  | namespace GestionIntegral.Api.Services.Distribucion | ||
|  | { | ||
|  |     public class CanillaService : ICanillaService | ||
|  |     { | ||
|  |         private readonly ICanillaRepository _canillaRepository; | ||
|  |         private readonly IZonaRepository _zonaRepository; | ||
|  |         private readonly IEmpresaRepository _empresaRepository; | ||
|  |         private readonly DbConnectionFactory _connectionFactory; | ||
|  |         private readonly ILogger<CanillaService> _logger; | ||
|  | 
 | ||
|  |         public CanillaService( | ||
|  |             ICanillaRepository canillaRepository, | ||
|  |             IZonaRepository zonaRepository, | ||
|  |             IEmpresaRepository empresaRepository, | ||
|  |             DbConnectionFactory connectionFactory, | ||
|  |             ILogger<CanillaService> logger) | ||
|  |         { | ||
|  |             _canillaRepository = canillaRepository; | ||
|  |             _zonaRepository = zonaRepository; | ||
|  |             _empresaRepository = empresaRepository; | ||
|  |             _connectionFactory = connectionFactory; | ||
|  |             _logger = logger; | ||
|  |         } | ||
|  | 
 | ||
|  |         // CORREGIDO: MapToDto ahora acepta una tupla con tipos anulables | ||
|  |         private CanillaDto? MapToDto((Canilla? Canilla, string? NombreZona, string? NombreEmpresa) data) | ||
|  |         { | ||
|  |             if (data.Canilla == null) return null; | ||
|  | 
 | ||
|  |             return new CanillaDto | ||
|  |             { | ||
|  |                 IdCanilla = data.Canilla.IdCanilla, | ||
|  |                 Legajo = data.Canilla.Legajo, | ||
|  |                 NomApe = data.Canilla.NomApe, | ||
|  |                 Parada = data.Canilla.Parada, | ||
|  |                 IdZona = data.Canilla.IdZona, | ||
|  |                 NombreZona = data.NombreZona ?? "N/A", // Manejar null | ||
|  |                 Accionista = data.Canilla.Accionista, | ||
|  |                 Obs = data.Canilla.Obs, | ||
|  |                 Empresa = data.Canilla.Empresa, | ||
|  |                 NombreEmpresa = data.NombreEmpresa ?? "N/A (Accionista)", // Manejar null | ||
|  |                 Baja = data.Canilla.Baja, | ||
|  |                 FechaBaja = data.Canilla.FechaBaja?.ToString("dd/MM/yyyy") | ||
|  |             }; | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<IEnumerable<CanillaDto>> ObtenerTodosAsync(string? nomApeFilter, int? legajoFilter, bool? soloActivos) | ||
|  |         { | ||
|  |             var canillasData = await _canillaRepository.GetAllAsync(nomApeFilter, legajoFilter, soloActivos); | ||
|  |             // Filtrar nulos y asegurar al compilador que no hay nulos en la lista final | ||
|  |             return canillasData.Select(MapToDto).Where(dto => dto != null).Select(dto => dto!); | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<CanillaDto?> ObtenerPorIdAsync(int id) | ||
|  |         { | ||
|  |             var data = await _canillaRepository.GetByIdAsync(id); | ||
|  |             // MapToDto ahora devuelve CanillaDto? así que esto es correcto | ||
|  |             return MapToDto(data); | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<(CanillaDto? Canilla, string? Error)> CrearAsync(CreateCanillaDto createDto, int idUsuario) | ||
|  |         { | ||
|  |             if (createDto.Legajo.HasValue && createDto.Legajo != 0 && await _canillaRepository.ExistsByLegajoAsync(createDto.Legajo.Value)) | ||
|  |             { | ||
|  |                 return (null, "El legajo ingresado ya existe para otro canillita."); | ||
|  |             } | ||
|  |             var zona = await _zonaRepository.GetByIdAsync(createDto.IdZona); // GetByIdAsync de Zona ya considera solo activas | ||
|  |             if (zona == null) | ||
|  |             { | ||
|  |                 return (null, "La zona seleccionada no es válida o no está activa."); | ||
|  |             } | ||
|  |             if (createDto.Empresa != 0) // Solo validar empresa si no es 0 | ||
|  |             { | ||
|  |                  var empresa = await _empresaRepository.GetByIdAsync(createDto.Empresa); | ||
|  |                  if(empresa == null) | ||
|  |                  { | ||
|  |                     return (null, "La empresa seleccionada no es válida."); | ||
|  |                  } | ||
|  |             } | ||
|  | 
 | ||
|  |             // CORREGIDO: Usar directamente el valor booleano | ||
|  |             if (createDto.Accionista == true && createDto.Empresa != 0) | ||
|  |             { | ||
|  |                 return (null, "Un canillita accionista no debe tener una empresa asignada (Empresa debe ser 0)."); | ||
|  |             } | ||
|  |             if (createDto.Accionista == false && createDto.Empresa == 0) | ||
|  |             { | ||
|  |                 return (null, "Un canillita no accionista debe tener una empresa asignada (Empresa no puede ser 0)."); | ||
|  |             } | ||
|  | 
 | ||
|  | 
 | ||
|  |             var nuevoCanilla = new Canilla | ||
|  |             { | ||
|  |                 Legajo = createDto.Legajo == 0 ? null : createDto.Legajo, | ||
|  |                 NomApe = createDto.NomApe, | ||
|  |                 Parada = createDto.Parada, | ||
|  |                 IdZona = createDto.IdZona, | ||
|  |                 Accionista = createDto.Accionista, | ||
|  |                 Obs = createDto.Obs, | ||
|  |                 Empresa = createDto.Empresa, | ||
|  |                 Baja = false, | ||
|  |                 FechaBaja = null | ||
|  |             }; | ||
|  | 
 | ||
|  |             using var connection = _connectionFactory.CreateConnection(); | ||
|  |             if (connection is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); else connection.Open(); | ||
|  |             using var transaction = connection.BeginTransaction(); | ||
|  | 
 | ||
|  |             try | ||
|  |             { | ||
|  |                 var canillaCreado = await _canillaRepository.CreateAsync(nuevoCanilla, idUsuario, transaction); | ||
|  |                 if (canillaCreado == null) throw new DataException("Error al crear el canillita."); | ||
|  | 
 | ||
|  |                 transaction.Commit(); | ||
|  |                  | ||
|  |                 // Para el DTO de respuesta, necesitamos NombreZona y NombreEmpresa | ||
|  |                 string nombreEmpresaParaDto = "N/A (Accionista)"; | ||
|  |                 if (canillaCreado.Empresa != 0) | ||
|  |                 { | ||
|  |                     var empresaData = await _empresaRepository.GetByIdAsync(canillaCreado.Empresa); | ||
|  |                     nombreEmpresaParaDto = empresaData?.Nombre ?? "Empresa Desconocida"; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 var dtoCreado = new CanillaDto { | ||
|  |                      IdCanilla = canillaCreado.IdCanilla, Legajo = canillaCreado.Legajo, NomApe = canillaCreado.NomApe, | ||
|  |                      Parada = canillaCreado.Parada, IdZona = canillaCreado.IdZona, NombreZona = zona.Nombre, // Usar nombre de zona ya obtenido | ||
|  |                      Accionista = canillaCreado.Accionista, Obs = canillaCreado.Obs, Empresa = canillaCreado.Empresa, | ||
|  |                      NombreEmpresa = nombreEmpresaParaDto, | ||
|  |                      Baja = canillaCreado.Baja, FechaBaja = null | ||
|  |                 }; | ||
|  | 
 | ||
|  |                 _logger.LogInformation("Canilla ID {IdCanilla} creado por Usuario ID {IdUsuario}.", canillaCreado.IdCanilla, idUsuario); | ||
|  |                 return (dtoCreado, null); | ||
|  |             } | ||
|  |             catch (Exception ex) | ||
|  |             { | ||
|  |                 try { transaction.Rollback(); } catch {} | ||
|  |                 _logger.LogError(ex, "Error CrearAsync Canilla: {NomApe}", createDto.NomApe); | ||
|  |                 return (null, $"Error interno al crear el canillita: {ex.Message}"); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<(bool Exito, string? Error)> ActualizarAsync(int id, UpdateCanillaDto updateDto, int idUsuario) | ||
|  |         { | ||
|  |             var canillaExistente = await _canillaRepository.GetByIdSimpleAsync(id); | ||
|  |             if (canillaExistente == null) return (false, "Canillita no encontrado."); | ||
|  | 
 | ||
|  |             if (updateDto.Legajo.HasValue && updateDto.Legajo != 0 && await _canillaRepository.ExistsByLegajoAsync(updateDto.Legajo.Value, id)) | ||
|  |             { | ||
|  |                 return (false, "El legajo ingresado ya existe para otro canillita."); | ||
|  |             } | ||
|  |             if (await _zonaRepository.GetByIdAsync(updateDto.IdZona) == null) // GetByIdAsync de Zona ya considera solo activas | ||
|  |             { | ||
|  |                 return (false, "La zona seleccionada no es válida o no está activa."); | ||
|  |             } | ||
|  |             if (updateDto.Empresa != 0) // Solo validar empresa si no es 0 | ||
|  |             { | ||
|  |                  var empresa = await _empresaRepository.GetByIdAsync(updateDto.Empresa); | ||
|  |                  if(empresa == null) | ||
|  |                  { | ||
|  |                     return (false, "La empresa seleccionada no es válida."); | ||
|  |                  } | ||
|  |             } | ||
|  | 
 | ||
|  |             // Usar directamente el valor booleano para Accionista | ||
|  |             if (updateDto.Accionista == true && updateDto.Empresa != 0) | ||
|  |             { | ||
|  |                 // Al ser 'bool', no puede ser null. La comparación explícita con 'true'/'false' es para claridad. | ||
|  |                 return (false, "Un canillita accionista no debe tener una empresa asignada (Empresa debe ser 0)."); | ||
|  |             } | ||
|  |             if (updateDto.Accionista == false && updateDto.Empresa == 0) | ||
|  |             { | ||
|  |                 return (false, "Un canillita no accionista debe tener una empresa asignada (Empresa no puede ser 0)."); | ||
|  |             } | ||
|  | 
 | ||
|  |             // Mapear DTO a entidad existente | ||
|  |             canillaExistente.Legajo = updateDto.Legajo == 0 ? null : updateDto.Legajo; | ||
|  |             canillaExistente.NomApe = updateDto.NomApe; | ||
|  |             canillaExistente.Parada = updateDto.Parada; | ||
|  |             canillaExistente.IdZona = updateDto.IdZona; | ||
|  |             canillaExistente.Accionista = updateDto.Accionista; // Aquí Accionista ya es bool | ||
|  |             canillaExistente.Obs = updateDto.Obs; | ||
|  |             canillaExistente.Empresa = updateDto.Empresa; | ||
|  |             // Baja y FechaBaja se manejan por ToggleBajaAsync | ||
|  | 
 | ||
|  |             using var connection = _connectionFactory.CreateConnection(); | ||
|  |             if (connection is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); else connection.Open(); | ||
|  |             using var transaction = connection.BeginTransaction(); | ||
|  | 
 | ||
|  |             try | ||
|  |             { | ||
|  |                 var actualizado = await _canillaRepository.UpdateAsync(canillaExistente, idUsuario, transaction); | ||
|  |                  if (!actualizado) throw new DataException("Error al actualizar el canillita."); | ||
|  |                 transaction.Commit(); | ||
|  |                 _logger.LogInformation("Canilla ID {IdCanilla} actualizado por Usuario ID {IdUsuario}.", id, idUsuario); | ||
|  |                 return (true, null); | ||
|  |             } | ||
|  |             catch (KeyNotFoundException) { | ||
|  |                 try { transaction.Rollback(); } catch {} | ||
|  |                 return (false, "Canillita no encontrado durante la actualización."); | ||
|  |             } | ||
|  |             catch (Exception ex) | ||
|  |             { | ||
|  |                 try { transaction.Rollback(); } catch {} | ||
|  |                 _logger.LogError(ex, "Error ActualizarAsync Canilla ID: {IdCanilla}", id); | ||
|  |                 return (false, $"Error interno al actualizar el canillita: {ex.Message}"); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<(bool Exito, string? Error)> ToggleBajaAsync(int id, bool darDeBaja, int idUsuario) | ||
|  |         { | ||
|  |             var canilla = await _canillaRepository.GetByIdSimpleAsync(id); | ||
|  |             if (canilla == null) return (false, "Canillita no encontrado."); | ||
|  | 
 | ||
|  |             if (canilla.Baja == darDeBaja) | ||
|  |             { | ||
|  |                 return (false, darDeBaja ? "El canillita ya está dado de baja." : "El canillita ya está activo."); | ||
|  |             } | ||
|  | 
 | ||
|  |             DateTime? fechaBaja = darDeBaja ? DateTime.Now : (DateTime?)null; | ||
|  | 
 | ||
|  |             using var connection = _connectionFactory.CreateConnection(); | ||
|  |             if (connection is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); else connection.Open(); | ||
|  |             using var transaction = connection.BeginTransaction(); | ||
|  |             try | ||
|  |             { | ||
|  |                 var success = await _canillaRepository.ToggleBajaAsync(id, darDeBaja, fechaBaja, idUsuario, transaction); | ||
|  |                 if (!success) throw new DataException("Error al cambiar estado de baja del canillita."); | ||
|  |                 transaction.Commit(); | ||
|  |                 _logger.LogInformation("Estado de baja cambiado a {EstadoBaja} para Canilla ID {IdCanilla} por Usuario ID {IdUsuario}.", darDeBaja, id, idUsuario); | ||
|  |                 return (true, null); | ||
|  |             } | ||
|  |             catch (KeyNotFoundException) { | ||
|  |                  try { transaction.Rollback(); } catch {} | ||
|  |                 return (false, "Canillita no encontrado durante el cambio de estado de baja."); | ||
|  |             } | ||
|  |             catch (Exception ex) | ||
|  |             { | ||
|  |                 try { transaction.Rollback(); } catch {} | ||
|  |                 _logger.LogError(ex, "Error ToggleBajaAsync Canilla ID: {IdCanilla}", id); | ||
|  |                 return (false, $"Error interno al cambiar estado de baja: {ex.Message}"); | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | } |