Continuación del módulo de reportes. -Backend
This commit is contained in:
		| @@ -7,7 +7,10 @@ using System; | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using GestionIntegral.Api.Dtos.Reportes; | using GestionIntegral.Api.Dtos.Reportes; | ||||||
| using GestionIntegral.Api.Data.Repositories.Impresion; // Para ExistenciaPapelDto | using GestionIntegral.Api.Data.Repositories.Impresion; | ||||||
|  | using System.IO; | ||||||
|  | using System.Linq; | ||||||
|  | using GestionIntegral.Api.Data.Repositories.Distribucion; | ||||||
|  |  | ||||||
| namespace GestionIntegral.Api.Controllers | namespace GestionIntegral.Api.Controllers | ||||||
| { | { | ||||||
| @@ -16,18 +19,39 @@ namespace GestionIntegral.Api.Controllers | |||||||
|     [Authorize] |     [Authorize] | ||||||
|     public class ReportesController : ControllerBase |     public class ReportesController : ControllerBase | ||||||
|     { |     { | ||||||
|         private readonly IReportesService _reportesService; |         private readonly IReportesService _reportesService; // <--- CORREGIDO | ||||||
|         private readonly ILogger<ReportesController> _logger; |         private readonly ILogger<ReportesController> _logger; | ||||||
|         private readonly IPlantaRepository _plantaRepository; |         private readonly IPlantaRepository _plantaRepository; | ||||||
|  |         private readonly IPublicacionRepository _publicacionRepository; | ||||||
|  |         private readonly IEmpresaRepository _empresaRepository; | ||||||
|  |         private readonly IDistribuidorRepository _distribuidorRepository; // Para obtener el nombre del distribuidor | ||||||
|  |  | ||||||
|         // Asumimos un permiso genérico para reportes o uno específico |  | ||||||
|  |         // Permisos | ||||||
|         private const string PermisoVerReporteExistenciaPapel = "RR005"; |         private const string PermisoVerReporteExistenciaPapel = "RR005"; | ||||||
|  |         private const string PermisoVerReporteMovimientoBobinas = "RR006"; | ||||||
|  |         private const string PermisoVerListadoDistribucion = "RR002"; | ||||||
|  |         private const string PermisoVerControlDevoluciones = "RR003"; | ||||||
|  |         private const string PermisoVerComprobanteLiquidacionCanilla = "MC005"; | ||||||
|  |         private const string PermisoVerBalanceCuentas = "RR001"; | ||||||
|  |         private const string PermisoVerReporteTiradas = "RR008"; | ||||||
|  |         private const string PermisoVerReporteConsumoBobinas = "RR007"; | ||||||
|  |  | ||||||
|         public ReportesController(IReportesService reportesService, ILogger<ReportesController> logger, IPlantaRepository plantaRepository) |  | ||||||
|  |         public ReportesController( | ||||||
|  |             IReportesService reportesService, // <--- CORREGIDO | ||||||
|  |             ILogger<ReportesController> logger, | ||||||
|  |             IPlantaRepository plantaRepository, | ||||||
|  |             IPublicacionRepository publicacionRepository, | ||||||
|  |             IEmpresaRepository empresaRepository, | ||||||
|  |             IDistribuidorRepository distribuidorRepository) // Añadido | ||||||
|         { |         { | ||||||
|             _reportesService = reportesService; |             _reportesService = reportesService; // <--- CORREGIDO | ||||||
|             _logger = logger; |             _logger = logger; | ||||||
|             _plantaRepository = plantaRepository; |             _plantaRepository = plantaRepository; | ||||||
|  |             _publicacionRepository = publicacionRepository; | ||||||
|  |             _empresaRepository = empresaRepository; | ||||||
|  |             _distribuidorRepository = distribuidorRepository; // Añadido | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private bool TienePermiso(string codAcc) => User.IsInRole("SuperAdmin") || User.HasClaim(c => c.Type == "permission" && c.Value == codAcc); |         private bool TienePermiso(string codAcc) => User.IsInRole("SuperAdmin") || User.HasClaim(c => c.Type == "permission" && c.Value == codAcc); | ||||||
| @@ -41,8 +65,8 @@ namespace GestionIntegral.Api.Controllers | |||||||
|         public async Task<IActionResult> GetReporteExistenciaPapel( |         public async Task<IActionResult> GetReporteExistenciaPapel( | ||||||
|             [FromQuery] DateTime fechaDesde, |             [FromQuery] DateTime fechaDesde, | ||||||
|             [FromQuery] DateTime fechaHasta, |             [FromQuery] DateTime fechaHasta, | ||||||
|             [FromQuery] int? idPlanta,      // Opcional |             [FromQuery] int? idPlanta, | ||||||
|             [FromQuery] bool consolidado = false) // Por defecto no consolidado |             [FromQuery] bool consolidado = false) | ||||||
|         { |         { | ||||||
|             if (!TienePermiso(PermisoVerReporteExistenciaPapel)) |             if (!TienePermiso(PermisoVerReporteExistenciaPapel)) | ||||||
|             { |             { | ||||||
| @@ -50,7 +74,7 @@ namespace GestionIntegral.Api.Controllers | |||||||
|                 return Forbid(); |                 return Forbid(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             var (data, error) = await _reportesService.ObtenerExistenciaPapelAsync(fechaDesde, fechaHasta, idPlanta, consolidado); |             var (data, error) = await _reportesService.ObtenerExistenciaPapelAsync(fechaDesde, fechaHasta, idPlanta, consolidado); // <--- CORREGIDO | ||||||
|  |  | ||||||
|             if (error != null) |             if (error != null) | ||||||
|             { |             { | ||||||
| @@ -59,7 +83,6 @@ namespace GestionIntegral.Api.Controllers | |||||||
|             return Ok(data); |             return Ok(data); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Nuevo endpoint para PDF |  | ||||||
|         [HttpGet("existencia-papel/pdf")] |         [HttpGet("existencia-papel/pdf")] | ||||||
|         [ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)] |         [ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)] | ||||||
|         [ProducesResponseType(StatusCodes.Status400BadRequest)] |         [ProducesResponseType(StatusCodes.Status400BadRequest)] | ||||||
| @@ -73,7 +96,7 @@ namespace GestionIntegral.Api.Controllers | |||||||
|         { |         { | ||||||
|             if (!TienePermiso(PermisoVerReporteExistenciaPapel)) return Forbid(); |             if (!TienePermiso(PermisoVerReporteExistenciaPapel)) return Forbid(); | ||||||
|  |  | ||||||
|             var (data, error) = await _reportesService.ObtenerExistenciaPapelAsync(fechaDesde, fechaHasta, idPlanta, consolidado); |             var (data, error) = await _reportesService.ObtenerExistenciaPapelAsync(fechaDesde, fechaHasta, idPlanta, consolidado); // <--- CORREGIDO | ||||||
|  |  | ||||||
|             if (error != null) |             if (error != null) | ||||||
|             { |             { | ||||||
| @@ -87,17 +110,35 @@ namespace GestionIntegral.Api.Controllers | |||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 LocalReport report = new LocalReport(); |                 LocalReport report = new LocalReport(); | ||||||
|                 using (var fs = new FileStream("Controllers/Reportes/RDLC/ReporteExistenciaPapel.rdlc", FileMode.Open)) // Ruta a tu .rdlc |                 string rdlcPath = consolidado ? "Controllers/Reportes/RDLC/ReporteExistenciaPapelConsolidado.rdlc" : "Controllers/Reportes/RDLC/ReporteExistenciaPapel.rdlc"; | ||||||
|  |                  | ||||||
|  |                 using (var fs = new FileStream(rdlcPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|                 { |                 { | ||||||
|                     report.LoadReportDefinition(fs); |                     report.LoadReportDefinition(fs); | ||||||
|                 } |                 } | ||||||
|                 report.DataSources.Add(new ReportDataSource("DSConsumoBobinas", data)); // Nombre del DataSet en el RDLC |                 report.DataSources.Add(new ReportDataSource("DSConsumoBobinas", data)); | ||||||
|  |  | ||||||
|  |                 var parameters = new List<ReportParameter>(); | ||||||
|  |                 parameters.Add(new ReportParameter("FechaDesde", fechaDesde.ToString("dd/MM/yyyy"))); | ||||||
|  |                 parameters.Add(new ReportParameter("FechaHasta", fechaHasta.ToString("dd/MM/yyyy"))); | ||||||
|  |                  | ||||||
|  |                 string nombrePlantaParam = "Consolidado"; | ||||||
|  |                 if (!consolidado && idPlanta.HasValue) | ||||||
|  |                 { | ||||||
|  |                     var planta = await _plantaRepository.GetByIdAsync(idPlanta.Value); | ||||||
|  |                     nombrePlantaParam = planta?.Nombre ?? "N/A"; | ||||||
|  |                 } else if (consolidado) { | ||||||
|  |                      // Para el consolidado, el RDLC ReporteExistenciaPapelConsolidado.txt NO espera NomPlanta | ||||||
|  |                 } | ||||||
|  |                 else { // No consolidado pero idPlanta es NULL (aunque el servicio ya valida esto) | ||||||
|  |                     nombrePlantaParam = "N/A"; | ||||||
|  |                 } | ||||||
|  |                 // Solo añadir NomPlanta si NO es consolidado, porque el RDLC consolidado no lo tiene. | ||||||
|  |                 if (!consolidado) { | ||||||
|  |                      parameters.Add(new ReportParameter("NomPlanta", nombrePlantaParam)); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|                  |                  | ||||||
|                 var parameters = new ReportParameter[3]; |  | ||||||
|                 parameters[0] = new ReportParameter("FechaDesde", fechaDesde.ToString("dd/MM/yyyy")); |  | ||||||
|                 parameters[1] = new ReportParameter("FechaHasta", fechaHasta.ToString("dd/MM/yyyy")); |  | ||||||
|                 var planta = idPlanta.HasValue ? await _plantaRepository.GetByIdAsync(idPlanta.Value) : null; |  | ||||||
|                 parameters[2] = new ReportParameter("NomPlanta", consolidado ? "Consolidado" : planta?.Nombre ?? "N/A"); |  | ||||||
|                 report.SetParameters(parameters); |                 report.SetParameters(parameters); | ||||||
|  |  | ||||||
|                 byte[] pdfBytes = report.Render("PDF"); |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
| @@ -110,5 +151,719 @@ namespace GestionIntegral.Api.Controllers | |||||||
|                 return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al generar el PDF del reporte."); |                 return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al generar el PDF del reporte."); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         [HttpGet("movimiento-bobinas")] | ||||||
|  |         [ProducesResponseType(typeof(IEnumerable<MovimientoBobinasDto>), StatusCodes.Status200OK)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status400BadRequest)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status403Forbidden)] | ||||||
|  |         public async Task<IActionResult> GetReporteMovimientoBobinas( | ||||||
|  |             [FromQuery] DateTime fechaDesde, | ||||||
|  |             [FromQuery] DateTime fechaHasta, | ||||||
|  |             [FromQuery] int idPlanta) | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerReporteMovimientoBobinas)) return Forbid(); | ||||||
|  |  | ||||||
|  |             var (data, error) = await _reportesService.ObtenerMovimientoBobinasAsync(fechaDesde, fechaHasta, idPlanta); // <--- CORREGIDO | ||||||
|  |             if (error != null) return BadRequest(new { message = error }); | ||||||
|  |              | ||||||
|  |             return Ok(data); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [HttpGet("movimiento-bobinas/pdf")] | ||||||
|  |         [ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status400BadRequest)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status403Forbidden)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||||
|  |         public async Task<IActionResult> GetReporteMovimientoBobinasPdf( | ||||||
|  |             [FromQuery] DateTime fechaDesde, | ||||||
|  |             [FromQuery] DateTime fechaHasta, | ||||||
|  |             [FromQuery] int idPlanta) | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerReporteMovimientoBobinas)) return Forbid(); | ||||||
|  |              | ||||||
|  |             var (data, error) = await _reportesService.ObtenerMovimientoBobinasAsync(fechaDesde, fechaHasta, idPlanta); // <--- CORREGIDO | ||||||
|  |  | ||||||
|  |             if (error != null) return BadRequest(new { message = error }); | ||||||
|  |             if (data == null || !data.Any()) | ||||||
|  |             { | ||||||
|  |                 return NotFound(new { message = "No hay datos para generar el PDF del movimiento de bobinas con los parámetros seleccionados." }); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                 using (var fs = new FileStream("Controllers/Reportes/RDLC/ReporteMovimientoBobinas.rdlc", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSMovimientoBobinas", data)); // El RDLC usa "DSMovimientoBobinas" | ||||||
|  |  | ||||||
|  |                 var planta = await _plantaRepository.GetByIdAsync(idPlanta); | ||||||
|  |                 var parameters = new List<ReportParameter>(); | ||||||
|  |                 parameters.Add(new ReportParameter("FechaDesde", fechaDesde.ToString("dd/MM/yyyy"))); | ||||||
|  |                 parameters.Add(new ReportParameter("FechaHasta", fechaHasta.ToString("dd/MM/yyyy"))); | ||||||
|  |                 parameters.Add(new ReportParameter("NomPlanta", planta?.Nombre ?? "N/A")); | ||||||
|  |                  | ||||||
|  |                 report.SetParameters(parameters); | ||||||
|  |  | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 string fileName = $"MovimientoBobinas_Planta{idPlanta}_{fechaDesde:yyyyMMdd}_{fechaHasta:yyyyMMdd}.pdf"; | ||||||
|  |                 return File(pdfBytes, "application/pdf", fileName); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(ex, "Error al generar PDF para Movimiento de Bobinas."); | ||||||
|  |                 return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al generar el PDF del reporte."); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [HttpGet("movimiento-bobinas-estado/pdf")] | ||||||
|  |         [ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status400BadRequest)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status403Forbidden)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||||
|  |         public async Task<IActionResult> GetReporteMovimientoBobinasEstadoPdf( | ||||||
|  |             [FromQuery] DateTime fechaDesde, | ||||||
|  |             [FromQuery] DateTime fechaHasta, | ||||||
|  |             [FromQuery] int idPlanta) | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerReporteMovimientoBobinas)) return Forbid(); | ||||||
|  |  | ||||||
|  |             var (detalle, totales, error) = await _reportesService.ObtenerMovimientoBobinasPorEstadoAsync(fechaDesde, fechaHasta, idPlanta); // <--- CORREGIDO | ||||||
|  |  | ||||||
|  |             if (error != null) return BadRequest(new { message = error }); | ||||||
|  |             if ((detalle == null || !detalle.Any()) && (totales == null || !totales.Any())) | ||||||
|  |             { | ||||||
|  |                  return NotFound(new { message = "No hay datos para generar el PDF del movimiento de bobinas por estado con los parámetros seleccionados." }); | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                 using (var fs = new FileStream("Controllers/Reportes/RDLC/ReporteMovimientoBobinasEstado.rdlc", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSMovimientoBobinasEstado", detalle ?? new List<MovimientoBobinaEstadoDetalleDto>()));  | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSMovimientoBobinasEstadoTotales", totales ?? new List<MovimientoBobinaEstadoTotalDto>()));  | ||||||
|  |  | ||||||
|  |                 var planta = await _plantaRepository.GetByIdAsync(idPlanta); | ||||||
|  |                 var parameters = new List<ReportParameter>(); | ||||||
|  |                 parameters.Add(new ReportParameter("FechaDesde", fechaDesde.ToString("dd/MM/yyyy"))); | ||||||
|  |                 parameters.Add(new ReportParameter("FechaHasta", fechaHasta.ToString("dd/MM/yyyy"))); | ||||||
|  |                 parameters.Add(new ReportParameter("NomPlanta", planta?.Nombre ?? "N/A")); | ||||||
|  |                  | ||||||
|  |                 report.SetParameters(parameters); | ||||||
|  |  | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 string fileName = $"MovimientoBobinasEstado_Planta{idPlanta}_{fechaDesde:yyyyMMdd}_{fechaHasta:yyyyMMdd}.pdf"; | ||||||
|  |                 return File(pdfBytes, "application/pdf", fileName); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(ex, "Error al generar PDF para Movimiento de Bobinas por Estado."); | ||||||
|  |                 return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al generar el PDF del reporte."); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // --- Nuevos Endpoints --- | ||||||
|  |  | ||||||
|  |         [HttpGet("listado-distribucion-general/pdf")] | ||||||
|  |         [ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status400BadRequest)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status403Forbidden)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||||
|  |         public async Task<IActionResult> GetListadoDistribucionGeneralPdf( | ||||||
|  |             [FromQuery] int idPublicacion, | ||||||
|  |             [FromQuery] DateTime fechaDesde, // Usado para Mes y Año en el SP | ||||||
|  |             [FromQuery] DateTime fechaHasta) // Usado para el nombre del archivo y potencialmente como parámetro si el SP cambia | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerListadoDistribucion)) return Forbid(); | ||||||
|  |  | ||||||
|  |             var (resumen, promedios, error) = await _reportesService.ObtenerListadoDistribucionGeneralAsync(idPublicacion, fechaDesde, fechaHasta); | ||||||
|  |  | ||||||
|  |             if (error != null) return BadRequest(new { message = error }); | ||||||
|  |             if ((resumen == null || !resumen.Any()) && (promedios == null || !promedios.Any())) | ||||||
|  |             { | ||||||
|  |                 return NotFound(new { message = "No hay datos para generar el PDF." }); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                 using (var fs = new FileStream("Controllers/Reportes/RDLC/ReporteListadoDistribucionGeneral.rdlc", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                 // Los nombres de DataSet deben coincidir con los del RDLC. Basado en DSListadoDistribucion.txt | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSResumenMensual", resumen ?? new List<ListadoDistribucionGeneralResumenDto>())); | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSResumenMensualPorDiaSemana", promedios ?? new List<ListadoDistribucionGeneralPromedioDiaDto>())); | ||||||
|  |  | ||||||
|  |                 var publicacion = await _publicacionRepository.GetByIdSimpleAsync(idPublicacion); | ||||||
|  |                 var parameters = new List<ReportParameter> | ||||||
|  |                 { | ||||||
|  |                     new ReportParameter("NomPubli", publicacion?.Nombre ?? "N/A"), | ||||||
|  |                     new ReportParameter("FechaDesde", fechaDesde.ToString("MMMM 'de' yyyy")) // El RDLC espera un parámetro FechaDesde | ||||||
|  |                 }; | ||||||
|  |                 report.SetParameters(parameters); | ||||||
|  |  | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 string fileName = $"ListadoDistribucionGeneral_Pub{idPublicacion}_{fechaDesde:yyyyMM}.pdf"; | ||||||
|  |                 return File(pdfBytes, "application/pdf", fileName); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(ex, "Error al generar PDF para Listado Distribucion General."); | ||||||
|  |                 return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al generar el PDF del reporte."); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [HttpGet("listado-distribucion-canillas/pdf")] | ||||||
|  |         [ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status400BadRequest)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status403Forbidden)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||||
|  |         public async Task<IActionResult> GetListadoDistribucionCanillasPdf( | ||||||
|  |             [FromQuery] int idPublicacion, | ||||||
|  |             [FromQuery] DateTime fechaDesde, | ||||||
|  |             [FromQuery] DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerListadoDistribucion)) return Forbid(); | ||||||
|  |  | ||||||
|  |             var (simple, promedios, error) = await _reportesService.ObtenerListadoDistribucionCanillasAsync(idPublicacion, fechaDesde, fechaHasta); | ||||||
|  |  | ||||||
|  |             if (error != null) return BadRequest(new { message = error }); | ||||||
|  |             if ((simple == null || !simple.Any()) && (promedios == null || !promedios.Any())) | ||||||
|  |             { | ||||||
|  |                 return NotFound(new { message = "No hay datos para generar el PDF." }); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                 using (var fs = new FileStream("Controllers/Reportes/RDLC/ReporteListadoDistribucionCanillas.rdlc", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSListadoDistribucion", simple ?? new List<ListadoDistribucionCanillasSimpleDto>())); | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSListadoDistribucionAgDias", promedios ?? new List<ListadoDistribucionCanillasPromedioDiaDto>())); | ||||||
|  |  | ||||||
|  |                 var publicacion = await _publicacionRepository.GetByIdSimpleAsync(idPublicacion); | ||||||
|  |                 var parameters = new List<ReportParameter> | ||||||
|  |                 { | ||||||
|  |                     new ReportParameter("NomPubli", publicacion?.Nombre ?? "N/A"), | ||||||
|  |                     new ReportParameter("FechaDesde", fechaDesde.ToString("dd/MM/yyyy")), | ||||||
|  |                     new ReportParameter("FechaHasta", fechaHasta.ToString("dd/MM/yyyy")) | ||||||
|  |                 }; | ||||||
|  |                 report.SetParameters(parameters); | ||||||
|  |  | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 string fileName = $"ListadoDistribucionCanillas_Pub{idPublicacion}_{fechaDesde:yyyyMMdd}_{fechaHasta:yyyyMMdd}.pdf"; | ||||||
|  |                 return File(pdfBytes, "application/pdf", fileName); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(ex, "Error al generar PDF para Listado Distribucion Canillas."); | ||||||
|  |                 return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al generar el PDF del reporte."); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         [HttpGet("listado-distribucion-canillas-importe/pdf")] | ||||||
|  |         [ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status400BadRequest)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status403Forbidden)] | ||||||
|  |         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||||
|  |         public async Task<IActionResult> GetListadoDistribucionCanillasConImportePdf( | ||||||
|  |             [FromQuery] int idPublicacion, | ||||||
|  |             [FromQuery] DateTime fechaDesde, | ||||||
|  |             [FromQuery] DateTime fechaHasta, | ||||||
|  |             [FromQuery] bool esAccionista)  | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerListadoDistribucion)) return Forbid(); | ||||||
|  |  | ||||||
|  |             var (data, error) = await _reportesService.ObtenerListadoDistribucionCanillasConImporteAsync(idPublicacion, fechaDesde, fechaHasta, esAccionista); | ||||||
|  |  | ||||||
|  |             if (error != null) return BadRequest(new { message = error }); | ||||||
|  |             if (data == null || !data.Any()) | ||||||
|  |             { | ||||||
|  |                 return NotFound(new { message = "No hay datos para generar el PDF." }); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                  using (var fs = new FileStream("Controllers/Reportes/RDLC/ReporteListadoDistribucionCanImp.rdlc", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSListadoDistribucionCan", data)); | ||||||
|  |  | ||||||
|  |                 var publicacion = await _publicacionRepository.GetByIdSimpleAsync(idPublicacion); | ||||||
|  |                 var parameters = new List<ReportParameter> | ||||||
|  |                 { | ||||||
|  |                     new ReportParameter("NomPubli", publicacion?.Nombre ?? "N/A"), | ||||||
|  |                     new ReportParameter("FechaDesde", fechaDesde.ToString("dd/MM/yyyy")), | ||||||
|  |                     new ReportParameter("FechaHasta", fechaHasta.ToString("dd/MM/yyyy")), | ||||||
|  |                     new ReportParameter("CanAcc", esAccionista ? "1" : "0")  | ||||||
|  |                 }; | ||||||
|  |                 report.SetParameters(parameters); | ||||||
|  |                  | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 string tipoVendedor = esAccionista ? "Accionistas" : "Canillitas"; | ||||||
|  |                 string fileName = $"ListadoDistCanImp_Pub{idPublicacion}_{tipoVendedor}_{fechaDesde:yyyyMMdd}_{fechaHasta:yyyyMMdd}.pdf"; | ||||||
|  |                 return File(pdfBytes, "application/pdf", fileName); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(ex, "Error al generar PDF para Listado Distribucion Canillas con Importe."); | ||||||
|  |                 return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al generar el PDF del reporte."); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [HttpGet("venta-mensual-secretaria/el-dia/pdf")] | ||||||
|  |         public async Task<IActionResult> GetVentaMensualSecretariaElDiaPdf([FromQuery] DateTime fechaDesde, [FromQuery] DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerListadoDistribucion)) return Forbid(); // Asumiendo RR002 | ||||||
|  |             var (data, error) = await _reportesService.ObtenerVentaMensualSecretariaElDiaAsync(fechaDesde, fechaHasta); | ||||||
|  |             if (error != null) return BadRequest(new { message = error }); | ||||||
|  |             if (data == null || !data.Any()) return NotFound(new { message = "No hay datos para el reporte." }); | ||||||
|  |  | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                 using (var fs = new FileStream("Controllers/Reportes/RDLC/ReporteVentaMensualSecretariaElDia.rdlc", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSListadoDistribucion", data)); // Basado en el RDLC | ||||||
|  |                 report.SetParameters(new[] {  | ||||||
|  |                     new ReportParameter("FechaDesde", fechaDesde.ToString("dd/MM/yyyy")), | ||||||
|  |                     new ReportParameter("FechaHasta", fechaHasta.ToString("dd/MM/yyyy")) | ||||||
|  |                 }); | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 return File(pdfBytes, "application/pdf", $"VentaMensualSecretaria_ElDia_{fechaDesde:yyyyMMdd}_{fechaHasta:yyyyMMdd}.pdf"); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error PDF VentaMensualSecretariaElDia."); return StatusCode(500, "Error interno."); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [HttpGet("venta-mensual-secretaria/el-plata/pdf")] | ||||||
|  |         public async Task<IActionResult> GetVentaMensualSecretariaElPlataPdf([FromQuery] DateTime fechaDesde, [FromQuery] DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerListadoDistribucion)) return Forbid(); // Asumiendo RR002 | ||||||
|  |             var (data, error) = await _reportesService.ObtenerVentaMensualSecretariaElPlataAsync(fechaDesde, fechaHasta); | ||||||
|  |             if (error != null) return BadRequest(new { message = error }); | ||||||
|  |             if (data == null || !data.Any()) return NotFound(new { message = "No hay datos para el reporte." }); | ||||||
|  |              | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                 using (var fs = new FileStream("Controllers/Reportes/RDLC/ReporteVentaMensualSecretariaElPlata.rdlc", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSListadoDistribucion", data)); // Basado en el RDLC | ||||||
|  |                  report.SetParameters(new[] {  | ||||||
|  |                     new ReportParameter("FechaDesde", fechaDesde.ToString("dd/MM/yyyy")), | ||||||
|  |                     new ReportParameter("FechaHasta", fechaHasta.ToString("dd/MM/yyyy")) | ||||||
|  |                 }); | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 return File(pdfBytes, "application/pdf", $"VentaMensualSecretaria_ElPlata_{fechaDesde:yyyyMMdd}_{fechaHasta:yyyyMMdd}.pdf"); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error PDF VentaMensualSecretariaElPlata."); return StatusCode(500, "Error interno."); } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         [HttpGet("venta-mensual-secretaria/tirada-devolucion/pdf")] | ||||||
|  |         public async Task<IActionResult> GetVentaMensualSecretariaTirDevoPdf([FromQuery] DateTime fechaDesde, [FromQuery] DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerListadoDistribucion)) return Forbid(); // Asumiendo RR002 | ||||||
|  |             var (data, error) = await _reportesService.ObtenerVentaMensualSecretariaTirDevoAsync(fechaDesde, fechaHasta); | ||||||
|  |             if (error != null) return BadRequest(new { message = error }); | ||||||
|  |             if (data == null || !data.Any()) return NotFound(new { message = "No hay datos para el reporte." }); | ||||||
|  |              | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                 using (var fs = new FileStream("Controllers/Reportes/RDLC/ReporteVentaMensualSecretariaTirDevo.rdlc", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSListadoDistribucion", data)); // Basado en el RDLC | ||||||
|  |                  report.SetParameters(new[] {  | ||||||
|  |                     new ReportParameter("FechaDesde", fechaDesde.ToString("dd/MM/yyyy")), | ||||||
|  |                     new ReportParameter("FechaHasta", fechaHasta.ToString("dd/MM/yyyy")) | ||||||
|  |                 }); | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 return File(pdfBytes, "application/pdf", $"VentaMensualSecretaria_TirDevo_{fechaDesde:yyyyMMdd}_{fechaHasta:yyyyMMdd}.pdf"); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error PDF VentaMensualSecretariaTirDevo."); return StatusCode(500, "Error interno."); } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         [HttpGet("distribucion-canillas/pdf")] | ||||||
|  |         public async Task<IActionResult> GetReporteDistribucionCanillasPdf([FromQuery] DateTime fecha, [FromQuery] int idEmpresa, [FromQuery] bool soloTotales = false) | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerComprobanteLiquidacionCanilla)) return Forbid(); | ||||||
|  |  | ||||||
|  |             var (canillas, canillasAcc, canillasAll, canillasFechaLiq, canillasAccFechaLiq, ctrlDevoluciones, ctrlDevolucionesParaDistCan, error) =  | ||||||
|  |                 await _reportesService.ObtenerReporteDistribucionCanillasAsync(fecha, idEmpresa); | ||||||
|  |  | ||||||
|  |             if (error != null) return BadRequest(new { message = error }); | ||||||
|  |              | ||||||
|  |             bool noHayDatosParaTotales = (canillasAll == null || !canillasAll.Any()) && | ||||||
|  |                                          (ctrlDevoluciones == null || !ctrlDevoluciones.Any()) && | ||||||
|  |                                          (ctrlDevolucionesParaDistCan == null || !ctrlDevolucionesParaDistCan.Any()); | ||||||
|  |             bool noHayDatosParaDetalle = noHayDatosParaTotales && | ||||||
|  |                                          (canillas == null || !canillas.Any()) && | ||||||
|  |                                          (canillasAcc == null || !canillasAcc.Any()) && | ||||||
|  |                                          (canillasFechaLiq == null || !canillasFechaLiq.Any()) && | ||||||
|  |                                          (canillasAccFechaLiq == null || !canillasAccFechaLiq.Any()); | ||||||
|  |  | ||||||
|  |             if ((soloTotales && noHayDatosParaTotales) || (!soloTotales && noHayDatosParaDetalle)) | ||||||
|  |             { | ||||||
|  |                 return NotFound(new { message = "No hay datos para generar el PDF del reporte de distribución de canillas." }); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                 string rdlcPath = soloTotales ? "Controllers/Reportes/RDLC/ReporteDistribucionCanillasTotales.rdlc" : "Controllers/Reportes/RDLC/ReporteDistribucionCanillas.rdlc"; | ||||||
|  |                  | ||||||
|  |                 using (var fs = new FileStream(rdlcPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                  | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSListadoDistribucionCan", canillas ?? new List<DetalleDistribucionCanillaDto>())); | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSListadoDistribucionCanAcc", canillasAcc ?? new List<DetalleDistribucionCanillaDto>())); | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSListadoDistribucionCanALL", canillasAll ?? new List<DetalleDistribucionCanillaAllDto>())); | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSListadoDistribucionCanFechaLiq", canillasFechaLiq ?? new List<DetalleDistribucionCanillaDto>())); | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSListadoDistribucionCanAccFechaLiq", canillasAccFechaLiq ?? new List<DetalleDistribucionCanillaDto>())); | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSObtenerCtrlDevoluciones", ctrlDevoluciones ?? new List<ObtenerCtrlDevolucionesDto>())); | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSCtrlDevoluciones", ctrlDevolucionesParaDistCan ?? new List<ControlDevolucionesReporteDto>())); | ||||||
|  |  | ||||||
|  |                 var empresa = await _empresaRepository.GetByIdAsync(idEmpresa); | ||||||
|  |                 var parameters = new List<ReportParameter> | ||||||
|  |                 { | ||||||
|  |                     new ReportParameter("FechaConsultada", fecha.ToString("dd/MM/yyyy")), | ||||||
|  |                     new ReportParameter("Empresa", empresa?.Nombre ?? "N/A") | ||||||
|  |                 }; | ||||||
|  |                 report.SetParameters(parameters); | ||||||
|  |  | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 string tipoReporte = soloTotales ? "Totales" : "Detalle"; | ||||||
|  |                 string fileName = $"DistribucionCanillas_{tipoReporte}_Emp{idEmpresa}_{fecha:yyyyMMdd}.pdf"; | ||||||
|  |                 return File(pdfBytes, "application/pdf", fileName); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(ex, "Error al generar PDF para Reporte Distribucion Canillas."); | ||||||
|  |                 return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al generar el PDF del reporte."); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         [HttpGet("control-devoluciones/pdf")] | ||||||
|  |         public async Task<IActionResult> GetReporteControlDevolucionesPdf([FromQuery] DateTime fecha, [FromQuery] int idEmpresa) | ||||||
|  |         { | ||||||
|  |              if (!TienePermiso(PermisoVerControlDevoluciones)) return Forbid(); | ||||||
|  |             var ( | ||||||
|  |                 _, _, _, _, _,  | ||||||
|  |                 ctrlDevolucionesData, // Este es el que usa el DataSet "DSObtenerCtrlDevoluciones" | ||||||
|  |                 ctrlDevolucionesParaDistCanData,  // Este es el que usa el DataSet "DSCtrlDevoluciones" | ||||||
|  |                 error | ||||||
|  |             ) = await _reportesService.ObtenerReporteDistribucionCanillasAsync(fecha, idEmpresa); | ||||||
|  |  | ||||||
|  |             if (error != null) return BadRequest(new { message = error }); | ||||||
|  |             if ((ctrlDevolucionesData == null || !ctrlDevolucionesData.Any()) && (ctrlDevolucionesParaDistCanData == null || !ctrlDevolucionesParaDistCanData.Any())) | ||||||
|  |             { | ||||||
|  |                 return NotFound(new { message = "No hay datos para generar el PDF para control de devoluciones." }); | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                 using (var fs = new FileStream("Controllers/Reportes/RDLC/ReporteCtrlDevoluciones.rdlc", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSCtrlDevoluciones", ctrlDevolucionesParaDistCanData ?? new List<ControlDevolucionesReporteDto>())); | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSObtenerCtrlDevoluciones", ctrlDevolucionesData ?? new List<ObtenerCtrlDevolucionesDto>())); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |                 var empresa = await _empresaRepository.GetByIdAsync(idEmpresa); | ||||||
|  |                 var parameters = new List<ReportParameter> | ||||||
|  |                 { | ||||||
|  |                     new ReportParameter("FechaConsultada", fecha.ToString("dd/MM/yyyy")), | ||||||
|  |                     new ReportParameter("NomEmp", empresa?.Nombre ?? "N/A") | ||||||
|  |                 }; | ||||||
|  |                 report.SetParameters(parameters); | ||||||
|  |  | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 string fileName = $"ControlDevoluciones_Emp{idEmpresa}_{fecha:yyyyMMdd}.pdf"; | ||||||
|  |                 return File(pdfBytes, "application/pdf", fileName); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(ex, "Error al generar PDF para Control Devoluciones."); | ||||||
|  |                 return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al generar el PDF del reporte."); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         [HttpGet("cuentas-distribuidores/pdf")] | ||||||
|  |         public async Task<IActionResult> GetReporteCuentasDistribuidoresPdf( | ||||||
|  |             [FromQuery] int idDistribuidor, | ||||||
|  |             [FromQuery] int idEmpresa, | ||||||
|  |             [FromQuery] DateTime fechaDesde, | ||||||
|  |             [FromQuery] DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerBalanceCuentas)) return Forbid(); | ||||||
|  |  | ||||||
|  |             var (entradasSalidas, debitosCreditos, pagos, saldos, error) =  | ||||||
|  |                 await _reportesService.ObtenerReporteCuentasDistribuidorAsync(idDistribuidor, idEmpresa, fechaDesde, fechaHasta); | ||||||
|  |  | ||||||
|  |             if (error != null) return BadRequest(new { message = error }); | ||||||
|  |             if (!entradasSalidas.Any() && !debitosCreditos.Any() && !pagos.Any() && !saldos.Any()) | ||||||
|  |             { | ||||||
|  |                  return NotFound(new { message = "No hay datos para generar el reporte de cuenta del distribuidor." }); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                 using (var fs = new FileStream("Controllers/Reportes/RDLC/ReporteCuentasDistribuidores.rdlc", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSDistribuidoresEntradasSalidas", entradasSalidas ?? new List<BalanceCuentaDistDto>())); | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSDistribuidoresDebCred", debitosCreditos ?? new List<BalanceCuentaDebCredDto>())); | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSDistribuidoresPagos", pagos ?? new List<BalanceCuentaPagosDto>())); | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSDistribuidoresSaldos", saldos ?? new List<SaldoDto>())); | ||||||
|  |                  | ||||||
|  |                 var parameters = new List<ReportParameter> | ||||||
|  |                 { | ||||||
|  |                     new ReportParameter("FechaDesde", fechaDesde.ToString("dd/MM/yyyy")), | ||||||
|  |                     new ReportParameter("FechaHasta", fechaHasta.ToString("dd/MM/yyyy")) | ||||||
|  |                 }; | ||||||
|  |                 report.SetParameters(parameters); | ||||||
|  |  | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 string fileName = $"CuentaDistribuidor_{idDistribuidor}_Emp{idEmpresa}_{fechaDesde:yyyyMMdd}_{fechaHasta:yyyyMMdd}.pdf"; | ||||||
|  |                 return File(pdfBytes, "application/pdf", fileName); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(ex, "Error al generar PDF para Cuentas Distribuidores."); | ||||||
|  |                 return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al generar el PDF del reporte."); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [HttpGet("tiradas-publicaciones-secciones/pdf")] | ||||||
|  |         public async Task<IActionResult> GetReporteTiradasPublicacionesSeccionesPdf( | ||||||
|  |             [FromQuery] int idPublicacion, | ||||||
|  |             [FromQuery] DateTime fechaDesde,  | ||||||
|  |             [FromQuery] DateTime fechaHasta,  | ||||||
|  |             [FromQuery] int? idPlanta,      | ||||||
|  |             [FromQuery] bool consolidado = false) | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerReporteTiradas)) return Forbid(); | ||||||
|  |  | ||||||
|  |             IEnumerable<TiradasPublicacionesSeccionesDto> data; | ||||||
|  |             string? errorMsg; // Para recibir el mensaje de error | ||||||
|  |  | ||||||
|  |             if (consolidado) | ||||||
|  |             { | ||||||
|  |                 (data, errorMsg) = await _reportesService.ObtenerTiradasPublicacionesSeccionesConsolidadoAsync(idPublicacion, fechaDesde, fechaHasta); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 if (!idPlanta.HasValue) return BadRequest(new { message = "Se requiere IdPlanta para reportes no consolidados." }); | ||||||
|  |                 (data, errorMsg) = await _reportesService.ObtenerTiradasPublicacionesSeccionesAsync(idPublicacion, fechaDesde, fechaHasta, idPlanta.Value); | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             if (errorMsg != null) return BadRequest(new { message = errorMsg }); | ||||||
|  |             if (data == null || !data.Any()) return NotFound(new { message = "No hay datos para generar el reporte." }); | ||||||
|  |  | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                 string rdlcPath = consolidado ?  | ||||||
|  |                     "Controllers/Reportes/RDLC/ReporteTiradasPublicacionesSeccionesConsolidado.rdlc" :  | ||||||
|  |                     "Controllers/Reportes/RDLC/ReporteTiradasPublicacionesSecciones.rdlc"; | ||||||
|  |  | ||||||
|  |                 using (var fs = new FileStream(rdlcPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSTiradasPublicacionesSecciones", data)); | ||||||
|  |  | ||||||
|  |                 var publicacion = await _publicacionRepository.GetByIdSimpleAsync(idPublicacion); | ||||||
|  |                 var parameters = new List<ReportParameter> | ||||||
|  |                 { | ||||||
|  |                     new ReportParameter("Mes", fechaDesde.ToString("MMMM yyyy")),  | ||||||
|  |                     new ReportParameter("NomPubli", publicacion?.Nombre ?? "N/A") | ||||||
|  |                 }; | ||||||
|  |                 if (!consolidado && idPlanta.HasValue) | ||||||
|  |                 { | ||||||
|  |                     var planta = await _plantaRepository.GetByIdAsync(idPlanta.Value); | ||||||
|  |                     parameters.Add(new ReportParameter("NomPlanta", planta?.Nombre ?? "N/A")); | ||||||
|  |                 } | ||||||
|  |                  | ||||||
|  |                 report.SetParameters(parameters); | ||||||
|  |  | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 string fileName = $"TiradasSecciones_Pub{idPublicacion}_{(consolidado ? "Consolidado" : $"Planta{idPlanta}")}_{fechaDesde:yyyyMM}.pdf"; | ||||||
|  |                 return File(pdfBytes, "application/pdf", fileName); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error PDF Tiradas Publicaciones Secciones."); return StatusCode(500, "Error interno."); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [HttpGet("consumo-bobinas-seccion/pdf")] | ||||||
|  |         public async Task<IActionResult> GetReporteConsumoBobinasSeccionPdf( | ||||||
|  |             [FromQuery] DateTime fechaDesde, | ||||||
|  |             [FromQuery] DateTime fechaHasta, | ||||||
|  |             [FromQuery] int? idPlanta, | ||||||
|  |             [FromQuery] bool consolidado = false) | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerReporteConsumoBobinas)) return Forbid();  | ||||||
|  |  | ||||||
|  |             IEnumerable<ConsumoBobinasSeccionDto> data; | ||||||
|  |             string? errorMsg; | ||||||
|  |  | ||||||
|  |             if (consolidado) | ||||||
|  |             { | ||||||
|  |                 (data, errorMsg) = await _reportesService.ObtenerConsumoBobinasPorSeccionConsolidadoAsync(fechaDesde, fechaHasta); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 if (!idPlanta.HasValue) return BadRequest(new { message = "Se requiere IdPlanta para reportes no consolidados." }); | ||||||
|  |                 (data, errorMsg) = await _reportesService.ObtenerConsumoBobinasPorSeccionAsync(fechaDesde, fechaHasta, idPlanta.Value); | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             if (errorMsg != null) return BadRequest(new { message = errorMsg }); | ||||||
|  |             if (data == null || !data.Any()) return NotFound(new { message = "No hay datos para generar el reporte." }); | ||||||
|  |  | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                  string rdlcPath = consolidado ?  | ||||||
|  |                     "Controllers/Reportes/RDLC/ReporteConsumoBobinasSeccionConsolidado.rdlc" :  | ||||||
|  |                     "Controllers/Reportes/RDLC/ReporteConsumoBobinasSeccion.rdlc"; | ||||||
|  |                 using (var fs = new FileStream(rdlcPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSConsumoBobinasSeccion", data)); | ||||||
|  |                  | ||||||
|  |                 var parameters = new List<ReportParameter> | ||||||
|  |                 { | ||||||
|  |                     new ReportParameter("FechaDesde", fechaDesde.ToString("dd/MM/yyyy")), | ||||||
|  |                     new ReportParameter("FechaHasta", fechaHasta.ToString("dd/MM/yyyy")) | ||||||
|  |                 }; | ||||||
|  |                  if (!consolidado && idPlanta.HasValue) | ||||||
|  |                 { | ||||||
|  |                     var planta = await _plantaRepository.GetByIdAsync(idPlanta.Value); | ||||||
|  |                     parameters.Add(new ReportParameter("NomPlanta", planta?.Nombre ?? "N/A")); | ||||||
|  |                 } | ||||||
|  |                 report.SetParameters(parameters); | ||||||
|  |  | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 string fileName = $"ConsumoBobinasSeccion_{(consolidado ? "Consolidado" : $"Planta{idPlanta}")}_{fechaDesde:yyyyMMdd}_{fechaHasta:yyyyMMdd}.pdf"; | ||||||
|  |                 return File(pdfBytes, "application/pdf", fileName); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error PDF Consumo Bobinas por Seccion."); return StatusCode(500, "Error interno."); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [HttpGet("consumo-bobinas-publicacion/pdf")] | ||||||
|  |         public async Task<IActionResult> GetReporteConsumoBobinasPublicacionPdf( | ||||||
|  |             [FromQuery] DateTime fechaDesde, | ||||||
|  |             [FromQuery] DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             if (!TienePermiso(PermisoVerReporteConsumoBobinas)) return Forbid();  | ||||||
|  |              | ||||||
|  |             var (data, error) = await _reportesService.ObtenerConsumoBobinasPorPublicacionAsync(fechaDesde, fechaHasta); | ||||||
|  |              | ||||||
|  |             if (error != null) return BadRequest(new { message = error }); | ||||||
|  |             if (data == null || !data.Any()) return NotFound(new { message = "No hay datos para generar el reporte." }); | ||||||
|  |  | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                 using (var fs = new FileStream("Controllers/Reportes/RDLC/ReporteConsumoBobinasPublicacion.rdlc", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSConsumoBobinasPublicacion", data)); | ||||||
|  |                  | ||||||
|  |                 var parameters = new List<ReportParameter> | ||||||
|  |                 { | ||||||
|  |                     new ReportParameter("FechaDesde", fechaDesde.ToString("dd/MM/yyyy")), | ||||||
|  |                     new ReportParameter("FechaHasta", fechaHasta.ToString("dd/MM/yyyy")) | ||||||
|  |                 }; | ||||||
|  |                 report.SetParameters(parameters); | ||||||
|  |  | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 string fileName = $"ConsumoBobinasPublicacion_{fechaDesde:yyyyMMdd}_{fechaHasta:yyyyMMdd}.pdf"; | ||||||
|  |                 return File(pdfBytes, "application/pdf", fileName); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error PDF Consumo Bobinas por Publicacion."); return StatusCode(500, "Error interno."); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [HttpGet("comparativa-consumo-bobinas/pdf")] | ||||||
|  |         public async Task<IActionResult> GetReporteComparativaConsumoBobinasPdf( | ||||||
|  |             [FromQuery] DateTime fechaInicioMesA, [FromQuery] DateTime fechaFinMesA, | ||||||
|  |             [FromQuery] DateTime fechaInicioMesB, [FromQuery] DateTime fechaFinMesB, | ||||||
|  |             [FromQuery] int? idPlanta, | ||||||
|  |             [FromQuery] bool consolidado = false) | ||||||
|  |         { | ||||||
|  |              if (!TienePermiso(PermisoVerReporteConsumoBobinas)) return Forbid();  | ||||||
|  |  | ||||||
|  |             IEnumerable<ComparativaConsumoBobinasDto> data; | ||||||
|  |             string? errorMsg; | ||||||
|  |  | ||||||
|  |             if (consolidado) | ||||||
|  |             { | ||||||
|  |                 (data, errorMsg) = await _reportesService.ObtenerComparativaConsumoBobinasConsolidadoAsync(fechaInicioMesA, fechaFinMesA, fechaInicioMesB, fechaFinMesB); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 if (!idPlanta.HasValue) return BadRequest(new { message = "Se requiere IdPlanta para reportes no consolidados." }); | ||||||
|  |                 (data, errorMsg) = await _reportesService.ObtenerComparativaConsumoBobinasAsync(fechaInicioMesA, fechaFinMesA, fechaInicioMesB, fechaFinMesB, idPlanta.Value); | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             if (errorMsg != null) return BadRequest(new { message = errorMsg }); | ||||||
|  |             if (data == null || !data.Any()) return NotFound(new { message = "No hay datos para generar el reporte." }); | ||||||
|  |  | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 LocalReport report = new LocalReport(); | ||||||
|  |                 string rdlcPath = consolidado ?  | ||||||
|  |                     "Controllers/Reportes/RDLC/ReporteConsumoBobinasMesesConsolidado.rdlc" :  | ||||||
|  |                     "Controllers/Reportes/RDLC/ReporteConsumoBobinasMeses.rdlc"; | ||||||
|  |  | ||||||
|  |                 using (var fs = new FileStream(rdlcPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) | ||||||
|  |                 { | ||||||
|  |                     report.LoadReportDefinition(fs); | ||||||
|  |                 } | ||||||
|  |                 report.DataSources.Add(new ReportDataSource("DSConsumoBobinasMeses", data)); | ||||||
|  |                  | ||||||
|  |                 var parameters = new List<ReportParameter> | ||||||
|  |                 { | ||||||
|  |                     new ReportParameter("MesA", fechaInicioMesA.ToString("MMMM yyyy")), | ||||||
|  |                     new ReportParameter("MesB", fechaInicioMesB.ToString("MMMM yyyy")) | ||||||
|  |                 }; | ||||||
|  |                  if (!consolidado && idPlanta.HasValue) | ||||||
|  |                 { | ||||||
|  |                     var planta = await _plantaRepository.GetByIdAsync(idPlanta.Value); | ||||||
|  |                     parameters.Add(new ReportParameter("NomPlanta", planta?.Nombre ?? "N/A")); | ||||||
|  |                 } | ||||||
|  |                 report.SetParameters(parameters); | ||||||
|  |  | ||||||
|  |                 byte[] pdfBytes = report.Render("PDF"); | ||||||
|  |                 string fileName = $"ComparativaConsumoBobinas_{(consolidado ? "Consolidado" : $"Planta{idPlanta}")}_{fechaInicioMesA:yyyyMM}_vs_{fechaInicioMesB:yyyyMM}.pdf"; | ||||||
|  |                 return File(pdfBytes, "application/pdf", fileName); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error PDF Comparativa Consumo Bobinas."); return StatusCode(500, "Error interno."); } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1,4 +1,5 @@ | |||||||
| using GestionIntegral.Api.Dtos.Reportes; // Para ExistenciaPapelDto | // src/Data/Repositories/Reportes/IReportesRepository.cs | ||||||
|  | using GestionIntegral.Api.Dtos.Reportes; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| @@ -8,6 +9,36 @@ namespace GestionIntegral.Api.Data.Repositories.Reportes | |||||||
|     public interface IReportesRepository |     public interface IReportesRepository | ||||||
|     { |     { | ||||||
|         Task<IEnumerable<ExistenciaPapelDto>> GetExistenciaPapelAsync(DateTime fechaDesde, DateTime fechaHasta, int? idPlanta, bool consolidado); |         Task<IEnumerable<ExistenciaPapelDto>> GetExistenciaPapelAsync(DateTime fechaDesde, DateTime fechaHasta, int? idPlanta, bool consolidado); | ||||||
|         // ... Aquí irán los métodos para otros reportes ... |         Task<IEnumerable<MovimientoBobinasDto>> GetMovimientoBobinasAsync(DateTime fechaInicio, int diasPeriodo, int idPlanta); | ||||||
|  |         Task<IEnumerable<MovimientoBobinaEstadoDetalleDto>> GetMovimientoBobinasEstadoDetalleAsync(DateTime fechaInicio, DateTime fechaFin, int idPlanta); | ||||||
|  |         Task<IEnumerable<MovimientoBobinaEstadoTotalDto>> GetMovimientoBobinasEstadoTotalesAsync(DateTime fechaInicio, DateTime fechaFin, int idPlanta); | ||||||
|  |  | ||||||
|  |         // --- MÉTODOS AÑADIDOS AQUÍ --- | ||||||
|  |         Task<IEnumerable<ListadoDistribucionGeneralResumenDto>> GetListadoDistribucionGeneralResumenAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<IEnumerable<ListadoDistribucionGeneralPromedioDiaDto>> GetListadoDistribucionGeneralPromedioDiaAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<IEnumerable<ListadoDistribucionCanillasSimpleDto>> GetListadoDistribucionCanillasSimpleAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<IEnumerable<ListadoDistribucionCanillasPromedioDiaDto>> GetListadoDistribucionCanillasPromedioDiaAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<IEnumerable<ListadoDistribucionCanillasImporteDto>> GetListadoDistribucionCanillasImporteAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta, bool esAccionista); | ||||||
|  |         Task<IEnumerable<VentaMensualSecretariaElDiaDto>> GetVentaMensualSecretariaElDiaAsync(DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<IEnumerable<VentaMensualSecretariaElPlataDto>> GetVentaMensualSecretariaElPlataAsync(DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<IEnumerable<VentaMensualSecretariaTirDevoDto>> GetVentaMensualSecretariaTirDevoAsync(DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<IEnumerable<DetalleDistribucionCanillaDto>> GetDetalleDistribucionCanillasPubliAsync(DateTime fecha, int idEmpresa); | ||||||
|  |         Task<IEnumerable<DetalleDistribucionCanillaDto>> GetDetalleDistribucionCanillasAccPubliAsync(DateTime fecha, int idEmpresa); | ||||||
|  |         Task<IEnumerable<DetalleDistribucionCanillaAllDto>> GetDetalleDistribucionCanillasAllPubliAsync(DateTime fecha, int idEmpresa); | ||||||
|  |         Task<IEnumerable<DetalleDistribucionCanillaDto>> GetDetalleDistribucionCanillasPubliFechaLiqAsync(DateTime fechaLiquidacion, int idEmpresa); | ||||||
|  |         Task<IEnumerable<DetalleDistribucionCanillaDto>> GetDetalleDistribucionCanillasAccPubliFechaLiqAsync(DateTime fechaLiquidacion, int idEmpresa); | ||||||
|  |         Task<IEnumerable<ObtenerCtrlDevolucionesDto>> GetReporteObtenerCtrlDevolucionesAsync(DateTime fecha, int idEmpresa); | ||||||
|  |         Task<IEnumerable<ControlDevolucionesReporteDto>> GetReporteCtrlDevolucionesParaDistCanAsync(DateTime fecha, int idEmpresa); | ||||||
|  |         Task<IEnumerable<TiradasPublicacionesSeccionesDto>> GetTiradasPublicacionesSeccionesAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta, int idPlanta); | ||||||
|  |         Task<IEnumerable<TiradasPublicacionesSeccionesDto>> GetTiradasPublicacionesSeccionesConsolidadoAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<IEnumerable<ConsumoBobinasSeccionDto>> GetConsumoBobinasPorSeccionAsync(DateTime fechaDesde, DateTime fechaHasta, int idPlanta); | ||||||
|  |         Task<IEnumerable<ConsumoBobinasSeccionDto>> GetConsumoBobinasPorSeccionConsolidadoAsync(DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<IEnumerable<ConsumoBobinasPublicacionDto>> GetConsumoBobinasPorPublicacionAsync(DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<IEnumerable<ComparativaConsumoBobinasDto>> GetComparativaConsumoBobinasAsync(DateTime fechaInicioMesA, DateTime fechaFinMesA, DateTime fechaInicioMesB, DateTime fechaFinMesB, int idPlanta); | ||||||
|  |         Task<IEnumerable<ComparativaConsumoBobinasDto>> GetComparativaConsumoBobinasConsolidadoAsync(DateTime fechaInicioMesA, DateTime fechaFinMesA, DateTime fechaInicioMesB, DateTime fechaFinMesB); | ||||||
|  |         Task<IEnumerable<BalanceCuentaDistDto>> GetBalanceCuentaDistEntradaSalidaPorEmpresaAsync(int idDistribuidor, int idEmpresa, DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<IEnumerable<BalanceCuentaDebCredDto>> GetBalanceCuentDistDebCredEmpresaAsync(int idDistribuidor, int idEmpresa, DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<IEnumerable<BalanceCuentaPagosDto>> GetBalanceCuentDistPagosEmpresaAsync(int idDistribuidor, int idEmpresa, DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<IEnumerable<SaldoDto>> GetBalanceCuentSaldosEmpresasAsync(string destino, int idDestino, int idEmpresa); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | // src/Data/Repositories/Reportes/ReportesRepository.cs | ||||||
| using Dapper; | using Dapper; | ||||||
| using GestionIntegral.Api.Dtos.Reportes; | using GestionIntegral.Api.Dtos.Reportes; | ||||||
| using Microsoft.Extensions.Logging; | using Microsoft.Extensions.Logging; | ||||||
| @@ -26,24 +27,16 @@ namespace GestionIntegral.Api.Data.Repositories.Reportes | |||||||
|             var parameters = new DynamicParameters(); |             var parameters = new DynamicParameters(); | ||||||
|              |              | ||||||
|             parameters.Add("FechaDesde", fechaDesde, DbType.Date); |             parameters.Add("FechaDesde", fechaDesde, DbType.Date); | ||||||
|             parameters.Add("FechaHasta", fechaHasta, DbType.Date); // SP_ConsumoBobinasConsolidado solo usa estas dos |             parameters.Add("FechaHasta", fechaHasta, DbType.Date); | ||||||
|  |  | ||||||
|             if (!consolidado) |             if (!consolidado) | ||||||
|             { |             { | ||||||
|                 if (!idPlanta.HasValue) |                 if (!idPlanta.HasValue) | ||||||
|                 { |                 { | ||||||
|                     _logger.LogError("idPlanta es requerido para el reporte de existencia de papel no consolidado."); |                     throw new ArgumentNullException(nameof(idPlanta), "El ID de planta es requerido para el reporte no consolidado de existencia de papel."); | ||||||
|                     // Podríamos lanzar una ArgumentNullException o devolver una lista vacía. |  | ||||||
|                     // Por ahora, el servicio debería validar esto antes. |  | ||||||
|                     // Para el repositorio, asumimos que si no es consolidado, idPlanta viene. |  | ||||||
|                     throw new ArgumentNullException(nameof(idPlanta), "El ID de planta es requerido para el reporte no consolidado."); |  | ||||||
|                 } |                 } | ||||||
|                 parameters.Add("@idPlanta", idPlanta.Value, DbType.Int32); |                 parameters.Add("@idPlanta", idPlanta.Value, DbType.Int32); | ||||||
|                  |  | ||||||
|             } |             } | ||||||
|             // Si los SPs realmente necesitaran @DiasPeriodo, lo calcularíamos así: |  | ||||||
|             // int diasPeriodo = (fechaHasta - fechaDesde).Days + 1; // +1 para incluir ambos días |  | ||||||
|             // parameters.Add("DiasPeriodo", diasPeriodo, DbType.Int32); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|             _logger.LogInformation("Ejecutando SP: {SPName} con parámetros: FechaDesde={FechaDesde}, FechaHasta={FechaHasta}, IdPlanta={IdPlanta}, Consolidado={Consolidado}", |             _logger.LogInformation("Ejecutando SP: {SPName} con parámetros: FechaDesde={FechaDesde}, FechaHasta={FechaHasta}, IdPlanta={IdPlanta}, Consolidado={Consolidado}", | ||||||
| @@ -63,6 +56,358 @@ namespace GestionIntegral.Api.Data.Repositories.Reportes | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // ... Implementaciones para otros reportes ... |         public async Task<IEnumerable<MovimientoBobinasDto>> GetMovimientoBobinasAsync(DateTime fechaInicio, int diasPeriodo, int idPlanta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_MovimientoBobinas"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@FechaInicio", fechaInicio, DbType.Date); // El SP espera DateTime | ||||||
|  |             parameters.Add("@DiasPeriodo", diasPeriodo, DbType.Int32); | ||||||
|  |             parameters.Add("@idPlanta", idPlanta, DbType.Int32); | ||||||
|  |  | ||||||
|  |             _logger.LogInformation("Ejecutando SP: {SPName} con parámetros: FechaInicio={FechaInicio}, DiasPeriodo={DiasPeriodo}, IdPlanta={IdPlanta}", | ||||||
|  |                 spName, fechaInicio, diasPeriodo, idPlanta); | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 using var connection = _dbConnectionFactory.CreateConnection(); | ||||||
|  |                 return await connection.QueryAsync<MovimientoBobinasDto>(spName, parameters, commandType: CommandType.StoredProcedure); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(ex, "Error al ejecutar SP {SPName} para Movimiento de Bobinas.", spName); | ||||||
|  |                 return Enumerable.Empty<MovimientoBobinasDto>(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<MovimientoBobinaEstadoDetalleDto>> GetMovimientoBobinasEstadoDetalleAsync(DateTime fechaInicio, DateTime fechaFin, int idPlanta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_MovimientosBobinasEstado"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@FechaInicio", fechaInicio, DbType.Date); | ||||||
|  |             parameters.Add("@FechaFin", fechaFin, DbType.Date); | ||||||
|  |             parameters.Add("@IdPlanta", idPlanta, DbType.Int32); | ||||||
|  |  | ||||||
|  |             _logger.LogInformation("Ejecutando SP: {SPName} con parámetros: FechaInicio={FechaInicio}, FechaFin={FechaFin}, IdPlanta={IdPlanta}", | ||||||
|  |                 spName, fechaInicio, fechaFin, idPlanta); | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 using var connection = _dbConnectionFactory.CreateConnection(); | ||||||
|  |                 return await connection.QueryAsync<MovimientoBobinaEstadoDetalleDto>(spName, parameters, commandType: CommandType.StoredProcedure); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(ex, "Error al ejecutar SP {SPName} para Detalle de Movimiento de Bobinas por Estado.", spName); | ||||||
|  |                 return Enumerable.Empty<MovimientoBobinaEstadoDetalleDto>(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<MovimientoBobinaEstadoTotalDto>> GetMovimientoBobinasEstadoTotalesAsync(DateTime fechaInicio, DateTime fechaFin, int idPlanta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_MovimientosBobinasEstadoTotales"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@FechaInicio", fechaInicio, DbType.Date); | ||||||
|  |             parameters.Add("@FechaFin", fechaFin, DbType.Date); | ||||||
|  |             parameters.Add("@IdPlanta", idPlanta, DbType.Int32); | ||||||
|  |  | ||||||
|  |             _logger.LogInformation("Ejecutando SP: {SPName} con parámetros: FechaInicio={FechaInicio}, FechaFin={FechaFin}, IdPlanta={IdPlanta}", | ||||||
|  |                 spName, fechaInicio, fechaFin, idPlanta); | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 using var connection = _dbConnectionFactory.CreateConnection(); | ||||||
|  |                 return await connection.QueryAsync<MovimientoBobinaEstadoTotalDto>(spName, parameters, commandType: CommandType.StoredProcedure); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(ex, "Error al ejecutar SP {SPName} para Totales de Movimiento de Bobinas por Estado.", spName); | ||||||
|  |                 return Enumerable.Empty<MovimientoBobinaEstadoTotalDto>(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Implementaciones que faltaban | ||||||
|  |         public async Task<IEnumerable<ListadoDistribucionGeneralResumenDto>> GetListadoDistribucionGeneralResumenAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_DistObtenerResumenMensual"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@Id_Publicacion", idPublicacion, DbType.Int32); | ||||||
|  |             parameters.Add("@Mes", fechaDesde.Month, DbType.Int32); | ||||||
|  |             parameters.Add("@Anio", fechaDesde.Year, DbType.Int32); | ||||||
|  |             // El SP no usa fechaHasta explícitamente, calcula el fin de mes internamente | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<ListadoDistribucionGeneralResumenDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<ListadoDistribucionGeneralResumenDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<ListadoDistribucionGeneralPromedioDiaDto>> GetListadoDistribucionGeneralPromedioDiaAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_DistObtenerResumenMensualPorDiaSemana"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@Id_Publicacion", idPublicacion, DbType.Int32); | ||||||
|  |             parameters.Add("@Mes", fechaDesde.Month, DbType.Int32); | ||||||
|  |             parameters.Add("@Anio", fechaDesde.Year, DbType.Int32); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<ListadoDistribucionGeneralPromedioDiaDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<ListadoDistribucionGeneralPromedioDiaDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<ListadoDistribucionCanillasSimpleDto>> GetListadoDistribucionCanillasSimpleAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_CantidadEntradaSalidaCanillas"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@idPublicacion", idPublicacion, DbType.Int32); | ||||||
|  |             parameters.Add("@fechaDesde", fechaDesde, DbType.DateTime); | ||||||
|  |             parameters.Add("@fechaHasta", fechaHasta, DbType.DateTime); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<ListadoDistribucionCanillasSimpleDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<ListadoDistribucionCanillasSimpleDto>(); } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public async Task<IEnumerable<ListadoDistribucionCanillasPromedioDiaDto>> GetListadoDistribucionCanillasPromedioDiaAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_CantidadEntradaSalidaCPromAgDiaCanilla"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@idPublicacion", idPublicacion, DbType.Int32); | ||||||
|  |             parameters.Add("@fechaDesde", fechaDesde, DbType.DateTime); | ||||||
|  |             parameters.Add("@fechaHasta", fechaHasta, DbType.DateTime); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<ListadoDistribucionCanillasPromedioDiaDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<ListadoDistribucionCanillasPromedioDiaDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<ListadoDistribucionCanillasImporteDto>> GetListadoDistribucionCanillasImporteAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta, bool esAccionista) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_CantidadESCanillasConImporte"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@idPublicacion", idPublicacion, DbType.Int32); | ||||||
|  |             parameters.Add("@fechaDesde", fechaDesde, DbType.DateTime); | ||||||
|  |             parameters.Add("@fechaHasta", fechaHasta, DbType.DateTime); | ||||||
|  |             parameters.Add("@accionista", esAccionista, DbType.Boolean); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<ListadoDistribucionCanillasImporteDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<ListadoDistribucionCanillasImporteDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<VentaMensualSecretariaElDiaDto>> GetVentaMensualSecretariaElDiaAsync(DateTime fechaDesde, DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_VentaMensualSecretariaElDia"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@fechaDesde", fechaDesde, DbType.DateTime); | ||||||
|  |             parameters.Add("@fechaHasta", fechaHasta, DbType.DateTime); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<VentaMensualSecretariaElDiaDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<VentaMensualSecretariaElDiaDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<VentaMensualSecretariaElPlataDto>> GetVentaMensualSecretariaElPlataAsync(DateTime fechaDesde, DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_VentaMensualSecretariaElPlata"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@fechaDesde", fechaDesde, DbType.DateTime); | ||||||
|  |             parameters.Add("@fechaHasta", fechaHasta, DbType.DateTime); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<VentaMensualSecretariaElPlataDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<VentaMensualSecretariaElPlataDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<VentaMensualSecretariaTirDevoDto>> GetVentaMensualSecretariaTirDevoAsync(DateTime fechaDesde, DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_VentaMensualSecretariaTirDevo"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@fechaDesde", fechaDesde, DbType.DateTime); | ||||||
|  |             parameters.Add("@fechaHasta", fechaHasta, DbType.DateTime); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<VentaMensualSecretariaTirDevoDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<VentaMensualSecretariaTirDevoDto>(); } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public async Task<IEnumerable<DetalleDistribucionCanillaDto>> GetDetalleDistribucionCanillasPubliAsync(DateTime fecha, int idEmpresa) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_DistCanillasEntradaSalidaPubli"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@fecha", fecha, DbType.DateTime); | ||||||
|  |             parameters.Add("@idEmpresa", idEmpresa, DbType.Int32); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<DetalleDistribucionCanillaDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<DetalleDistribucionCanillaDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<DetalleDistribucionCanillaDto>> GetDetalleDistribucionCanillasAccPubliAsync(DateTime fecha, int idEmpresa) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_DistCanillasAccEntradaSalidaPubli"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@fecha", fecha, DbType.DateTime); | ||||||
|  |             parameters.Add("@idEmpresa", idEmpresa, DbType.Int32); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<DetalleDistribucionCanillaDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<DetalleDistribucionCanillaDto>(); } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public async Task<IEnumerable<DetalleDistribucionCanillaAllDto>> GetDetalleDistribucionCanillasAllPubliAsync(DateTime fecha, int idEmpresa) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_DistCanALLEntradaSalidaPubli"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@fecha", fecha, DbType.DateTime); | ||||||
|  |             parameters.Add("@idEmpresa", idEmpresa, DbType.Int32); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<DetalleDistribucionCanillaAllDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<DetalleDistribucionCanillaAllDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<DetalleDistribucionCanillaDto>> GetDetalleDistribucionCanillasPubliFechaLiqAsync(DateTime fechaLiquidacion, int idEmpresa) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_DistCanillasEntradaSalidaPubliFechaLiq"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@fecha", fechaLiquidacion, DbType.DateTime); | ||||||
|  |             parameters.Add("@idEmpresa", idEmpresa, DbType.Int32); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<DetalleDistribucionCanillaDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<DetalleDistribucionCanillaDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<DetalleDistribucionCanillaDto>> GetDetalleDistribucionCanillasAccPubliFechaLiqAsync(DateTime fechaLiquidacion, int idEmpresa) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_DistCanillasAccEntradaSalidaPubliFechaLiq"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@fecha", fechaLiquidacion, DbType.DateTime); | ||||||
|  |             parameters.Add("@idEmpresa", idEmpresa, DbType.Int32); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<DetalleDistribucionCanillaDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<DetalleDistribucionCanillaDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<ObtenerCtrlDevolucionesDto>> GetReporteObtenerCtrlDevolucionesAsync(DateTime fecha, int idEmpresa) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_ObtenerCtrlDevoluciones"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@Fecha", fecha, DbType.DateTime); | ||||||
|  |             parameters.Add("@IdEmpresa", idEmpresa, DbType.Int32); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<ObtenerCtrlDevolucionesDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<ObtenerCtrlDevolucionesDto>(); } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public async Task<IEnumerable<ControlDevolucionesReporteDto>> GetReporteCtrlDevolucionesParaDistCanAsync(DateTime fecha, int idEmpresa) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_DistCanillasCantidadEntradaSalida"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@fecha", fecha, DbType.DateTime); | ||||||
|  |             parameters.Add("@idEmpresa", idEmpresa, DbType.Int32); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<ControlDevolucionesReporteDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<ControlDevolucionesReporteDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<TiradasPublicacionesSeccionesDto>> GetTiradasPublicacionesSeccionesAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta, int idPlanta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_TiradasPublicacionesSecciones"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@IdPublicacion", idPublicacion, DbType.Int32); | ||||||
|  |             parameters.Add("@FechaInicio", fechaDesde, DbType.Date); | ||||||
|  |             parameters.Add("@FechaFin", fechaHasta, DbType.Date); | ||||||
|  |             parameters.Add("@IdPlanta", idPlanta, DbType.Int32); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<TiradasPublicacionesSeccionesDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<TiradasPublicacionesSeccionesDto>(); } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public async Task<IEnumerable<TiradasPublicacionesSeccionesDto>> GetTiradasPublicacionesSeccionesConsolidadoAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_TiradasPublicacionesSeccionesConsolidado"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@IdPublicacion", idPublicacion, DbType.Int32); | ||||||
|  |             parameters.Add("@FechaInicio", fechaDesde, DbType.Date); | ||||||
|  |             parameters.Add("@FechaFin", fechaHasta, DbType.Date); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<TiradasPublicacionesSeccionesDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<TiradasPublicacionesSeccionesDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<ConsumoBobinasSeccionDto>> GetConsumoBobinasPorSeccionAsync(DateTime fechaDesde, DateTime fechaHasta, int idPlanta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_BobinasUtilizadasPorSeccion"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@FechaInicio", fechaDesde, DbType.DateTime2); | ||||||
|  |             parameters.Add("@FechaFin", fechaHasta, DbType.DateTime2); | ||||||
|  |             parameters.Add("@idPlanta", idPlanta, DbType.Int32); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<ConsumoBobinasSeccionDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<ConsumoBobinasSeccionDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<ConsumoBobinasSeccionDto>> GetConsumoBobinasPorSeccionConsolidadoAsync(DateTime fechaDesde, DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_BobinasUtilizadasPorSeccionConsolidado"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@FechaInicio", fechaDesde, DbType.DateTime2); | ||||||
|  |             parameters.Add("@FechaFin", fechaHasta, DbType.DateTime2); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<ConsumoBobinasSeccionDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<ConsumoBobinasSeccionDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<ConsumoBobinasPublicacionDto>> GetConsumoBobinasPorPublicacionAsync(DateTime fechaDesde, DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_BobinasUtilizadasPorPublicacion"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@FechaInicio", fechaDesde, DbType.DateTime2); | ||||||
|  |             parameters.Add("@FechaFin", fechaHasta, DbType.DateTime2); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<ConsumoBobinasPublicacionDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<ConsumoBobinasPublicacionDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<ComparativaConsumoBobinasDto>> GetComparativaConsumoBobinasAsync(DateTime fechaInicioMesA, DateTime fechaFinMesA, DateTime fechaInicioMesB, DateTime fechaFinMesB, int idPlanta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_CompararConsumoBobinasMeses"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@FechaInicioMesA", fechaInicioMesA, DbType.Date); | ||||||
|  |             parameters.Add("@FechaFinMesA", fechaFinMesA, DbType.Date); | ||||||
|  |             parameters.Add("@FechaInicioMesB", fechaInicioMesB, DbType.Date); | ||||||
|  |             parameters.Add("@FechaFinMesB", fechaFinMesB, DbType.Date); | ||||||
|  |             parameters.Add("@IdPlanta", idPlanta, DbType.Int32); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<ComparativaConsumoBobinasDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<ComparativaConsumoBobinasDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task<IEnumerable<ComparativaConsumoBobinasDto>> GetComparativaConsumoBobinasConsolidadoAsync(DateTime fechaInicioMesA, DateTime fechaFinMesA, DateTime fechaInicioMesB, DateTime fechaFinMesB) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_CompararConsumoBobinasMesesConsolidado"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@FechaInicioMesA", fechaInicioMesA, DbType.Date); | ||||||
|  |             parameters.Add("@FechaFinMesA", fechaFinMesA, DbType.Date); | ||||||
|  |             parameters.Add("@FechaInicioMesB", fechaInicioMesB, DbType.Date); | ||||||
|  |             parameters.Add("@FechaFinMesB", fechaFinMesB, DbType.Date); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<ComparativaConsumoBobinasDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<ComparativaConsumoBobinasDto>(); } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         // Implementación para SP_BalanceCuentaDistEntradaSalidaPorEmpresa | ||||||
|  |         public async Task<IEnumerable<BalanceCuentaDistDto>> GetBalanceCuentaDistEntradaSalidaPorEmpresaAsync(int idDistribuidor, int idEmpresa, DateTime fechaDesde, DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_BalanceCuentaDistEntradaSalidaPorEmpresa"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@idDistribuidor", idDistribuidor, DbType.Int32); | ||||||
|  |             parameters.Add("@idEmpresa", idEmpresa, DbType.Int32); | ||||||
|  |             parameters.Add("@fechaDesde", fechaDesde, DbType.DateTime); | ||||||
|  |             parameters.Add("@fechaHasta", fechaHasta, DbType.DateTime); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<BalanceCuentaDistDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<BalanceCuentaDistDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Implementación para SP_BalanceCuentDistDebCredEmpresa | ||||||
|  |         public async Task<IEnumerable<BalanceCuentaDebCredDto>> GetBalanceCuentDistDebCredEmpresaAsync(int idDistribuidor, int idEmpresa, DateTime fechaDesde, DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_BalanceCuentDistDebCredEmpresa"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@idDistribuidor", idDistribuidor, DbType.Int32); | ||||||
|  |             parameters.Add("@idEmpresa", idEmpresa, DbType.Int32); | ||||||
|  |             parameters.Add("@fechaDesde", fechaDesde, DbType.DateTime); | ||||||
|  |             parameters.Add("@fechaHasta", fechaHasta, DbType.DateTime); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<BalanceCuentaDebCredDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<BalanceCuentaDebCredDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Implementación para SP_BalanceCuentDistPagosEmpresa | ||||||
|  |         public async Task<IEnumerable<BalanceCuentaPagosDto>> GetBalanceCuentDistPagosEmpresaAsync(int idDistribuidor, int idEmpresa, DateTime fechaDesde, DateTime fechaHasta) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_BalanceCuentDistPagosEmpresa"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@idDistribuidor", idDistribuidor, DbType.Int32); | ||||||
|  |             parameters.Add("@idEmpresa", idEmpresa, DbType.Int32); | ||||||
|  |             parameters.Add("@fechaDesde", fechaDesde, DbType.DateTime); | ||||||
|  |             parameters.Add("@fechaHasta", fechaHasta, DbType.DateTime); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<BalanceCuentaPagosDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<BalanceCuentaPagosDto>(); } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Implementación para SP_BalanceCuentSaldosEmpresas | ||||||
|  |         public async Task<IEnumerable<SaldoDto>> GetBalanceCuentSaldosEmpresasAsync(string destino, int idDestino, int idEmpresa) | ||||||
|  |         { | ||||||
|  |             const string spName = "dbo.SP_BalanceCuentSaldosEmpresas"; | ||||||
|  |             var parameters = new DynamicParameters(); | ||||||
|  |             parameters.Add("@Destino", destino, DbType.String); | ||||||
|  |             parameters.Add("@idDestino", idDestino, DbType.Int32); | ||||||
|  |             parameters.Add("@idEmpresa", idEmpresa, DbType.Int32); | ||||||
|  |             try { using var connection = _dbConnectionFactory.CreateConnection(); return await connection.QueryAsync<SaldoDto>(spName, parameters, commandType: CommandType.StoredProcedure); } | ||||||
|  |             catch (Exception ex) { _logger.LogError(ex, "Error SP {SPName}", spName); return Enumerable.Empty<SaldoDto>(); } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | public class BalanceCuentaDebCredDto // Para SP_BalanceCuentDistDebCred y SP_BalanceCuentDistDebCredEmpresa | ||||||
|  | { | ||||||
|  |     public DateTime Fecha { get; set; } | ||||||
|  |     public string? Referencia { get; set; } | ||||||
|  |     public decimal Debe { get; set; } | ||||||
|  |     public decimal Haber { get; set; } | ||||||
|  | } | ||||||
| @@ -0,0 +1,11 @@ | |||||||
|  | public class BalanceCuentaDistDto // Para SP_BalanceCuentaDistEntradaSalida y SP_BalanceCuentaDistEntradaSalidaPorEmpresa | ||||||
|  | { | ||||||
|  |     public DateTime Fecha { get; set; } | ||||||
|  |     public string Publicacion { get; set; } = string.Empty; | ||||||
|  |     public string Distribuidor { get; set; } = string.Empty; | ||||||
|  |     public int Cantidad { get; set; } | ||||||
|  |     public string Remito { get; set; } = string.Empty; // En SP es int, pero en RDLC puede ser string | ||||||
|  |     public string? Observacion { get; set; } | ||||||
|  |     public decimal Debe { get; set; } | ||||||
|  |     public decimal Haber { get; set; } | ||||||
|  | } | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | public class BalanceCuentaPagosDto // Para SP_BalanceCuentDistPagos y SP_BalanceCuentDistPagosEmpresa | ||||||
|  | { | ||||||
|  |     public DateTime Fecha { get; set; } | ||||||
|  |     public int Recibo { get; set; } | ||||||
|  |     public string Tipo { get; set; } = string.Empty; | ||||||
|  |     public decimal Debe { get; set; } | ||||||
|  |     public decimal Haber { get; set; } | ||||||
|  |     public string? Detalle { get; set; } | ||||||
|  | } | ||||||
| @@ -0,0 +1,13 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class ComparativaConsumoBobinasDto | ||||||
|  |     { | ||||||
|  |         public string TipoBobina { get; set; } = string.Empty; | ||||||
|  |         public int BobinasUtilizadasMesA { get; set; } | ||||||
|  |         public int BobinasUtilizadasMesB { get; set; } | ||||||
|  |         public int DiferenciaBobinasUtilizadas { get; set; } | ||||||
|  |         public int KilosUtilizadosMesA { get; set; } | ||||||
|  |         public int KilosUtilizadosMesB { get; set; } | ||||||
|  |         public int DiferenciaKilosUtilizados { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,10 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class ConsumoBobinasPublicacionDto | ||||||
|  |     { | ||||||
|  |         public string NombrePlanta { get; set; } = string.Empty; | ||||||
|  |         public string NombrePublicacion { get; set; } = string.Empty; | ||||||
|  |         public int TotalKilos { get; set; } | ||||||
|  |         public int CantidadBobinas { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,11 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class ConsumoBobinasSeccionDto | ||||||
|  |     { | ||||||
|  |         public string NombrePublicacion { get; set; } = string.Empty; | ||||||
|  |         public string NombreSeccion { get; set; } = string.Empty; | ||||||
|  |         public string NombreBobina { get; set; } = string.Empty; | ||||||
|  |         public int CantidadBobinas { get; set; } | ||||||
|  |         public int TotalKilos { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,14 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class ControlDevolucionesReporteDto | ||||||
|  |     { | ||||||
|  |         public int Ingresados { get; set; } | ||||||
|  |         public int Sobrantes { get; set; } | ||||||
|  |         public string Publicacion { get; set; } = string.Empty; | ||||||
|  |         public int Llevados { get; set; } | ||||||
|  |         public int Devueltos { get; set; } | ||||||
|  |         public string Tipo { get; set; } = string.Empty; // "Accionistas" o "Canillitas" | ||||||
|  |         public int TotalNoAccionistas { get; set; } | ||||||
|  |         public int SinCargo {get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,11 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class DetalleDistribucionCanillaAllDto | ||||||
|  |     { | ||||||
|  |         public string Publicacion { get; set; } = string.Empty; | ||||||
|  |         public int TotalCantSalida { get; set; } | ||||||
|  |         public int TotalCantEntrada { get; set; } | ||||||
|  |         public decimal TotalRendir { get; set; } | ||||||
|  |         public string TipoVendedor { get; set; } = string.Empty; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,14 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class DetalleDistribucionCanillaDto | ||||||
|  |     { | ||||||
|  |         public string Publicacion { get; set; } = string.Empty; | ||||||
|  |         public string Canilla { get; set; } = string.Empty; | ||||||
|  |         public int TotalCantSalida { get; set; } | ||||||
|  |         public int TotalCantEntrada { get; set; } | ||||||
|  |         public decimal TotalRendir { get; set; } | ||||||
|  |         // 'Fecha' si es para SP_DistCanillasEntradaSalidaPubliFechaLiq | ||||||
|  |         // y SP_DistCanillasAccEntradaSalidaPubliFechaLiq | ||||||
|  |         public DateTime? Fecha { get; set; } // Hacemos nullable para adaptarlo | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,12 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class ListadoDistribucionCanillasImporteDto | ||||||
|  |     { | ||||||
|  |         public string Fecha { get; set; } = string.Empty; | ||||||
|  |         public int Llevados { get; set; } | ||||||
|  |         public int Devueltos { get; set; } | ||||||
|  |         public int Vendidos { get; set; } | ||||||
|  |         public decimal TotalRendirPublicacion { get; set; } | ||||||
|  |         public decimal TotalRendirGeneral { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,13 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class ListadoDistribucionCanillasPromedioDiaDto | ||||||
|  |     { | ||||||
|  |         public string Dia { get; set; } = string.Empty; // Nombre del día | ||||||
|  |         public int Cant { get; set; } // Cantidad de días con ese nombre en el mes | ||||||
|  |         public int Llevados { get; set; } | ||||||
|  |         public int Devueltos { get; set; } | ||||||
|  |         public int Promedio_Llevados { get; set; } | ||||||
|  |         public int Promedio_Devueltos { get; set; } | ||||||
|  |         public int Promedio_Ventas { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class ListadoDistribucionCanillasSimpleDto | ||||||
|  |     { | ||||||
|  |         public int Dia { get; set; } // Día del mes | ||||||
|  |         public int Llevados { get; set; } | ||||||
|  |         public int Devueltos { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,14 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class ListadoDistribucionGeneralPromedioDiaDto | ||||||
|  |     { | ||||||
|  |         public string Dia { get; set; } = string.Empty; | ||||||
|  |         public int CantidadDias { get; set; } | ||||||
|  |         public int PromedioTirada { get; set; } | ||||||
|  |         public int PromedioSinCargo { get; set; } | ||||||
|  |         public int PromedioPerdidos { get; set; } | ||||||
|  |         public int PromedioLlevados { get; set; } | ||||||
|  |         public int PromedioDevueltos { get; set; } | ||||||
|  |         public int PromedioVendidos { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,15 @@ | |||||||
|  | using System; | ||||||
|  |  | ||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class ListadoDistribucionGeneralResumenDto | ||||||
|  |     { | ||||||
|  |         public DateTime Fecha { get; set; } | ||||||
|  |         public int CantidadTirada { get; set; } | ||||||
|  |         public int SinCargo { get; set; } | ||||||
|  |         public int Perdidos { get; set; } | ||||||
|  |         public int Llevados { get; set; } | ||||||
|  |         public int Devueltos { get; set; } | ||||||
|  |         public int Vendidos { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,13 @@ | |||||||
|  | using System; | ||||||
|  |  | ||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class MovimientoBobinaEstadoDetalleDto | ||||||
|  |     { | ||||||
|  |         public string TipoBobina { get; set; } = string.Empty; | ||||||
|  |         public string NumeroRemito { get; set; } = string.Empty; | ||||||
|  |         public DateTime FechaMovimiento { get; set; } | ||||||
|  |         public int Cantidad { get; set; } | ||||||
|  |         public string TipoMovimiento { get; set; } = string.Empty; // "Ingreso", "Utilizada", "Dañada" | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class MovimientoBobinaEstadoTotalDto | ||||||
|  |     { | ||||||
|  |         public string TipoMovimiento { get; set; } = string.Empty; // "Ingresos", "Utilizadas", "Dañadas" | ||||||
|  |         public int TotalBobinas { get; set; } | ||||||
|  |         public int TotalKilos { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,17 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class MovimientoBobinasDto | ||||||
|  |     { | ||||||
|  |         public string TipoBobina { get; set; } = string.Empty; | ||||||
|  |         public int BobinasIniciales { get; set; } | ||||||
|  |         public int KilosIniciales { get; set; } | ||||||
|  |         public int BobinasCompradas { get; set; } | ||||||
|  |         public int KilosComprados { get; set; } | ||||||
|  |         public int BobinasConsumidas { get; set; } | ||||||
|  |         public int KilosConsumidos { get; set; } | ||||||
|  |         public int BobinasDaniadas { get; set; } | ||||||
|  |         public int KilosDaniados { get; set; } | ||||||
|  |         public int BobinasFinales { get; set; } | ||||||
|  |         public int KilosFinales { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class ObtenerCtrlDevolucionesDto | ||||||
|  |     { | ||||||
|  |         public int Remito { get; set; } // El SP devuelve una columna 'Remito' que en la tabla es 'Entrada' | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,4 @@ | |||||||
|  | public class SaldoDto // Para SP_BalanceCuentSaldos y SP_BalanceCuentSaldosEmpresas | ||||||
|  | { | ||||||
|  |     public decimal Monto { get; set; } | ||||||
|  | } | ||||||
| @@ -0,0 +1,12 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class TiradasPublicacionesSeccionesDto | ||||||
|  |     { | ||||||
|  |         public string NombreSeccion { get; set; } = string.Empty; | ||||||
|  |         public int TotalPaginasImpresas { get; set; } | ||||||
|  |         public int CantidadTiradas { get; set; } | ||||||
|  |         public int TotalPaginasEjemplares { get; set; } | ||||||
|  |         public int TotalEjemplares { get; set; } | ||||||
|  |         public int PromedioPaginasPorEjemplar { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,13 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class VentaMensualSecretariaElDiaDto | ||||||
|  |     { | ||||||
|  |         public int Dia { get; set; } | ||||||
|  |         public int CantidadCanillas { get; set; } | ||||||
|  |         public int Tirajes { get; set; } | ||||||
|  |         public int Ventas { get; set; } | ||||||
|  |         public int Accionistas { get; set; } | ||||||
|  |         public int TotalCooperativa { get; set; } | ||||||
|  |         public int TotalGeneral { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,13 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class VentaMensualSecretariaElPlataDto | ||||||
|  |     { | ||||||
|  |         public int Dia { get; set; } | ||||||
|  |         public int TiradaCoop { get; set; } | ||||||
|  |         public int DevolucionCoop { get; set; } | ||||||
|  |         public int VentaCoop { get; set; } | ||||||
|  |         public int TiradaCan { get; set; } | ||||||
|  |         public int VentaCan { get; set; } | ||||||
|  |         public int Total { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,20 @@ | |||||||
|  | namespace GestionIntegral.Api.Dtos.Reportes | ||||||
|  | { | ||||||
|  |     public class VentaMensualSecretariaTirDevoDto | ||||||
|  |     { | ||||||
|  |         public int Dia { get; set; } | ||||||
|  |         public int TiradaCoop { get; set; } | ||||||
|  |         public int DevolucionCoop { get; set; } | ||||||
|  |         public int VentaCoop { get; set; } | ||||||
|  |         public int VentaCan { get; set; } | ||||||
|  |         public int TiradaPopular { get; set; } | ||||||
|  |         public int DevolucionPopular { get; set; } | ||||||
|  |         public int VentaPopular { get; set; } | ||||||
|  |         public int TiradaClarin { get; set; } | ||||||
|  |         public int DevolucionClarin { get; set; } | ||||||
|  |         public int VentaClarin { get; set; } | ||||||
|  |         public int TiradaNacion { get; set; } | ||||||
|  |         public int DevolucionNacion { get; set; } | ||||||
|  |         public int VentaNacion { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | // src/Services/Reportes/IReportesService.cs | ||||||
| using GestionIntegral.Api.Dtos.Reportes; | using GestionIntegral.Api.Dtos.Reportes; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| @@ -8,6 +9,57 @@ namespace GestionIntegral.Api.Services.Reportes | |||||||
|     public interface IReportesService |     public interface IReportesService | ||||||
|     { |     { | ||||||
|         Task<(IEnumerable<ExistenciaPapelDto> Data, string? Error)> ObtenerExistenciaPapelAsync(DateTime fechaDesde, DateTime fechaHasta, int? idPlanta, bool consolidado); |         Task<(IEnumerable<ExistenciaPapelDto> Data, string? Error)> ObtenerExistenciaPapelAsync(DateTime fechaDesde, DateTime fechaHasta, int? idPlanta, bool consolidado); | ||||||
|         // ... |         Task<(IEnumerable<MovimientoBobinasDto> Data, string? Error)> ObtenerMovimientoBobinasAsync(DateTime fechaDesde, DateTime fechaHasta, int idPlanta); | ||||||
|  |         Task<(IEnumerable<MovimientoBobinaEstadoDetalleDto> Detalle, IEnumerable<MovimientoBobinaEstadoTotalDto> Totales, string? Error)> ObtenerMovimientoBobinasPorEstadoAsync(DateTime fechaDesde, DateTime fechaHasta, int idPlanta); | ||||||
|  |  | ||||||
|  |         // Reporte Listado Distribucion General (RR002) | ||||||
|  |         Task<(IEnumerable<ListadoDistribucionGeneralResumenDto> Resumen, IEnumerable<ListadoDistribucionGeneralPromedioDiaDto> Promedios, string? Error)> ObtenerListadoDistribucionGeneralAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |  | ||||||
|  |         // Reporte Listado Distribucion Canillas (RR002) | ||||||
|  |         Task<(IEnumerable<ListadoDistribucionCanillasSimpleDto> Simple, IEnumerable<ListadoDistribucionCanillasPromedioDiaDto> Promedios, string? Error)> ObtenerListadoDistribucionCanillasAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |  | ||||||
|  |         // Reporte Listado Distribucion Canillas con Importes (RR002) | ||||||
|  |         Task<(IEnumerable<ListadoDistribucionCanillasImporteDto> Data, string? Error)> ObtenerListadoDistribucionCanillasConImporteAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta, bool esAccionista); | ||||||
|  |  | ||||||
|  |         // Reportes Venta Mensual Secretaria | ||||||
|  |         Task<(IEnumerable<VentaMensualSecretariaElDiaDto> Data, string? Error)> ObtenerVentaMensualSecretariaElDiaAsync(DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<(IEnumerable<VentaMensualSecretariaElPlataDto> Data, string? Error)> ObtenerVentaMensualSecretariaElPlataAsync(DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |         Task<(IEnumerable<VentaMensualSecretariaTirDevoDto> Data, string? Error)> ObtenerVentaMensualSecretariaTirDevoAsync(DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |  | ||||||
|  |         // Reporte Distribucion Canillas (MC005) - Este es un reporte más complejo | ||||||
|  |         Task<( | ||||||
|  |             IEnumerable<DetalleDistribucionCanillaDto> Canillas, | ||||||
|  |             IEnumerable<DetalleDistribucionCanillaDto> CanillasAcc, | ||||||
|  |             IEnumerable<DetalleDistribucionCanillaAllDto> CanillasAll, | ||||||
|  |             IEnumerable<DetalleDistribucionCanillaDto> CanillasFechaLiq, | ||||||
|  |             IEnumerable<DetalleDistribucionCanillaDto> CanillasAccFechaLiq, | ||||||
|  |             IEnumerable<ObtenerCtrlDevolucionesDto> CtrlDevoluciones, | ||||||
|  |             IEnumerable<ControlDevolucionesReporteDto> CtrlDevolucionesParaDistCan, | ||||||
|  |             string? Error | ||||||
|  |         )> ObtenerReporteDistribucionCanillasAsync(DateTime fecha, int idEmpresa); // ESTA ES LA FIRMA CORRECTA Y ÚNICA PARA ESTE MÉTODO | ||||||
|  |  | ||||||
|  |         // Reporte Tiradas por Publicación y Secciones (RR008) | ||||||
|  |         Task<(IEnumerable<TiradasPublicacionesSeccionesDto> Data, string? Error)> ObtenerTiradasPublicacionesSeccionesAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta, int idPlanta); | ||||||
|  |         Task<(IEnumerable<TiradasPublicacionesSeccionesDto> Data, string? Error)> ObtenerTiradasPublicacionesSeccionesConsolidadoAsync(int idPublicacion, DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |  | ||||||
|  |         // Reporte Consumo Bobinas por Seccion (RR007) | ||||||
|  |         Task<(IEnumerable<ConsumoBobinasSeccionDto> Data, string? Error)> ObtenerConsumoBobinasPorSeccionAsync(DateTime fechaDesde, DateTime fechaHasta, int idPlanta); | ||||||
|  |         Task<(IEnumerable<ConsumoBobinasSeccionDto> Data, string? Error)> ObtenerConsumoBobinasPorSeccionConsolidadoAsync(DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |  | ||||||
|  |         // Reporte Consumo Bobinas por Publicacion (RR007) - Consolidado | ||||||
|  |         Task<(IEnumerable<ConsumoBobinasPublicacionDto> Data, string? Error)> ObtenerConsumoBobinasPorPublicacionAsync(DateTime fechaDesde, DateTime fechaHasta); | ||||||
|  |  | ||||||
|  |         // Reporte Comparativa Consumo Bobinas (RR007) | ||||||
|  |         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 | ||||||
|  |         Task<( | ||||||
|  |             IEnumerable<BalanceCuentaDistDto> EntradasSalidas, | ||||||
|  |             IEnumerable<BalanceCuentaDebCredDto> DebitosCreditos, | ||||||
|  |             IEnumerable<BalanceCuentaPagosDto> Pagos, | ||||||
|  |             IEnumerable<SaldoDto> Saldos, | ||||||
|  |             string? Error | ||||||
|  |         )> ObtenerReporteCuentasDistribuidorAsync(int idDistribuidor, int idEmpresa, DateTime fechaDesde, DateTime fechaHasta); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | // src/Services/Reportes/ReportesService.cs | ||||||
| using GestionIntegral.Api.Data.Repositories.Reportes; | using GestionIntegral.Api.Data.Repositories.Reportes; | ||||||
| using GestionIntegral.Api.Dtos.Reportes; | using GestionIntegral.Api.Dtos.Reportes; | ||||||
| using Microsoft.Extensions.Logging; | using Microsoft.Extensions.Logging; | ||||||
| @@ -12,6 +13,7 @@ namespace GestionIntegral.Api.Services.Reportes | |||||||
|     { |     { | ||||||
|         private readonly IReportesRepository _reportesRepository; |         private readonly IReportesRepository _reportesRepository; | ||||||
|         private readonly ILogger<ReportesService> _logger; |         private readonly ILogger<ReportesService> _logger; | ||||||
|  |         // No necesitas _connectionFactory aquí si toda la lógica de BD está en el repositorio. | ||||||
|  |  | ||||||
|         public ReportesService(IReportesRepository reportesRepository, ILogger<ReportesService> logger) |         public ReportesService(IReportesRepository reportesRepository, ILogger<ReportesService> logger) | ||||||
|         { |         { | ||||||
| @@ -35,34 +37,386 @@ namespace GestionIntegral.Api.Services.Reportes | |||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 var dataFromRepo = await _reportesRepository.GetExistenciaPapelAsync(fechaDesde, fechaHasta, idPlanta, consolidado); |                 var dataFromRepo = await _reportesRepository.GetExistenciaPapelAsync(fechaDesde, fechaHasta, idPlanta, consolidado); | ||||||
|  |  | ||||||
|                 // Ajustar DateTimeKind a Utc aquí |  | ||||||
|                 var dataWithUtcDates = dataFromRepo.Select(dto => |                 var dataWithUtcDates = dataFromRepo.Select(dto => | ||||||
|                 { |                 { | ||||||
|                     if (dto.FechaEstimacionFinStock.HasValue) |                     if (dto.FechaEstimacionFinStock.HasValue) | ||||||
|                     { |                     { | ||||||
|                         // Aseguramos que solo tomamos la parte de la fecha y la especificamos como UTC |  | ||||||
|                         // Si ya viene con hora 00:00:00 del SP, .Date no cambia nada. |  | ||||||
|                         // Si viniera con hora, .Date la trunca a 00:00:00. |  | ||||||
|                         dto.FechaEstimacionFinStock = DateTime.SpecifyKind(dto.FechaEstimacionFinStock.Value.Date, DateTimeKind.Utc); |                         dto.FechaEstimacionFinStock = DateTime.SpecifyKind(dto.FechaEstimacionFinStock.Value.Date, DateTimeKind.Utc); | ||||||
|                     } |                     } | ||||||
|                     return dto; |                     return dto; | ||||||
|                 }).ToList(); |                 }).ToList(); | ||||||
|  |  | ||||||
|                 return (dataWithUtcDates, null); |                 return (dataWithUtcDates, null); | ||||||
|             } |             } | ||||||
|             catch (ArgumentNullException ex) when (ex.ParamName == "idPlanta") // Capturar la excepción del repositorio |             catch (ArgumentNullException ex) when (ex.ParamName == "idPlanta") | ||||||
|             { |             { | ||||||
|                 _logger.LogWarning(ex, "ArgumentNullException para idPlanta en ObtenerExistenciaPapelAsync."); |                 _logger.LogWarning(ex, "ArgumentNullException para idPlanta en ObtenerExistenciaPapelAsync."); | ||||||
|                 return (Enumerable.Empty<ExistenciaPapelDto>(), ex.Message); // Devolver el mensaje de error del repo |                 return (Enumerable.Empty<ExistenciaPapelDto>(), ex.Message); | ||||||
|             } |             } | ||||||
|             catch (Exception ex) |             catch (Exception ex) | ||||||
|             { |             { | ||||||
|                 _logger.LogError(ex, "Error en ReportesService al obtener Existencia de Papel."); |                 _logger.LogError(ex, "Error en ReportesService al obtener Existencia de Papel."); | ||||||
|                 return (Enumerable.Empty<ExistenciaPapelDto>(), "Error interno al generar el reporte."); |                 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> CtrlDevoluciones, | ||||||
|  |             IEnumerable<ControlDevolucionesReporteDto> CtrlDevolucionesParaDistCan, | ||||||
|  |             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 ctrlDevolucionesTask = _reportesRepository.GetReporteObtenerCtrlDevolucionesAsync(fecha, idEmpresa); | ||||||
|  |                 var ctrlDevolucionesParaDistCanTask = _reportesRepository.GetReporteCtrlDevolucionesParaDistCanAsync(fecha, idEmpresa); | ||||||
|  |  | ||||||
|  |                 await Task.WhenAll(canillasTask, canillasAccTask, canillasAllTask, canillasFechaLiqTask, canillasAccFechaLiqTask, ctrlDevolucionesTask, ctrlDevolucionesParaDistCanTask); | ||||||
|  |  | ||||||
|  |                 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 ctrlDevolucionesTask ?? Enumerable.Empty<ObtenerCtrlDevolucionesDto>(), | ||||||
|  |                     await ctrlDevolucionesParaDistCanTask ?? Enumerable.Empty<ControlDevolucionesReporteDto>(), | ||||||
|  |                     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>(), | ||||||
|  |                     "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." | ||||||
|  |                 ); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -13,7 +13,7 @@ using System.Reflection; | |||||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("GestionIntegral.Api")] | [assembly: System.Reflection.AssemblyCompanyAttribute("GestionIntegral.Api")] | ||||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3c1fe15b1f03aef4b6b6b6482c8e9fa92dfbf7cd")] | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+298bc0d0941b976d5de4c53a7b17a88b500bc8e2")] | ||||||
| [assembly: System.Reflection.AssemblyProductAttribute("GestionIntegral.Api")] | [assembly: System.Reflection.AssemblyProductAttribute("GestionIntegral.Api")] | ||||||
| [assembly: System.Reflection.AssemblyTitleAttribute("GestionIntegral.Api")] | [assembly: System.Reflection.AssemblyTitleAttribute("GestionIntegral.Api")] | ||||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| {"GlobalPropertiesHash":"C9goqBDGh4B0L1HpPwpJHjfbRNoIuzqnU7zFMHk1LhM=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["lgiSIq1Xdt6PC6CpA82eiZlqBZS3M8jckHELlrL00LI=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y=","\u002BzMwu5DIAA49kPmSydn2WMzj\u002Bdcf0MC3YakKoR6HwYg=","FUb20tYUiusFv5/KhAPdh2OB4ArUWiGApXbQJdx8tX0=","pTWqrhLBwEeWg1GsRlTKzfOAnT1JEklZ8F1/EYlc1Nk=","Hu0oNH4YYNcbnR5Ts4qd5yzC5j5JbY2kEDXces8V1vs=","TKMARE0bLM2dm9NOqxxWztnuqao5IvCh24TEHCtht6I=","84UEEMEbmmNwHVXD5Iw3dtKHTZC0Zqbk3rIRO\u002BxOq4o=","qfTzsJ\u002B5ilLyrc6EhNm61KkSH37yRi85MtgW1\u002BUD2Vo=","4ayt/JAApEOfr0yjg9szkYMPzSs6x2k3QEwmrK5RZVY=","d0weYwKWe3mH5R2BURuNLkAyytO/viA6zivv9AcIBtQ=","Ssyx6SvSGgWMOzhc9pQpk6f6\u002BmVbKQNKeDJbvVA2tjs=","FSqDybxILZmKXw160ANhj76usnM83geRrbPvJxr89OA=","fdI2RZZ9M9QOVHCYU5cE\u002BgVVuT7ssRbMzdXvX8rHofc=","8ePFhqKT0OT9nEg3b5T7COC81U\u002BQBcf\u002BindBGyMy6z0=","/ghcduGmSd1I25YtYli\u002BqxF0xuscxc4cTDkbEC6XYVA=","/a3YEu0oBUeA5Qr2VMdppqLuz4CQPWJt2JfBl2dtUwA=","jEO/q4IO3UFTWxlyFwRr7kbGWcTIiS\u002BClxx3kahX/Fk=","4iYOCKYvhsROdGkA1hINVBejb6r8IkwFj9SNMKub3DM=","CeDswsZIn5a7t\u002BKeHJA222yhFvDVVEW1ky98Xxnxebc=","50j34YXOc950QSqaQBMtgezD3tV5mWWR9c5qZcYQoz4=","W/aX9jIKpjNEVoGrU6RXFOY8SDJVT6XB4Rg4QCaeQkQ=","16IbB\u002B3zYHZvsWbCQK6hBFmKJ6Z28SecBn2jm8R3w8I=","COJtHNQqycTJqXkFv2hhpLUT\u002B/AD4IWyQlmxkUVQPNk=","cp6a5bdvkLnUn3x47KQODzPycnx57RmWO\u002B9q8MuoGQo=","oKZRNhIQRaZrETEa3L6JiwIp0\u002BmjzJo193EWBoCuVUg=","sjwbCAEQX51sEWhYVGBihWUNBxniUKZALVJIGK\u002BYgsk=","A4m4kVcox60bvdkJ1CswoZADAT70WPcs4TAKdpMoUjM=","zSzyOuNcK0NQJLwK8Yg4sH4EflX7RPf65Fl2CZUWIGs=","88ziwhzzz1t8H52ibX38BcmB6qWJK\u002BVe/a7PtkJkK7w="],"CachedAssets":{},"CachedCopyCandidates":{}} | {"GlobalPropertiesHash":"C9goqBDGh4B0L1HpPwpJHjfbRNoIuzqnU7zFMHk1LhM=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["lgiSIq1Xdt6PC6CpA82eiZlqBZS3M8jckHELlrL00LI=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y=","\u002BzMwu5DIAA49kPmSydn2WMzj\u002Bdcf0MC3YakKoR6HwYg=","FUb20tYUiusFv5/KhAPdh2OB4ArUWiGApXbQJdx8tX0=","pTWqrhLBwEeWg1GsRlTKzfOAnT1JEklZ8F1/EYlc1Nk=","Hu0oNH4YYNcbnR5Ts4qd5yzC5j5JbY2kEDXces8V1vs=","TKMARE0bLM2dm9NOqxxWztnuqao5IvCh24TEHCtht6I=","84UEEMEbmmNwHVXD5Iw3dtKHTZC0Zqbk3rIRO\u002BxOq4o=","qfTzsJ\u002B5ilLyrc6EhNm61KkSH37yRi85MtgW1\u002BUD2Vo=","4ayt/JAApEOfr0yjg9szkYMPzSs6x2k3QEwmrK5RZVY=","d0weYwKWe3mH5R2BURuNLkAyytO/viA6zivv9AcIBtQ=","Ssyx6SvSGgWMOzhc9pQpk6f6\u002BmVbKQNKeDJbvVA2tjs=","FSqDybxILZmKXw160ANhj76usnM83geRrbPvJxr89OA=","fdI2RZZ9M9QOVHCYU5cE\u002BgVVuT7ssRbMzdXvX8rHofc=","8ePFhqKT0OT9nEg3b5T7COC81U\u002BQBcf\u002BindBGyMy6z0=","/ghcduGmSd1I25YtYli\u002BqxF0xuscxc4cTDkbEC6XYVA=","/a3YEu0oBUeA5Qr2VMdppqLuz4CQPWJt2JfBl2dtUwA=","jEO/q4IO3UFTWxlyFwRr7kbGWcTIiS\u002BClxx3kahX/Fk=","4iYOCKYvhsROdGkA1hINVBejb6r8IkwFj9SNMKub3DM=","CeDswsZIn5a7t\u002BKeHJA222yhFvDVVEW1ky98Xxnxebc=","50j34YXOc950QSqaQBMtgezD3tV5mWWR9c5qZcYQoz4=","W/aX9jIKpjNEVoGrU6RXFOY8SDJVT6XB4Rg4QCaeQkQ=","16IbB\u002B3zYHZvsWbCQK6hBFmKJ6Z28SecBn2jm8R3w8I=","COJtHNQqycTJqXkFv2hhpLUT\u002B/AD4IWyQlmxkUVQPNk=","cp6a5bdvkLnUn3x47KQODzPycnx57RmWO\u002B9q8MuoGQo=","oKZRNhIQRaZrETEa3L6JiwIp0\u002BmjzJo193EWBoCuVUg=","sjwbCAEQX51sEWhYVGBihWUNBxniUKZALVJIGK\u002BYgsk=","A4m4kVcox60bvdkJ1CswoZADAT70WPcs4TAKdpMoUjM=","zSzyOuNcK0NQJLwK8Yg4sH4EflX7RPf65Fl2CZUWIGs=","NpxIifDE4FyR4jhkRXHNdK9IIbA/joaTINJDnFlccPA="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||||
| @@ -1 +1 @@ | |||||||
| {"GlobalPropertiesHash":"w3MBbMV9Msh0YEq9AW/8s16bzXJ93T9lMVXKPm/r6es=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["lgiSIq1Xdt6PC6CpA82eiZlqBZS3M8jckHELlrL00LI=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y=","\u002BzMwu5DIAA49kPmSydn2WMzj\u002Bdcf0MC3YakKoR6HwYg=","FUb20tYUiusFv5/KhAPdh2OB4ArUWiGApXbQJdx8tX0=","pTWqrhLBwEeWg1GsRlTKzfOAnT1JEklZ8F1/EYlc1Nk=","Hu0oNH4YYNcbnR5Ts4qd5yzC5j5JbY2kEDXces8V1vs=","TKMARE0bLM2dm9NOqxxWztnuqao5IvCh24TEHCtht6I=","84UEEMEbmmNwHVXD5Iw3dtKHTZC0Zqbk3rIRO\u002BxOq4o=","qfTzsJ\u002B5ilLyrc6EhNm61KkSH37yRi85MtgW1\u002BUD2Vo=","4ayt/JAApEOfr0yjg9szkYMPzSs6x2k3QEwmrK5RZVY=","d0weYwKWe3mH5R2BURuNLkAyytO/viA6zivv9AcIBtQ=","Ssyx6SvSGgWMOzhc9pQpk6f6\u002BmVbKQNKeDJbvVA2tjs=","FSqDybxILZmKXw160ANhj76usnM83geRrbPvJxr89OA=","fdI2RZZ9M9QOVHCYU5cE\u002BgVVuT7ssRbMzdXvX8rHofc=","8ePFhqKT0OT9nEg3b5T7COC81U\u002BQBcf\u002BindBGyMy6z0=","/ghcduGmSd1I25YtYli\u002BqxF0xuscxc4cTDkbEC6XYVA=","/a3YEu0oBUeA5Qr2VMdppqLuz4CQPWJt2JfBl2dtUwA=","jEO/q4IO3UFTWxlyFwRr7kbGWcTIiS\u002BClxx3kahX/Fk=","4iYOCKYvhsROdGkA1hINVBejb6r8IkwFj9SNMKub3DM=","CeDswsZIn5a7t\u002BKeHJA222yhFvDVVEW1ky98Xxnxebc=","50j34YXOc950QSqaQBMtgezD3tV5mWWR9c5qZcYQoz4=","W/aX9jIKpjNEVoGrU6RXFOY8SDJVT6XB4Rg4QCaeQkQ=","16IbB\u002B3zYHZvsWbCQK6hBFmKJ6Z28SecBn2jm8R3w8I=","COJtHNQqycTJqXkFv2hhpLUT\u002B/AD4IWyQlmxkUVQPNk=","cp6a5bdvkLnUn3x47KQODzPycnx57RmWO\u002B9q8MuoGQo=","oKZRNhIQRaZrETEa3L6JiwIp0\u002BmjzJo193EWBoCuVUg=","sjwbCAEQX51sEWhYVGBihWUNBxniUKZALVJIGK\u002BYgsk=","A4m4kVcox60bvdkJ1CswoZADAT70WPcs4TAKdpMoUjM=","zSzyOuNcK0NQJLwK8Yg4sH4EflX7RPf65Fl2CZUWIGs=","88ziwhzzz1t8H52ibX38BcmB6qWJK\u002BVe/a7PtkJkK7w="],"CachedAssets":{},"CachedCopyCandidates":{}} | {"GlobalPropertiesHash":"w3MBbMV9Msh0YEq9AW/8s16bzXJ93T9lMVXKPm/r6es=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["lgiSIq1Xdt6PC6CpA82eiZlqBZS3M8jckHELlrL00LI=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y=","\u002BzMwu5DIAA49kPmSydn2WMzj\u002Bdcf0MC3YakKoR6HwYg=","FUb20tYUiusFv5/KhAPdh2OB4ArUWiGApXbQJdx8tX0=","pTWqrhLBwEeWg1GsRlTKzfOAnT1JEklZ8F1/EYlc1Nk=","Hu0oNH4YYNcbnR5Ts4qd5yzC5j5JbY2kEDXces8V1vs=","TKMARE0bLM2dm9NOqxxWztnuqao5IvCh24TEHCtht6I=","84UEEMEbmmNwHVXD5Iw3dtKHTZC0Zqbk3rIRO\u002BxOq4o=","qfTzsJ\u002B5ilLyrc6EhNm61KkSH37yRi85MtgW1\u002BUD2Vo=","4ayt/JAApEOfr0yjg9szkYMPzSs6x2k3QEwmrK5RZVY=","d0weYwKWe3mH5R2BURuNLkAyytO/viA6zivv9AcIBtQ=","Ssyx6SvSGgWMOzhc9pQpk6f6\u002BmVbKQNKeDJbvVA2tjs=","FSqDybxILZmKXw160ANhj76usnM83geRrbPvJxr89OA=","fdI2RZZ9M9QOVHCYU5cE\u002BgVVuT7ssRbMzdXvX8rHofc=","8ePFhqKT0OT9nEg3b5T7COC81U\u002BQBcf\u002BindBGyMy6z0=","/ghcduGmSd1I25YtYli\u002BqxF0xuscxc4cTDkbEC6XYVA=","/a3YEu0oBUeA5Qr2VMdppqLuz4CQPWJt2JfBl2dtUwA=","jEO/q4IO3UFTWxlyFwRr7kbGWcTIiS\u002BClxx3kahX/Fk=","4iYOCKYvhsROdGkA1hINVBejb6r8IkwFj9SNMKub3DM=","CeDswsZIn5a7t\u002BKeHJA222yhFvDVVEW1ky98Xxnxebc=","50j34YXOc950QSqaQBMtgezD3tV5mWWR9c5qZcYQoz4=","W/aX9jIKpjNEVoGrU6RXFOY8SDJVT6XB4Rg4QCaeQkQ=","16IbB\u002B3zYHZvsWbCQK6hBFmKJ6Z28SecBn2jm8R3w8I=","COJtHNQqycTJqXkFv2hhpLUT\u002B/AD4IWyQlmxkUVQPNk=","cp6a5bdvkLnUn3x47KQODzPycnx57RmWO\u002B9q8MuoGQo=","oKZRNhIQRaZrETEa3L6JiwIp0\u002BmjzJo193EWBoCuVUg=","sjwbCAEQX51sEWhYVGBihWUNBxniUKZALVJIGK\u002BYgsk=","A4m4kVcox60bvdkJ1CswoZADAT70WPcs4TAKdpMoUjM=","zSzyOuNcK0NQJLwK8Yg4sH4EflX7RPf65Fl2CZUWIGs=","NpxIifDE4FyR4jhkRXHNdK9IIbA/joaTINJDnFlccPA="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||||
		Reference in New Issue
	
	Block a user