QuestPdf Implementado en la totalidad de reportes.
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 7m55s

This commit is contained in:
2025-06-24 12:52:37 -03:00
parent a5bcbefa52
commit 229eb937f5
51 changed files with 4009 additions and 954 deletions

View File

@@ -0,0 +1,114 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Globalization;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class ComparativaConsumoBobinasDocument : IDocument
{
public ComparativaConsumoBobinasViewModel Model { get; }
public ComparativaConsumoBobinasDocument(ComparativaConsumoBobinasViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(9));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Spacing(5);
column.Item().AlignCenter().Text("Reporte de Consumo de Bobinas - Comparativa Mensual").SemiBold().FontSize(14);
string subTitle = Model.EsConsolidado ? "Consolidado" : $"Planta: {Model.NombrePlanta}";
column.Item().AlignCenter().Text(subTitle).FontSize(12);
column.Item().PaddingTop(5, Unit.Millimetre).Row(row =>
{
// Le damos una proporción menor al texto de la izquierda (que es corto y fijo).
row.RelativeItem(1).Text(text =>
{
text.Span("Fecha del Reporte: ").SemiBold().FontSize(12);
text.Span(Model.FechaReporte);
});
// Le damos una proporción mayor al texto de la derecha (que es largo y variable).
// El factor "2" significa que tendrá el doble de espacio disponible que el item con factor "1".
row.RelativeItem(2).AlignRight().Text(text =>
{
text.Span("Meses: ").SemiBold().FontSize(12);
text.Span($"{Model.MesA} (Mes A) contra {Model.MesB} (Mes B)").FontSize(12);
});
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(5, Unit.Millimetre).Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(3); // Tipo Bobina
columns.RelativeColumn(1); columns.RelativeColumn(1); columns.RelativeColumn(1); // Grupo Cantidad
columns.RelativeColumn(1); columns.RelativeColumn(1); columns.RelativeColumn(1); // Grupo Kilos
});
table.Header(header =>
{
// Fila 1 del Encabezado
header.Cell().RowSpan(2).Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignMiddle().Text("Tipo Bobina").SemiBold();
header.Cell().ColumnSpan(3).Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignCenter().Text("Cantidad Bobinas").SemiBold();
header.Cell().ColumnSpan(3).Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignCenter().Text("Kilos Utilizados").SemiBold();
// Fila 2 del Encabezado
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Mes A").SemiBold();
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Mes B").SemiBold();
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Diferencia").SemiBold();
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Kg Mes A").SemiBold();
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Kg Mes B").SemiBold();
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Diferencia").SemiBold();
});
foreach (var item in Model.Detalles.OrderBy(x => x.TipoBobina))
{
table.Cell().Border(1).Padding(3).Text(item.TipoBobina);
table.Cell().Border(1).Padding(3).AlignRight().Text(item.BobinasUtilizadasMesA.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.BobinasUtilizadasMesB.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.DiferenciaBobinasUtilizadas.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.KilosUtilizadosMesA.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.KilosUtilizadosMesB.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.DiferenciaKilosUtilizados.ToString("N0"));
}
// Fila de Totales
var style = TextStyle.Default.SemiBold();
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span("Totales").Style(style));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(Model.Detalles.Sum(x => x.BobinasUtilizadasMesA).ToString("N0")).Style(style));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(Model.Detalles.Sum(x => x.BobinasUtilizadasMesB).ToString("N0")).Style(style));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(Model.Detalles.Sum(x => x.DiferenciaBobinasUtilizadas).ToString("N0")).Style(style));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(Model.Detalles.Sum(x => x.KilosUtilizadosMesA).ToString("N0")).Style(style));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(Model.Detalles.Sum(x => x.KilosUtilizadosMesB).ToString("N0")).Style(style));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(Model.Detalles.Sum(x => x.DiferenciaKilosUtilizados).ToString("N0")).Style(style));
});
}
}
}

View File

@@ -0,0 +1,98 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class ConsumoBobinasPublicacionDocument : IDocument
{
public ConsumoBobinasPublicacionViewModel Model { get; }
public ConsumoBobinasPublicacionDocument(ConsumoBobinasPublicacionViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1.5f, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(10));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Spacing(5);
column.Item().AlignCenter().Text("Reporte de Consumo de Bobinas por Publicaciones").SemiBold().FontSize(14);
column.Item().PaddingTop(5, Unit.Millimetre).Row(row =>
{
row.RelativeItem().Text(text => { text.Span("Fecha del Reporte: ").SemiBold(); text.Span(Model.FechaReporte); });
row.RelativeItem().AlignRight().Text(text => { text.Span("Periodo: ").SemiBold(); text.Span($"{Model.FechaDesde} - {Model.FechaHasta}"); });
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(1, Unit.Centimetre).Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(2); // Planta
columns.RelativeColumn(3); // Publicación
columns.RelativeColumn(1.5f); // Kilos
columns.RelativeColumn(1.5f); // Cant. Bobinas
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Planta");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Publicación");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Kilos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Cant. Bobinas");
});
var gruposPorPlanta = Model.Detalles.GroupBy(p => p.NombrePlanta);
foreach (var grupoPlanta in gruposPorPlanta)
{
var primeraFilaDePlanta = true;
foreach (var detalle in grupoPlanta.OrderBy(d => d.NombrePublicacion))
{
// Celda de Planta (solo en la primera fila del grupo)
if (primeraFilaDePlanta)
{
table.Cell().RowSpan((uint)grupoPlanta.Count()).Border(1).Padding(3).AlignTop().Text(grupoPlanta.Key).SemiBold();
primeraFilaDePlanta = false;
}
table.Cell().Border(1).Padding(3).Text(detalle.NombrePublicacion);
table.Cell().Border(1).Padding(3).AlignRight().Text(detalle.TotalKilos.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(detalle.CantidadBobinas.ToString("N0"));
}
}
// Fila de Totales Generales
var totalGeneralKilos = Model.Detalles.Sum(d => d.TotalKilos);
var totalGeneralBobinas = Model.Detalles.Sum(d => d.CantidadBobinas);
table.Cell().ColumnSpan(2).BorderTop(1.5f).BorderColor(Colors.Black).Padding(3).AlignRight().Text("Totales").ExtraBold();
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).Padding(3).AlignRight().Text(t => t.Span(totalGeneralKilos.ToString("N0")).ExtraBold());
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).Padding(3).AlignRight().Text(t => t.Span(totalGeneralBobinas.ToString("N0")).ExtraBold());
});
}
}
}

View File

@@ -0,0 +1,139 @@
using GestionIntegral.Api.Dtos.Reportes;
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Collections.Generic;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class ConsumoBobinasSeccionDocument : IDocument
{
public ConsumoBobinasSeccionViewModel Model { get; }
public ConsumoBobinasSeccionDocument(ConsumoBobinasSeccionViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1.5f, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(9));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Spacing(5);
column.Item().AlignCenter().Text("Reporte de Consumo de Bobinas por Secciones").SemiBold().FontSize(14);
string subTitle = Model.EsConsolidado ? "Consolidado" : $"Planta: {Model.NombrePlanta}";
column.Item().AlignCenter().Text(subTitle).FontSize(12);
column.Item().PaddingTop(5, Unit.Millimetre).Row(row =>
{
row.RelativeItem().Text(text => { text.Span("Fecha del Reporte: ").SemiBold(); text.Span(Model.FechaReporte); });
row.RelativeItem().AlignRight().Text(text => { text.Span("Periodo: ").SemiBold(); text.Span($"{Model.FechaDesde} - {Model.FechaHasta}"); });
});
// Encabezado de la tabla principal
column.Item().PaddingTop(10).BorderBottom(1.5f).BorderColor(Colors.Black).Padding(4).Row(row =>
{
row.RelativeItem(1.5f).Text("Publicación").SemiBold();
row.RelativeItem(1.5f).Text("Sección").SemiBold();
row.RelativeItem(3).Text("Bobina").SemiBold();
row.RelativeItem(1).AlignRight().Text("Cant. Bobinas").SemiBold();
row.RelativeItem(1).AlignRight().Text("Kilos").SemiBold();
});
});
}
void ComposeContent(IContainer container)
{
container.Column(column =>
{
var gruposPorPublicacion = Model.Detalles.GroupBy(p => p.NombrePublicacion);
foreach (var grupoPub in gruposPorPublicacion)
{
column.Item().Element(c => ComposePublicacionSection(c, grupoPub));
}
// Fila de Totales Generales al final
var totalGeneralBobinas = Model.Detalles.Sum(d => d.CantidadBobinas);
var totalGeneralKilos = Model.Detalles.Sum(d => d.TotalKilos);
column.Item().PaddingTop(10).Row(row =>
{
row.RelativeItem(6).AlignRight().Text("Total General").ExtraBold().FontSize(12);
row.RelativeItem(1).AlignRight().Text(totalGeneralBobinas.ToString("N0")).ExtraBold().FontSize(12);
row.RelativeItem(1).AlignRight().Text(totalGeneralKilos.ToString("N0")).ExtraBold().FontSize(12);
});
});
}
// --- COMPONENTE PARA UNA PUBLICACIÓN ENTERA ---
void ComposePublicacionSection(IContainer container, IGrouping<string, ConsumoBobinasSeccionDto> grupoPub)
{
container.Row(row =>
{
// Columna 1: Nombre de la Publicación
row.RelativeItem(1.5f).BorderBottom(1).BorderLeft(1).BorderRight(1).BorderColor(Colors.Grey.Medium).Padding(3).Text(grupoPub.Key).SemiBold();
// Columna 2: Contiene todas las sub-tablas de secciones
row.RelativeItem(6.5f).Column(seccionesColumn =>
{
var gruposPorSeccion = grupoPub.GroupBy(s => s.NombreSeccion);
foreach(var grupoSec in gruposPorSeccion)
{
seccionesColumn.Item().Element(c => ComposeSeccionTable(c, grupoSec));
}
});
});
}
// --- COMPONENTE PARA LA TABLA DE UNA SECCIÓN ---
void ComposeSeccionTable(IContainer container, IGrouping<string, ConsumoBobinasSeccionDto> grupoSec)
{
container.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(1.5f); // Sección
columns.RelativeColumn(3); // Bobina
columns.RelativeColumn(1); // Cantidad
columns.RelativeColumn(1); // Kilos
});
// Filas de detalle
foreach (var detalle in grupoSec.OrderBy(d => d.NombreBobina))
{
table.Cell().Border(1).BorderColor(Colors.Grey.Medium).Padding(3).Text(grupoSec.Key);
table.Cell().Border(1).BorderColor(Colors.Grey.Medium).Padding(3).Text(detalle.NombreBobina);
table.Cell().Border(1).BorderColor(Colors.Grey.Medium).Padding(3).AlignRight().Text(detalle.CantidadBobinas.ToString("N0"));
table.Cell().Border(1).BorderColor(Colors.Grey.Medium).Padding(3).AlignRight().Text(detalle.TotalKilos.ToString("N0"));
}
// Fila de total de la sección
var totalCantSeccion = grupoSec.Sum(d => d.CantidadBobinas);
var totalKilosSeccion = grupoSec.Sum(d => d.TotalKilos);
table.Cell().ColumnSpan(2).Border(1).BorderColor(Colors.Grey.Medium).AlignRight().Padding(3).Text("Total Sección").SemiBold();
table.Cell().Border(1).BorderColor(Colors.Grey.Medium).Padding(3).AlignRight().Text(t => t.Span(totalCantSeccion.ToString("N0")).SemiBold());
table.Cell().Border(1).BorderColor(Colors.Grey.Medium).Padding(3).AlignRight().Text(t => t.Span(totalKilosSeccion.ToString("N0")).SemiBold());
});
}
}
}

