2025-08-01 14:38:15 -03:00
using GestionIntegral.Api.Data ;
using GestionIntegral.Api.Data.Repositories.Suscripciones ;
using GestionIntegral.Api.Data.Repositories.Usuarios ;
using GestionIntegral.Api.Dtos.Suscripciones ;
using GestionIntegral.Api.Models.Suscripciones ;
using System.Data ;
namespace GestionIntegral.Api.Services.Suscripciones
{
public class AjusteService : IAjusteService
{
private readonly IAjusteRepository _ajusteRepository ;
private readonly ISuscriptorRepository _suscriptorRepository ;
private readonly IUsuarioRepository _usuarioRepository ;
private readonly DbConnectionFactory _connectionFactory ;
private readonly ILogger < AjusteService > _logger ;
public AjusteService (
IAjusteRepository ajusteRepository ,
ISuscriptorRepository suscriptorRepository ,
IUsuarioRepository usuarioRepository ,
DbConnectionFactory connectionFactory ,
ILogger < AjusteService > logger )
{
_ajusteRepository = ajusteRepository ;
_suscriptorRepository = suscriptorRepository ;
_usuarioRepository = usuarioRepository ;
_connectionFactory = connectionFactory ;
_logger = logger ;
}
private async Task < AjusteDto ? > MapToDto ( Ajuste ajuste )
{
if ( ajuste = = null ) return null ;
var usuario = await _usuarioRepository . GetByIdAsync ( ajuste . IdUsuarioAlta ) ;
return new AjusteDto
{
IdAjuste = ajuste . IdAjuste ,
IdSuscriptor = ajuste . IdSuscriptor ,
2025-08-08 09:48:15 -03:00
FechaAjuste = ajuste . FechaAjuste . ToString ( "yyyy-MM-dd" ) ,
2025-08-01 14:38:15 -03:00
TipoAjuste = ajuste . TipoAjuste ,
Monto = ajuste . Monto ,
Motivo = ajuste . Motivo ,
Estado = ajuste . Estado ,
IdFacturaAplicado = ajuste . IdFacturaAplicado ,
FechaAlta = ajuste . FechaAlta . ToString ( "yyyy-MM-dd HH:mm" ) ,
NombreUsuarioAlta = usuario ! = null ? $"{usuario.Nombre} {usuario.Apellido}" : "N/A"
} ;
}
2025-08-08 09:48:15 -03:00
public async Task < IEnumerable < AjusteDto > > ObtenerAjustesPorSuscriptor ( int idSuscriptor , DateTime ? fechaDesde , DateTime ? fechaHasta )
2025-08-01 14:38:15 -03:00
{
2025-08-08 09:48:15 -03:00
var ajustes = await _ajusteRepository . GetAjustesPorSuscriptorAsync ( idSuscriptor , fechaDesde , fechaHasta ) ;
2025-08-01 14:38:15 -03:00
var dtosTasks = ajustes . Select ( a = > MapToDto ( a ) ) ;
var dtos = await Task . WhenAll ( dtosTasks ) ;
return dtos . Where ( dto = > dto ! = null ) ! ;
}
public async Task < ( AjusteDto ? Ajuste , string? Error ) > CrearAjusteManual ( CreateAjusteDto createDto , int idUsuario )
{
var suscriptor = await _suscriptorRepository . GetByIdAsync ( createDto . IdSuscriptor ) ;
if ( suscriptor = = null )
{
return ( null , "El suscriptor especificado no existe." ) ;
}
2025-08-08 09:48:15 -03:00
2025-08-01 14:38:15 -03:00
var nuevoAjuste = new Ajuste
{
IdSuscriptor = createDto . IdSuscriptor ,
2025-08-08 09:48:15 -03:00
FechaAjuste = createDto . FechaAjuste . Date ,
2025-08-01 14:38:15 -03:00
TipoAjuste = createDto . TipoAjuste ,
Monto = createDto . Monto ,
Motivo = createDto . Motivo ,
IdUsuarioAlta = idUsuario
} ;
using var connection = _connectionFactory . CreateConnection ( ) ;
await ( connection as System . Data . Common . DbConnection ) ! . OpenAsync ( ) ;
using var transaction = connection . BeginTransaction ( ) ;
try
{
var ajusteCreado = await _ajusteRepository . CreateAsync ( nuevoAjuste , transaction ) ;
if ( ajusteCreado = = null ) throw new DataException ( "Error al crear el registro de ajuste." ) ;
transaction . Commit ( ) ;
_logger . LogInformation ( "Ajuste manual ID {IdAjuste} creado para Suscriptor ID {IdSuscriptor} por Usuario ID {IdUsuario}" , ajusteCreado . IdAjuste , ajusteCreado . IdSuscriptor , idUsuario ) ;
var dto = await MapToDto ( ajusteCreado ) ;
return ( dto , null ) ;
}
catch ( Exception ex )
{
try { transaction . Rollback ( ) ; } catch { }
_logger . LogError ( ex , "Error al crear ajuste manual para Suscriptor ID {IdSuscriptor}" , createDto . IdSuscriptor ) ;
return ( null , "Error interno al registrar el ajuste." ) ;
}
}
public async Task < ( bool Exito , string? Error ) > AnularAjuste ( int idAjuste , int idUsuario )
{
using var connection = _connectionFactory . CreateConnection ( ) ;
await ( connection as System . Data . Common . DbConnection ) ! . OpenAsync ( ) ;
using var transaction = connection . BeginTransaction ( ) ;
try
{
var ajuste = await _ajusteRepository . GetByIdAsync ( idAjuste ) ;
if ( ajuste = = null ) return ( false , "Ajuste no encontrado." ) ;
if ( ajuste . Estado ! = "Pendiente" ) return ( false , $"No se puede anular un ajuste en estado '{ajuste.Estado}'." ) ;
var exito = await _ajusteRepository . AnularAjusteAsync ( idAjuste , idUsuario , transaction ) ;
if ( ! exito ) throw new DataException ( "No se pudo anular el ajuste." ) ;
transaction . Commit ( ) ;
_logger . LogInformation ( "Ajuste ID {IdAjuste} anulado por Usuario ID {IdUsuario}" , idAjuste , idUsuario ) ;
return ( true , null ) ;
}
catch ( Exception ex )
{
try { transaction . Rollback ( ) ; } catch { }
_logger . LogError ( ex , "Error al anular ajuste ID {IdAjuste}" , idAjuste ) ;
return ( false , "Error interno al anular el ajuste." ) ;
}
}
2025-08-08 09:48:15 -03:00
public async Task < ( bool Exito , string? Error ) > ActualizarAjuste ( int idAjuste , UpdateAjusteDto updateDto )
{
using var connection = _connectionFactory . CreateConnection ( ) ;
await ( connection as System . Data . Common . DbConnection ) ! . OpenAsync ( ) ;
using var transaction = connection . BeginTransaction ( ) ;
try
{
var ajuste = await _ajusteRepository . GetByIdAsync ( idAjuste ) ;
if ( ajuste = = null ) return ( false , "Ajuste no encontrado." ) ;
if ( ajuste . Estado ! = "Pendiente" ) return ( false , $"No se puede modificar un ajuste en estado '{ajuste.Estado}'." ) ;
ajuste . FechaAjuste = updateDto . FechaAjuste ;
ajuste . TipoAjuste = updateDto . TipoAjuste ;
ajuste . Monto = updateDto . Monto ;
ajuste . Motivo = updateDto . Motivo ;
var actualizado = await _ajusteRepository . UpdateAsync ( ajuste , transaction ) ;
if ( ! actualizado ) throw new DataException ( "La actualización falló o el ajuste ya no estaba pendiente." ) ;
transaction . Commit ( ) ;
_logger . LogInformation ( "Ajuste ID {IdAjuste} actualizado." , idAjuste ) ;
return ( true , null ) ;
}
catch ( Exception ex )
{
try { transaction . Rollback ( ) ; } catch { }
_logger . LogError ( ex , "Error al actualizar ajuste ID {IdAjuste}" , idAjuste ) ;
return ( false , "Error interno al actualizar el ajuste." ) ;
}
}
2025-08-01 14:38:15 -03:00
}
}