Se introduce una nueva funcionalidad de reporte crucial para la logística y se realiza una refactorización mayor del sistema de ajustes para garantizar la correcta imputación contable. ### ✨ Nuevas Características - **Nuevo Reporte de Distribución de Suscripciones (RR011):** - Se añade un nuevo reporte en PDF que genera un listado de todas las suscripciones activas en un rango de fechas. - El reporte está diseñado para el equipo de reparto, incluyendo datos clave como nombre del suscriptor, dirección, teléfono, días de entrega y observaciones. - Se implementa el endpoint, la lógica de servicio, la consulta a la base de datos y el template de QuestPDF en el backend. - Se crea la página correspondiente en el frontend (React) con su selector de fechas y se añade la ruta y el enlace en el menú de reportes. ### 🔄 Refactorización Mayor - **Asociación de Ajustes a Empresas:** - Se refactoriza por completo la entidad `Ajuste` para incluir una referencia obligatoria a una `IdEmpresa`. - **Motivo:** Corregir un error crítico en la lógica de negocio donde los ajustes de un suscriptor se aplicaban a la primera factura generada, sin importar a qué empresa correspondía el ajuste. - Se provee un script de migración SQL para actualizar el esquema de la base de datos (`susc_Ajustes`). - Se actualizan todos los DTOs, repositorios y servicios (backend) para manejar la nueva relación. - Se modifica el `FacturacionService` para que ahora aplique los ajustes pendientes correspondientes a cada empresa dentro de su bucle de facturación. - Se actualiza el formulario de creación/edición de ajustes en el frontend (React) para incluir un selector de empresa obligatorio. ### ⚡️ Optimizaciones de Rendimiento - **Solución de N+1 Queries:** - Se optimiza el método `ObtenerTodos` en `SuscriptorService` para obtener todas las formas de pago en una única consulta en lugar de una por cada suscriptor. - Se optimiza el método `ObtenerAjustesPorSuscriptor` en `AjusteService` para obtener todos los nombres de usuarios y empresas en dos consultas masivas, en lugar de N consultas individuales. - Se añade el método `GetByIdsAsync` al `IUsuarioRepository` y su implementación para soportar esta optimización. ### 🐛 Corrección de Errores - Se corrigen múltiples errores en el script de migración de base de datos (uso de `GO` dentro de transacciones, error de "columna inválida"). - Se soluciona un error de SQL (`INSERT` statement) en `AjusteRepository` que impedía la creación de nuevos ajustes. - Se corrige un bug en el `AjusteService` que causaba que el nombre de la empresa apareciera como "N/A" en la UI debido a un mapeo incompleto en el método optimizado. - Se corrige la lógica de generación de emails en `FacturacionService` para mostrar correctamente el nombre de la empresa en cada sección del resumen de cuenta.
572 lines
32 KiB
C#
572 lines
32 KiB
C#
using GestionIntegral.Api.Data.Repositories.Distribucion;
|
|
using GestionIntegral.Api.Data.Repositories.Reportes;
|
|
using GestionIntegral.Api.Data.Repositories.Suscripciones;
|
|
using GestionIntegral.Api.Dtos.Reportes;
|
|
|
|
namespace GestionIntegral.Api.Services.Reportes
|
|
{
|
|
public class ReportesService : IReportesService
|
|
{
|
|
private readonly IReportesRepository _reportesRepository;
|
|
private readonly IFacturaRepository _facturaRepository;
|
|
private readonly IFacturaDetalleRepository _facturaDetalleRepository;
|
|
private readonly IPublicacionRepository _publicacionRepository;
|
|
private readonly IEmpresaRepository _empresaRepository;
|
|
private readonly ISuscriptorRepository _suscriptorRepository;
|
|
private readonly ISuscripcionRepository _suscripcionRepository;
|
|
private readonly ILogger<ReportesService> _logger;
|
|
|
|
public ReportesService(IReportesRepository reportesRepository, IFacturaRepository facturaRepository, IFacturaDetalleRepository facturaDetalleRepository, IPublicacionRepository publicacionRepository, IEmpresaRepository empresaRepository
|
|
, ISuscriptorRepository suscriptorRepository, ISuscripcionRepository suscripcionRepository, ILogger<ReportesService> logger)
|
|
{
|
|
_reportesRepository = reportesRepository;
|
|
_facturaRepository = facturaRepository;
|
|
_facturaDetalleRepository = facturaDetalleRepository;
|
|
_publicacionRepository = publicacionRepository;
|
|
_empresaRepository = empresaRepository;
|
|
_suscriptorRepository = suscriptorRepository;
|
|
_suscripcionRepository = suscripcionRepository;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<(IEnumerable<ExistenciaPapelDto> Data, string? Error)> ObtenerExistenciaPapelAsync(
|
|
DateTime fechaDesde, DateTime fechaHasta, int? idPlanta, bool consolidado)
|
|
{
|
|
if (fechaDesde > fechaHasta)
|
|
{
|
|
return (Enumerable.Empty<ExistenciaPapelDto>(), "La fecha 'Desde' no puede ser mayor que la fecha 'Hasta'.");
|
|
}
|
|
|
|
if (!consolidado && !idPlanta.HasValue)
|
|
{
|
|
return (Enumerable.Empty<ExistenciaPapelDto>(), "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<ExistenciaPapelDto>(), ex.Message);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error en ReportesService al obtener Existencia de Papel.");
|
|
return (Enumerable.Empty<ExistenciaPapelDto>(), "Error interno al generar el reporte de existencia de papel.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<MovimientoBobinasDto> Data, string? Error)> ObtenerMovimientoBobinasAsync(DateTime fechaDesde, DateTime fechaHasta, int idPlanta)
|
|
{
|
|
if (fechaDesde > fechaHasta)
|
|
{
|
|
return (Enumerable.Empty<MovimientoBobinasDto>(), "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<MovimientoBobinasDto>(), "Error interno al generar el reporte de movimiento de bobinas.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<MovimientoBobinaEstadoDetalleDto> Detalle, IEnumerable<MovimientoBobinaEstadoTotalDto> Totales, string? Error)> ObtenerMovimientoBobinasPorEstadoAsync(DateTime fechaDesde, DateTime fechaHasta, int idPlanta)
|
|
{
|
|
if (fechaDesde > fechaHasta)
|
|
{
|
|
return (Enumerable.Empty<MovimientoBobinaEstadoDetalleDto>(), Enumerable.Empty<MovimientoBobinaEstadoTotalDto>(), "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<MovimientoBobinaEstadoDetalleDto>(), Enumerable.Empty<MovimientoBobinaEstadoTotalDto>(), "Error interno al generar el reporte de movimiento de bobinas por estado.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<ListadoDistribucionGeneralResumenDto> Resumen, IEnumerable<ListadoDistribucionGeneralPromedioDiaDto> Promedios, string? Error)> ObtenerListadoDistribucionGeneralAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta)
|
|
{
|
|
if (fechaDesde > fechaHasta)
|
|
return (Enumerable.Empty<ListadoDistribucionGeneralResumenDto>(), Enumerable.Empty<ListadoDistribucionGeneralPromedioDiaDto>(), "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<ListadoDistribucionGeneralResumenDto>(), Enumerable.Empty<ListadoDistribucionGeneralPromedioDiaDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<ListadoDistribucionCanillasSimpleDto> Simple, IEnumerable<ListadoDistribucionCanillasPromedioDiaDto> Promedios, string? Error)> ObtenerListadoDistribucionCanillasAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta)
|
|
{
|
|
if (fechaDesde > fechaHasta)
|
|
return (Enumerable.Empty<ListadoDistribucionCanillasSimpleDto>(), Enumerable.Empty<ListadoDistribucionCanillasPromedioDiaDto>(), "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<ListadoDistribucionCanillasSimpleDto>(), Enumerable.Empty<ListadoDistribucionCanillasPromedioDiaDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<ListadoDistribucionCanillasImporteDto> Data, string? Error)> ObtenerListadoDistribucionCanillasConImporteAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta, bool esAccionista)
|
|
{
|
|
if (fechaDesde > fechaHasta)
|
|
return (Enumerable.Empty<ListadoDistribucionCanillasImporteDto>(), "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<ListadoDistribucionCanillasImporteDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<VentaMensualSecretariaElDiaDto> Data, string? Error)> ObtenerVentaMensualSecretariaElDiaAsync(DateTime fechaDesde, DateTime fechaHasta)
|
|
{
|
|
if (fechaDesde > fechaHasta) return (Enumerable.Empty<VentaMensualSecretariaElDiaDto>(), "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<VentaMensualSecretariaElDiaDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<VentaMensualSecretariaElPlataDto> Data, string? Error)> ObtenerVentaMensualSecretariaElPlataAsync(DateTime fechaDesde, DateTime fechaHasta)
|
|
{
|
|
if (fechaDesde > fechaHasta) return (Enumerable.Empty<VentaMensualSecretariaElPlataDto>(), "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<VentaMensualSecretariaElPlataDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<VentaMensualSecretariaTirDevoDto> Data, string? Error)> ObtenerVentaMensualSecretariaTirDevoAsync(DateTime fechaDesde, DateTime fechaHasta)
|
|
{
|
|
if (fechaDesde > fechaHasta) return (Enumerable.Empty<VentaMensualSecretariaTirDevoDto>(), "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<VentaMensualSecretariaTirDevoDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(
|
|
IEnumerable<DetalleDistribucionCanillaDto> Canillas,
|
|
IEnumerable<DetalleDistribucionCanillaDto> CanillasAcc,
|
|
IEnumerable<DetalleDistribucionCanillaAllDto> CanillasAll,
|
|
IEnumerable<DetalleDistribucionCanillaDto> CanillasFechaLiq,
|
|
IEnumerable<DetalleDistribucionCanillaDto> CanillasAccFechaLiq,
|
|
IEnumerable<ObtenerCtrlDevolucionesDto> CtrlDevolucionesRemitos,
|
|
IEnumerable<ControlDevolucionesReporteDto> CtrlDevolucionesParaDistCan,
|
|
IEnumerable<DevueltosOtrosDiasDto> 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
|
|
);
|
|
|
|
var detallesOriginales = await ctrlDevolucionesParaDistCanTask ?? Enumerable.Empty<ControlDevolucionesReporteDto>();
|
|
var detallesOrdenados = detallesOriginales.OrderBy(d => d.Tipo).ToList();
|
|
|
|
Func<IEnumerable<DetalleDistribucionCanillaDto>, IEnumerable<DetalleDistribucionCanillaDto>> toUtc =
|
|
items => items?.Select(c => { if (c.Fecha.HasValue) c.Fecha = DateTime.SpecifyKind(c.Fecha.Value.Date, DateTimeKind.Utc); return c; }).ToList()
|
|
?? Enumerable.Empty<DetalleDistribucionCanillaDto>();
|
|
|
|
return (
|
|
toUtc(await canillasTask),
|
|
toUtc(await canillasAccTask),
|
|
await canillasAllTask ?? Enumerable.Empty<DetalleDistribucionCanillaAllDto>(),
|
|
toUtc(await canillasFechaLiqTask),
|
|
toUtc(await canillasAccFechaLiqTask),
|
|
await ctrlDevolucionesRemitosTask ?? Enumerable.Empty<ObtenerCtrlDevolucionesDto>(),
|
|
detallesOrdenados,
|
|
await ctrlDevolucionesOtrosDiasTask ?? Enumerable.Empty<DevueltosOtrosDiasDto>(),
|
|
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<DetalleDistribucionCanillaDto>(),
|
|
Enumerable.Empty<DetalleDistribucionCanillaDto>(),
|
|
Enumerable.Empty<DetalleDistribucionCanillaAllDto>(),
|
|
Enumerable.Empty<DetalleDistribucionCanillaDto>(),
|
|
Enumerable.Empty<DetalleDistribucionCanillaDto>(),
|
|
Enumerable.Empty<ObtenerCtrlDevolucionesDto>(),
|
|
Enumerable.Empty<ControlDevolucionesReporteDto>(),
|
|
Enumerable.Empty<DevueltosOtrosDiasDto>(),
|
|
"Error interno al generar el reporte de distribución de canillas."
|
|
);
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<TiradasPublicacionesSeccionesDto> Data, string? Error)> ObtenerTiradasPublicacionesSeccionesAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta, int idPlanta)
|
|
{
|
|
if (fechaDesde > fechaHasta) return (Enumerable.Empty<TiradasPublicacionesSeccionesDto>(), "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<TiradasPublicacionesSeccionesDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<TiradasPublicacionesSeccionesDto> Data, string? Error)> ObtenerTiradasPublicacionesSeccionesConsolidadoAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta)
|
|
{
|
|
if (fechaDesde > fechaHasta) return (Enumerable.Empty<TiradasPublicacionesSeccionesDto>(), "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<TiradasPublicacionesSeccionesDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<ConsumoBobinasSeccionDto> Data, string? Error)> ObtenerConsumoBobinasPorSeccionAsync(DateTime fechaDesde, DateTime fechaHasta, int idPlanta)
|
|
{
|
|
if (fechaDesde > fechaHasta) return (Enumerable.Empty<ConsumoBobinasSeccionDto>(), "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<ConsumoBobinasSeccionDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<ConsumoBobinasSeccionDto> Data, string? Error)> ObtenerConsumoBobinasPorSeccionConsolidadoAsync(DateTime fechaDesde, DateTime fechaHasta)
|
|
{
|
|
if (fechaDesde > fechaHasta) return (Enumerable.Empty<ConsumoBobinasSeccionDto>(), "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<ConsumoBobinasSeccionDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<ConsumoBobinasPublicacionDto> Data, string? Error)> ObtenerConsumoBobinasPorPublicacionAsync(DateTime fechaDesde, DateTime fechaHasta)
|
|
{
|
|
if (fechaDesde > fechaHasta) return (Enumerable.Empty<ConsumoBobinasPublicacionDto>(), "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<ConsumoBobinasPublicacionDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<ComparativaConsumoBobinasDto> Data, string? Error)> ObtenerComparativaConsumoBobinasAsync(DateTime fechaInicioMesA, DateTime fechaFinMesA, DateTime fechaInicioMesB, DateTime fechaFinMesB, int idPlanta)
|
|
{
|
|
if (fechaInicioMesA > fechaFinMesA || fechaInicioMesB > fechaFinMesB) return (Enumerable.Empty<ComparativaConsumoBobinasDto>(), "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<ComparativaConsumoBobinasDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<ComparativaConsumoBobinasDto> Data, string? Error)> ObtenerComparativaConsumoBobinasConsolidadoAsync(DateTime fechaInicioMesA, DateTime fechaFinMesA, DateTime fechaInicioMesB, DateTime fechaFinMesB)
|
|
{
|
|
if (fechaInicioMesA > fechaFinMesA || fechaInicioMesB > fechaFinMesB) return (Enumerable.Empty<ComparativaConsumoBobinasDto>(), "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<ComparativaConsumoBobinasDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
// Implementación para ReporteCuentasDistribuidores
|
|
public async Task<(
|
|
IEnumerable<BalanceCuentaDistDto> EntradasSalidas,
|
|
IEnumerable<BalanceCuentaDebCredDto> DebitosCreditos,
|
|
IEnumerable<BalanceCuentaPagosDto> Pagos,
|
|
IEnumerable<SaldoDto> Saldos,
|
|
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'.");
|
|
|
|
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<BalanceCuentaDistDto>, IEnumerable<BalanceCuentaDistDto>> esToUtc =
|
|
items => items?.Select(i => { i.Fecha = DateTime.SpecifyKind(i.Fecha.Date, DateTimeKind.Utc); return i; }).ToList()
|
|
?? Enumerable.Empty<BalanceCuentaDistDto>();
|
|
Func<IEnumerable<BalanceCuentaDebCredDto>, IEnumerable<BalanceCuentaDebCredDto>> dcToUtc =
|
|
items => items?.Select(i => { i.Fecha = DateTime.SpecifyKind(i.Fecha.Date, DateTimeKind.Utc); return i; }).ToList()
|
|
?? Enumerable.Empty<BalanceCuentaDebCredDto>();
|
|
Func<IEnumerable<BalanceCuentaPagosDto>, IEnumerable<BalanceCuentaPagosDto>> paToUtc =
|
|
items => items?.Select(i => { i.Fecha = DateTime.SpecifyKind(i.Fecha.Date, DateTimeKind.Utc); return i; }).ToList()
|
|
?? Enumerable.Empty<BalanceCuentaPagosDto>();
|
|
|
|
return (
|
|
esToUtc(await esTask),
|
|
dcToUtc(await dcTask),
|
|
paToUtc(await paTask),
|
|
await saTask ?? Enumerable.Empty<SaldoDto>(),
|
|
null
|
|
);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error en ReportesService al obtener Reporte Cuentas Distribuidor.");
|
|
return (
|
|
Enumerable.Empty<BalanceCuentaDistDto>(),
|
|
Enumerable.Empty<BalanceCuentaDebCredDto>(),
|
|
Enumerable.Empty<BalanceCuentaPagosDto>(),
|
|
Enumerable.Empty<SaldoDto>(),
|
|
"Error interno al generar el reporte."
|
|
);
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<ListadoDistribucionDistSimpleDto> Simple, IEnumerable<ListadoDistribucionDistPromedioDiaDto> Promedios, string? Error)> ObtenerListadoDistribucionDistribuidoresAsync(int idDistribuidor, int idPublicacion, DateTime fechaDesde, DateTime fechaHasta)
|
|
{
|
|
if (fechaDesde > fechaHasta)
|
|
return (Enumerable.Empty<ListadoDistribucionDistSimpleDto>(), Enumerable.Empty<ListadoDistribucionDistPromedioDiaDto>(), "La fecha 'Desde' no puede ser mayor que la fecha 'Hasta'.");
|
|
|
|
try
|
|
{
|
|
// Llamar a los métodos específicos del repositorio
|
|
var simpleDataTask = _reportesRepository.GetListadoDistribucionDistSimpleAsync(idDistribuidor, idPublicacion, fechaDesde, fechaHasta);
|
|
var promediosDataTask = _reportesRepository.GetListadoDistribucionDistPromedioDiaAsync(idDistribuidor, idPublicacion, fechaDesde, fechaHasta);
|
|
|
|
await Task.WhenAll(simpleDataTask, promediosDataTask);
|
|
|
|
return (await simpleDataTask, await promediosDataTask, null);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error en ReportesService al obtener Listado Distribucion (Distribuidores). Params: Dist={idDistribuidor}, Pub={idPublicacion}, Desde={fechaDesde}, Hasta={fechaHasta}", idDistribuidor, idPublicacion, fechaDesde, fechaHasta);
|
|
return (Enumerable.Empty<ListadoDistribucionDistSimpleDto>(), Enumerable.Empty<ListadoDistribucionDistPromedioDiaDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(
|
|
IEnumerable<LiquidacionCanillaDetalleDto> Detalles,
|
|
IEnumerable<LiquidacionCanillaGananciaDto> Ganancias,
|
|
string? Error
|
|
)> ObtenerDatosTicketLiquidacionAsync(DateTime fecha, int idCanilla)
|
|
{
|
|
try
|
|
{
|
|
var detallesTask = _reportesRepository.GetLiquidacionCanillaDetalleAsync(fecha, idCanilla);
|
|
var gananciasTask = _reportesRepository.GetLiquidacionCanillaGananciasAsync(fecha, idCanilla);
|
|
|
|
await Task.WhenAll(detallesTask, gananciasTask);
|
|
|
|
var detalles = await detallesTask;
|
|
var ganancias = await gananciasTask;
|
|
|
|
if ((detalles == null || !detalles.Any()) && (ganancias == null || !ganancias.Any()))
|
|
{
|
|
// Podrías optar por no devolver error aquí si es válido que uno de los dos esté vacío
|
|
// y manejarlo en el controlador o el RDLC.
|
|
}
|
|
|
|
// Convertir fechas a UTC si es necesario para el RDLC (aunque estos DTOs no tienen fechas)
|
|
|
|
return (
|
|
detalles ?? Enumerable.Empty<LiquidacionCanillaDetalleDto>(),
|
|
ganancias ?? Enumerable.Empty<LiquidacionCanillaGananciaDto>(),
|
|
null
|
|
);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error en ReportesService al obtener datos para Ticket Liquidación Canilla. Fecha: {Fecha}, Canilla: {IdCanilla}", fecha, idCanilla);
|
|
return (
|
|
Enumerable.Empty<LiquidacionCanillaDetalleDto>(),
|
|
Enumerable.Empty<LiquidacionCanillaGananciaDto>(),
|
|
"Error interno al obtener los datos para el ticket de liquidación."
|
|
);
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<ListadoDistCanMensualDiariosDto> Data, string? Error)> ObtenerReporteMensualDiariosAsync(DateTime fechaDesde, DateTime fechaHasta, bool esAccionista)
|
|
{
|
|
try
|
|
{
|
|
var data = await _reportesRepository.GetReporteMensualDiariosAsync(fechaDesde, fechaHasta, esAccionista);
|
|
return (data, null);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error al obtener reporte mensual canillitas (diarios).");
|
|
return (Enumerable.Empty<ListadoDistCanMensualDiariosDto>(), "Error al obtener datos del reporte (diarios).");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<ListadoDistCanMensualPubDto> Data, string? Error)> ObtenerReporteMensualPorPublicacionAsync(DateTime fechaDesde, DateTime fechaHasta, bool esAccionista)
|
|
{
|
|
try
|
|
{
|
|
var data = await _reportesRepository.GetReporteMensualPorPublicacionAsync(fechaDesde, fechaHasta, esAccionista);
|
|
return (data, null);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error al obtener reporte mensual canillitas (por publicación).");
|
|
return (Enumerable.Empty<ListadoDistCanMensualPubDto>(), "Error al obtener datos del reporte (por publicación).");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<FacturasParaReporteDto> Data, string? Error)> ObtenerFacturasParaReportePublicidad(int anio, int mes)
|
|
{
|
|
if (anio < 2020 || mes < 1 || mes > 12)
|
|
{
|
|
return (Enumerable.Empty<FacturasParaReporteDto>(), "Período no válido.");
|
|
}
|
|
var periodo = $"{anio}-{mes:D2}";
|
|
try
|
|
{
|
|
// Llamada directa al nuevo método del repositorio
|
|
var data = await _reportesRepository.GetDatosReportePublicidadAsync(periodo);
|
|
return (data, null);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error en servicio al obtener datos para reporte de publicidad para el período {Periodo}", periodo);
|
|
return (new List<FacturasParaReporteDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
|
|
public async Task<(IEnumerable<DistribucionSuscripcionDto> Data, string? Error)> ObtenerReporteDistribucionSuscripcionesAsync(DateTime fechaDesde, DateTime fechaHasta)
|
|
{
|
|
if (fechaDesde > fechaHasta)
|
|
{
|
|
return (Enumerable.Empty<DistribucionSuscripcionDto>(), "La fecha 'Desde' no puede ser mayor que la fecha 'Hasta'.");
|
|
}
|
|
try
|
|
{
|
|
var data = await _reportesRepository.GetDistribucionSuscripcionesAsync(fechaDesde, fechaHasta);
|
|
return (data, null);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error en servicio al obtener datos para reporte de distribución de suscripciones.");
|
|
return (new List<DistribucionSuscripcionDto>(), "Error interno al generar el reporte.");
|
|
}
|
|
}
|
|
}
|
|
} |