View File

@@ -0,0 +1,126 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class ControlDevolucionesDocument : IDocument
{
public ControlDevolucionesViewModel Model { get; }
public ControlDevolucionesDocument(ControlDevolucionesViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public DocumentSettings GetSettings() => DocumentSettings.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Roboto").FontSize(11));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Item().AlignCenter().Text("Control de Devoluciones").SemiBold().FontSize(16);
column.Item().AlignCenter().Text("Canillas / Accionistas").FontSize(13);
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(1, Unit.Centimetre).Column(column =>
{
column.Spacing(15);
column.Item().Row(row =>
{
row.RelativeItem().Text(text =>
{
text.Span("Fecha Consultada: ").SemiBold();
text.Span(Model.FechaConsultada);
});
row.RelativeItem().AlignRight().Text(text =>
{
text.Span("Cantidad Canillas: ").SemiBold();
text.Span(Model.CantidadCanillas.ToString());
});
});
column.Item().PaddingTop(5).Border(1).Background(Colors.Grey.Lighten3).AlignCenter().Padding(2).Text(Model.NombreEmpresa).SemiBold();
column.Item().Border(1).Padding(10).Column(innerCol =>
{
innerCol.Spacing(5);
// Fila de "Ingresados por Remito" con borde inferior sólido.
innerCol.Item().BorderBottom(1, Unit.Point).BorderColor(Colors.Grey.Medium).Row(row =>
{
row.RelativeItem().Text("Ingresados por Remito:").SemiBold();
row.RelativeItem().AlignRight().Text(Model.TotalIngresadosPorRemito.ToString("N0"));
}); // <-- SOLUCIÓN: Borde sólido simple.
foreach (var item in Model.Detalles)
{
var totalSeccion = item.Devueltos - item.Llevados;
innerCol.Item().PaddingTop(5).Row(row =>
{
row.ConstantItem(100).Text(item.Tipo).SemiBold();
row.RelativeItem().Column(sub =>
{
sub.Spacing(2);
sub.Item().Row(r => {
r.RelativeItem().Text("Llevados");
r.RelativeItem().AlignRight().Text($"-{item.Llevados:N0}");
});
sub.Item().Row(r => {
r.RelativeItem().Text("Devueltos");
r.RelativeItem().AlignRight().Text($"{item.Devueltos:N0}");
});
sub.Item().BorderTop(1.5f).BorderColor(Colors.Black).PaddingTop(2).Row(r => {
r.RelativeItem().Text(t => t.Span("Total").SemiBold());
r.RelativeItem().AlignRight().Text(t => t.Span(totalSeccion.ToString("N0")).SemiBold());
});
});
});
}
});
column.Item().PaddingTop(10).Column(finalCol =>
{
finalCol.Spacing(2);
Action<RowDescriptor, string, string, bool> AddTotalRow = (row, label, value, isBold) =>
{
var text = row.RelativeItem().Text(label);
if (isBold) text.SemiBold();
var valueText = row.ConstantItem(80).AlignRight().Text(value);
if (isBold) valueText.SemiBold();
};
// Usamos bordes superiores para separar las líneas de total
finalCol.Item().BorderTop(2f).BorderColor(Colors.Black).PaddingTop(2).Row(row => AddTotalRow(row, "Total Devolución a la Fecha", Model.TotalDevolucionALaFecha.ToString("N0"), false));
finalCol.Item().BorderTop(1).BorderColor(Colors.Grey.Lighten2).PaddingTop(2).Row(row => AddTotalRow(row, "Total Devolución Días Anteriores", Model.TotalDevolucionDiasAnteriores.ToString("N0"), false));
finalCol.Item().BorderTop(1).BorderColor(Colors.Grey.Lighten2).PaddingTop(2).Row(row => AddTotalRow(row, "Total Devolución", Model.TotalDevolucionGeneral.ToString("N0"), false));
finalCol.Item().BorderTop(2f).BorderColor(Colors.Black).PaddingTop(5).Row(row => AddTotalRow(row, "Sin Cargo", Model.TotalSinCargo.ToString("N0"), false));
finalCol.Item().BorderTop(1).BorderColor(Colors.Grey.Lighten2).PaddingTop(2).Row(row => AddTotalRow(row, "Sobrantes", $"-{Model.TotalSobrantes.ToString("N0")}", false));
finalCol.Item().BorderTop(1).BorderColor(Colors.Grey.Lighten2).BorderBottom(1).BorderColor(Colors.Grey.Lighten2).PaddingTop(5).Row(row => AddTotalRow(row, "Diferencia", Model.DiferenciaFinal.ToString("N0"), true));
});
});
}
}
}

View File

@@ -0,0 +1,260 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Globalization;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class CuentasDistribuidorDocument : IDocument
{
public CuentasDistribuidorViewModel Model { get; }
private static readonly CultureInfo CultureAr = new CultureInfo("es-AR", false)
{
NumberFormat = { CurrencySymbol = "$" }
};
public CuentasDistribuidorDocument(CuentasDistribuidorViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public DocumentSettings GetSettings() => DocumentSettings.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(9));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); x.Span(" de "); x.TotalPages(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Item().Row(row =>
{
row.RelativeItem().Text($"Fecha de Reporte {Model.FechaReporte}");
row.RelativeItem().AlignCenter().Text("Cuenta De Distribuidor").SemiBold().FontSize(14);
row.RelativeItem();
});
column.Item().AlignCenter().Text(Model.NombreDistribuidor).FontSize(12);
column.Item().PaddingTop(2, Unit.Millimetre).Row(row =>
{
row.RelativeItem(2);
row.RelativeItem(8).AlignCenter().Text(text =>
{
text.Span("Fecha Consultada: Desde ").SemiBold();
text.Span(Model.FechaDesde);
text.Span(" Hasta ").SemiBold();
text.Span(Model.FechaHasta);
});
row.RelativeItem(2);
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(1, Unit.Centimetre).Column(column =>
{
column.Spacing(20);
if (Model.Movimientos.Any()) column.Item().Element(ComposeMovimientosTable);
if (Model.Pagos.Any()) column.Item().Element(ComposePagosTable);
if (Model.DebitosCreditos.Any()) column.Item().Element(ComposeDebCredTable);
column.Item().Element(ComposeResumenPeriodo);
column.Item().Element(ComposeSaldoFinal);
});
}
void ComposeMovimientosTable(IContainer container)
{
container.Column(column =>
{
column.Item().PaddingBottom(5).Text("Movimientos").SemiBold().FontSize(11);
column.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(60);
columns.RelativeColumn(2);
columns.ConstantColumn(50);
columns.ConstantColumn(50);
columns.RelativeColumn(1.5f);
columns.RelativeColumn(1.5f);
columns.RelativeColumn(2);
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Fecha");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Publicacion");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Remito");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignCenter().Text("Cantidad");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Debe");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Haber");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Saldo");
});
decimal saldoAcumulado = 0; // Inicia en CERO
foreach (var item in Model.Movimientos.OrderBy(m => m.Fecha))
{
saldoAcumulado += (item.Debe - item.Haber);
table.Cell().Border(1).Padding(2).Text(item.Fecha.ToString("dd/MM/yyyy"));
table.Cell().Border(1).Padding(2).Text(item.Publicacion);
table.Cell().Border(1).Padding(2).Text(item.Remito);
table.Cell().Border(1).Padding(2).AlignCenter().Text(item.Cantidad.ToString("N0"));
table.Cell().Border(1).Padding(2).AlignRight().Text(item.Debe.ToString("C", CultureAr));
table.Cell().Border(1).Padding(2).AlignRight().Text(item.Haber.ToString("C", CultureAr));
table.Cell().Border(1).Padding(2).AlignRight().Text(saldoAcumulado.ToString("C", CultureAr));
}
table.Cell().ColumnSpan(4).Border(1).AlignRight().Padding(2).Text(t => t.Span("Totales").SemiBold());
table.Cell().Border(1).AlignRight().Padding(2).Text(t => t.Span(Model.Movimientos.Sum(x => x.Debe).ToString("C", CultureAr)).SemiBold());
table.Cell().Border(1).AlignRight().Padding(2).Text(t => t.Span(Model.Movimientos.Sum(x => x.Haber).ToString("C", CultureAr)).SemiBold());
table.Cell().Border(1).AlignRight().Padding(2).Text(t => t.Span(saldoAcumulado.ToString("C", CultureAr)).SemiBold());
});
});
}
void ComposePagosTable(IContainer container)
{
container.Column(column =>
{
column.Item().PaddingBottom(5).Text("Pagos").SemiBold().FontSize(12);
column.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(60);
columns.RelativeColumn(1.5f);
columns.ConstantColumn(50);
columns.RelativeColumn(1.5f);
columns.RelativeColumn(1.5f);
columns.RelativeColumn(1.5f);
columns.RelativeColumn(2);
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Fecha");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Recibo");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Tipo");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Debe");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Haber");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Saldo");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Detalle");
});
decimal saldoAcumulado = Model.TotalMovimientos;
foreach (var item in Model.Pagos.OrderBy(p => p.Fecha).ThenBy(p => p.Recibo))
{
saldoAcumulado += (item.Debe - item.Haber);
table.Cell().Border(1).Padding(2).Text(item.Fecha.ToString("dd/MM/yyyy"));
table.Cell().Border(1).Padding(2).Text(item.Recibo.ToString());
table.Cell().Border(1).Padding(2).Text(item.Tipo);
table.Cell().Border(1).Padding(2).AlignRight().Text(item.Debe.ToString("C", CultureAr));
table.Cell().Border(1).Padding(2).AlignRight().Text(item.Haber.ToString("C", CultureAr));
table.Cell().Border(1).Padding(2).AlignRight().Text(saldoAcumulado.ToString("C", CultureAr));
table.Cell().Border(1).Padding(2).Text(item.Detalle);
}
table.Cell().ColumnSpan(3).Border(1).AlignRight().Padding(2).Text(t => t.Span("Totales").SemiBold());
table.Cell().Border(1).AlignRight().Padding(2).Text(t => t.Span(Model.Pagos.Sum(x => x.Debe).ToString("C", CultureAr)).SemiBold());
table.Cell().Border(1).AlignRight().Padding(2).Text(t => t.Span(Model.Pagos.Sum(x => x.Haber).ToString("C", CultureAr)).SemiBold());
table.Cell().Border(1).AlignRight().Padding(2).Text(t => t.Span(saldoAcumulado.ToString("C", CultureAr)).SemiBold());
table.Cell().Border(1);
});
});
}
void ComposeDebCredTable(IContainer container)
{
container.Column(column =>
{
column.Item().PaddingBottom(5).Text("Débitos / Créditos").SemiBold().FontSize(12);
column.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(65);
columns.RelativeColumn(2);
columns.RelativeColumn(1);
columns.RelativeColumn(1);
columns.RelativeColumn(2);
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Fecha");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Referencia");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Debe");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Haber");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Saldo");
});
decimal saldoAcumulado = Model.TotalMovimientos + Model.TotalPagos;
foreach (var item in Model.DebitosCreditos.OrderBy(dc => dc.Fecha))
{
saldoAcumulado += (item.Debe - item.Haber);
table.Cell().Border(1).Padding(2).Text(item.Fecha.ToString("dd/MM/yyyy"));
table.Cell().Border(1).Padding(2).Text(item.Referencia);
table.Cell().Border(1).Padding(2).AlignRight().Text(item.Debe.ToString("C", CultureAr));
table.Cell().Border(1).Padding(2).AlignRight().Text(item.Haber.ToString("C", CultureAr));
table.Cell().Border(1).Padding(2).AlignRight().Text(saldoAcumulado.ToString("C", CultureAr));
}
table.Cell().ColumnSpan(2).Border(1).AlignRight().Padding(2).Text(t => t.Span("Totales").SemiBold());
table.Cell().Border(1).AlignRight().Padding(2).Text(t => t.Span(Model.DebitosCreditos.Sum(x => x.Debe).ToString("C", CultureAr)).SemiBold());
table.Cell().Border(1).AlignRight().Padding(2).Text(t => t.Span(Model.DebitosCreditos.Sum(x => x.Haber).ToString("C", CultureAr)).SemiBold());
table.Cell().Border(1).AlignRight().Padding(2).Text(t => t.Span(saldoAcumulado.ToString("C", CultureAr)).SemiBold());
});
});
}
void ComposeResumenPeriodo(IContainer container)
{
container.PaddingTop(5, Unit.Millimetre).AlignLeft().Column(column =>
{
column.Item().Border(1).Padding(5).Width(300, Unit.Point).Column(col =>
{
col.Spacing(5);
col.Item().Text("Datos totales del periodo consultado").SemiBold();
Action<RowDescriptor, string, decimal> AddResumenRow = (row, label, value) =>
{
row.RelativeItem().Text(label);
row.ConstantItem(120).AlignRight().Text(value.ToString("C", CultureAr));
};
col.Item().Row(row => AddResumenRow(row, "Movimientos", Model.TotalMovimientos));
col.Item().Row(row => AddResumenRow(row, "Débitos/Créditos", Model.TotalDebitosCreditos));
col.Item().Row(row => AddResumenRow(row, "Pagos", Model.TotalPagos));
col.Item().BorderTop(1.5f).BorderColor(Colors.Black).PaddingTop(5).Row(row =>
{
row.RelativeItem().Text("Total").SemiBold();
row.ConstantItem(120).AlignRight().Text(t => t.Span(Model.TotalPeriodo.ToString("C", CultureAr)).SemiBold());
});
});
});
}
void ComposeSaldoFinal(IContainer container)
{
container.PaddingTop(5, Unit.Millimetre).AlignLeft().Text(text =>
{
text.Span($"Saldo Total del Distribuidor al {Model.FechaReporte} ").SemiBold().FontSize(12);
text.Span(Model.SaldoDeCuenta.ToString("C", CultureAr)).SemiBold().FontSize(12);
});
}
}
}

