Init
This commit is contained in:
237
Server/Model/InvoiceDocument.cs
Normal file
237
Server/Model/InvoiceDocument.cs
Normal file
@@ -0,0 +1,237 @@
|
||||
using System.Globalization;
|
||||
using System.Net.Mime;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace Server.Model
|
||||
{
|
||||
public class InvoiceDocument(InvoiceModel model) : IDocument
|
||||
{
|
||||
private InvoiceModel Model { get; } = model;
|
||||
|
||||
public void Compose(IDocumentContainer container)
|
||||
{
|
||||
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.Header().Element(ComposeHeader);
|
||||
page.Content().Element(ComposeContent);
|
||||
page.Footer().Element(ComposeFooter);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void ComposeContent(IContainer container)
|
||||
{
|
||||
container.PaddingVertical(40).Column(column =>
|
||||
{
|
||||
column.Spacing(5);
|
||||
|
||||
column.Item().Element(ComposeTable);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Model.Comment))
|
||||
column.Item().PaddingTop(25).Element(ComposeComments);
|
||||
});
|
||||
}
|
||||
|
||||
private void ComposeTable(IContainer container)
|
||||
{
|
||||
container.Table(table =>
|
||||
{
|
||||
// Define columns
|
||||
table.ColumnsDefinition(columns =>
|
||||
{
|
||||
columns.ConstantColumn(30, Unit.Millimetre);
|
||||
columns.RelativeColumn(3);
|
||||
columns.RelativeColumn();
|
||||
columns.RelativeColumn();
|
||||
});
|
||||
|
||||
// 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");
|
||||
|
||||
static IContainer CellStyle(IContainer container)
|
||||
{
|
||||
return container.DefaultTextStyle(x => x.SemiBold()).BorderBottom(1).BorderColor(Colors.Black);
|
||||
}
|
||||
});
|
||||
|
||||
// Describe content
|
||||
foreach (var item in Model.Items ?? [])
|
||||
{
|
||||
table.Cell().Element(CellStyle).AlignCenter().Text(txt => txt.Span($"{item.Quantity:N2}"));
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
// string as currency format
|
||||
table.Cell().Element(CellStyle).AlignRight().Text($"{item.PriceNetto:N2} €");
|
||||
table.Cell().Element(CellStyle).AlignRight().Text($"{item.PriceNetto * 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().Element(CellStyle).PaddingTop(10).AlignRight().Text($"{Model.Items.Sum(x=> x.PriceBrutto*x.Quantity):N2} €").Medium();
|
||||
|
||||
return;
|
||||
|
||||
static IContainer CellStyle(IContainer container) => container.BorderBottom(1).BorderColor(Colors.Grey.Lighten2).PaddingVertical(5);
|
||||
});
|
||||
}
|
||||
|
||||
private void ComposeComments(IContainer container)
|
||||
{
|
||||
container.Background(Colors.Grey.Lighten3).Padding(10).Column(column =>
|
||||
{
|
||||
column.Spacing(5);
|
||||
column.Item().Text(Model.Comment);
|
||||
});
|
||||
}
|
||||
|
||||
private void ComposeFooter(IContainer container)
|
||||
{
|
||||
container.Column(outerColumn =>
|
||||
{
|
||||
outerColumn.Item().DefaultTextStyle(style => style.FontSize(10)).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}"));
|
||||
});
|
||||
|
||||
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}"));
|
||||
});
|
||||
|
||||
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}"));
|
||||
});
|
||||
});
|
||||
|
||||
outerColumn.Item().PaddingTop(3, Unit.Millimetre).AlignCenter().Text(txt =>
|
||||
{
|
||||
txt.CurrentPageNumber();
|
||||
txt.Span(" / ");
|
||||
txt.TotalPages();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void ComposeHeader(IContainer container)
|
||||
{
|
||||
container.Column(outerColumn =>
|
||||
{
|
||||
outerColumn.Item().AlignCenter().Row(row =>
|
||||
{
|
||||
row.RelativeItem().AlignCenter().Column(col =>
|
||||
{
|
||||
col.Item().Height(25, Unit.Millimetre).Image("bit.bmp");
|
||||
});
|
||||
});
|
||||
|
||||
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());
|
||||
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);
|
||||
column.Item().Text($"{Model.Customer?.Zip} {Model.Customer?.City}");
|
||||
});
|
||||
|
||||
row.RelativeItem();
|
||||
|
||||
row.AutoItem().DefaultTextStyle(style => style.FontSize(10)).Column(column =>
|
||||
{
|
||||
column.Item().Text(txt =>
|
||||
{
|
||||
txt.Span("Steuer-Nr:").Bold().Underline();
|
||||
txt.Span(" ");
|
||||
txt.Span(Model.Seller?.TaxId);
|
||||
});
|
||||
|
||||
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}");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user