2025-06-09 19:37:07 -03:00
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 ( ) ; } }
}
2025-06-12 19:36:21 -03:00
public async Task < IEnumerable < CambioParadaHistorialDto > > ObtenerCambiosParadaHistorialAsync (
DateTime ? fechaDesde , DateTime ? fechaHasta ,
int? idUsuarioModifico , string? tipoModificacion ,
int? idCanillaAfectado )
{
var historialData = await _paradaRepo . GetCambiosParadaHistorialAsync ( fechaDesde , fechaHasta , idUsuarioModifico , tipoModificacion , idCanillaAfectado ) ;
return historialData . Select ( h = > new CambioParadaHistorialDto
{
Id_Registro = h . Historial . Id_Registro ,
Id_Canilla = h . Historial . Id_Canilla ,
NombreCanilla = h . NombreCanilla ,
Parada = h . Historial . Parada ,
VigenciaD = h . Historial . VigenciaD ,
VigenciaH = h . Historial . VigenciaH ? ? default ( DateTime ) ,
Id_Usuario = h . Historial . Id_Usuario ,
NombreUsuarioModifico = h . NombreUsuarioModifico ,
FechaMod = h . Historial . FechaMod ,
TipoMod = h . Historial . TipoMod
} ) . ToList ( ) ;
}
2025-06-09 19:37:07 -03:00
}
}