Layout Updates

This commit is contained in:
Andre Beging
2024-11-14 20:34:16 +01:00
parent b76dcdb746
commit 7dc50d51f9
7 changed files with 207 additions and 96 deletions

View File

@@ -1,5 +1,6 @@
using System.Globalization;
using System.Net.Mime;
using QuestPDF.Drawing;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
@@ -13,13 +14,19 @@ namespace Server.Model
public void Compose(IDocumentContainer container)
{
if(File.Exists("NotoSans-VariableFont_wdth,wght.ttf"))
FontManager.RegisterFont(File.OpenRead("NotoSans-VariableFont_wdth,wght.ttf"));
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(10, Unit.Millimetre);
page.MarginLeft(20, Unit.Millimetre);
page.PageColor(Colors.White);
page.DefaultTextStyle(x => x.FontSize(12).FontFamily(Fonts.Calibri).Light());
page.DefaultTextStyle(x => x
.FontSize(10)
.FontFamily("NotoSans")
.Light());
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
@@ -30,38 +37,126 @@ namespace Server.Model
private void ComposeContent(IContainer container)
{
container.PaddingVertical(40).Column(column =>
container.PaddingVertical(40).Column(outerColumn =>
{
column.Spacing(5);
outerColumn.Item().Element(ComposeItemTable);
outerColumn.Item().Row(row =>
{
row.RelativeItem().PaddingRight(10).Column(col =>
{
if (!string.IsNullOrWhiteSpace(Model.Comment))
col.Item().PaddingTop(25).Element(ComposeComments);
});
row.AutoItem().Column(col =>
{
col.Item().Element(ComposeTaxTable);
});
});
outerColumn.Spacing(5);
});
}
column.Item().Element(ComposeTable);
private void ComposeTaxTable(IContainer container)
{
container.PaddingTop(25).Table(table =>
{
table.ColumnsDefinition(c =>
{
c.ConstantColumn(70);
c.ConstantColumn(25);
c.ConstantColumn(70);
c.ConstantColumn(45);
});
table.Header(header =>
{
header.Cell();
header.Cell().AlignRight().TextSmall("", true);
header.Cell().AlignRight().TextSmall("Zwischensumme", true);
header.Cell().AlignRight().TextSmall("", true);
header.Cell().Element(c => c.BorderBottom(1).BorderColor(Colors.Black));
header.Cell().Element(c => c.BorderBottom(1).BorderColor(Colors.Black)).AlignRight().TextSmall("USt. %", true);
header.Cell().Element(c => c.BorderBottom(1).BorderColor(Colors.Black)).AlignRight().TextSmall("(ohne USt.)", true);
header.Cell().Element(c => c.BorderBottom(1).BorderColor(Colors.Black)).AlignRight().TextSmall("USt.", true);
});
if (!string.IsNullOrWhiteSpace(Model.Comment))
column.Item().PaddingTop(25).Element(ComposeComments);
var totalTax = 0d;
// 7%
var tax7Items = Model.Items?.Where(x => x.TaxType == TaxType.Tax7).ToList() ?? [];
if (tax7Items.Count > 0)
{
var tax7Netto = tax7Items.Sum(x => x.PriceNetto * x.Quantity);
var tax7Tax = tax7Netto * 0.07;
totalTax += tax7Tax;
table.Cell();
table.Cell().AlignRight().TextSmall("7%");
table.Cell().AlignRight().TextSmall($"{tax7Netto:N2} €");
table.Cell().AlignRight().TextSmall($"{tax7Tax:N2} €");
}
// 19%
var tax19Items = Model.Items?.Where(x => x.TaxType == TaxType.Tax19).ToList() ?? [];
if (tax19Items.Count > 0)
{
var tax19Netto = tax19Items.Sum(x => x.PriceNetto * x.Quantity);
var tax19Tax = tax19Netto * 0.19;
totalTax += tax19Tax;
table.Cell();
table.Cell().AlignRight().TextSmall("19%");
table.Cell().AlignRight().TextSmall($"{tax19Netto:N2} €");
table.Cell().AlignRight().TextSmall($"{tax19Tax:N2} €");
}
// SUMME
table.Cell().Element(c => c.BorderTop(1).BorderColor(Colors.Black)).TextSmall("USt. Gesamt");
table.Cell().Element(c => c.BorderTop(1).BorderColor(Colors.Black));
table.Cell().Element(c => c.BorderTop(1).BorderColor(Colors.Black)).AlignRight().TextSmall($"{Model.Items?.Sum(x => x.PriceNetto * x.Quantity):N2} €");
table.Cell().Element(c => c.BorderTop(1).BorderColor(Colors.Black)).AlignRight().TextSmall($"{totalTax:N2} €");
});
}
private void ComposeTable(IContainer container)
private void ComposeItemTable(IContainer container)
{
container.Table(table =>
{
// Define columns
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(30, Unit.Millimetre);
columns.RelativeColumn(3);
columns.RelativeColumn();
columns.RelativeColumn();
columns.ConstantColumn(20, Unit.Millimetre);
columns.ConstantColumn(24, Unit.Millimetre);
columns.ConstantColumn(15, Unit.Millimetre);
columns.ConstantColumn(24, Unit.Millimetre);
columns.ConstantColumn(24, Unit.Millimetre);
});
// Describe header
table.Header(header =>
{
header.Cell().Element(CellStyle).AlignCenter().Text("Menge");
header.Cell().Element(CellStyle).Text("Bezeichnung");
header.Cell().Element(CellStyle).AlignRight().Text("Einzelpreis");
header.Cell().Element(CellStyle).AlignRight().Text("Gesamtpreis");
header.Cell().Text("").SemiBold();
header.Cell().Text("").SemiBold();
header.Cell().AlignRight().Text("Einzelpreis").SemiBold();
header.Cell().Text("").SemiBold();
header.Cell().AlignRight().Text("Einzelpreis").SemiBold();
header.Cell().AlignRight().Text("Gesamtpreis").SemiBold();
header.Cell().Element(CellStyle).Text("Beschreibung").SemiBold();
header.Cell().Element(CellStyle).AlignCenter().Text("Menge").SemiBold();
header.Cell().Element(CellStyle).AlignRight().Text("(ohne USt.)").SemiBold();
header.Cell().Element(CellStyle).AlignRight().Text("USt. %").SemiBold();
header.Cell().Element(CellStyle).AlignRight().Text("(inkl USt.)").SemiBold();
header.Cell().Element(CellStyle).AlignRight().Text("(inkl USt.)").SemiBold();
static IContainer CellStyle(IContainer container)
{
return container.DefaultTextStyle(x => x.SemiBold()).BorderBottom(1).BorderColor(Colors.Black);
@@ -71,54 +166,28 @@ namespace Server.Model
// Describe content
foreach (var item in Model.Items ?? [])
{
table.Cell().Element(CellStyle).AlignCenter().Text(txt => txt.Span($"{item.Quantity:N2}"));
// Beschreibung
table.Cell().Element(CellStyle).Column(column =>
{
column.Item().Text(item.Name);
if(!string.IsNullOrWhiteSpace(item.Description)) column.Item().Text(txt =>
{
txt.Span(item.Description).FontSize(8);
});
if(!string.IsNullOrWhiteSpace(item.Description))
column.Item().TextSmall(item.Description);
});
table.Cell().Element(CellStyle).AlignCenter().Text(txt => txt.Span($"{item.Quantity:N2}"));
// string as currency format
table.Cell().Element(CellStyle).AlignRight().Text($"{item.PriceNetto:N2} €");
table.Cell().Element(CellStyle).AlignRight().Text($"{item.PriceNetto * item.Quantity:N2} €");
table.Cell().Element(CellStyle).AlignRight().Text($"{(int)item.TaxType}%");
table.Cell().Element(CellStyle).AlignRight().Text($"{item.PriceBrutto:N2} €");
table.Cell().Element(CellStyle).AlignRight().Text($"{item.PriceBrutto * item.Quantity:N2} €");
continue;
}
// Gesamt Netto
table.Cell().ColumnSpan(3).PaddingTop(10).Text("Gesamt Netto");
table.Cell().PaddingTop(10).AlignRight().Text($"{Model.TotalNetto:N2} €");
// 7%
var tax7Items = Model.Items?.Where(x => x.TaxType == TaxType.Tax7).ToList() ?? [];
if (tax7Items.Count > 0)
{
var tax7Netto = tax7Items.Sum(x => x.PriceNetto * x.Quantity);
var tax7Tax = tax7Netto * 0.07;
table.Cell().ColumnSpan(2).Text("zzgl. 7% USt. auf");
table.Cell().AlignRight().Text($"{tax7Netto:N2} €");
table.Cell().AlignRight().Text($"{tax7Tax:N2} €");
}
// 19%
var tax19Items = Model.Items?.Where(x => x.TaxType == TaxType.Tax19).ToList() ?? [];
if (tax19Items.Count > 0)
{
var tax19Netto = tax19Items.Sum(x => x.PriceNetto * x.Quantity);
var tax19Tax = tax19Netto * 0.19;
table.Cell().ColumnSpan(2).Text("zzgl. 19% USt. auf");
table.Cell().AlignRight().Text($"{tax19Netto:N2} €");
table.Cell().AlignRight().Text($"{tax19Tax:N2} €");
}
table.Cell().ColumnSpan(3).Element(CellStyle).PaddingTop(10).Text("Rechnungsbetrag").Medium();
table.Cell().ColumnSpan(5).Element(CellStyle).PaddingTop(10).Text("Rechnungsbetrag").Medium();
table.Cell().Element(CellStyle).PaddingTop(10).AlignRight().Text($"{Model.Items.Sum(x=> x.PriceBrutto*x.Quantity):N2} €").Medium();
return;
@@ -140,37 +209,27 @@ namespace Server.Model
{
container.Column(outerColumn =>
{
outerColumn.Item().DefaultTextStyle(style => style.FontSize(10)).Row(row =>
outerColumn.Item().Row(row =>
{
row.RelativeItem().Column(column =>
{
column.Item().Text(txt => txt.Span(Model.Seller?.Name).Bold());
column.Item().Text(txt => txt.Span(Model.Seller?.Street));
column.Item().Text(txt => txt.Span($"{Model.Seller?.Zip} {Model.Seller?.City}"));
column.Item().TextSmall(Model.Seller?.Name, true);
column.Item().TextSmall(Model.Seller?.Street);
column.Item().TextSmall($"{Model.Seller?.Zip} {Model.Seller?.City}");
});
row.RelativeItem().Column(column =>
{
if(!string.IsNullOrWhiteSpace(Model.Seller?.Phone))
column.Item().Text(txt => txt.Span($"Tel.: {Model.Seller?.Phone}"));
if(!string.IsNullOrWhiteSpace(Model.Seller?.Email))
column.Item().Text(txt => txt.Span($"E-Mail: {Model.Seller?.Email}"));
if(!string.IsNullOrWhiteSpace(Model.Seller?.Web))
column.Item().Text(txt => txt.Span($"Web: {Model.Seller?.Web}"));
if(!string.IsNullOrWhiteSpace(Model.Seller?.Phone)) column.Item().TextSmall($"Tel.: {Model.Seller?.Phone}");
if(!string.IsNullOrWhiteSpace(Model.Seller?.Email)) column.Item().TextSmall($"E-Mail: {Model.Seller?.Email}");
if(!string.IsNullOrWhiteSpace(Model.Seller?.Web)) column.Item().TextSmall($"Web: {Model.Seller?.Web}");
});
row.RelativeItem().Column(column =>
{
if(!string.IsNullOrWhiteSpace(Model.PaymentData?.BankName))
column.Item().Text(txt => txt.Span(Model.PaymentData?.BankName));
if(!string.IsNullOrWhiteSpace(Model.PaymentData?.Iban))
column.Item().Text(txt => txt.Span($"IBAN: {Model.PaymentData?.Iban}"));
if(!string.IsNullOrWhiteSpace(Model.PaymentData?.Bic))
column.Item().Text(txt => txt.Span($"BIC: {Model.PaymentData?.Bic}"));
if(!string.IsNullOrWhiteSpace(Model.PaymentData?.BankName)) column.Item().TextSmall(Model.PaymentData?.BankName);
if(!string.IsNullOrWhiteSpace(Model.PaymentData?.Iban)) column.Item().TextSmall($"IBAN: {Model.PaymentData?.Iban}");
if(!string.IsNullOrWhiteSpace(Model.PaymentData?.Bic)) column.Item().TextSmall($"BIC: {Model.PaymentData?.Bic}");
});
});
@@ -187,9 +246,9 @@ namespace Server.Model
{
container.Column(outerColumn =>
{
outerColumn.Item().AlignCenter().Row(row =>
outerColumn.Item().Row(row =>
{
row.RelativeItem().AlignCenter().Column(col =>
row.RelativeItem().Column(col =>
{
if (!string.IsNullOrWhiteSpace(SettingsData.Instance.Logo) && File.Exists(SettingsData.Instance.Logo))
@@ -198,13 +257,18 @@ namespace Server.Model
col.Item().Height(25, Unit.Millimetre);
});
row.RelativeItem().AlignMiddle().PaddingRight(10, Unit.Millimetre).Background(Colors.Red.Medium).Column(col =>
{
col.Item().AlignRight().Text("www.example.com");
});
});
outerColumn.Item().PaddingTop(15, Unit.Millimetre).Row(row =>
{
row.AutoItem().Column(column =>
{
column.Item().Text(Model.Seller?.ToString()).Style(new TextStyle().FontSize(8).SemiBold().Underline());
column.Item().PaddingBottom(5).TextSmall(Model.Seller?.ToString(), true);
if(!string.IsNullOrWhiteSpace(Model.Customer?.Name)) column.Item().Text(Model.Customer?.Name);
if(!string.IsNullOrWhiteSpace(Model.Customer?.Name2)) column.Item().Text(Model.Customer?.Name2);
column.Item().Text(Model.Customer?.Street);
@@ -213,27 +277,24 @@ namespace Server.Model
row.RelativeItem();
row.AutoItem().DefaultTextStyle(style => style.FontSize(10)).Column(column =>
row.AutoItem().Column(col =>
{
column.Item().Text(txt =>
col.Item().Table(table =>
{
txt.Span("Steuer-Nr:").Bold().Underline();
txt.Span(" ");
txt.Span(Model.Seller?.TaxId);
});
table.ColumnsDefinition(c =>
{
c.ConstantColumn(50);
c.ConstantColumn(50);
});
column.Item().Text(txt =>
{
txt.Span("Datum:").Bold().Underline();
txt.Span(" ");
txt.Span(Model.IssueDate.ToShortDateString());
});
column.Item().Text(txt =>
{
txt.Span("Rechnung:").Bold();
txt.Span(" ");
txt.Span($"#{Model.InvoiceId}");
table.Cell().TextSmall("Steuer-Nr:", true);
table.Cell().TextSmall(Model.Seller?.TaxId);
table.Cell().TextSmall("Datum:", true);
table.Cell().TextSmall(Model.IssueDate.ToShortDateString());
table.Cell().TextSmall("Rechnung:", true);
table.Cell().TextSmall($"#{Model.InvoiceId}");
});
});
});