Files
GestionIntegralWeb/Backend/GestionIntegral.Api/Services/Distribucion/CambioParadaService.cs

185 lines
9.3 KiB
C#
Raw Normal View History

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;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
namespace GestionIntegral.Api.Services.Distribucion
{
public class CambioParadaService : ICambioParadaService
{
private readonly ICambioParadaRepository _paradaRepo;
private readonly ICanillaRepository _canillaRepo; // Para nombre y validación
private readonly DbConnectionFactory _connectionFactory;
private readonly ILogger<CambioParadaService> _logger;
public CambioParadaService(
ICambioParadaRepository paradaRepo,
ICanillaRepository canillaRepo,
DbConnectionFactory connectionFactory,
ILogger<CambioParadaService> logger)
{
_paradaRepo = paradaRepo;
_canillaRepo = canillaRepo;
_connectionFactory = connectionFactory;
_logger = logger;
}
private async Task<CambioParadaDto> MapToDto(CambioParadaCanilla parada)
{
var canillaData = await _canillaRepo.GetByIdAsync(parada.IdCanilla);
return new CambioParadaDto
{
IdRegistro = parada.IdRegistro,
IdCanilla = parada.IdCanilla,
NombreCanilla = canillaData.Canilla?.NomApe ?? "N/A",
Parada = parada.Parada,
VigenciaD = parada.VigenciaD.ToString("yyyy-MM-dd"),
VigenciaH = parada.VigenciaH?.ToString("yyyy-MM-dd")
};
}
public async Task<IEnumerable<CambioParadaDto>> ObtenerPorCanillaAsync(int idCanilla)
{
var paradas = await _paradaRepo.GetByCanillaAsync(idCanilla);
var dtos = new List<CambioParadaDto>();
foreach (var p in paradas) { dtos.Add(await MapToDto(p)); }
return dtos;
}
public async Task<CambioParadaDto?> ObtenerPorIdAsync(int idRegistro)
{
var parada = await _paradaRepo.GetByIdAsync(idRegistro);
return parada == null ? null : await MapToDto(parada);
}
public async Task<(CambioParadaDto? Parada, string? Error)> CrearNuevaParadaAsync(int idCanilla, CreateCambioParadaDto createDto, int idUsuario)
{
var canilla = await _canillaRepo.GetByIdSimpleAsync(idCanilla);
if (canilla == null) return (null, "Canillita no encontrado.");
if (createDto.VigenciaD.Date < DateTime.Today.AddYears(-5) || createDto.VigenciaD.Date > DateTime.Today.AddYears(5)) // Validación básica de fecha
return (null, "Fecha de Vigencia Desde inválida.");
using var connection = _connectionFactory.CreateConnection();
if (connection.State != ConnectionState.Open) { if (connection is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); else connection.Open(); }
using var transaction = connection.BeginTransaction();
try
{
// 1. Buscar la parada activa actual (si existe) para cerrarla
var paradaActual = await _paradaRepo.GetCurrentParadaAsync(idCanilla, transaction);
if (paradaActual != null)
{
if (createDto.VigenciaD.Date <= paradaActual.VigenciaD.Date)
{
transaction.Rollback();
return (null, "La Vigencia Desde de la nueva parada debe ser posterior a la Vigencia Desde de la parada activa actual.");
}
// Cerrar la parada actual estableciendo VigenciaH al día anterior de la nueva VigenciaD
DateTime vigenciaHAactual = createDto.VigenciaD.Date.AddDays(-1);
bool cerrada = await _paradaRepo.UpdateVigenciaHAsync(paradaActual.IdRegistro, vigenciaHAactual, idUsuario, transaction);
if (!cerrada) throw new DataException("No se pudo cerrar la parada activa anterior.");
_logger.LogInformation("Parada anterior ID {IdRegistro} cerrada con VigenciaH {VigenciaH}", paradaActual.IdRegistro, vigenciaHAactual);
}
// 2. Crear la nueva parada
var nuevaParada = new CambioParadaCanilla
{
IdCanilla = idCanilla,
Parada = createDto.Parada,
VigenciaD = createDto.VigenciaD.Date,
VigenciaH = null // Nueva parada siempre inicia activa
};
var paradaCreada = await _paradaRepo.CreateAsync(nuevaParada, idUsuario, transaction);
if (paradaCreada == null) throw new DataException("Error al crear el nuevo registro de parada.");
// 3. Actualizar la parada principal en dist_dtCanillas
canilla.Parada = paradaCreada.Parada; // Actualizar el campo Parada en la tabla principal
bool canillaActualizado = await _canillaRepo.UpdateAsync(canilla, idUsuario, transaction); // Asume que tu repo de canilla tiene UpdateAsync que toma la entidad
if (!canillaActualizado) throw new DataException("Error al actualizar la parada principal del canillita.");
transaction.Commit();
_logger.LogInformation("Nueva parada ID {IdRegistro} creada para Canilla ID {IdCanilla}. Parada principal actualizada.", paradaCreada.IdRegistro, idCanilla);
return (await MapToDto(paradaCreada), null);
}
catch (Exception ex)
{
try { transaction.Rollback(); } catch { }
_logger.LogError(ex, "Error en CrearNuevaParadaAsync para Canilla ID {IdCanilla}", idCanilla);
return (null, $"Error interno: {ex.Message}");
}
finally { if (connection.State == ConnectionState.Open) { if (connection is System.Data.Common.DbConnection dbConn) await dbConn.CloseAsync(); else connection.Close(); } }
}
public async Task<(bool Exito, string? Error)> CerrarParadaAsync(int idRegistro, UpdateCambioParadaDto updateDto, int idUsuario)
{
// Este método es para cerrar una parada manualmente si es necesario,
// por ejemplo, si se cometió un error y no se creó una nueva que la cierre.
var paradaExistente = await _paradaRepo.GetByIdAsync(idRegistro);
if (paradaExistente == null) return (false, "Registro de parada no encontrado.");
if (paradaExistente.VigenciaH.HasValue) return (false, "Esta parada ya tiene una fecha de Vigencia Hasta.");
if (updateDto.VigenciaH.Date < paradaExistente.VigenciaD.Date)
return (false, "La Vigencia Hasta no puede ser anterior a la Vigencia Desde.");
using var connection = _connectionFactory.CreateConnection();
if (connection.State != ConnectionState.Open) { if (connection is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); else connection.Open(); }
using var transaction = connection.BeginTransaction();
try
{
bool actualizada = await _paradaRepo.UpdateVigenciaHAsync(idRegistro, updateDto.VigenciaH.Date, idUsuario, transaction);
if (!actualizada) throw new DataException("Error al actualizar la Vigencia Hasta de la parada.");
// Opcional: Si esta era la parada activa en dist_dtCanillas, podrías querer limpiarla o marcarla de alguna forma
// Esto depende de si el campo 'Parada' en dist_dtCanillas siempre debe reflejar la última activa.
// Por simplicidad, no se actualiza dist_dtCanillas aquí al cerrar una parada manualmente.
transaction.Commit();
_logger.LogInformation("VigenciaH actualizada para Parada ID {IdRegistro}", idRegistro);
return (true, null);
}
catch (Exception ex)
{
try { transaction.Rollback(); } catch { }
_logger.LogError(ex, "Error al cerrar Parada ID {IdRegistro}", idRegistro);
return (false, $"Error interno: {ex.Message}");
}
finally { if (connection.State == ConnectionState.Open) { if (connection is System.Data.Common.DbConnection dbConn) await dbConn.CloseAsync(); else connection.Close(); } }
}
public async Task<(bool Exito, string? Error)> EliminarParadaAsync(int idRegistro, int idUsuario)
{
// La eliminación puede ser problemática si rompe la secuencia histórica.
// Considera si realmente quieres permitir esto o solo "cerrar" paradas.
var paradaExistente = await _paradaRepo.GetByIdAsync(idRegistro);
if (paradaExistente == null) return (false, "Registro de parada no encontrado.");
if (paradaExistente.VigenciaH == null)
return (false, "No se puede eliminar una parada activa. Primero debe cerrarla o crear una nueva que la reemplace.");
using var connection = _connectionFactory.CreateConnection();
if (connection.State != ConnectionState.Open) { if (connection is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); else connection.Open(); }
using var transaction = connection.BeginTransaction();
try
{
bool eliminado = await _paradaRepo.DeleteAsync(idRegistro, idUsuario, transaction);
if (!eliminado) throw new DataException("Error al eliminar el registro de parada.");
transaction.Commit();
_logger.LogInformation("Registro de Parada ID {IdRegistro} eliminado por Usuario ID {IdUsuario}", idRegistro, idUsuario);
return (true, null);
}
catch (Exception ex)
{
try { transaction.Rollback(); } catch { }
_logger.LogError(ex, "Error al eliminar Parada ID {IdRegistro}", idRegistro);
return (false, $"Error interno: {ex.Message}");
}
finally { if (connection.State == ConnectionState.Open) { if (connection is System.Data.Common.DbConnection dbConn) await dbConn.CloseAsync(); else connection.Close(); } }
}
}
}