using GestionIntegral.Api.Data.Repositories.Reportes; using GestionIntegral.Api.Dtos.Reportes; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace GestionIntegral.Api.Services.Reportes { public class ReportesService : IReportesService { private readonly IReportesRepository _reportesRepository; private readonly ILogger _logger; // No necesitas _connectionFactory aquí si toda la lógica de BD está en el repositorio. public ReportesService(IReportesRepository reportesRepository, ILogger logger) { _reportesRepository = reportesRepository; _logger = logger; } public async Task<(IEnumerable Data, string? Error)> ObtenerExistenciaPapelAsync( DateTime fechaDesde, DateTime fechaHasta, int? idPlanta, bool consolidado) { if (fechaDesde > fechaHasta) { return (Enumerable.Empty(), "La fecha 'Desde' no puede ser mayor que la fecha 'Hasta'."); } if (!consolidado && !idPlanta.HasValue) { return (Enumerable.Empty(), "Se requiere un ID de planta para reportes no consolidados."); } try { var dataFromRepo = await _reportesRepository.GetExistenciaPapelAsync(fechaDesde, fechaHasta, idPlanta, consolidado); var dataWithUtcDates = dataFromRepo.Select(dto => { if (dto.FechaEstimacionFinStock.HasValue) { dto.FechaEstimacionFinStock = DateTime.SpecifyKind(dto.FechaEstimacionFinStock.Value.Date, DateTimeKind.Utc); } return dto; }).ToList(); return (dataWithUtcDates, null); } catch (ArgumentNullException ex) when (ex.ParamName == "idPlanta") { _logger.LogWarning(ex, "ArgumentNullException para idPlanta en ObtenerExistenciaPapelAsync."); return (Enumerable.Empty(), ex.Message); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Existencia de Papel."); return (Enumerable.Empty(), "Error interno al generar el reporte de existencia de papel."); } } public async Task<(IEnumerable Data, string? Error)> ObtenerMovimientoBobinasAsync(DateTime fechaDesde, DateTime fechaHasta, int idPlanta) { if (fechaDesde > fechaHasta) { return (Enumerable.Empty(), "La fecha 'Desde' no puede ser mayor que la fecha 'Hasta'."); } int diasPeriodo = (fechaHasta.Date - fechaDesde.Date).Days + 1; try { var data = await _reportesRepository.GetMovimientoBobinasAsync(fechaDesde.Date, diasPeriodo, idPlanta); return (data, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Movimiento de Bobinas."); return (Enumerable.Empty(), "Error interno al generar el reporte de movimiento de bobinas."); } } public async Task<(IEnumerable Detalle, IEnumerable Totales, string? Error)> ObtenerMovimientoBobinasPorEstadoAsync(DateTime fechaDesde, DateTime fechaHasta, int idPlanta) { if (fechaDesde > fechaHasta) { return (Enumerable.Empty(), Enumerable.Empty(), "La fecha 'Desde' no puede ser mayor que la fecha 'Hasta'."); } try { var detalle = await _reportesRepository.GetMovimientoBobinasEstadoDetalleAsync(fechaDesde.Date, fechaHasta.Date, idPlanta); var totales = await _reportesRepository.GetMovimientoBobinasEstadoTotalesAsync(fechaDesde.Date, fechaHasta.Date, idPlanta); var detalleUtc = detalle.Select(d => { d.FechaMovimiento = DateTime.SpecifyKind(d.FechaMovimiento, DateTimeKind.Utc); return d; }).ToList(); return (detalleUtc, totales, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Movimiento de Bobinas por Estado."); return (Enumerable.Empty(), Enumerable.Empty(), "Error interno al generar el reporte de movimiento de bobinas por estado."); } } public async Task<(IEnumerable Resumen, IEnumerable Promedios, string? Error)> ObtenerListadoDistribucionGeneralAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta) { if (fechaDesde > fechaHasta) return (Enumerable.Empty(), Enumerable.Empty(), "La fecha 'Desde' no puede ser mayor que la fecha 'Hasta'."); try { // El SP SP_DistObtenerResumenMensual usa Mes y Año de fechaDesde. // El SP SP_DistObtenerResumenMensualPorDiaSemana también. var resumenData = await _reportesRepository.GetListadoDistribucionGeneralResumenAsync(idPublicacion, fechaDesde, fechaHasta); var promediosData = await _reportesRepository.GetListadoDistribucionGeneralPromedioDiaAsync(idPublicacion, fechaDesde, fechaHasta); var resumenUtc = resumenData.Select(r => { r.Fecha = DateTime.SpecifyKind(r.Fecha, DateTimeKind.Utc); return r; }).ToList(); return (resumenUtc, promediosData, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Listado Distribucion General."); return (Enumerable.Empty(), Enumerable.Empty(), "Error interno al generar el reporte."); } } public async Task<(IEnumerable Simple, IEnumerable Promedios, string? Error)> ObtenerListadoDistribucionCanillasAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta) { if (fechaDesde > fechaHasta) return (Enumerable.Empty(), Enumerable.Empty(), "La fecha 'Desde' no puede ser mayor que la fecha 'Hasta'."); try { var simpleData = await _reportesRepository.GetListadoDistribucionCanillasSimpleAsync(idPublicacion, fechaDesde, fechaHasta); var promediosData = await _reportesRepository.GetListadoDistribucionCanillasPromedioDiaAsync(idPublicacion, fechaDesde, fechaHasta); return (simpleData, promediosData, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Listado Distribucion Canillas."); return (Enumerable.Empty(), Enumerable.Empty(), "Error interno al generar el reporte."); } } public async Task<(IEnumerable Data, string? Error)> ObtenerListadoDistribucionCanillasConImporteAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta, bool esAccionista) { if (fechaDesde > fechaHasta) return (Enumerable.Empty(), "La fecha 'Desde' no puede ser mayor que la fecha 'Hasta'."); try { var data = await _reportesRepository.GetListadoDistribucionCanillasImporteAsync(idPublicacion, fechaDesde, fechaHasta, esAccionista); return (data, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Listado Distribucion Canillas con Importe."); return (Enumerable.Empty(), "Error interno al generar el reporte."); } } public async Task<(IEnumerable Data, string? Error)> ObtenerVentaMensualSecretariaElDiaAsync(DateTime fechaDesde, DateTime fechaHasta) { if (fechaDesde > fechaHasta) return (Enumerable.Empty(), "La fecha 'Desde' no puede ser mayor que la fecha 'Hasta'."); try { var data = await _reportesRepository.GetVentaMensualSecretariaElDiaAsync(fechaDesde, fechaHasta); return (data, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Venta Mensual Secretaria El Dia."); return (Enumerable.Empty(), "Error interno al generar el reporte."); } } public async Task<(IEnumerable Data, string? Error)> ObtenerVentaMensualSecretariaElPlataAsync(DateTime fechaDesde, DateTime fechaHasta) { if (fechaDesde > fechaHasta) return (Enumerable.Empty(), "La fecha 'Desde' no puede ser mayor que la fecha 'Hasta'."); try { var data = await _reportesRepository.GetVentaMensualSecretariaElPlataAsync(fechaDesde, fechaHasta); return (data, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Venta Mensual Secretaria El Plata."); return (Enumerable.Empty(), "Error interno al generar el reporte."); } } public async Task<(IEnumerable Data, string? Error)> ObtenerVentaMensualSecretariaTirDevoAsync(DateTime fechaDesde, DateTime fechaHasta) { if (fechaDesde > fechaHasta) return (Enumerable.Empty(), "La fecha 'Desde' no puede ser mayor que la fecha 'Hasta'."); try { var data = await _reportesRepository.GetVentaMensualSecretariaTirDevoAsync(fechaDesde, fechaHasta); return (data, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Venta Mensual Secretaria Tirada/Devolucion."); return (Enumerable.Empty(), "Error interno al generar el reporte."); } } public async Task<( IEnumerable Canillas, IEnumerable CanillasAcc, IEnumerable CanillasAll, IEnumerable CanillasFechaLiq, IEnumerable CanillasAccFechaLiq, IEnumerable CtrlDevolucionesRemitos, IEnumerable CtrlDevolucionesParaDistCan, IEnumerable CtrlDevolucionesOtrosDias, string? Error )> ObtenerReporteDistribucionCanillasAsync(DateTime fecha, int idEmpresa) { try { var canillasTask = _reportesRepository.GetDetalleDistribucionCanillasPubliAsync(fecha, idEmpresa); var canillasAccTask = _reportesRepository.GetDetalleDistribucionCanillasAccPubliAsync(fecha, idEmpresa); var canillasAllTask = _reportesRepository.GetDetalleDistribucionCanillasAllPubliAsync(fecha, idEmpresa); var canillasFechaLiqTask = _reportesRepository.GetDetalleDistribucionCanillasPubliFechaLiqAsync(fecha, idEmpresa); var canillasAccFechaLiqTask = _reportesRepository.GetDetalleDistribucionCanillasAccPubliFechaLiqAsync(fecha, idEmpresa); var ctrlDevolucionesRemitosTask = _reportesRepository.GetReporteObtenerCtrlDevolucionesAsync(fecha, idEmpresa); // SP_ObtenerCtrlDevoluciones var ctrlDevolucionesParaDistCanTask = _reportesRepository.GetReporteCtrlDevolucionesParaDistCanAsync(fecha, idEmpresa); // SP_DistCanillasCantidadEntradaSalida var ctrlDevolucionesOtrosDiasTask = _reportesRepository.GetEntradaSalidaOtrosDiasAsync(fecha, idEmpresa); // SP_DistCanillasCantidadEntradaSalidaOtrosDias await Task.WhenAll( canillasTask, canillasAccTask, canillasAllTask, canillasFechaLiqTask, canillasAccFechaLiqTask, ctrlDevolucionesRemitosTask, ctrlDevolucionesParaDistCanTask, ctrlDevolucionesOtrosDiasTask ); Func, IEnumerable> toUtc = items => items?.Select(c => { if (c.Fecha.HasValue) c.Fecha = DateTime.SpecifyKind(c.Fecha.Value.Date, DateTimeKind.Utc); return c; }).ToList() ?? Enumerable.Empty(); return ( toUtc(await canillasTask), toUtc(await canillasAccTask), await canillasAllTask ?? Enumerable.Empty(), toUtc(await canillasFechaLiqTask), toUtc(await canillasAccFechaLiqTask), await ctrlDevolucionesRemitosTask ?? Enumerable.Empty(), await ctrlDevolucionesParaDistCanTask ?? Enumerable.Empty(), await ctrlDevolucionesOtrosDiasTask ?? Enumerable.Empty(), null ); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Reporte Distribucion Canillas para fecha {Fecha} y empresa {IdEmpresa}.", fecha, idEmpresa); return ( Enumerable.Empty(), Enumerable.Empty(), Enumerable.Empty(), Enumerable.Empty(), Enumerable.Empty(), Enumerable.Empty(), Enumerable.Empty(), Enumerable.Empty(), "Error interno al generar el reporte de distribución de canillas." ); } } public async Task<(IEnumerable Data, string? Error)> ObtenerTiradasPublicacionesSeccionesAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta, int idPlanta) { if (fechaDesde > fechaHasta) return (Enumerable.Empty(), "Fecha 'Desde' no puede ser mayor que 'Hasta'."); try { var data = await _reportesRepository.GetTiradasPublicacionesSeccionesAsync(idPublicacion, fechaDesde, fechaHasta, idPlanta); return (data, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Tiradas por Publicación y Secciones."); return (Enumerable.Empty(), "Error interno al generar el reporte."); } } public async Task<(IEnumerable Data, string? Error)> ObtenerTiradasPublicacionesSeccionesConsolidadoAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta) { if (fechaDesde > fechaHasta) return (Enumerable.Empty(), "Fecha 'Desde' no puede ser mayor que 'Hasta'."); try { var data = await _reportesRepository.GetTiradasPublicacionesSeccionesConsolidadoAsync(idPublicacion, fechaDesde, fechaHasta); return (data, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Tiradas por Publicación y Secciones (Consolidado)."); return (Enumerable.Empty(), "Error interno al generar el reporte."); } } public async Task<(IEnumerable Data, string? Error)> ObtenerConsumoBobinasPorSeccionAsync(DateTime fechaDesde, DateTime fechaHasta, int idPlanta) { if (fechaDesde > fechaHasta) return (Enumerable.Empty(), "Fecha 'Desde' no puede ser mayor que 'Hasta'."); try { var data = await _reportesRepository.GetConsumoBobinasPorSeccionAsync(fechaDesde, fechaHasta, idPlanta); return (data, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Consumo de Bobinas por Sección."); return (Enumerable.Empty(), "Error interno al generar el reporte."); } } public async Task<(IEnumerable Data, string? Error)> ObtenerConsumoBobinasPorSeccionConsolidadoAsync(DateTime fechaDesde, DateTime fechaHasta) { if (fechaDesde > fechaHasta) return (Enumerable.Empty(), "Fecha 'Desde' no puede ser mayor que 'Hasta'."); try { var data = await _reportesRepository.GetConsumoBobinasPorSeccionConsolidadoAsync(fechaDesde, fechaHasta); return (data, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Consumo de Bobinas por Sección (Consolidado)."); return (Enumerable.Empty(), "Error interno al generar el reporte."); } } public async Task<(IEnumerable Data, string? Error)> ObtenerConsumoBobinasPorPublicacionAsync(DateTime fechaDesde, DateTime fechaHasta) { if (fechaDesde > fechaHasta) return (Enumerable.Empty(), "Fecha 'Desde' no puede ser mayor que 'Hasta'."); try { var data = await _reportesRepository.GetConsumoBobinasPorPublicacionAsync(fechaDesde, fechaHasta); return (data, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Consumo de Bobinas por Publicación."); return (Enumerable.Empty(), "Error interno al generar el reporte."); } } public async Task<(IEnumerable Data, string? Error)> ObtenerComparativaConsumoBobinasAsync(DateTime fechaInicioMesA, DateTime fechaFinMesA, DateTime fechaInicioMesB, DateTime fechaFinMesB, int idPlanta) { if (fechaInicioMesA > fechaFinMesA || fechaInicioMesB > fechaFinMesB) return (Enumerable.Empty(), "Fechas de inicio no pueden ser mayores que las de fin para los meses."); try { var data = await _reportesRepository.GetComparativaConsumoBobinasAsync(fechaInicioMesA, fechaFinMesA, fechaInicioMesB, fechaFinMesB, idPlanta); return (data, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Comparativa de Consumo de Bobinas."); return (Enumerable.Empty(), "Error interno al generar el reporte."); } } public async Task<(IEnumerable Data, string? Error)> ObtenerComparativaConsumoBobinasConsolidadoAsync(DateTime fechaInicioMesA, DateTime fechaFinMesA, DateTime fechaInicioMesB, DateTime fechaFinMesB) { if (fechaInicioMesA > fechaFinMesA || fechaInicioMesB > fechaFinMesB) return (Enumerable.Empty(), "Fechas de inicio no pueden ser mayores que las de fin para los meses."); try { var data = await _reportesRepository.GetComparativaConsumoBobinasConsolidadoAsync(fechaInicioMesA, fechaFinMesA, fechaInicioMesB, fechaFinMesB); return (data, null); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Comparativa de Consumo de Bobinas (Consolidado)."); return (Enumerable.Empty(), "Error interno al generar el reporte."); } } // Implementación para ReporteCuentasDistribuidores public async Task<( IEnumerable EntradasSalidas, IEnumerable DebitosCreditos, IEnumerable Pagos, IEnumerable Saldos, string? Error )> ObtenerReporteCuentasDistribuidorAsync(int idDistribuidor, int idEmpresa, DateTime fechaDesde, DateTime fechaHasta) { if (fechaDesde > fechaHasta) return (Enumerable.Empty(), Enumerable.Empty(), Enumerable.Empty(), Enumerable.Empty(), "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); await Task.WhenAll(esTask, dcTask, paTask, saTask); Func, IEnumerable> esToUtc = items => items?.Select(i => { i.Fecha = DateTime.SpecifyKind(i.Fecha.Date, DateTimeKind.Utc); return i; }).ToList() ?? Enumerable.Empty(); Func, IEnumerable> dcToUtc = items => items?.Select(i => { i.Fecha = DateTime.SpecifyKind(i.Fecha.Date, DateTimeKind.Utc); return i; }).ToList() ?? Enumerable.Empty(); Func, IEnumerable> paToUtc = items => items?.Select(i => { i.Fecha = DateTime.SpecifyKind(i.Fecha.Date, DateTimeKind.Utc); return i; }).ToList() ?? Enumerable.Empty(); return ( esToUtc(await esTask), dcToUtc(await dcTask), paToUtc(await paTask), await saTask ?? Enumerable.Empty(), null ); } catch (Exception ex) { _logger.LogError(ex, "Error en ReportesService al obtener Reporte Cuentas Distribuidor."); return ( Enumerable.Empty(), Enumerable.Empty(), Enumerable.Empty(), Enumerable.Empty(), "Error interno al generar el reporte." ); } } } }