View File

@@ -0,0 +1,243 @@
// --- REEMPLAZAR ARCHIVO: Controllers/Reportes/PdfTemplates/DistribucionCanillasDocument.cs ---
using GestionIntegral.Api.Dtos.Reportes;
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class DistribucionCanillasDocument : IDocument
{
public DistribucionCanillasViewModel Model { get; }
private static readonly CultureInfo CultureAr = new CultureInfo("es-AR");
public DistribucionCanillasDocument(DistribucionCanillasViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(9));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Item().Row(row => {
row.RelativeItem().Text("Listado de Distribución: Canillas / Accionistas").FontSize(12);
row.RelativeItem().AlignRight().Text(text => {
text.Span("Fecha Consultada ").SemiBold().FontSize(12);
text.Span(Model.FechaConsultada).FontSize(12);
});
});
column.Item().PaddingTop(5).Row(row => {
row.RelativeItem().Text(text => {
text.Span("Fecha de Generación del Reporte ").SemiBold().FontSize(12);
text.Span(Model.FechaReporte);
});
row.RelativeItem().AlignRight().Text(text => {
text.Span("Empresa ").SemiBold().FontSize(12);
text.Span(Model.Empresa).FontSize(12);
});
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(5, Unit.Millimetre).Column(column =>
{
column.Spacing(15);
if(Model.Canillas.Any())
column.Item().Element(c => ComposeTablaDetallada(c, "Canillas", Model.Canillas));
if(Model.CanillasAccionistas.Any())
column.Item().Element(c => ComposeTablaDetallada(c, "Accionistas", Model.CanillasAccionistas));
if(Model.CanillasLiquidadasOtraFecha.Any())
column.Item().Element(c => ComposeTablaLiquidacion(c, "Liquidación de movimientos de otras fechas canillas", Model.CanillasLiquidadasOtraFecha));
if(Model.CanillasAccionistasLiquidadasOtraFecha.Any())
column.Item().Element(c => ComposeTablaLiquidacion(c, "Liquidación de movimientos de otras fechas accionistas", Model.CanillasAccionistasLiquidadasOtraFecha));
if(Model.CanillasTodos.Any())
column.Item().Element(c => ComposeTablaTotales(c, "Recuento de Publicaciones", Model.CanillasTodos));
if(Model.RemitoIngresado > 0)
column.Item().Element(ComposeResumenDevoluciones);
});
}
void ComposeTablaDetallada(IContainer container, string title, IEnumerable<DetalleDistribucionCanillaDto> data)
{
container.Column(column =>
{
column.Item().PaddingBottom(4).Text(title).SemiBold().FontSize(11);
column.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(3); columns.RelativeColumn(3);
columns.RelativeColumn(1); columns.RelativeColumn(1);
columns.RelativeColumn(1); columns.RelativeColumn(1.2f);
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Vendedor");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Publicación");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Llevados");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Devueltos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Vendidos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("A Rendir");
});
foreach (var grupoCanilla in data.GroupBy(c => c.Canilla))
{
var primeraFila = true;
// El RowSpan es el número de publicaciones + la fila de total
var totalFilasGrupo = grupoCanilla.Count() + 1;
foreach (var item in grupoCanilla.OrderBy(p => p.Publicacion))
{
if (primeraFila)
{
table.Cell().RowSpan((uint)totalFilasGrupo).Border(1).Padding(2).AlignTop().Text(item.Canilla);
primeraFila = false;
}
table.Cell().Border(1).Padding(2).Text(item.Publicacion);
table.Cell().Border(1).Padding(2).AlignRight().Text(item.TotalCantSalida.ToString("N0"));
table.Cell().Border(1).Padding(2).AlignRight().Text(item.TotalCantEntrada.ToString("N0"));
table.Cell().Border(1).Padding(2).AlignRight().Text((item.TotalCantSalida - item.TotalCantEntrada).ToString("N0"));
table.Cell().Border(1).Padding(2).AlignRight().Text(item.TotalRendir.ToString("C", CultureAr));
}
// Subtotal por canilla
table.Cell().Border(1).Padding(2).AlignRight().Text("Totales").SemiBold();
table.Cell().Border(1).Padding(2).AlignRight().Text(t => t.Span(grupoCanilla.Sum(i => i.TotalCantSalida).ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(2).AlignRight().Text(t => t.Span(grupoCanilla.Sum(i => i.TotalCantEntrada).ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(2).AlignRight().Text(t => t.Span(grupoCanilla.Sum(i => i.TotalCantSalida - i.TotalCantEntrada).ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(2).AlignRight().Text(t => t.Span(grupoCanilla.Sum(i => i.TotalRendir).ToString("C", CultureAr)).SemiBold());
}
var boldStyle = TextStyle.Default.ExtraBold();
table.Cell().ColumnSpan(2).BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span("Total " + title).Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(data.Sum(i => i.TotalCantSalida).ToString("N0")).Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(data.Sum(i => i.TotalCantEntrada).ToString("N0")).Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(data.Sum(i => i.TotalCantSalida - i.TotalCantEntrada).ToString("N0")).Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(data.Sum(i => i.TotalRendir).ToString("C", CultureAr)).Style(boldStyle));
});
});
}
void ComposeTablaLiquidacion(IContainer container, string title, IEnumerable<DetalleDistribucionCanillaDto> data)
{
container.Column(column =>
{
column.Item().PaddingBottom(4).Text(title).SemiBold().FontSize(11);
column.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(3); columns.RelativeColumn(1.5f);
columns.RelativeColumn(3); columns.RelativeColumn(1);
columns.RelativeColumn(1); columns.RelativeColumn(1);
columns.RelativeColumn(1.2f);
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Vendedor");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Fecha");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Publicación");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Llevados");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Devueltos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Vendidos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("A Rendir");
});
foreach(var item in data.OrderBy(d => d.Canilla).ThenBy(d => d.Fecha))
{
table.Cell().Border(1).Padding(2).Text(item.Canilla);
table.Cell().Border(1).Padding(2).Text(item.Fecha?.ToString("dd/MM/yyyy") ?? "");
table.Cell().Border(1).Padding(2).Text(item.Publicacion);
table.Cell().Border(1).Padding(2).AlignRight().Text(item.TotalCantSalida.ToString("N0"));
table.Cell().Border(1).Padding(2).AlignRight().Text(item.TotalCantEntrada.ToString("N0"));
table.Cell().Border(1).Padding(2).AlignRight().Text((item.TotalCantSalida - item.TotalCantEntrada).ToString("N0"));
table.Cell().Border(1).Padding(2).AlignRight().Text(item.TotalRendir.ToString("C", CultureAr));
}
var boldStyle = TextStyle.Default.ExtraBold();
table.Cell().ColumnSpan(3).BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span("Total").Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(data.Sum(i => i.TotalCantSalida).ToString("N0")).Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(data.Sum(i => i.TotalCantEntrada).ToString("N0")).Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(data.Sum(i => i.TotalCantSalida - i.TotalCantEntrada).ToString("N0")).Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(data.Sum(i => i.TotalRendir).ToString("C", CultureAr)).Style(boldStyle));
});
});
}
void ComposeTablaTotales(IContainer container, string title, IEnumerable<DetalleDistribucionCanillaAllDto> data)
{
container.Column(column =>
{
column.Item().PaddingBottom(4).Text(title).SemiBold().FontSize(11);
column.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(2); columns.RelativeColumn(3);
columns.RelativeColumn(1.2f); columns.RelativeColumn(1.2f);
columns.RelativeColumn(1.2f); columns.RelativeColumn(1.5f);
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Tipo Vendedor");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Publicación");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Llevados");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Devueltos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Vendidos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("A Rendir");
});
foreach(var item in data.OrderBy(d => d.TipoVendedor).ThenBy(d => d.Publicacion))
{
table.Cell().Border(1).Padding(2).Text(item.TipoVendedor);
table.Cell().Border(1).Padding(2).Text(item.Publicacion);
table.Cell().Border(1).Padding(2).AlignRight().Text(item.TotalCantSalida.ToString("N0"));
table.Cell().Border(1).Padding(2).AlignRight().Text(item.TotalCantEntrada.ToString("N0"));
table.Cell().Border(1).Padding(2).AlignRight().Text((item.TotalCantSalida-item.TotalCantEntrada).ToString("N0"));
table.Cell().Border(1).Padding(2).AlignRight().Text(item.TotalRendir.ToString("C", CultureAr));
}
var boldStyle = TextStyle.Default.ExtraBold();
table.Cell().ColumnSpan(2).BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span("Total General").Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(data.Sum(i => i.TotalCantSalida).ToString("N0")).Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(data.Sum(i => i.TotalCantEntrada).ToString("N0")).Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(data.Sum(i => i.TotalCantSalida - i.TotalCantEntrada).ToString("N0")).Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(data.Sum(i => i.TotalRendir).ToString("C", CultureAr)).Style(boldStyle));
});
});
}
void ComposeResumenDevoluciones(IContainer container)
{
container.PaddingTop(5).Column(column => {
column.Item().Row(row => {
row.Spacing(15);
row.AutoItem().Text(text => { text.Span("Remito: ").SemiBold().FontSize(11); text.Span(Model.RemitoIngresado.ToString("N0")).FontSize(11); });
row.AutoItem().Text(text => { text.Span("Devolución: ").SemiBold().FontSize(11); text.Span(Model.DevolucionTotal.ToString("N0")).FontSize(11); });
row.AutoItem().Text(text => { text.Span("Venta: ").SemiBold().FontSize(11); text.Span(Model.VentaTotal.ToString("N0")).FontSize(11); });
});
});
}
}
}

