Files
elwig/Elwig/Documents/MemberDataSheet.cs
Lorenz Stechauner 0a9c800116
All checks were successful
Test / Run tests (push) Successful in 2m0s
BusinessDocument: Add DateFrom to be used for ShowDateAndLocation
2026-04-07 12:06:06 +02:00

207 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Elwig.Helpers;
using Elwig.Models.Entities;
using iText.Kernel.Colors;
using iText.Kernel.Pdf;
using iText.Layout.Borders;
using iText.Layout.Element;
using iText.Layout.Properties;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Elwig.Documents {
public class MemberDataSheet : BusinessDocument {
public new static string Name => "Stammdatenblatt";
public Season? Season;
public int MemberDeliveredWeight;
public Dictionary<string, MemberBucket> MemberBuckets = [];
public List<AreaCom> ActiveAreaCommitments = [];
public MemberDataSheet(Member m) :
base($"{Name} {m.AdministrativeName}", m, DateOnly.FromDateTime(m.ModifiedAt)) {
ShowDateAndLocation = true;
DocumentId = $"{Name} {m.MgNr}";
}
public static async Task<MemberDataSheet> Initialize(int mgnr) {
using var ctx = new AppDbContext();
return new MemberDataSheet(await ctx.FetchMembers(mgnr, true, true).SingleAsync());
}
protected override async Task LoadData(AppDbContext ctx) {
await base.LoadData(ctx);
Season = await ctx.FetchSeasons().FirstOrDefaultAsync() ?? throw new ArgumentException("Invalid season");
MemberBuckets = await ctx.GetMemberBuckets(Utils.CurrentYear, Member.MgNr);
ActiveAreaCommitments = await Member.ActiveAreaCommitments(ctx)
.Include(c => c.Contract).ThenInclude(c => c.Revisions)
.ToListAsync();
MemberDeliveredWeight = await ctx.Deliveries
.Where(d => d.Year == Season.Year && d.MgNr == Member.MgNr)
.SelectMany(d => d.Parts)
.SumAsync(p => p.Weight);
}
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
if (Season == null) throw new Exception("Call LoadData before RenderBody");
base.RenderBody(doc, pdf);
doc.Add(NewMemberData(Season).SetMarginBottomMM(5));
doc.Add(NewBucketTable(Season, MemberBuckets, MemberDeliveredWeight, includeDelivery: false));
if (ActiveAreaCommitments.Count != 0) {
bool firstOnPage = false;
if (pdf.GetNumberOfPages() == 1) {
doc.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));
firstOnPage = true;
}
doc.Add(new KernedParagraph(12).Add(Bold($"Flächenbindungen per {Date:dd.MM.yyyy}")).SetMargins(firstOnPage ? 0 : 24, 0, 12, 0));
doc.Add(NewAreaComTable(ActiveAreaCommitments));
}
}
protected Cell NewDataHdr(string title, int colspan) {
return NewTd(title, 10, colspan: colspan, bold: true, italic: true, center: true, borderTop: true)
.SetBackgroundColor(new DeviceRgb(0xe0, 0xe0, 0xe0));
}
protected Cell NewDataTh(string text, float fontSize = 10, int colspan = 1) {
return NewTd(text, fontSize, colspan: colspan, italic: true)
.SetPaddingRightMM(0);
}
protected Table NewMemberData(Season season) {
var tbl = new Table(ColsMM(30.0, 51.5, 20.0, 12.0, 18.0, 31.5))
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
.SetBorder(new SolidBorder(BorderThickness));
tbl.AddCell(NewDataHdr("Persönliche Daten", 6));
if (Member.IsJuridicalPerson) {
tbl
.AddCell(NewDataTh("Name", 8, colspan: 3))
.AddCell(NewDataTh("Zu Handen", 8, colspan: 3))
.AddCell(NewTd(Member.Name, 12, colspan: 3))
.AddCell(NewTd(Member.ForTheAttentionOf, 12, colspan: 3));
} else {
tbl
.AddCell(NewDataTh("Titel (vorangestellt)", 8))
.AddCell(NewDataTh("Vorname", 8))
.AddCell(NewDataTh("Nachname", 8, colspan: 3))
.AddCell(NewDataTh("Titel (nachgestellt)", 8))
.AddCell(NewTd(Member.Prefix, 12))
.AddCell(NewTd($"{Member.GivenName} {Member.MiddleName}", 12))
.AddCell(NewTd(Member.Name, 12, colspan: 3))
.AddCell(NewTd(Member.Suffix, 12));
}
tbl
.AddCell(NewDataTh("Mitglieds-Nr.:")).AddCell(NewTd($"{Member.MgNr}"))
.AddCell(NewDataTh(Member.IsJuridicalPerson ? "Gründungsjahr/-tag:" : "Geburtsjahr/-tag:", colspan: 2))
.AddCell(NewTd(string.Join('.', Member.Birthday?.Split('-')?.Reverse() ?? []), colspan: 2))
.AddCell(NewDataTh("Adresse:")).AddCell(NewTd(Member.Address, colspan: 5))
.AddCell(NewDataTh("PLZ/Ort:"))
.AddCell(NewTd($"{Member.PostalDest.AtPlz?.Plz} {Member.PostalDest.AtPlz?.Dest} ({Member.PostalDest.AtPlz?.Ort.Name})", colspan: 5))
.AddCell(NewDataHdr("Rechnungsadresse (optional)", colspan: 6))
.AddCell(NewDataTh("Name:")).AddCell(NewTd(Member.BillingAddress?.FullName, colspan: 5))
.AddCell(NewDataTh("Adresse:")).AddCell(NewTd(Member.BillingAddress?.Address, colspan: 5))
.AddCell(NewDataTh("PLZ/Ort:"))
.AddCell(NewTd(Member.BillingAddress != null ? $"{Member.BillingAddress.PostalDest.AtPlz?.Plz} {Member.BillingAddress.PostalDest.AtPlz?.Dest} ({Member.BillingAddress.PostalDest.AtPlz?.Ort.Name})" : "", colspan: 5));
tbl.AddCell(NewDataHdr("Kontaktdaten", colspan: 3))
.AddCell(NewDataHdr("Bankverbindung", colspan: 3).SetBorderLeft(new SolidBorder(BorderThickness)));
List<string?[]> subTbl1 = [
.. Member.EmailAddresses.Select(a => new[] { "E-Mail-Adresse", a.Address }),
.. Member.TelephoneNumbers.Select(n => new[] { Utils.PhoneNrTypeToString(n.Type), n.Number, n.Comment }),
["Tel.-Nr./E-Mail-Adr.", null],
];
List<string?[]> subTbl2 = [
["IBAN", Member.Iban != null ? Utils.FormatIban(Member.Iban) : null],
["BIC", Member.Bic],
];
for (int i = 0; i < Math.Max(subTbl1.Count, subTbl2.Count); i++) {
tbl.AddCell(NewDataTh(i < subTbl1.Count ? subTbl1[i][0] + ":" : ""));
if (i < subTbl1.Count && subTbl1[i].Length >= 3 && subTbl1[i][2] != null) {
tbl.AddCell(NewTd(subTbl1[i][1])).AddCell(NewTd($"({subTbl1[i][2]})"));
} else {
tbl.AddCell(NewTd(i < subTbl1.Count ? subTbl1[i][1] : "", colspan: 2));
}
tbl.AddCell(NewDataTh(i < subTbl2.Count ? subTbl2[i][0] + ":" : "").SetBorderLeft(new SolidBorder(BorderThickness)))
.AddCell(NewTd(i < subTbl2.Count ? subTbl2[i][1] : "", colspan: 2));
}
tbl.AddCell(NewDataHdr("Betrieb", colspan: 6))
.AddCell(NewDataTh("Betriebs-Nr.:")).AddCell(NewTd(Member.LfbisNr))
.AddCell(NewDataTh("UID:", colspan: 2)).AddCell(NewTd(Member.UstIdNr, colspan: 2))
.AddCell(NewDataTh("Stammgemeinde:")).AddCell(NewTd(Member.DefaultKg?.Name))
.AddCell(NewDataTh("Buchführend:", colspan: 2)).AddCell(NewTd(new KernedParagraph(Member.IsBuchführend ? "Ja " : "Nein ", 10)
.Add(Normal($"({(Member.IsBuchführend ? season.VatNormal : season.VatFlatrate) * 100:N0}% USt.)", 8)), colspan: 2))
.AddCell(NewDataTh("(Katastralgemeinde mit dem größten Anteil an Weinbauflächen)", 8, colspan: 2))
.AddCell(NewDataTh("Bio:", colspan: 2)).AddCell(NewTd(Member.IsOrganic ? "Ja" : "Nein", colspan: 2))
.AddCell(NewDataHdr("Genossenschaft", colspan: 6))
.AddCell(NewDataTh("Status:")).AddCell(NewTd(new KernedParagraph(Member.IsActive ? "Aktiv " : "Nicht aktiv ", 10)
.Add(Normal("(" + (Member.ExitDate != null ? $"{Member.EntryDate:dd.MM.yyyy}\u2013{Member.ExitDate:dd.MM.yyyy}" : $"seit {Member.EntryDate:dd.MM.yyyy}") + ")", 8))))
.AddCell(NewDataTh("Geschäftsanteile:", colspan: 2)).AddCell(NewTd($"{Member.BusinessShares:N0}", colspan: 2))
.AddCell(NewDataTh("Stamm-Zweigstelle:")).AddCell(NewTd(Member.Branch?.Name))
.AddCell(NewDataTh("Volllieferant:", colspan: 2)).AddCell(NewTd(Member.IsVollLieferant ? "Ja" : "Nein", colspan: 2))
.AddCell(NewDataTh("Zusendungen per\u2026")).AddCell(NewTd(new KernedParagraph(10)
.Add(Italic("Post:")).Add(Normal(Member.ContactViaPost ? " Ja \u2013 " : " Nein \u2013 "))
.Add(Italic("E-Mail:")).Add(Normal(Member.ContactViaEmail ? " Ja" : " Nein"))))
.AddCell(NewDataTh("Funktionär:", colspan: 2)).AddCell(NewTd(Member.IsFunktionär ? "Ja" : "Nein", colspan: 2));
return tbl;
}
protected Table NewAreaComTable(IEnumerable<AreaCom> activeAreaComs) {
var areaComs = activeAreaComs.GroupBy(a => a.AreaComType).Select(group => new {
Type = group.Key,
AreaComs = group.OrderBy(c => c.Contract.Kg.AtKg.Name).ToList(),
Size = group.Sum(c => c.Area)
}).OrderByDescending(a => a.Size).ToList();
var tbl = new Table(ColsMM(40, 30, 35, 15, 25, 20), true)
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
.SetBorder(Border.NO_BORDER)
.SetFontSize(10);
tbl.AddHeaderCell(NewTh("Katastralgemeinde", rowspan: 2, left: true))
.AddHeaderCell(NewTh("Ried", rowspan: 2, left: true))
.AddHeaderCell(NewTh("Parzelle(n)", rowspan: 2, left: true))
.AddHeaderCell(NewTh("Fläche"))
.AddHeaderCell(NewTh("Bewirt.", rowspan: 2))
.AddHeaderCell(NewTh("Laufzeit", rowspan: 2))
.AddHeaderCell(NewTh("[m²]"));
var lastContract = "";
foreach (var contractType in areaComs) {
tbl.AddCell(NewCell(new KernedParagraph(10).Add(BoldItalic($"{contractType.Type.WineVar.Name} {(contractType.Type.WineAttr != null ? "(" + contractType.Type.WineAttr + ")" : "")}")), colspan: 3)
.SetBorderTop(contractType.Type.DisplayName != lastContract && lastContract != "" ? new SolidBorder(BorderThickness) : Border.NO_BORDER))
.AddCell(NewCell(new KernedParagraph(10).Add(Bold($"{contractType.Size:N0}")).SetTextAlignment(TextAlignment.RIGHT))
.SetBorderTop(contractType.Type.DisplayName != lastContract && lastContract != "" ? new SolidBorder(BorderThickness) : Border.NO_BORDER))
.AddCell(NewCell(colspan: 2)
.SetBorderTop(contractType.Type.DisplayName != lastContract && lastContract != "" ? new SolidBorder(BorderThickness) : Border.NO_BORDER));
foreach (var areaCom in contractType.AreaComs) {
var c = areaCom.Contract;
tbl.AddCell(NewTd(new KernedParagraph(10).Add(Normal($"{c.Kg.AtKg.Name} ")).Add(Normal($"({c.Kg.AtKg.KgNr:00000})", 8))))
.AddCell(NewTd(c.Rd?.Name))
.AddCell(NewTd(Regex.Replace(areaCom.GstNr.Replace(",", ", ").Replace("-", "\u2013"), @"\s+", " "), 10))
.AddCell(NewTd($"{areaCom.Area:N0}", right: true))
.AddCell(NewTd(areaCom.WineCult?.Name, center: true))
.AddCell(NewTd(c.YearTo == null ? (c.YearFrom == null ? "unbefristet" : $"ab {c.YearFrom}") : (c.YearFrom == null ? $"bis {c.YearTo}" : $"{c.YearFrom}{c.YearTo}"), center: true));
lastContract = contractType.Type.DisplayName;
}
}
tbl.AddCell(NewTd("Gesamt:", 12, colspan: 2, bold: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1));
tbl.AddCell(NewTd($"{activeAreaComs.Sum(a => a.Area):N0}", 12, colspan: 2, right: true, bold: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1));
tbl.AddCell(NewTd(colspan: 2, borderTop: true).SetPaddingsMM(1, 1, 1, 1));
return tbl;
}
}
}