185 lines
9.3 KiB
C#
185 lines
9.3 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;
|
||
|
|
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(); } }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|