View File

@@ -0,0 +1,126 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Globalization;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class DistribucionCanillasTotalesDocument : IDocument
{
public DistribucionCanillasViewModel Model { get; }
private static readonly CultureInfo CultureAr = new CultureInfo("es-AR");
public DistribucionCanillasTotalesDocument(DistribucionCanillasViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(10));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Item().Row(row => {
row.RelativeItem().Text("Listado de Distribución: Canillas / Accionistas (Totales)").FontSize(12);
row.RelativeItem().AlignRight().Text(text => {
text.Span("Fecha Consultada ").SemiBold().FontSize(12);
text.Span(Model.FechaConsultada).FontSize(12);
});
});
column.Item().PaddingTop(5).Row(row => {
row.RelativeItem().Text(text => {
text.Span("Fecha de Generación del Reporte ").SemiBold().FontSize(12);
text.Span(Model.FechaReporte).FontSize(12);
});
row.RelativeItem().AlignRight().Text(text => {
text.Span("Empresa ").SemiBold().FontSize(12);
text.Span(Model.Empresa).FontSize(12);
});
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(5, Unit.Millimetre).Column(column =>
{
column.Spacing(15);
if(Model.CanillasTodos.Any())
column.Item().Element(ComposeTablaTotales);
if(Model.RemitoIngresado > 0)
column.Item().Element(ComposeResumenDevoluciones);
});
}
void ComposeTablaTotales(IContainer container)
{
container.Column(column =>
{
column.Item().PaddingBottom(4).Text("Recuento de Publicaciones").SemiBold().FontSize(11);
column.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(2); columns.RelativeColumn(3);
columns.RelativeColumn(1.2f); columns.RelativeColumn(1.2f);
columns.RelativeColumn(1.2f); columns.RelativeColumn(1.5f);
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Tipo Vendedor");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).Text("Publicación");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Llevados");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Devueltos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("Vendidos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(2).AlignRight().Text("A Rendir");
});
foreach(var item in Model.CanillasTodos.OrderBy(d => d.TipoVendedor).ThenBy(d => d.Publicacion))
{
table.Cell().Border(1).Padding(2).Text(item.TipoVendedor);
table.Cell().Border(1).Padding(2).Text(item.Publicacion);
table.Cell().Border(1).Padding(2).AlignRight().Text(item.TotalCantSalida.ToString("N0"));
table.Cell().Border(1).Padding(2).AlignRight().Text(item.TotalCantEntrada.ToString("N0"));
table.Cell().Border(1).Padding(2).AlignRight().Text((item.TotalCantSalida-item.TotalCantEntrada).ToString("N0"));
table.Cell().Border(1).Padding(2).AlignRight().Text(item.TotalRendir.ToString("C", CultureAr));
}
var boldStyle = TextStyle.Default.ExtraBold();
table.Cell().ColumnSpan(2).BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span("Total General").Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(Model.CanillasTodos.Sum(i => i.TotalCantSalida).ToString("N0")).Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(Model.CanillasTodos.Sum(i => i.TotalCantEntrada).ToString("N0")).Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(Model.CanillasTodos.Sum(i => i.TotalCantSalida - i.TotalCantEntrada).ToString("N0")).Style(boldStyle));
table.Cell().BorderTop(2).BorderColor(Colors.Black).Padding(2).AlignRight().Text(t => t.Span(Model.CanillasTodos.Sum(i => i.TotalRendir).ToString("C", CultureAr)).Style(boldStyle));
});
});
}
void ComposeResumenDevoluciones(IContainer container)
{
container.PaddingTop(10).Column(column => {
column.Item().Row(row => {
row.Spacing(15);
row.AutoItem().Text(text => { text.Span("Remito: ").SemiBold(); text.Span(Model.RemitoIngresado.ToString("N0")); });
row.AutoItem().Text(text => { text.Span("Devolución: ").SemiBold(); text.Span(Model.DevolucionTotal.ToString("N0")); });
row.AutoItem().Text(text => { text.Span("Venta: ").SemiBold(); text.Span(Model.VentaTotal.ToString("N0")); });
});
});
}
}
}

View File

@@ -23,7 +23,7 @@ namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
container
.Page(page =>
{
page.Margin(1.5f, Unit.Centimetre);
page.Margin(1, Unit.Centimetre);
page.PageColor(Colors.White);
page.DefaultTextStyle(x => x.FontFamily("Roboto").FontSize(10));

View File

@@ -26,7 +26,7 @@ namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
container
.Page(page =>
{
page.Margin(1.5f, Unit.Centimetre);
page.Margin(1, Unit.Centimetre);
page.PageColor(Colors.White);
page.DefaultTextStyle(x => x.FontFamily("Roboto").FontSize(10));

View File

@@ -0,0 +1,136 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Globalization;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class LiquidacionCanillaDocument : IDocument
{
public LiquidacionCanillaViewModel Model { get; }
private static readonly CultureInfo CultureAr = new CultureInfo("es-AR");
public LiquidacionCanillaDocument(LiquidacionCanillaViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
// CORRECCIÓN: El método GetSettings ya no es necesario para este diseño.
// La configuración por defecto es suficiente.
// public DocumentSettings GetSettings() => DocumentSettings.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Size(PageSizes.A5);
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(9));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Item().Text("EL DIA S.A.I.C. y F.");
column.Item().Text(text =>
{
text.Span("Liquidación venta de diarios del: ");
text.Span(Model.FechaLiquidacion);
});
column.Item().PaddingTop(5).Text($"Vendedor: {Model.NombreVendedor}").SemiBold();
column.Item().PaddingTop(10);
});
}
void ComposeContent(IContainer container)
{
container.Column(column =>
{
column.Spacing(15);
column.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(2);
columns.RelativeColumn(2);
columns.RelativeColumn(1);
});
foreach (var item in Model.Detalles.OrderBy(d => d.Publicacion))
{
var vendidos = item.TotalCantSalida - item.TotalCantEntrada;
table.Cell().ColumnSpan(3).Text(item.Publicacion).SemiBold();
table.Cell();
table.Cell().Text("Retirados");
table.Cell().AlignRight().Text(item.TotalCantSalida.ToString("N0"));
table.Cell();
table.Cell().Text("Devueltos");
table.Cell().AlignRight().Text(item.TotalCantEntrada.ToString("N0"));
table.Cell();
table.Cell().Text("Vendidos");
table.Cell().AlignRight().Text(vendidos.ToString("N0"));
table.Cell();
table.Cell().Text("Precio Unitario");
table.Cell().AlignRight().Text(item.PrecioEjemplar.ToString("C", CultureAr));
table.Cell();
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).PaddingTop(2).Text(t => t.Span("Importe Vendido").SemiBold());
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).PaddingTop(2).AlignRight().Text(t => t.Span(item.TotalRendir.ToString("C", CultureAr)).SemiBold());
}
});
column.Item().BorderTop(2).BorderColor(Colors.Black).PaddingTop(4).Row(row =>
{
row.RelativeItem().Text("Total A Rendir").SemiBold().FontSize(10);
row.RelativeItem().AlignRight().Text(text => text.Span(Model.TotalARendir.ToString("C", CultureAr)).SemiBold().FontSize(10));
});
if (!Model.EsAccionista && Model.Ganancias.Any())
{
column.Item().PaddingTop(10).Element(ComposeGananciasTable);
}
});
}
void ComposeGananciasTable(IContainer container)
{
container.Column(column =>
{
column.Item().Text("Comisiones Acreditadas").SemiBold().FontSize(11);
column.Item().PaddingTop(5).Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(2);
columns.RelativeColumn(1);
});
foreach (var item in Model.Ganancias)
{
table.Cell().Border(1).BorderColor(Colors.Grey.Lighten2).Padding(3).Text(item.Publicacion);
table.Cell().Border(1).BorderColor(Colors.Grey.Lighten2).Padding(3).AlignRight().Text(item.TotalRendir.ToString("C", CultureAr));
}
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).Padding(3).Text("Total Comisiones").SemiBold();
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).Padding(3).AlignRight().Text(t => t.Span(Model.TotalComisiones.ToString("C", CultureAr)).SemiBold());
});
});
}
}
}

View File

