feat(contables): cierre mensual de cuenta corriente de distribuidor

Permite congelar el saldo de un distribuidor por empresa a una fecha de
corte y bloquear modificaciones retroactivas sobre el período cerrado.
El saldo se calcula sumando movimientos en rango (sin tocar cue_Saldos).
Incluye reapertura controlada exclusivamente por SuperAdmin, reporte con
saldo inicial, atajo "Desde último cierre", y auditoría del ciclo de
vida _H. Permisos CC001/CC002/CC003. Middleware global mapea bloqueos
por período cerrado a HTTP 409.
This commit is contained in:
2026-05-07 12:03:26 -03:00
parent 7e274ef114
commit 24eaf18fd9
62 changed files with 2813 additions and 162 deletions

View File

@@ -53,12 +53,14 @@ namespace GestionIntegral.Api.Services.Reportes
Task<(IEnumerable<ComparativaConsumoBobinasDto> Data, string? Error)> ObtenerComparativaConsumoBobinasAsync(DateTime fechaInicioMesA, DateTime fechaFinMesA, DateTime fechaInicioMesB, DateTime fechaFinMesB, int idPlanta);
Task<(IEnumerable<ComparativaConsumoBobinasDto> Data, string? Error)> ObtenerComparativaConsumoBobinasConsolidadoAsync(DateTime fechaInicioMesA, DateTime fechaFinMesA, DateTime fechaInicioMesB, DateTime fechaFinMesB);
// DTOs para ReporteCuentasDistribuidores
// DTOs para ReporteCuentasDistribuidores.
// El antiguo IEnumerable<SaldoDto> Saldos (saldo actual del distribuidor, sin sentido temporal en un reporte por período)
// se reemplazó por decimal SaldoInicial calculado en base al último cierre vigente.
Task<(
IEnumerable<BalanceCuentaDistDto> EntradasSalidas,
IEnumerable<BalanceCuentaDebCredDto> DebitosCreditos,
IEnumerable<BalanceCuentaPagosDto> Pagos,
IEnumerable<SaldoDto> Saldos,
decimal SaldoInicial,
string? Error
)> ObtenerReporteCuentasDistribuidorAsync(int idDistribuidor, int idEmpresa, DateTime fechaDesde, DateTime fechaHasta);
Task<(IEnumerable<ListadoDistribucionDistSimpleDto> Simple, IEnumerable<ListadoDistribucionDistPromedioDiaDto> Promedios, string? Error)> ObtenerListadoDistribucionDistribuidoresAsync(int idDistribuidor, int idPublicacion, DateTime fechaDesde, DateTime fechaHasta);

View File