@@ -0,0 +1,99 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Globalization;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class ListadoDistCanMensualDiariosDocument : IDocument
{
public ListadoDistCanMensualDiariosViewModel Model { get; }
private static readonly CultureInfo CultureAr = new CultureInfo("es-AR");
public ListadoDistCanMensualDiariosDocument(ListadoDistCanMensualDiariosViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(9));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Item().AlignCenter().Text($"Ventas por {Model.TipoDestinatario} desde el {Model.FechaDesde} hasta el {Model.FechaHasta}").SemiBold().FontSize(12);
});
}
void ComposeContent(IContainer container)
{
// APLICAMOS LA SOLUCIÓN AQUÍ: .AlignTop()
container.PaddingTop(1, Unit.Centimetre).AlignTop().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(3); // Nombre
columns.ConstantColumn(50); // El Día
columns.ConstantColumn(50); // El Plata
columns.ConstantColumn(60); // Vendidos
columns.RelativeColumn(1.5f); // Imp. El Día
columns.RelativeColumn(1.5f); // Imp. El Plata
columns.RelativeColumn(1.5f); // Importe Total
});
table.Header(header =>
{
header.Cell().BorderBottom(1).BorderColor(Colors.Grey.Medium).Padding(4).Text("Nombre").SemiBold();
header.Cell().BorderBottom(1).BorderColor(Colors.Grey.Medium).Padding(4).AlignCenter().Text("El Día").SemiBold();
header.Cell().BorderBottom(1).BorderColor(Colors.Grey.Medium).Padding(4).AlignCenter().Text("El Plata").SemiBold();
header.Cell().BorderBottom(1).BorderColor(Colors.Grey.Medium).Padding(4).AlignCenter().Text("Vendidos").SemiBold();
header.Cell().BorderBottom(1).BorderColor(Colors.Grey.Medium).Padding(4).AlignRight().Text("Imp. El Día").SemiBold();
header.Cell().BorderBottom(1).BorderColor(Colors.Grey.Medium).Padding(4).AlignRight().Text("Imp. El Plata").SemiBold();
header.Cell().BorderBottom(1).BorderColor(Colors.Grey.Medium).Padding(4).AlignRight().Text("Importe Total").SemiBold();
});
foreach (var item in Model.Detalles.OrderBy(d => d.Canilla))
{
table.Cell().Padding(3).PaddingRight(10).Text(item.Canilla);
table.Cell().Padding(3).AlignCenter().Text(item.ElDia?.ToString("N0") ?? "0");
table.Cell().Padding(3).AlignCenter().Text(item.ElPlata?.ToString("N0") ?? "0");
table.Cell().Padding(3).AlignCenter().Text(item.Vendidos?.ToString("N0") ?? "0");
table.Cell().Padding(3).AlignRight().Text(item.ImporteElDia?.ToString("C", CultureAr) ?? "$ 0.00");
table.Cell().Padding(3).AlignRight().Text(item.ImporteElPlata?.ToString("C", CultureAr) ?? "$ 0.00");
table.Cell().Padding(3).AlignRight().Text(item.ImporteTotal?.ToString("C", CultureAr) ?? "$ 0.00");
}
// Fila de Totales
var totalElDia = Model.Detalles.Sum(x => x.ElDia ?? 0);
var totalElPlata = Model.Detalles.Sum(x => x.ElPlata ?? 0);
var totalVendidos = Model.Detalles.Sum(x => x.Vendidos ?? 0);
var totalImpElDia = Model.Detalles.Sum(x => x.ImporteElDia ?? 0);
var totalImpElPlata = Model.Detalles.Sum(x => x.ImporteElPlata ?? 0);
var totalImpTotal = Model.Detalles.Sum(x => x.ImporteTotal ?? 0);
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).PaddingTop(4).Text("Totales").SemiBold();
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).PaddingTop(4).AlignCenter().Text(t => t.Span(totalElDia.ToString("N0")).SemiBold());
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).PaddingTop(4).AlignCenter().Text(t => t.Span(totalElPlata.ToString("N0")).SemiBold());
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).PaddingTop(4).AlignCenter().Text(t => t.Span(totalVendidos.ToString("N0")).SemiBold());
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).PaddingTop(4).AlignRight().Text(t => t.Span(totalImpElDia.ToString("C", CultureAr)).SemiBold());
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).PaddingTop(4).AlignRight().Text(t => t.Span(totalImpElPlata.ToString("C", CultureAr)).SemiBold());
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).PaddingTop(4).AlignRight().Text(t => t.Span(totalImpTotal.ToString("C", CultureAr)).SemiBold());
});
}
}
}

View File

@@ -0,0 +1,113 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Globalization;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class ListadoDistCanMensualDocument : IDocument
{
public ListadoDistCanMensualViewModel Model { get; }
private static readonly CultureInfo CultureAr = new CultureInfo("es-AR");
public ListadoDistCanMensualDocument(ListadoDistCanMensualViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1.5f, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(10));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Item().AlignCenter().Text("Listado de Distribución Mensual").SemiBold().FontSize(14);
column.Item().AlignCenter().Text(Model.TipoDestinatario).FontSize(12);
column.Item().PaddingTop(5, Unit.Millimetre).Row(row =>
{
row.RelativeItem().Text(text => { text.Span("Fecha de Reporte: ").SemiBold(); text.Span(Model.FechaReporte); });
row.RelativeItem().AlignRight().Text(text => { text.Span("Periodo: ").SemiBold(); text.Span($"{Model.FechaDesde} - {Model.FechaHasta}"); });
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(1, Unit.Centimetre).Column(column =>
{
column.Spacing(10);
// Agrupamos los datos por Canilla
var gruposPorCanilla = Model.Detalles.GroupBy(d => d.Canilla);
// Creamos una tabla principal que contendrá todo
column.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(2.5f); // Canilla / Publicación
columns.RelativeColumn(); // Llevados
columns.RelativeColumn(); // Devueltos
columns.RelativeColumn(1.2f); // Importe
});
// Encabezado principal de la tabla
table.Header(header =>
{
header.Cell().BorderBottom(1.5f).BorderColor(Colors.Black).Padding(4).Text("Canilla / Publicación").SemiBold();
header.Cell().BorderBottom(1.5f).BorderColor(Colors.Black).Padding(4).AlignRight().Text("Llevados").SemiBold();
header.Cell().BorderBottom(1.5f).BorderColor(Colors.Black).Padding(4).AlignRight().Text("Devueltos").SemiBold();
header.Cell().BorderBottom(1.5f).BorderColor(Colors.Black).Padding(4).AlignRight().Text("Importe").SemiBold();
});
// Iteramos sobre cada grupo de canilla
foreach (var grupo in gruposPorCanilla)
{
// Fila del nombre del Canilla
table.Cell().ColumnSpan(4).PaddingTop(8).Text(grupo.Key).SemiBold();
// Filas de detalle para ese canilla
foreach (var detalle in grupo)
{
table.Cell().PaddingLeft(15).Padding(2).Text(detalle.Publicacion);
table.Cell().Padding(2).AlignRight().Text(detalle.TotalCantSalida?.ToString("N0") ?? "0");
table.Cell().Padding(2).AlignRight().Text(detalle.TotalCantEntrada?.ToString("N0") ?? "0");
table.Cell().Padding(2).AlignRight().Text(detalle.TotalRendir?.ToString("C", CultureAr) ?? "$ 0.00");
}
// Fila de total por canilla
var totalRendirCanilla = grupo.Sum(d => d.TotalRendir ?? 0);
table.Cell().ColumnSpan(3).BorderTop(1.5f).BorderColor(Colors.Black).AlignRight().Padding(2).Text("A Rendir").SemiBold();
table.Cell().BorderTop(1.5f).BorderColor(Colors.Black).AlignRight().Padding(2).Text(t => t.Span(totalRendirCanilla.ToString("C", CultureAr)).SemiBold());
}
// --- Fila de TOTALES GENERALES ---
var totalGeneralLlevados = Model.Detalles.Sum(d => d.TotalCantSalida ?? 0);
var totalGeneralDevueltos = Model.Detalles.Sum(d => d.TotalCantEntrada ?? 0);
var totalGeneralRendir = Model.Detalles.Sum(d => d.TotalRendir ?? 0);
table.Cell().BorderTop(2).BorderColor(Colors.Black).PaddingTop(5).Text("TOTALES").ExtraBold();
table.Cell().BorderTop(2).BorderColor(Colors.Black).PaddingTop(5).AlignRight().Text(t => t.Span(totalGeneralLlevados.ToString("N0")).ExtraBold());
table.Cell().BorderTop(2).BorderColor(Colors.Black).PaddingTop(5).AlignRight().Text(t => t.Span(totalGeneralDevueltos.ToString("N0")).ExtraBold());
table.Cell().BorderTop(2).BorderColor(Colors.Black).PaddingTop(5).AlignRight().Text(t => t.Span(totalGeneralRendir.ToString("C", CultureAr)).ExtraBold());
});
});
}
}
}

View File

@@ -0,0 +1,103 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Globalization;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class ListadoDistCanillasImporteDocument : IDocument
{
public ListadoDistCanillasImporteViewModel Model { get; }
private static readonly CultureInfo CultureAr = new CultureInfo("es-AR");
public ListadoDistCanillasImporteDocument(ListadoDistCanillasImporteViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1.5f, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(10));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Item().AlignCenter().Text("Listado de Distribución con Importes").SemiBold().FontSize(14);
column.Item().AlignCenter().Text(Model.TipoDestinatario).FontSize(12);
column.Item().AlignCenter().Text(Model.NombrePublicacion).FontSize(12);
column.Item().PaddingTop(5, Unit.Millimetre).Row(row =>
{
row.RelativeItem().Text(text => { text.Span("Fecha de Reporte: ").SemiBold(); text.Span(Model.FechaReporte); });
row.RelativeItem().AlignRight().Text(text => { text.Span("Periodo: ").SemiBold(); text.Span($"{Model.FechaDesde} - {Model.FechaHasta}"); });
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(1, Unit.Centimetre).Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(); // Fecha
columns.RelativeColumn(); // Llevados
columns.RelativeColumn(); // Devueltos
columns.RelativeColumn(); // Vendidos
columns.RelativeColumn(1.5f); // Importe Publicación
columns.RelativeColumn(1.5f); // A Rendir
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Fecha");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Llevados");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Devueltos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Vendidos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Imp. Publicación");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("A Rendir");
});
foreach (var item in Model.Detalles)
{
table.Cell().Border(1).Padding(3).Text(item.Fecha);
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Llevados.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Devueltos.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Vendidos.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.TotalRendirPublicacion.ToString("C", CultureAr));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.TotalRendirGeneral.ToString("C", CultureAr));
}
// Fila de Totales
var totalLlevados = Model.Detalles.Sum(x => x.Llevados);
var totalDevueltos = Model.Detalles.Sum(x => x.Devueltos);
var totalVendidos = Model.Detalles.Sum(x => x.Vendidos);
var totalRendirPub = Model.Detalles.Sum(x => x.TotalRendirPublicacion);
var totalRendirGral = Model.Detalles.Sum(x => x.TotalRendirGeneral);
var boldStyle = TextStyle.Default.SemiBold();
table.Cell().Border(1).Padding(3); // Celda vacía
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(totalLlevados.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(totalDevueltos.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(totalVendidos.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(totalRendirPub.ToString("C", CultureAr)).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(totalRendirGral.ToString("C", CultureAr)).Style(boldStyle));
});
}
}
}

View File

@@ -0,0 +1,179 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Collections.Generic;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class ListadoDistribucionCanillasDocument : IDocument
{
public ListadoDistribucionCanillasViewModel Model { get; }
public ListadoDistribucionCanillasDocument(ListadoDistribucionCanillasViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(10));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Item().AlignCenter().Text("Listado de Distribución - Canillitas").SemiBold().FontSize(14);
column.Item().AlignCenter().Text(Model.NombrePublicacion).FontSize(12);
column.Item().PaddingTop(5, Unit.Millimetre).Row(row =>
{
row.RelativeItem().Text(text => { text.Span("Fecha de Reporte: ").SemiBold(); text.Span(Model.FechaReporte); });
row.RelativeItem().AlignRight().Text(text => { text.Span("Periodo: ").SemiBold(); text.Span($"{Model.FechaDesde} - {Model.FechaHasta}"); });
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(8, Unit.Millimetre).Column(column =>
{
column.Spacing(15);
column.Item().Text("Distribución").SemiBold().FontSize(12);
column.Item().Element(ComposeDetalleDiarioTable);
column.Item().PaddingTop(5, Unit.Millimetre);
column.Item().Text("Promedios").SemiBold().FontSize(12);
column.Item().Element(ComposePromediosTable);
});
}
void ComposeDetalleDiarioTable(IContainer container)
{
container.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(50); // Día
columns.RelativeColumn(); // Llevados
columns.RelativeColumn(); // Devueltos
columns.RelativeColumn(); // Venta Neta
columns.RelativeColumn(2); // Promedio (columna vacía en el original)
columns.RelativeColumn(2); // % Devolución
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Día");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Llevados");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Devueltos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Venta Neta");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Promedio");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("% Devolución");
});
decimal ventaNetaAcumulada = 0;
int conteoDias = 0;
foreach (var item in Model.DetalleDiario.OrderBy(x => x.Dia))
{
var ventaNetaDia = item.Llevados - item.Devueltos;
ventaNetaAcumulada += ventaNetaDia;
conteoDias++;
var promedio = ventaNetaAcumulada / conteoDias;
var porcDevolucion = item.Llevados > 0 ? (decimal)item.Devueltos * 100 / item.Llevados : 0;
table.Cell().Border(1).Padding(3).Text(item.Dia.ToString());
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Llevados.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Devueltos.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(ventaNetaDia.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(promedio.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(porcDevolucion.ToString("F2"));
}
var totalVentaNeta = Model.TotalesDetalleDiario.Llevados - Model.TotalesDetalleDiario.Devueltos;
var totalPorcDevolucion = Model.TotalesDetalleDiario.Llevados > 0 ? (decimal)Model.TotalesDetalleDiario.Devueltos * 100 / Model.TotalesDetalleDiario.Llevados : 0;
table.Cell().Border(1).Padding(3); // Celda vacía
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.TotalesDetalleDiario.Llevados.ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.TotalesDetalleDiario.Devueltos.ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(totalVentaNeta.ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span((ventaNetaAcumulada / (conteoDias > 0 ? conteoDias : 1)).ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(totalPorcDevolucion.ToString("F2")).SemiBold());
});
}
void ComposePromediosTable(IContainer container)
{
container.Column(column =>
{
column.Item().PaddingBottom(5).Text("Promedios por Día de Semana").SemiBold().FontSize(11);
column.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(1.5f);
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn(1.2f);
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Día Semana");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Cant. Días");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Prom. Llevados");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Prom. Devueltos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Prom. Ventas");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("% Devolución");
});
var dayOrder = new Dictionary<string, int> { { "Lunes", 1 }, { "Martes", 2 }, { "Miércoles", 3 }, { "Jueves", 4 }, { "Viernes", 5 }, { "Sábado", 6 }, { "Domingo", 7 } };
foreach (var item in Model.PromediosPorDia.OrderBy(d => dayOrder.GetValueOrDefault(d.Dia, 99)))
{
var porcDevolucion = item.Llevados > 0 ? (decimal)item.Devueltos * 100 / item.Llevados : 0;
table.Cell().Border(1).Padding(3).Text(item.Dia);
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Cant.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Promedio_Llevados.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Promedio_Devueltos.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Promedio_Ventas.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(porcDevolucion.ToString("F2") + "%");
}
// --- SECCIÓN AÑADIDA PARA LA FILA "GENERAL" ---
var general = Model.PromedioGeneral;
if (general != null)
{
var porcDevolucionGeneral = general.Promedio_Llevados > 0 ? (decimal)general.Promedio_Devueltos * 100 / general.Promedio_Llevados : 0;
var boldStyle = TextStyle.Default.SemiBold();
table.Cell().Border(1).Padding(3).Text(text => text.Span(general.Dia).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.Cant.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.Promedio_Llevados.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.Promedio_Devueltos.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.Promedio_Ventas.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(porcDevolucionGeneral.ToString("F2") + "%").Style(boldStyle));
}
});
});
}
}
}

View File

@@ -0,0 +1,178 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Collections.Generic;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class ListadoDistribucionDistribuidoresDocument : IDocument
{
public ListadoDistribucionDistribuidoresViewModel Model { get; }
public ListadoDistribucionDistribuidoresDocument(ListadoDistribucionDistribuidoresViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(10));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Item().AlignCenter().Text("Listado de Distribución").SemiBold().FontSize(14);
column.Item().AlignCenter().Text(Model.NombreDistribuidor).FontSize(12);
column.Item().AlignCenter().Text(Model.NombrePublicacion).FontSize(11);
column.Item().PaddingTop(5, Unit.Millimetre).Row(row =>
{
row.RelativeItem().Text(text => { text.Span("Fecha de Reporte: ").SemiBold(); text.Span(Model.FechaReporte); });
row.RelativeItem().AlignRight().Text(text => { text.Span("Periodo: ").SemiBold(); text.Span($"{Model.FechaDesde} - {Model.FechaHasta}"); });
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(8, Unit.Millimetre).Column(column =>
{
column.Spacing(15);
column.Item().Text("Distribución").SemiBold().FontSize(12);
column.Item().Element(ComposeDetalleDiarioTable);
column.Item().PaddingTop(5, Unit.Millimetre);
column.Item().Text("Promedios").SemiBold().FontSize(12);
column.Item().Element(ComposePromediosTable);
});
}
void ComposeDetalleDiarioTable(IContainer container)
{
container.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(50); columns.RelativeColumn();
columns.RelativeColumn(); columns.RelativeColumn();
columns.RelativeColumn(2); columns.RelativeColumn(2);
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Día");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Llevados");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Devueltos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Venta Neta");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Promedio");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("% Devolución");
});
decimal ventaNetaAcumulada = 0;
int conteoDias = 0;
foreach (var item in Model.DetalleDiario.OrderBy(x => x.Dia))
{
var llevados = item.Llevados ?? 0;
var devueltos = item.Devueltos ?? 0;
var ventaNetaDia = llevados - devueltos;
if(llevados > 0)
{
ventaNetaAcumulada += ventaNetaDia;
conteoDias++;
}
var promedio = conteoDias > 0 ? ventaNetaAcumulada / conteoDias : 0;
var porcDevolucion = llevados > 0 ? (decimal)devueltos * 100 / llevados : 0;
table.Cell().Border(1).Padding(3).Text(item.Dia.ToString());
table.Cell().Border(1).Padding(3).AlignRight().Text(llevados.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(devueltos.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(ventaNetaDia.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(promedio.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(porcDevolucion.ToString("F2") + "%");
}
var totalLlevados = Model.DetalleDiario.Sum(i => i.Llevados ?? 0);
var totalDevueltos = Model.DetalleDiario.Sum(i => i.Devueltos ?? 0);
var totalVentaNeta = totalLlevados - totalDevueltos;
var totalPorcDevolucion = totalLlevados > 0 ? (decimal)totalDevueltos * 100 / totalLlevados : 0;
var boldStyle = TextStyle.Default.SemiBold();
table.Cell().Border(1).Padding(3);
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(totalLlevados.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(totalDevueltos.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(totalVentaNeta.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span((ventaNetaAcumulada / (conteoDias > 0 ? conteoDias : 1)).ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(totalPorcDevolucion.ToString("F2") + "%").Style(boldStyle));
});
}
void ComposePromediosTable(IContainer container)
{
var dayOrder = new Dictionary<string, int> { { "Lunes", 1 }, { "Martes", 2 }, { "Miércoles", 3 }, { "Jueves", 4 }, { "Viernes", 5 }, { "Sábado", 6 }, { "Domingo", 7 }};
container.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(1.5f); columns.RelativeColumn();
columns.RelativeColumn(); columns.RelativeColumn();
columns.RelativeColumn(); columns.RelativeColumn(1.2f);
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Día");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Cant. Días");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Prom. Llevados");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Prom. Devueltos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Prom. Ventas");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("% Devolución");
});
foreach (var item in Model.PromediosPorDia.Where(p => p.Dia != "General").OrderBy(d => dayOrder.GetValueOrDefault(d.Dia, 99)))
{
var llevados = item.Promedio_Llevados ?? 0;
var devueltos = item.Promedio_Devueltos ?? 0;
var porcDevolucion = llevados > 0 ? (decimal)devueltos * 100 / llevados : 0;
table.Cell().Border(1).Padding(3).Text(item.Dia);
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Cant?.ToString("N0") ?? "0");
table.Cell().Border(1).Padding(3).AlignRight().Text(llevados.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(devueltos.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Promedio_Ventas?.ToString("N0") ?? "0");
table.Cell().Border(1).Padding(3).AlignRight().Text(porcDevolucion.ToString("F2") + "%");
}
// --- FILA GENERAL ---
var general = Model.PromedioGeneral;
if (general != null)
{
var boldStyle = TextStyle.Default.SemiBold();
var llevadosGeneral = general.Llevados ?? 0; // Usamos el total para el %
var devueltosGeneral = general.Devueltos ?? 0; // Usamos el total para el %
var porcDevolucionGeneral = llevadosGeneral > 0 ? (decimal)devueltosGeneral * 100 / llevadosGeneral : 0;
table.Cell().Border(1).Padding(3).Text(t => t.Span(general.Dia).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Cant?.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Promedio_Llevados?.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Promedio_Devueltos?.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Promedio_Ventas?.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(porcDevolucionGeneral.ToString("F2") + "%").Style(boldStyle));
}
});
}
}
}

View File

@@ -0,0 +1,179 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Collections.Generic;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class ListadoDistribucionGeneralDocument : IDocument
{
public ListadoDistribucionGeneralViewModel Model { get; }
public ListadoDistribucionGeneralDocument(ListadoDistribucionGeneralViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(10));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Item().AlignCenter().Text("Listado de Distribución General Mensual").SemiBold().FontSize(14);
column.Item().AlignCenter().Text(Model.NombrePublicacion).FontSize(12);
column.Item().PaddingTop(1, Unit.Millimetre).Row(row =>
{
row.RelativeItem().Text(text => { text.Span("Fecha de Reporte: ").SemiBold(); text.Span(Model.FechaReporte); });
row.RelativeItem().AlignRight().Text(text => { text.Span("Mes Consultado: ").SemiBold(); text.Span(Model.MesConsultado); });
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(1, Unit.Millimetre).Column(column =>
{
column.Spacing(20);
if (Model.ResumenMensual.Any())
{
column.Item().Element(ComposeResumenTable);
}
if (Model.PromediosPorDia.Any())
{
column.Item().Element(ComposePromediosTable);
}
});
}
void ComposeResumenTable(IContainer container)
{
container.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(40);
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Día");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Tirada");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Sin Cargo");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Perdidos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Llevados");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Devueltos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Vendidos");
});
foreach (var item in Model.ResumenMensual.OrderBy(x => x.Fecha))
{
table.Cell().Border(1).Padding(3).Text(item.Fecha.Day.ToString());
table.Cell().Border(1).Padding(3).AlignRight().Text(item.CantidadTirada.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.SinCargo.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Perdidos.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Llevados.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Devueltos.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.Vendidos.ToString("N0"));
}
table.Cell().Border(1).Padding(3);
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.ResumenMensual.Sum(x => x.CantidadTirada).ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.ResumenMensual.Sum(x => x.SinCargo).ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.ResumenMensual.Sum(x => x.Perdidos).ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.ResumenMensual.Sum(x => x.Llevados).ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.ResumenMensual.Sum(x => x.Devueltos).ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.ResumenMensual.Sum(x => x.Vendidos).ToString("N0")).SemiBold());
});
}
void ComposePromediosTable(IContainer container)
{
container.Column(column =>
{
// --- TÍTULO DE LA TABLA DE PROMEDIOS ---
column.Item().PaddingBottom(5).AlignCenter().Text("Promedios Diarios de Distribución").SemiBold();
column.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(1.2f);
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Día");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Cant. Días");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Tirada");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Sin Cargo");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Perdidos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Llevados");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Devueltos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Vendidos");
});
var dayOrder = new Dictionary<string, int> { { "Lunes", 1 }, { "Martes", 2 }, { "Miércoles", 3 }, { "Jueves", 4 }, { "Viernes", 5 }, { "Sábado", 6 }, { "Domingo", 7 } };
// Mostramos los promedios por día de la semana
foreach (var item in Model.PromediosPorDia.OrderBy(d => dayOrder.GetValueOrDefault(d.Dia, 99)))
{
table.Cell().Border(1).Padding(3).Text(item.Dia);
table.Cell().Border(1).Padding(3).AlignRight().Text(item.CantidadDias.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.PromedioTirada.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.PromedioSinCargo.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.PromedioPerdidos.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.PromedioLlevados.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.PromedioDevueltos.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.PromedioVendidos.ToString("N0"));
}
// --- FILA GENERAL CON DATOS CALCULADOS DEL VIEWMODEL ---
var general = Model.PromedioGeneral;
if (general != null)
{
var boldStyle = TextStyle.Default.SemiBold();
table.Cell().Border(1).Padding(3).Text(text => text.Span(general.Dia).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.CantidadDias.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.PromedioTirada.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.PromedioSinCargo.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.PromedioPerdidos.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.PromedioLlevados.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.PromedioDevueltos.ToString("N0")).Style(boldStyle));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.PromedioVendidos.ToString("N0")).Style(boldStyle));
}
});
});
}
}
}