@@ -2,6 +2,7 @@ using GestionIntegral.Api.Data.Repositories.Distribucion;
using GestionIntegral.Api.Data.Repositories.Reportes;
using GestionIntegral.Api.Data.Repositories.Suscripciones;
using GestionIntegral.Api.Dtos.Reportes;
using GestionIntegral.Api.Services.Contables;
namespace GestionIntegral.Api.Services.Reportes
{
@@ -14,10 +15,11 @@ namespace GestionIntegral.Api.Services.Reportes
private readonly IEmpresaRepository _empresaRepository;
private readonly ISuscriptorRepository _suscriptorRepository;
private readonly ISuscripcionRepository _suscripcionRepository;
private readonly ICierreCuentaCorrienteService _cierreService;
private readonly ILogger<ReportesService> _logger;
public ReportesService(IReportesRepository reportesRepository, IFacturaRepository facturaRepository, IFacturaDetalleRepository facturaDetalleRepository, IPublicacionRepository publicacionRepository, IEmpresaRepository empresaRepository
, ISuscriptorRepository suscriptorRepository, ISuscripcionRepository suscripcionRepository, ILogger<ReportesService> logger)
, ISuscriptorRepository suscriptorRepository, ISuscripcionRepository suscripcionRepository, ICierreCuentaCorrienteService cierreService, ILogger<ReportesService> logger)
{
_reportesRepository = reportesRepository;
_facturaRepository = facturaRepository;
@@ -26,6 +28,7 @@ namespace GestionIntegral.Api.Services.Reportes
_empresaRepository = empresaRepository;
_suscriptorRepository = suscriptorRepository;
_suscripcionRepository = suscripcionRepository;
_cierreService = cierreService;
_logger = logger;
}
@@ -420,26 +423,28 @@ namespace GestionIntegral.Api.Services.Reportes
}
}
// Implementación para ReporteCuentasDistribuidores
// Implementación para ReporteCuentasDistribuidores.
// Reemplaza el campo legacy "Saldos" (saldo actual sin sentido temporal) por "SaldoInicial":
// saldo del último cierre + movimientos netos hasta fechaDesde-1 (0 si no hay cierre previo).
public async Task<(
IEnumerable<BalanceCuentaDistDto> EntradasSalidas,
IEnumerable<BalanceCuentaDebCredDto> DebitosCreditos,
IEnumerable<BalanceCuentaPagosDto> Pagos,
IEnumerable<SaldoDto> Saldos,
decimal SaldoInicial,
string? Error
)> ObtenerReporteCuentasDistribuidorAsync(int idDistribuidor, int idEmpresa, DateTime fechaDesde, DateTime fechaHasta)
{
if (fechaDesde > fechaHasta)
return (Enumerable.Empty<BalanceCuentaDistDto>(), Enumerable.Empty<BalanceCuentaDebCredDto>(), Enumerable.Empty<BalanceCuentaPagosDto>(), Enumerable.Empty<SaldoDto>(), "Fecha 'Desde' no puede ser mayor que 'Hasta'.");
return (Enumerable.Empty<BalanceCuentaDistDto>(), Enumerable.Empty<BalanceCuentaDebCredDto>(), Enumerable.Empty<BalanceCuentaPagosDto>(), 0m, "Fecha 'Desde' no puede ser mayor que 'Hasta'.");
try
{
var esTask = _reportesRepository.GetBalanceCuentaDistEntradaSalidaPorEmpresaAsync(idDistribuidor, idEmpresa, fechaDesde, fechaHasta);
var dcTask = _reportesRepository.GetBalanceCuentDistDebCredEmpresaAsync(idDistribuidor, idEmpresa, fechaDesde, fechaHasta);
var paTask = _reportesRepository.GetBalanceCuentDistPagosEmpresaAsync(idDistribuidor, idEmpresa, fechaDesde, fechaHasta);
var saTask = _reportesRepository.GetBalanceCuentSaldosEmpresasAsync("Distribuidores", idDistribuidor, idEmpresa);
var siTask = _cierreService.CalcularSaldoInicialReporteAsync(idDistribuidor, idEmpresa, fechaDesde);
await Task.WhenAll(esTask, dcTask, paTask, saTask);
await Task.WhenAll(esTask, dcTask, paTask, siTask);
Func<IEnumerable<BalanceCuentaDistDto>, IEnumerable<BalanceCuentaDistDto>> esToUtc =
items => items?.Select(i => { i.Fecha = DateTime.SpecifyKind(i.Fecha.Date, DateTimeKind.Utc); return i; }).ToList()
@@ -455,7 +460,7 @@ namespace GestionIntegral.Api.Services.Reportes
esToUtc(await esTask),
dcToUtc(await dcTask),
paToUtc(await paTask),
await saTask ?? Enumerable.Empty<SaldoDto>(),
await siTask,
null
);
}
@@ -466,7 +471,7 @@ namespace GestionIntegral.Api.Services.Reportes
Enumerable.Empty<BalanceCuentaDistDto>(),
Enumerable.Empty<BalanceCuentaDebCredDto>(),
Enumerable.Empty<BalanceCuentaPagosDto>(),
Enumerable.Empty<SaldoDto>(),
0m,
"Error interno al generar el reporte."
);
}