View File

@@ -0,0 +1,122 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class MovimientoBobinasDocument : IDocument
{
public MovimientoBobinasViewModel Model { get; }
public MovimientoBobinasDocument(MovimientoBobinasViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public DocumentSettings GetSettings() => DocumentSettings.Default;
public void Compose(IDocumentContainer container)
{
container
.Page(page =>
{
// Configuramos la página en modo apaisado (landscape)
page.Size(PageSizes.A4.Landscape());
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Roboto").FontSize(9)); // Un poco más pequeño por la cantidad de columnas
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer()
.AlignCenter()
.Text(x =>
{
x.Span("Página ");
x.CurrentPageNumber();
});
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Spacing(5);
column.Item().AlignCenter().Text("Reporte de Movimiento de Bobinas").SemiBold().FontSize(14);
column.Item().AlignCenter().Text($"Planta: {Model.NombrePlanta}").FontSize(12);
column.Item().PaddingTop(2, Unit.Millimetre).Row(row =>
{
row.RelativeItem().Column(col =>
{
col.Item().Text(text =>
{
text.Span("Fecha del Reporte: ").SemiBold();
text.Span(Model.FechaReporte);
});
col.Item().Text($"Periodo Consultado: Desde {Model.FechaDesde} Hasta {Model.FechaHasta}");
});
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(1, Unit.Centimetre).Table(table =>
{
// Definimos 11 columnas. Usamos una combinación de relativas y constantes
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(2.5f); // Tipo
columns.ConstantColumn(50); // Cant. Inicial
columns.ConstantColumn(60); // Kg Iniciales
columns.ConstantColumn(50); // Compradas
columns.ConstantColumn(60); // Kg Comprados
columns.ConstantColumn(50); // Consumidas
columns.ConstantColumn(60); // Kg Consumidos
columns.ConstantColumn(50); // Dañadas
columns.ConstantColumn(60); // Kg Dañados
columns.ConstantColumn(50); // Cant. Final
columns.ConstantColumn(60); // Kg Final
});
// Encabezado de la tabla
table.Header(header =>
{
// Celda por celda para control total
header.Cell().Background(Colors.Grey.Lighten3).Padding(2).Text("Tipo");
header.Cell().Background(Colors.Grey.Lighten3).Padding(2).AlignCenter().Text("Cant. Inicial");
header.Cell().Background(Colors.Grey.Lighten3).Padding(2).AlignCenter().Text("Kg Inicial");
header.Cell().Background(Colors.Grey.Lighten3).Padding(2).AlignCenter().Text("Compradas");
header.Cell().Background(Colors.Grey.Lighten3).Padding(2).AlignCenter().Text("Kg Comprados");
header.Cell().Background(Colors.Grey.Lighten3).Padding(2).AlignCenter().Text("Consumidas");
header.Cell().Background(Colors.Grey.Lighten3).Padding(2).AlignCenter().Text("Kg Consumidos");
header.Cell().Background(Colors.Grey.Lighten3).Padding(2).AlignCenter().Text("Dañadas");
header.Cell().Background(Colors.Grey.Lighten3).Padding(2).AlignCenter().Text("Kg Dañados");
header.Cell().Background(Colors.Grey.Lighten3).Padding(2).AlignCenter().Text("Cant. Final");
header.Cell().Background(Colors.Grey.Lighten3).Padding(2).AlignCenter().Text("Kg Final");
});
// Filas de datos
foreach (var item in Model.Movimientos)
{
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(2).Text(item.TipoBobina);
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(2).AlignCenter().Text(item.BobinasIniciales.ToString("N0"));
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(2).AlignCenter().Text(item.KilosIniciales.ToString("N0"));
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(2).AlignCenter().Text(item.BobinasCompradas.ToString("N0"));
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(2).AlignCenter().Text(item.KilosComprados.ToString("N0"));
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(2).AlignCenter().Text(item.BobinasConsumidas.ToString("N0"));
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(2).AlignCenter().Text(item.KilosConsumidos.ToString("N0"));
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(2).AlignCenter().Text(item.BobinasDaniadas.ToString("N0"));
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(2).AlignCenter().Text(item.KilosDaniados.ToString("N0"));
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(2).AlignCenter().Text(item.BobinasFinales.ToString("N0"));
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(2).AlignCenter().Text(item.KilosFinales.ToString("N0"));
}
});
}
}
}

View File

@@ -0,0 +1,129 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class MovimientoBobinasEstadoDocument : IDocument
{
public MovimientoBobinasEstadoViewModel Model { get; }
public MovimientoBobinasEstadoDocument(MovimientoBobinasEstadoViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public DocumentSettings GetSettings() => DocumentSettings.Default;
public void Compose(IDocumentContainer container)
{
container
.Page(page =>
{
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Roboto").FontSize(10));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer()
.AlignCenter()
.Text(x =>
{
x.Span("Página ");
x.CurrentPageNumber();
});
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Spacing(5);
column.Item().AlignCenter().Text("Reporte de Movimiento de Bobinas por Estados").SemiBold().FontSize(14);
column.Item().AlignCenter().Text($"Planta: {Model.NombrePlanta}").FontSize(12);
column.Item().PaddingTop(2, Unit.Millimetre).Row(row =>
{
row.RelativeItem().Column(col =>
{
col.Item().Text(text =>
{
text.Span("Fecha del Reporte: ").SemiBold();
text.Span(Model.FechaReporte);
});
col.Item().Text($"Periodo Consultado: Desde {Model.FechaDesde} Hasta {Model.FechaHasta}");
});
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(1, Unit.Centimetre).Column(column =>
{
// Primera tabla: Detalle de Movimientos
column.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(3); // Tipo Bobina
columns.RelativeColumn(2); // Remito
columns.ConstantColumn(80); // Fecha
columns.ConstantColumn(60); // Cantidad
columns.RelativeColumn(2); // Tipo Movimiento
});
table.Header(header =>
{
header.Cell().Background(Colors.Grey.Lighten3).Padding(4).Text("Tipo Bobina");
header.Cell().Background(Colors.Grey.Lighten3).Padding(4).Text("N° Remito");
header.Cell().Background(Colors.Grey.Lighten3).Padding(4).AlignCenter().Text("Fecha Mov.");
header.Cell().Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Cantidad");
header.Cell().Background(Colors.Grey.Lighten3).Padding(4).Text("Tipo Movimiento");
});
foreach (var item in Model.Detalles)
{
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).Text(item.TipoBobina);
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).Text(item.NumeroRemito);
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).AlignCenter().Text(item.FechaMovimiento.ToString("dd/MM/yyyy"));
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).AlignRight().Text(item.Cantidad.ToString("N0"));
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).Text(item.TipoMovimiento);
}
});
// Espacio entre tablas
column.Item().PaddingTop(1, Unit.Centimetre);
// Segunda tabla: Totales
column.Item().AlignLeft().Table(table => // Alineamos la tabla a la izquierda para que no ocupe todo el ancho
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(120); // Tipo Movimiento
columns.ConstantColumn(80); // Total Bobinas
columns.ConstantColumn(80); // Total Kilos
});
table.Header(header =>
{
header.Cell().Background(Colors.Grey.Lighten3).Padding(4).Text("Totales por Movimiento");
header.Cell().Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Total Bobinas");
header.Cell().Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Total Kilos");
});
foreach (var total in Model.Totales)
{
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).Text(total.TipoMovimiento);
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).AlignRight().Text(total.TotalBobinas.ToString("N0"));
table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).AlignRight().Text(total.TotalKilos.ToString("N0"));
}
});
});
}
}
}

View File

@@ -0,0 +1,144 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Globalization;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class NovedadesCanillasDocument : IDocument
{
public NovedadesCanillasViewModel Model { get; }
private static readonly CultureInfo CultureAr = new CultureInfo("es-AR");
public NovedadesCanillasDocument(NovedadesCanillasViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1.5f, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(10));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Item().AlignCenter().Text("Listado de Novedades - Canillas").SemiBold().FontSize(16);
column.Item().PaddingTop(5, Unit.Millimetre).Row(row =>
{
row.RelativeItem().Text(text => { text.Span("Fecha de Reporte: ").SemiBold(); text.Span(Model.FechaReporte); });
row.RelativeItem().AlignRight().Text(text => { text.Span("Periodo: ").SemiBold(); text.Span($"{Model.FechaDesde} - {Model.FechaHasta}"); });
});
column.Item().PaddingTop(5).Border(1).Background(Colors.Grey.Lighten3).AlignCenter().Padding(2).Text(Model.NombreEmpresa).SemiBold();
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(1, Unit.Centimetre).Column(column =>
{
column.Spacing(20);
if (Model.ResumenCanillas.Any())
{
column.Item().Element(ComposeResumenTable);
}
if (Model.DetallesNovedades.Any())
{
column.Item().Element(ComposeDetallesNovedadesTable);
}
});
}
void ComposeResumenTable(IContainer container)
{
container.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(3); // Canilla
columns.RelativeColumn(1); // Legajo
columns.RelativeColumn(1); // Faltas
columns.RelativeColumn(1); // Francos
columns.RelativeColumn(1.5f); // Comisiones
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Canilla");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Legajo");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignCenter().Text("Faltas");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignCenter().Text("Francos");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Comisiones");
});
foreach (var item in Model.ResumenCanillas.OrderBy(x => x.Canilla))
{
table.Cell().Border(1).Padding(3).Text(item.Canilla);
table.Cell().Border(1).Padding(3).Text(item.Legajo?.ToString() ?? "-");
table.Cell().Border(1).Padding(3).AlignCenter().Text(item.Faltas?.ToString("N0") ?? "0");
table.Cell().Border(1).Padding(3).AlignCenter().Text(item.Francos?.ToString("N0") ?? "0");
table.Cell().Border(1).Padding(3).AlignRight().Text(item.TotalRendir?.ToString("C", CultureAr) ?? "$ 0.00");
}
// Fila de Totales
table.Cell().ColumnSpan(4).Border(1).Padding(3).AlignRight().Text("Total").SemiBold();
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(Model.ResumenCanillas.Sum(x => x.TotalRendir ?? 0).ToString("C", CultureAr)).SemiBold());
});
}
void ComposeDetallesNovedadesTable(IContainer container)
{
container.Column(column =>
{
column.Item().PaddingTop(10).Text("Otras Novedades").SemiBold().FontSize(12);
column.Item().PaddingTop(5).Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(2); // Nombre
columns.ConstantColumn(80); // Fecha
columns.RelativeColumn(4); // Detalle
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Nombre");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Fecha");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Detalle");
});
// Agrupamos por canillita para mostrar su nombre una sola vez
foreach (var grupo in Model.DetallesNovedades.GroupBy(x => x.NomApe))
{
// Celda con el nombre del canillita, abarcando todas las filas de sus novedades
table.Cell().RowSpan((uint)grupo.Count()).Border(1).Padding(3).Text(grupo.Key);
// Iteramos sobre las novedades del grupo
foreach (var detalle in grupo.OrderBy(d => d.Fecha))
{
table.Cell().Border(1).Padding(3).Text(detalle.Fecha.ToString("dd/MM/yyyy"));
table.Cell().Border(1).Padding(3).Text(detalle.Detalle);
}
}
});
});
}
}
}

View File

@@ -0,0 +1,99 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class TiradasPublicacionesSeccionesDocument : IDocument
{
public TiradasPublicacionesSeccionesViewModel Model { get; }
public TiradasPublicacionesSeccionesDocument(TiradasPublicacionesSeccionesViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(9));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Spacing(5);
column.Item().AlignCenter().Text("Reporte de Tiradas por Publicación Mensual").SemiBold().FontSize(14);
// Título secundario dinámico
string subTitle = Model.EsConsolidado
? $"Consolidado - Publicación: {Model.NombrePublicacion}"
: $"Planta: {Model.NombrePlanta} - Publicación: {Model.NombrePublicacion}";
column.Item().AlignCenter().Text(subTitle).FontSize(12);
column.Item().PaddingTop(5, Unit.Millimetre).Row(row =>
{
row.RelativeItem().Text(text => { text.Span("Fecha del Reporte: ").SemiBold(); text.Span(Model.FechaReporte); });
row.RelativeItem().AlignRight().Text(text => { text.Span("Mes Consultado: ").SemiBold(); text.Span(Model.MesConsultado); });
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(5, Unit.Millimetre).Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(2.5f); // Nombre Seccion
columns.RelativeColumn(1.5f); // Páginas Impresas
columns.RelativeColumn(1); // Total Ediciones
columns.RelativeColumn(1.5f); // Pág. Por Edición
columns.RelativeColumn(1.2f); // Total Ejemplares
columns.RelativeColumn(1.5f); // Pág. Ejemplar
});
table.Header(header =>
{
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Nombre Sección");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Páginas Impresas");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Total Ediciones");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Prom. Pág/Edición");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Total Ejemplares");
header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Prom. Pág/Ejemplar");
});
foreach (var item in Model.Detalles.OrderBy(x => x.NombreSeccion))
{
table.Cell().Border(1).Padding(3).Text(item.NombreSeccion);
table.Cell().Border(1).Padding(3).AlignRight().Text(item.TotalPaginasImpresas.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.CantidadTiradas.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.TotalPaginasEjemplares.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.TotalEjemplares.ToString("N0"));
table.Cell().Border(1).Padding(3).AlignRight().Text(item.PromedioPaginasPorEjemplar.ToString("N0"));
}
// Fila de Totales
var style = TextStyle.Default.SemiBold();
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span("Totales").Style(style));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(Model.Detalles.Sum(x => x.TotalPaginasImpresas).ToString("N0")).Style(style));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(Model.Detalles.Sum(x => x.CantidadTiradas).ToString("N0")).Style(style));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(Model.Detalles.Sum(x => x.TotalPaginasEjemplares).ToString("N0")).Style(style));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(Model.Detalles.Sum(x => x.TotalEjemplares).ToString("N0")).Style(style));
table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(Model.Detalles.Sum(x => x.PromedioPaginasPorEjemplar).ToString("N0")).Style(style));
});
}
}
}

View File

@@ -0,0 +1,89 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class VentaMensualSecretariaElDiaDocument : IDocument
{
public VentaMensualSecretariaElDiaViewModel Model { get; }
public VentaMensualSecretariaElDiaDocument(VentaMensualSecretariaElDiaViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(11));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Spacing(5);
column.Item().AlignCenter().Text("VENTA DIARIO EL DÍA").SemiBold().FontSize(16);
column.Item().AlignCenter().Text(text =>
{
text.Span("Fecha Consultada: Desde ").SemiBold().FontSize(12);
text.Span(Model.FechaDesde).FontSize(12);
text.Span(" Hasta ").SemiBold().FontSize(12);
text.Span(Model.FechaHasta).FontSize(12);
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(5, Unit.Millimetre).Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(50); // Día
columns.RelativeColumn(); // Canillas
columns.RelativeColumn(); // Tirajes
columns.RelativeColumn(); // Ventas
columns.RelativeColumn(); // Accionistas
columns.RelativeColumn(); // Total Coop.
columns.RelativeColumn(); // Total Gral.
});
table.Header(header =>
{
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("DÍA").FontColor(Colors.White).SemiBold());
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("CANILLAS").FontColor(Colors.White).SemiBold());
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("TIRAJES").FontColor(Colors.White).SemiBold());
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("VENTAS").FontColor(Colors.White).SemiBold());
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("ACCIONISTAS").FontColor(Colors.White).SemiBold());
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("TOTAL COOPERATIVA").FontColor(Colors.White).SemiBold());
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("TOTAL").FontColor(Colors.White).SemiBold());
});
foreach (var item in Model.VentasDiarias.OrderBy(x => x.Dia))
{
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.Dia.ToString());
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.CantidadCanillas.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.Tirajes.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.Ventas.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.Accionistas.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.TotalCooperativa.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(t => t.Span(item.TotalGeneral.ToString("N0")).SemiBold());
}
});
}
}
}

View File

@@ -0,0 +1,89 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class VentaMensualSecretariaElPlataDocument : IDocument
{
public VentaMensualSecretariaElPlataViewModel Model { get; }
public VentaMensualSecretariaElPlataDocument(VentaMensualSecretariaElPlataViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(11));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Spacing(5);
column.Item().AlignCenter().Text("VENTA DIARIO EL PLATA").SemiBold().FontSize(16);
column.Item().AlignCenter().Text(text =>
{
text.Span("Fecha Consultada: Desde ").SemiBold().FontSize(12);
text.Span(Model.FechaDesde).FontSize(12);
text.Span(" Hasta ").SemiBold().FontSize(12);
text.Span(Model.FechaHasta).FontSize(12);
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(5, Unit.Millimetre).Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(50); // Día
columns.RelativeColumn(); // Tirada Coop
columns.RelativeColumn(); // Devolución Coop
columns.RelativeColumn(); // Venta Coop
columns.RelativeColumn(); // Tirada Canillas
columns.RelativeColumn(); // Venta Canillas
columns.RelativeColumn(); // Total
});
table.Header(header =>
{
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("DÍA").FontColor(Colors.White).SemiBold());
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("TIRADA COOP.").FontColor(Colors.White).SemiBold());
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("DEVOLUCIÓN COOP.").FontColor(Colors.White).SemiBold());
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("VENTA COOP.").FontColor(Colors.White).SemiBold());
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("TIRADA CANILLAS").FontColor(Colors.White).SemiBold());
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("VENTA CANILLAS (TOTAL)").FontColor(Colors.White).SemiBold());
header.Cell().Background(Colors.Black).Border(1).BorderColor(Colors.White).Padding(4).AlignCenter().Text(text => text.Span("TOTAL").FontColor(Colors.White).SemiBold());
});
foreach (var item in Model.VentasDiarias.OrderBy(x => x.Dia))
{
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.Dia.ToString());
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.TiradaCoop.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.DevolucionCoop.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.VentaCoop.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.TiradaCan.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.VentaCan.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(t => t.Span(item.Total.ToString("N0")).SemiBold());
}
});
}
}
}

View File

@@ -0,0 +1,116 @@
using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Elements.Table;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Linq;
namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
public class VentaMensualSecretariaTirDevoDocument : IDocument
{
public VentaMensualSecretariaTirDevoViewModel Model { get; }
public VentaMensualSecretariaTirDevoDocument(VentaMensualSecretariaTirDevoViewModel model)
{
Model = model;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
// CORRECCIÓN: Se aplica Landscape() al tamaño de página.
page.Size(PageSizes.A4.Landscape());
page.Margin(1, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(12));
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
});
}
void ComposeHeader(IContainer container)
{
container.Column(column =>
{
column.Item().AlignCenter().Text("TIRADA Y DEVOLUCIÓN").SemiBold().FontSize(18);
column.Item().AlignCenter().Text(text =>
{
text.Span("Fecha Consultada: Desde ").SemiBold().FontSize(14);
text.Span(Model.FechaDesde).FontSize(14);
text.Span(" Hasta ").SemiBold().FontSize(14);
text.Span(Model.FechaHasta).FontSize(14);
});
});
}
void ComposeContent(IContainer container)
{
container.PaddingTop(5, Unit.Millimetre).Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(40);
columns.RelativeColumn(); columns.RelativeColumn(); columns.RelativeColumn(); // EL DÍA
columns.RelativeColumn(); columns.RelativeColumn(); columns.RelativeColumn(); // POPULAR
columns.RelativeColumn(); columns.RelativeColumn(); columns.RelativeColumn(); // CLARÍN
columns.RelativeColumn(); columns.RelativeColumn(); columns.RelativeColumn(); // LA NACIÓN
});
table.Header(header =>
{
// CORRECCIÓN: La sintaxis de VerticalAlign es un método.
header.Cell().RowSpan(2).Border(1).Background(Colors.Black).AlignCenter().AlignMiddle().Text(text => text.Span("Día").FontColor(Colors.White).SemiBold());
header.Cell().ColumnSpan(3).Border(1).Background(Colors.Black).AlignCenter().Text(text => text.Span("EL DÍA").FontColor(Colors.White).SemiBold());
header.Cell().ColumnSpan(3).Border(1).Background(Colors.Black).AlignCenter().Text(text => text.Span("POPULAR").FontColor(Colors.White).SemiBold());
header.Cell().ColumnSpan(3).Border(1).Background(Colors.Black).AlignCenter().Text(text => text.Span("CLARÍN").FontColor(Colors.White).SemiBold());
header.Cell().ColumnSpan(3).Border(1).Background(Colors.Black).AlignCenter().Text(text => text.Span("LA NACIÓN").FontColor(Colors.White).SemiBold());
// CORRECCIÓN: Se define una función local para crear y estilizar las celdas del sub-encabezado.
// Esto evita el error de "multiple child elements".
void SubHeaderCell(ITableCellContainer cell, string text)
{
cell.Border(1)
.Background(Colors.Black)
.AlignCenter()
.Text(txt => txt.Span(text).FontColor(Colors.White).SemiBold());
}
foreach (var _ in Enumerable.Range(0, 4))
{
SubHeaderCell(header.Cell(), "TIRADA");
SubHeaderCell(header.Cell(), "DEVOLUC");
SubHeaderCell(header.Cell(), "VENTA");
}
});
// Filas de datos (sin cambios)
foreach (var item in Model.VentasDiarias.OrderBy(x => x.Dia))
{
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.Dia.ToString());
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.TiradaCoop.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.DevolucionCoop.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(t => t.Span(item.VentaCoop.ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.TiradaPopular.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.DevolucionPopular.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(t => t.Span(item.VentaPopular.ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.TiradaClarin.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.DevolucionClarin.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(t => t.Span(item.VentaClarin.ToString("N0")).SemiBold());
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.TiradaNacion.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(item.DevolucionNacion.ToString("N0"));
table.Cell().Border(1).Padding(4).AlignCenter().Text(t => t.Span(item.VentaNacion.ToString("N0")).SemiBold());
}
});
}
}
}