From 9c39a2f8208a8ea3f02d64aac0edb45f80ce6e96 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Wed, 1 Apr 2026 16:24:03 +0200 Subject: [PATCH] [#79] Entities: Remove EF proxies --- Elwig/App.xaml.cs | 5 +- Elwig/Dialogs/DeliverySplittingDialog.xaml.cs | 1 - Elwig/Documents/BusinessDocument.cs | 8 +- Elwig/Documents/CreditNote.cs | 102 +++++++++++------- Elwig/Documents/DeliveryConfirmation.cs | 36 +++++-- Elwig/Documents/DeliveryNote.cs | 38 ++++++- Elwig/Documents/Document.cs | 6 +- Elwig/Documents/MemberDataSheet.cs | 53 ++++++--- Elwig/Documents/PaymentVariantSummary.cs | 94 +++++++++------- Elwig/Elwig.csproj | 1 - Elwig/Helpers/AppDbContext.cs | 52 ++++++++- Elwig/Helpers/Billing/Billing.cs | 2 +- Elwig/Helpers/Billing/BillingVariant.cs | 2 +- Elwig/Helpers/Export/ElwigData.cs | 2 +- Elwig/Helpers/Utils.cs | 16 ++- Elwig/Models/Dtos/CreditNoteDeliveryData.cs | 4 +- Elwig/Models/Dtos/DeliveryAncmtListData.cs | 7 +- .../Dtos/DeliveryConfirmationDeliveryData.cs | 8 +- Elwig/Models/Dtos/DeliveryJournalData.cs | 5 - Elwig/Models/Dtos/MemberListData.cs | 6 +- Elwig/Models/Entities/Delivery.cs | 12 +-- Elwig/Models/Entities/WineOrigin.cs | 6 +- Elwig/Services/DeliveryService.cs | 58 ++++++---- Elwig/Services/MemberService.cs | 34 ++---- Elwig/Services/PaymentVariantService.cs | 4 +- Elwig/Services/SyncService.cs | 25 +---- Elwig/ViewModels/MemberAdminViewModel.cs | 2 +- Elwig/Windows/AdministrationWindow.cs | 1 - Elwig/Windows/AreaComAdminWindow.xaml.cs | 13 +-- Elwig/Windows/BaseDataWindow.xaml.AreaCom.cs | 2 - Elwig/Windows/BaseDataWindow.xaml.Branch.cs | 4 +- Elwig/Windows/BaseDataWindow.xaml.Season.cs | 2 - Elwig/Windows/BaseDataWindow.xaml.cs | 5 +- Elwig/Windows/DeliveryAdminWindow.xaml.cs | 48 ++++----- .../Windows/DeliveryAncmtAdminWindow.xaml.cs | 14 +-- .../DeliveryScheduleAdminWindow.xaml.cs | 2 - Elwig/Windows/MailWindow.xaml.cs | 29 ++--- Elwig/Windows/MemberAdminWindow.xaml.cs | 14 ++- Elwig/Windows/OriginHierarchyWindow.xaml.cs | 14 ++- Elwig/Windows/PaymentVariantsWindow.xaml.cs | 1 - Tests/DatabaseSetup.cs | 3 +- Tests/Resources/Sql/DocumentInsert.sql | 4 + .../UnitTests/DocumentTests/CreditNoteTest.cs | 10 +- .../DocumentTests/DeliveryConfirmationTest.cs | 2 +- .../DocumentTests/DeliveryNoteTest.cs | 57 +++++++--- .../DocumentTests/MemberDataSheetTest.cs | 5 +- .../PaymentVariantSummaryTest.cs | 11 +- Tests/UnitTests/DocumentTests/Utils.cs | 5 +- .../ServiceTests/DeliveryServiceTest.cs | 1 - .../ServiceTests/MemberServiceTest.cs | 48 +++------ 50 files changed, 471 insertions(+), 413 deletions(-) diff --git a/Elwig/App.xaml.cs b/Elwig/App.xaml.cs index 82d1fcb..5b49877 100644 --- a/Elwig/App.xaml.cs +++ b/Elwig/App.xaml.cs @@ -6,6 +6,7 @@ using Elwig.Helpers.Printing; using Elwig.Helpers.Weighing; using Elwig.Models.Entities; using Elwig.Windows; +using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Data; @@ -104,7 +105,9 @@ namespace Elwig { Dictionary branches = []; using (var ctx = new AppDbContext()) { - branches = ctx.Branches.ToDictionary(b => b.Name.ToLower(), b => (b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Ort.Name, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr)); + branches = ctx.Branches + .Include(b => b.PostalDest) + .ToDictionary(b => b.Name.ToLower(), b => (b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Ort.Name, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr)); try { Client = new(ctx); } catch (Exception e) { diff --git a/Elwig/Dialogs/DeliverySplittingDialog.xaml.cs b/Elwig/Dialogs/DeliverySplittingDialog.xaml.cs index 3308549..f42b481 100644 --- a/Elwig/Dialogs/DeliverySplittingDialog.xaml.cs +++ b/Elwig/Dialogs/DeliverySplittingDialog.xaml.cs @@ -52,7 +52,6 @@ namespace Elwig.Dialogs { ControlUtils.RenewItemsSource(DeliveryInput, await ctx.Deliveries .Where(d => d.DateString == $"{_delivery.Date:yyyy-MM-dd}" && d.ZwstId == _delivery.ZwstId) .OrderBy(d => d.LsNr) - .Include(d => d.Member) .Include(d => d.Parts) .ToListAsync()); if (DeliveryInput.SelectedItem == null) diff --git a/Elwig/Documents/BusinessDocument.cs b/Elwig/Documents/BusinessDocument.cs index 8901917..dc4e993 100644 --- a/Elwig/Documents/BusinessDocument.cs +++ b/Elwig/Documents/BusinessDocument.cs @@ -261,7 +261,7 @@ namespace Elwig.Documents { } protected Table NewBucketTable( - Season season, Dictionary buckets, + Season season, Dictionary buckets, int deliveredWeight, bool includeDelivery = true, bool includePayment = false, bool isTiny = false, IEnumerable? filter = null ) { @@ -315,10 +315,8 @@ namespace Elwig.Documents { .OrderBy(b => b.Value.Name); tbl.AddCell(NewBucketTh("Gesamtlieferung lt. gez. GA", isTiny: isTiny)); - tbl.AddCells(FormatRow(Member.BusinessShares * season.MinKgPerBusinessShare, - Member.BusinessShares * season.MaxKgPerBusinessShare, - season.Deliveries.Where(d => d.MgNr == Member.MgNr).Sum(d => d.Weight), - isGa: true, showPayment: includePayment, showArea: !includeDelivery, isTiny: isTiny)); + tbl.AddCells(FormatRow(Member.BusinessShares * season.MinKgPerBusinessShare, Member.BusinessShares * season.MaxKgPerBusinessShare, + deliveredWeight, isGa: true, showPayment: includePayment, showArea: !includeDelivery, isTiny: isTiny)); if (fbs.Any()) { tbl.AddCell(NewBucketSubHdr("Flächenbindungen" + (vtr.Any() ? " (inkl. Verträge)" : "") + ":", includePayment ? 8 : 7, isTiny: isTiny)); diff --git a/Elwig/Documents/CreditNote.cs b/Elwig/Documents/CreditNote.cs index 3b5bd57..a41360c 100644 --- a/Elwig/Documents/CreditNote.cs +++ b/Elwig/Documents/CreditNote.cs @@ -1,55 +1,82 @@ using Elwig.Helpers; +using Elwig.Helpers.Billing; using Elwig.Models.Dtos; using Elwig.Models.Entities; 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.Threading.Tasks; namespace Elwig.Documents { public class CreditNote : BusinessDocument { public new static string Name => "Traubengutschrift"; - public PaymentMember? Payment; + public PaymentMember Payment; public Credit? Credit; - public CreditNoteDeliveryData Data; public string? Text; public string CurrencySymbol; public int Precision; - public string MemberModifier; + public string? MemberModifier; public List<(string Name, int Kg, decimal Amount)>? MemberUnderDeliveries; public decimal MemberTotalUnderDelivery; public int MemberAutoBusinessShares; public decimal MemberAutoBusinessSharesAmount; public PaymentCustom? CustomPayment; - public CreditNote( - AppDbContext ctx, - PaymentMember p, - CreditNoteDeliveryData data, - bool considerContractPenalties, - bool considerTotalPenalty, - bool considerAutoBusinessShares, - bool considerCustomModifiers, - Dictionary? underDeliveries = null - ) : + protected bool ConsiderContractPenalties; + protected bool ConsiderTotalPenalty; + protected bool ConsiderAutoBusinessShares; + protected bool ConsiderCustomModifiers; + + private CreditNoteDeliveryData? _data; + private Dictionary? _underDeliveries; + + public CreditNote(PaymentMember p, BillingData? billingData = null, CreditNoteDeliveryData? data = null, Dictionary? underDeliveries = null) : base($"{Name} {(p.Credit != null ? $"Nr. {p.Credit.Year}/{p.Credit.TgNr:000}" : p.Member.FullName)} – {p.Variant.Name}", p.Member) { UseBillingAddress = true; ShowDateAndLocation = true; - Data = data; Payment = p; Credit = p.Credit; - IsPreview = Payment == null || Credit == null; - var season = p.Variant.Season; - if (considerCustomModifiers) { - CustomPayment = ctx.CustomPayments.Find(p.Year, p.MgNr); + Text = App.Client.TextCreditNote; + DocumentId = $"Tr.-Gutschr. " + (Credit != null ? $"{Credit.Year}/{Credit.TgNr:000}" : Payment.MgNr); + IsPreview = Credit == null; + _data = data; + _underDeliveries = underDeliveries; + CurrencySymbol = Payment.Variant.Season.Currency.Symbol ?? Payment.Variant.Season.Currency.Code; + Precision = Payment.Variant.Season.Precision; + + billingData ??= BillingData.FromJson(Payment.Variant.Data); + ConsiderContractPenalties = billingData.ConsiderContractPenalties; + ConsiderTotalPenalty = billingData.ConsiderTotalPenalty; + ConsiderAutoBusinessShares = billingData.ConsiderAutoBusinessShares; + ConsiderCustomModifiers = billingData.ConsiderCustomModifiers; + } + + public static async Task Initialize(int year, int avnr, int mgnr, BillingData? billingData = null, CreditNoteDeliveryData? data = null, Dictionary? underDeliveries = null) { + using var ctx = new AppDbContext(); + var p = await ctx.MemberPayments + .Where(p => p.Year == year && p.AvNr == avnr && p.MgNr == mgnr) + .SingleAsync(); + return new CreditNote(p, billingData, data, underDeliveries); + } + + protected override async Task LoadData(AppDbContext ctx) { + await base.LoadData(ctx); + var season = Payment.Variant.Season; + if (ConsiderCustomModifiers) { + CustomPayment = await ctx.CustomPayments.FindAsync(Payment.Year, Payment.MgNr); } - var mod = App.Client.IsMatzen ? ctx.Modifiers.Where(m => m.Year == season.Year && m.Name.StartsWith("Treue")).FirstOrDefault() : null; + _data ??= (await CreditNoteDeliveryData.ForPaymentVariant(ctx.CreditNoteDeliveryRows, ctx.PaymentVariants, Payment.Year, Payment.AvNr))[Member.MgNr]; + _underDeliveries ??= await ctx.GetMemberUnderDelivery(Payment.Year, Member.MgNr); + + var mod = App.Client.IsMatzen ? await ctx.Modifiers.Where(m => m.Year == season.Year && m.Name.StartsWith("Treue")).FirstOrDefaultAsync() : null; if (CustomPayment?.ModComment != null) { MemberModifier = CustomPayment.ModComment; } else if (mod != null) { @@ -57,32 +84,28 @@ namespace Elwig.Documents { } else { MemberModifier = "Sonstige Zu-/Abschläge"; } - Text = App.Client.TextCreditNote; - DocumentId = $"Tr.-Gutschr. " + (p.Credit != null ? $"{p.Credit.Year}/{p.Credit.TgNr:000}" : p.MgNr); - CurrencySymbol = season.Currency.Symbol ?? season.Currency.Code; - Precision = season.Precision; - if (considerTotalPenalty) { - var total = data.Rows.SelectMany(r => r.Buckets).Sum(b => b.Value); - var totalUnderDelivery = total - p.Member.BusinessShares * season.MinKgPerBusinessShare; + if (ConsiderTotalPenalty) { + var total = _data.Rows.SelectMany(r => r.Buckets).Sum(b => b.Value); + var totalUnderDelivery = total - Member.BusinessShares * season.MinKgPerBusinessShare; MemberTotalUnderDelivery = totalUnderDelivery < 0 ? totalUnderDelivery * (season.PenaltyPerKg ?? 0) - (season.PenaltyAmount ?? 0) - (season.PenaltyPerBsAmount * Math.Floor(-(decimal)totalUnderDelivery / season.MinKgPerBusinessShare) ?? 0) : 0; if (total == 0) - MemberTotalUnderDelivery -= (season.PenaltyNone ?? 0) + (season.PenaltyPerBsNone * p.Member.BusinessShares ?? 0); + MemberTotalUnderDelivery -= (season.PenaltyNone ?? 0) + (season.PenaltyPerBsNone * Member.BusinessShares ?? 0); } - if (considerAutoBusinessShares) { + if (ConsiderAutoBusinessShares) { var fromDate = $"{season.Year}-01-01"; var toDate = $"{season.Year}-12-31"; - MemberAutoBusinessShares = ctx.MemberHistory - .Where(h => h.MgNr == p.Member.MgNr && h.Type == "auto") + MemberAutoBusinessShares = await ctx.MemberHistory + .Where(h => h.MgNr == Member.MgNr && h.Type == "auto") .Where(h => h.DateString.CompareTo(fromDate) >= 0 && h.DateString.CompareTo(toDate) <= 0) - .Sum(h => h.BusinessShares); + .SumAsync(h => h.BusinessShares); MemberAutoBusinessSharesAmount = MemberAutoBusinessShares * (-season.BusinessShareValue ?? 0); } - if (considerContractPenalties) { - var varieties = ctx.WineVarieties.ToDictionary(v => v.SortId, v => v); - var attributes = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a); - var comTypes = ctx.AreaCommitmentTypes.ToDictionary(t => t.VtrgId, t => t); - MemberUnderDeliveries = underDeliveries? + if (ConsiderContractPenalties) { + var varieties = await ctx.WineVarieties.ToDictionaryAsync(v => v.SortId, v => v); + var attributes = await ctx.WineAttributes.ToDictionaryAsync(a => a.AttrId, a => a); + var comTypes = await ctx.AreaCommitmentTypes.ToDictionaryAsync(t => t.VtrgId, t => t); + MemberUnderDeliveries = _underDeliveries? .OrderBy(u => u.Key) .Select(u => ( varieties[u.Key[..2]].Name + (u.Key.Length > 2 ? " " + attributes[u.Key[2..]].Name : ""), @@ -104,8 +127,9 @@ namespace Elwig.Documents { } protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) { + if (_data == null) throw new Exception("Call LoadData before RenderBody"); base.RenderBody(doc, pdf); - doc.Add(NewCreditTable(Data)); + doc.Add(NewCreditTable(_data)); var div = new Table(ColsMM(60, 105)) .SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout() @@ -131,7 +155,7 @@ namespace Elwig.Documents { .SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE) .SetKeepTogether(true); - var sum = Data.Rows.Sum(p => p.Amount); + var sum = _data.Rows.Sum(p => p.Amount); if (Payment == null) { tbl1.AddCells(FormatRow("Gesamt", sum, bold: true, noTopBorder: true)); } else { @@ -139,7 +163,7 @@ namespace Elwig.Documents { if (Payment.NetAmount != Payment.Amount) { tbl1.AddCells(FormatRow("Zwischensumme", Payment.NetAmount, noTopBorder: noBorder)); noBorder = false; - tbl1.AddCells(FormatRow(MemberModifier, Payment.Amount - Payment.NetAmount, add: true)); + tbl1.AddCells(FormatRow(MemberModifier ?? "", Payment.Amount - Payment.NetAmount, add: true)); } if (Credit == null) { tbl1.AddCells(FormatRow("Gesamtbetrag", Payment.Amount, bold: true, noTopBorder: noBorder)); diff --git a/Elwig/Documents/DeliveryConfirmation.cs b/Elwig/Documents/DeliveryConfirmation.cs index 38c32ce..5e828c2 100644 --- a/Elwig/Documents/DeliveryConfirmation.cs +++ b/Elwig/Documents/DeliveryConfirmation.cs @@ -5,33 +5,48 @@ 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.Threading.Tasks; namespace Elwig.Documents { public class DeliveryConfirmation : BusinessDocument { public new static string Name => "Anlieferungsbestätigung"; - public Season Season; - public DeliveryConfirmationDeliveryData Data; + private readonly int _year; + public Season? Season; + public int MemberDeliveredWeight; + public DeliveryConfirmationDeliveryData? Data; public string? Text = App.Client.TextDeliveryConfirmation; - public Dictionary MemberBuckets; - public List MemberStats; + public Dictionary MemberBuckets = []; + public List MemberStats = []; - public DeliveryConfirmation(AppDbContext ctx, int year, Member m, DeliveryConfirmationDeliveryData data) : + public DeliveryConfirmation(int year, Member m, DeliveryConfirmationDeliveryData? data = null) : base($"{Name} {year}", m) { - Season = ctx.Seasons.Find(year) ?? throw new ArgumentException("invalid season"); + _year = year; ShowDateAndLocation = true; UseBillingAddress = true; - DocumentId = $"Anl.-Best. {Season.Year}/{m.MgNr}"; + DocumentId = $"Anl.-Best. {_year}/{m.MgNr}"; Data = data; - MemberBuckets = ctx.GetMemberBuckets(Season.Year, m.MgNr).GetAwaiter().GetResult(); - MemberStats = AppDbContext.GetMemberStats(Season.Year, m.MgNr).GetAwaiter().GetResult(); + } + + protected override async Task LoadData(AppDbContext ctx) { + await base.LoadData(ctx); + Season = ctx.Seasons.Find(_year) ?? throw new ArgumentException("invalid season"); + MemberDeliveredWeight = await ctx.Deliveries + .Where(d => d.Year == Season.Year && d.MgNr == Member.MgNr) + .SelectMany(d => d.Parts) + .SumAsync(p => p.Weight); + MemberBuckets = await ctx.GetMemberBuckets(Season.Year, Member.MgNr); + MemberStats = await AppDbContext.GetMemberStats(Season.Year, Member.MgNr); + Data ??= await DeliveryConfirmationDeliveryData.ForMember(ctx.DeliveryParts, Season.Year, Member); } protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) { + if (Data == null) throw new Exception("Call LoadData before BeforeRenderBody"); base.BeforeRenderBody(doc, pdf); var firstDay = Data.Rows.MinBy(r => r.Date)?.Date; var lastDay = Data.Rows.MaxBy(r => r.Date)?.Date; @@ -42,12 +57,13 @@ namespace Elwig.Documents { } protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) { + if (Season == null || Data == null) throw new Exception("Call LoadData before RenderBody"); base.RenderBody(doc, pdf); doc.Add(NewDeliveryListTable(Data)); doc.Add(NewWeightsTable(MemberStats) .SetMarginTopMM(10).SetKeepTogether(true)); - doc.Add(NewBucketTable(Season, MemberBuckets, includePayment: true) + doc.Add(NewBucketTable(Season, MemberBuckets, MemberDeliveredWeight, includePayment: true) .SetMarginTopMM(10).SetKeepTogether(true)); if (Text != null) { diff --git a/Elwig/Documents/DeliveryNote.cs b/Elwig/Documents/DeliveryNote.cs index d3e8c23..93f87dc 100644 --- a/Elwig/Documents/DeliveryNote.cs +++ b/Elwig/Documents/DeliveryNote.cs @@ -5,10 +5,12 @@ using iText.Layout.Borders; using iText.Layout.Element; using iText.Layout.Layout; 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 DeliveryNote : BusinessDocument { @@ -17,7 +19,8 @@ namespace Elwig.Documents { public Delivery Delivery; public string? Text; - public Dictionary MemberBuckets; + public int MemberDeliveredWeight; + public Dictionary MemberBuckets = []; // 0 - none // 1 - GA only @@ -25,7 +28,7 @@ namespace Elwig.Documents { // 3 - full public int DisplayStats = App.Client.ModeDeliveryNoteStats; - public DeliveryNote(Delivery d, AppDbContext? ctx = null) : + public DeliveryNote(Delivery d) : base($"{Name} Nr. {d.LsNr}", d.Member) { UseBillingAddress = true; ShowDateAndLocation = true; @@ -34,7 +37,34 @@ namespace Elwig.Documents { DocumentId = d.LsNr; Date = DateOnly.FromDateTime(d.ModifiedAt); IsDoublePaged = true; - MemberBuckets = ctx?.GetMemberBuckets(d.Year, d.Member.MgNr).GetAwaiter().GetResult() ?? []; + } + + public static async Task Initialize(int year, int did) { + using var ctx = new AppDbContext(); + await ctx.WineOrigins.LoadAsync(); + var d = await ctx.Deliveries + .Where(d => d.Year == year && d.DId == did) + .Include(d => d.Parts).ThenInclude(p => p.PartModifiers) + .SingleAsync(); + return new DeliveryNote(d); + } + + public static async Task Initialize(string lsnr) { + using var ctx = new AppDbContext(); + await ctx.WineOrigins.LoadAsync(); + var d = await ctx.Deliveries + .Where(d => d.LsNr == lsnr) + .Include(d => d.Parts).ThenInclude(p => p.PartModifiers) + .SingleAsync(); + return new DeliveryNote(d); + } + + protected override async Task LoadData(AppDbContext ctx) { + await base.LoadData(ctx); + MemberDeliveredWeight = await ctx.DeliveryParts + .Where(d => d.Year == Delivery.Year && d.Delivery.MgNr == Member.MgNr) + .SumAsync(p => p.Weight); + MemberBuckets = await ctx.GetMemberBuckets(Delivery.Year, Member.MgNr) ?? []; } protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) { @@ -53,7 +83,7 @@ namespace Elwig.Documents { doc.Add(new KernedParagraph($"Anmerkung zur Lieferung: {Delivery.Comment}", 10).SetMarginsMM(5, 0, 0, 0)); } if (DisplayStats > 0) { - doc.Add(NewBucketTable(Delivery.Season, MemberBuckets, isTiny: true, + doc.Add(NewBucketTable(Delivery.Season, MemberBuckets, MemberDeliveredWeight, isTiny: true, filter: DisplayStats > 2 ? null : DisplayStats == 1 ? [] : Delivery.Parts.Select(p => p.SortId).Distinct().ToList()) .SetKeepTogether(true) .SetMarginsMM(5, 0, 0, 0)); diff --git a/Elwig/Documents/Document.cs b/Elwig/Documents/Document.cs index 9be1be1..78836da 100644 --- a/Elwig/Documents/Document.cs +++ b/Elwig/Documents/Document.cs @@ -128,6 +128,8 @@ namespace Elwig.Documents { } } + protected virtual async Task LoadData(AppDbContext ctx) { } + protected virtual void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) { } protected virtual void RenderBody(iText.Layout.Document doc, PdfDocument pdf) { } @@ -136,7 +138,7 @@ namespace Elwig.Documents { return new KernedParagraph(App.Client.NameFull, 10); } - public async Task Generate(CancellationToken? cancelToken = null, IProgress? progress = null) { + public async Task Generate(AppDbContext ctx, CancellationToken? cancelToken = null, IProgress? progress = null) { if (_pdfFile != null) return; progress?.Report(0.0); @@ -181,6 +183,7 @@ namespace Elwig.Documents { merger.Merge(src, 1, src.GetNumberOfPages()); p += src.GetNumberOfPages(); } else { + await doc.LoadData(ctx); int pageNum = doc.Render(tmpPdf.FilePath); if (IsDoublePaged && doc is Letterhead) { using var reader = new PdfReader(tmpPdf.FilePath); @@ -233,6 +236,7 @@ namespace Elwig.Documents { throw new OperationCanceledException("Dokumentenerzeugung abgebrochen!"); var pdf = new TempFile("pdf"); try { + await LoadData(ctx); TotalPages = Render(pdf.FilePath); } catch { pdf.Dispose(); diff --git a/Elwig/Documents/MemberDataSheet.cs b/Elwig/Documents/MemberDataSheet.cs index 50a63e5..fde9036 100644 --- a/Elwig/Documents/MemberDataSheet.cs +++ b/Elwig/Documents/MemberDataSheet.cs @@ -5,32 +5,55 @@ 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 Dictionary MemberBuckets; - public List ActiveAreaCommitments; + public Season? Season; + public int MemberDeliveredWeight; + public Dictionary MemberBuckets = []; + public List ActiveAreaCommitments = []; - public MemberDataSheet(Member m, AppDbContext ctx) : + public MemberDataSheet(Member m) : base($"{Name} {m.AdministrativeName}", m) { DocumentId = $"{Name} {m.MgNr}"; - Season = ctx.Seasons.ToList().MaxBy(s => s.Year) ?? throw new ArgumentException("invalid season"); - MemberBuckets = ctx.GetMemberBuckets(Utils.CurrentYear, m.MgNr).GetAwaiter().GetResult(); - ActiveAreaCommitments = [.. m.ActiveAreaCommitments(ctx)]; + } + + public static async Task Initialize(int mgnr) { + using var ctx = new AppDbContext(); + return new MemberDataSheet(await ctx.Members + .Include(m => m.EmailAddresses) + .Include(m => m.TelephoneNumbers) + .Where(m => m.MgNr == mgnr) + .SingleAsync()); + } + + protected override async Task LoadData(AppDbContext ctx) { + await base.LoadData(ctx); + Season = await ctx.Seasons.OrderBy(s => s.Year).LastOrDefaultAsync() ?? 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().SetMarginBottomMM(5)); - doc.Add(NewBucketTable(Season, MemberBuckets, includeDelivery: false)); + 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) { @@ -38,7 +61,7 @@ namespace Elwig.Documents { 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()); + doc.Add(NewAreaComTable(ActiveAreaCommitments)); } } @@ -52,7 +75,7 @@ namespace Elwig.Documents { .SetPaddingRightMM(0); } - protected Table NewMemberData() { + 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) @@ -117,7 +140,7 @@ namespace Elwig.Documents { .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)) + .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)) @@ -134,8 +157,8 @@ namespace Elwig.Documents { return tbl; } - protected Table NewAreaComTable() { - var areaComs = ActiveAreaCommitments.GroupBy(a => a.AreaComType).Select(group => new { + protected Table NewAreaComTable(IEnumerable 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) @@ -177,7 +200,7 @@ namespace Elwig.Documents { } tbl.AddCell(NewTd("Gesamt:", 12, colspan: 2, bold: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1)); - tbl.AddCell(NewTd($"{ActiveAreaCommitments.Sum(a => a.Area):N0}", 12, colspan: 2, right: true, 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; diff --git a/Elwig/Documents/PaymentVariantSummary.cs b/Elwig/Documents/PaymentVariantSummary.cs index a994097..2b156aa 100644 --- a/Elwig/Documents/PaymentVariantSummary.cs +++ b/Elwig/Documents/PaymentVariantSummary.cs @@ -7,40 +7,60 @@ 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.Threading.Tasks; namespace Elwig.Documents { public class PaymentVariantSummary : Document { public new static string Name => "Auszahlungsvariante"; - public PaymentVariantSummaryData Data; + public PaymentVariantSummaryData? Data; public PaymentVar Variant; public BillingData BillingData; public string CurrencySymbol; public int MemberNum; public int DeliveryNum; public int DeliveryPartNum; - public List ModifierStat; - public Dictionary Modifiers; + public List? ModifierStat; + public Dictionary? Modifiers; - public PaymentVariantSummary(PaymentVar v, PaymentVariantSummaryData data) : + private List _credits = []; + private List _parts = []; + + public PaymentVariantSummary(PaymentVar v, PaymentVariantSummaryData? data = null) : base($"{Name} {v.Year} - {v.Name}") { Variant = v; BillingData = BillingData.FromJson(v.Data); Data = data; CurrencySymbol = v.Season.Currency.Symbol ?? v.Season.Currency.Code; - MemberNum = v.Credits.Count; + } + + public static async Task Initialize(int year, int avnr, PaymentVariantSummaryData? data = null) { + using var ctx = new AppDbContext(); + var v = await ctx.PaymentVariants + .Where(v => v.Year == year && v.AvNr == avnr) + .SingleAsync(); + return new PaymentVariantSummary(v, data); + } + + protected override async Task LoadData(AppDbContext ctx) { + _credits = await ctx.Credits.Where(c => c.Year == Variant.Year && c.AvNr == Variant.AvNr).ToListAsync(); + _parts = await ctx.PaymentDeliveryParts.Where(p => p.Year == Variant.Year && p.AvNr == Variant.AvNr).ToListAsync(); + MemberNum = _credits.Count; IsPreview = MemberNum == 0; - DeliveryNum = v.DeliveryPartPayments.DistinctBy(p => p.DeliveryPart.Delivery).Count(); - DeliveryPartNum = v.DeliveryPartPayments.Count; - ModifierStat = AppDbContext.GetModifierStats(v.Year, v.AvNr).GetAwaiter().GetResult(); - Modifiers = v.Season.Modifiers.ToDictionary(m => m.ModId); + DeliveryNum = await ctx.Deliveries.Where(d => d.Year == Variant.Year).CountAsync(); + DeliveryPartNum = await ctx.DeliveryParts.Where(d => d.Year == Variant.Year).CountAsync(); + Data ??= await PaymentVariantSummaryData.ForPaymentVariant(Variant, ctx.PaymentVariantSummaryRows); + ModifierStat = await AppDbContext.GetModifierStats(Variant.Year, Variant.AvNr); + Modifiers = await ctx.Modifiers.Where(m => m.Year == Variant.Year).ToDictionaryAsync(m => m.ModId); } protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) { + if (Data == null || Modifiers == null || ModifierStat == null) throw new Exception("Call LoadData before RenderBody"); base.RenderBody(doc, pdf); doc.Add(new KernedParagraph($"{Name} Lese {Variant.Year}", 24) .SetTextAlignment(TextAlignment.CENTER).SetFont(BF) @@ -48,10 +68,10 @@ namespace Elwig.Documents { doc.Add(new KernedParagraph(Variant.Name, 14) .SetTextAlignment(TextAlignment.CENTER).SetFont(BF) .SetMarginsMM(0, 0, 10, 0)); - doc.Add(NewVariantStatTable().SetMarginBottomMM(10)); - doc.Add(NewModifierStatTable()); + doc.Add(NewVariantStatTable(Data).SetMarginBottomMM(10)); + doc.Add(NewModifierStatTable(Modifiers, ModifierStat)); doc.Add(new AreaBreak(AreaBreakType.NEXT_PAGE)); - doc.Add(NewPriceTable()); + doc.Add(NewPriceTable(Data)); } protected Cell NewSectionHdr(string text, int colspan = 1, bool borderLeft = false) { @@ -67,33 +87,33 @@ namespace Elwig.Documents { .SetBorderLeft(borderLeft ? new SolidBorder(BorderThickness) : Border.NO_BORDER); } - protected Table NewVariantStatTable() { + protected Table NewVariantStatTable(PaymentVariantSummaryData data) { var tbl = new Table(ColsMM(20, 30, 4.5, 4.5, 23.5, 47.5, 15, 20)) .SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout() .SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE) .SetBorder(new SolidBorder(BorderThickness)); - //var sum1 = Variant.DeliveryPartPayments.Sum(p => p.NetAmount); - //var sum2 = Variant.Credits.Sum(p => p.); //Variant.MemberPayments.Sum(p => p.Amount); - var deliveryModifiers = Variant.DeliveryPartPayments.Sum(p => p.Amount - p.NetAmount); - var memberModifiers = Variant.Credits.Sum(c => c.Payment.Amount - c.Payment.NetAmount); - var sum2 = Variant.Credits.Sum(p => p.NetAmount); + //var sum1 = _parts.Sum(p => p.NetAmount); + //var sum2 = _credits.Sum(p => p.); //Variant.MemberPayments.Sum(p => p.Amount); + var deliveryModifiers = _parts.Sum(p => p.Amount - p.NetAmount); + var memberModifiers = _credits.Sum(c => c.Payment.Amount - c.Payment.NetAmount); + var sum2 = _credits.Sum(p => p.NetAmount); var sum1 = sum2 - deliveryModifiers - memberModifiers; - var payed = -Variant.Credits.Sum(p => p.PrevNetAmount ?? 0m); - var netSum = Variant.Credits.Sum(p => p.NetAmount) - Variant.Credits.Sum(p => p.PrevNetAmount ?? 0m); - var vat = Variant.Credits.Sum(p => p.VatAmount); - var grossSum = Variant.Credits.Sum(p => p.GrossAmount); - var totalMods = Variant.Credits.Sum(p => p.Modifiers ?? 0m); - var considered = -Variant.Credits.Sum(p => p.PrevModifiers ?? 0m); - var totalSum = Variant.Credits.Sum(p => p.Amount); + var payed = -_credits.Sum(p => p.PrevNetAmount ?? 0m); + var netSum = _credits.Sum(p => p.NetAmount) - _credits.Sum(p => p.PrevNetAmount ?? 0m); + var vat = _credits.Sum(p => p.VatAmount); + var grossSum = _credits.Sum(p => p.GrossAmount); + var totalMods = _credits.Sum(p => p.Modifiers ?? 0m); + var considered = -_credits.Sum(p => p.PrevModifiers ?? 0m); + var totalSum = _credits.Sum(p => p.Amount); - var weiRows = Data.Rows.Where(r => r.QualityLevel == "Wein"); + var weiRows = data.Rows.Where(r => r.QualityLevel == "Wein"); var minWei = weiRows.Min(r => r.Ungeb.MinPrice); var maxWei = weiRows.Max(r => r.Ungeb.MaxPrice); - var quwRows = Data.Rows.Where(r => r.QualityLevel != "Wein"); + var quwRows = data.Rows.Where(r => r.QualityLevel != "Wein"); var minPrice = quwRows.Min(r => r.Ungeb.MinPrice); var maxPrice = quwRows.Max(r => r.Ungeb.MaxPrice); - var gebRows = Data.Rows + var gebRows = data.Rows .Where(r => r.Geb.MaxPrice != null && r.Ungeb.MinPrice != null) .Select(r => r.Geb.MaxPrice - r.Ungeb.MinPrice); var minGeb = gebRows.Min(); @@ -191,26 +211,26 @@ namespace Elwig.Documents { .AddCell(NewTd(CurrencySymbol)) .AddCell(NewTd($"{Math.Abs(totalMods):N2}", right: true)) .AddCell(NewSectionTh("Menge (ungebunden):", borderLeft: true, borderTop: true)) - .AddCell(NewTd($"{Data.Rows.Sum(r => r.Ungeb.Weight):N0} kg", colspan: 2, right: true, borderTop: true)) + .AddCell(NewTd($"{data.Rows.Sum(r => r.Ungeb.Weight):N0} kg", colspan: 2, right: true, borderTop: true)) .AddCell(NewSectionTh("Bereits berücksichtigte Abzüge:", colspan: 2)) .AddCell(NewTd(Utils.GetSign(considered))) .AddCell(NewTd(CurrencySymbol)) .AddCell(NewTd($"{Math.Abs(considered):N2}", right: true)) .AddCell(NewSectionTh("Menge (gebunden):", borderLeft: true)) - .AddCell(NewTd($"{Data.Rows.Sum(r => r.Geb.Weight + r.LowGeb.Weight):N0} kg", colspan: 2, right: true)) + .AddCell(NewTd($"{data.Rows.Sum(r => r.Geb.Weight + r.LowGeb.Weight):N0} kg", colspan: 2, right: true)) .AddCell(NewSectionTh("Auszahlungsbetrag:", colspan: 2)) .AddCell(NewTd(borderTop: true)) .AddCell(NewTd(CurrencySymbol, borderTop: true)) .AddCell(NewTd($"{totalSum:N2}", right: true, borderTop: true)) .AddCell(NewSectionTh("Gesamtmenge:", borderLeft: true)) - .AddCell(NewTd($"{Data.Rows.Sum(r => r.Ungeb.Weight + r.LowGeb.Weight + r.Geb.Weight):N0} kg", colspan: 2, right: true, borderTop: true)); + .AddCell(NewTd($"{data.Rows.Sum(r => r.Ungeb.Weight + r.LowGeb.Weight + r.Geb.Weight):N0} kg", colspan: 2, right: true, borderTop: true)); return tbl; } - protected Table NewModifierStatTable() { + protected Table NewModifierStatTable(Dictionary modifiers, IEnumerable modStat) { var tbl = new Table(ColsMM(35, 30, 25, 25, 25, 25)) .SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout() .SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE) @@ -228,8 +248,8 @@ namespace Elwig.Documents { .AddCell(NewTh($"[{CurrencySymbol}]")) .AddCell(NewTh($"[{CurrencySymbol}]")); - foreach (var m in ModifierStat) { - var mod = Modifiers[m.ModId]; + foreach (var m in modStat) { + var mod = modifiers[m.ModId]; tbl.AddCell(NewTd(mod.Name, italic: true)) .AddCell(NewTd(mod.ValueStr, right: true)) .AddCell(NewTd($"{m.Count:N0}", right: true)) @@ -241,7 +261,7 @@ namespace Elwig.Documents { return tbl; } - protected Table NewPriceTable() { + protected Table NewPriceTable(PaymentVariantSummaryData data) { var tbl = new Table(ColsMM(25, 19, 18, 15, 18, 15, 18, 15, 22)) .SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout() .SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE); @@ -262,10 +282,10 @@ namespace Elwig.Documents { .AddHeaderCell(NewTh($"[{CurrencySymbol}]")); string? lastHdr = null; - foreach (var row in Data.Rows) { + foreach (var row in data.Rows) { var hdr = $"{row.Variety}{(row.Attribute != null ? " / " : "")}{row.Attribute}{(row.Cultivation != null ? " / " : "")}{row.Cultivation}"; if (lastHdr != hdr) { - var rows = Data.Rows + var rows = data.Rows .Where(r => r.Variety == row.Variety && r.Attribute == row.Attribute && r.Cultivation == row.Cultivation) .ToList(); var border = lastHdr != null; diff --git a/Elwig/Elwig.csproj b/Elwig/Elwig.csproj index b3fe799..766e1f3 100644 --- a/Elwig/Elwig.csproj +++ b/Elwig/Elwig.csproj @@ -29,7 +29,6 @@ - diff --git a/Elwig/Helpers/AppDbContext.cs b/Elwig/Helpers/AppDbContext.cs index 6006449..b18ebd8 100644 --- a/Elwig/Helpers/AppDbContext.cs +++ b/Elwig/Helpers/AppDbContext.cs @@ -119,11 +119,55 @@ namespace Elwig.Helpers { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite(ConnectionString); - optionsBuilder.UseLazyLoadingProxies(); optionsBuilder.LogTo(Log, LogLevel.Information); base.OnConfiguring(optionsBuilder); } + protected override void OnModelCreating(ModelBuilder modelBuilder) { + modelBuilder.Entity().Navigation(k => k.AtKg).AutoInclude(); + modelBuilder.Entity().Navigation(k => k.Gl).AutoInclude(); + modelBuilder.Entity().Navigation(k => k.Gem).AutoInclude(); + modelBuilder.Entity().Navigation(p => p.Country).AutoInclude(); + modelBuilder.Entity().Navigation(p => p.AtPlz).AutoInclude(); + modelBuilder.Entity().Navigation(p => p.AtPlz).AutoInclude(); + modelBuilder.Entity().Navigation(p => p.Ort).AutoInclude(); + modelBuilder.Entity().Navigation(m => m.DefaultWbKg).AutoInclude(); + modelBuilder.Entity().Navigation(m => m.Country).AutoInclude(); + modelBuilder.Entity().Navigation(m => m.PostalDest).AutoInclude(); + modelBuilder.Entity().Navigation(m => m.BillingAddress).AutoInclude(); + modelBuilder.Entity().Navigation(a => a.Country).AutoInclude(); + modelBuilder.Entity().Navigation(a => a.PostalDest).AutoInclude(); + modelBuilder.Entity().Navigation(m => m.Season).AutoInclude(); + modelBuilder.Entity().Navigation(s => s.Currency).AutoInclude(); + modelBuilder.Entity().Navigation(v => v.Season).AutoInclude(); + modelBuilder.Entity().Navigation(p => p.Variant).AutoInclude(); + modelBuilder.Entity().Navigation(c => c.Payment).AutoInclude(); + modelBuilder.Entity().Navigation(d => d.Member).AutoInclude(); + modelBuilder.Entity().Navigation(d => d.Season).AutoInclude(); + modelBuilder.Entity().Navigation(d => d.Branch).AutoInclude(); + modelBuilder.Entity().Navigation(p => p.Quality).AutoInclude(); + modelBuilder.Entity().Navigation(p => p.Variety).AutoInclude(); + modelBuilder.Entity().Navigation(p => p.Attribute).AutoInclude(); + modelBuilder.Entity().Navigation(p => p.Cultivation).AutoInclude(); + modelBuilder.Entity().Navigation(p => p.Kg).AutoInclude(); + modelBuilder.Entity().Navigation(p => p.Rd).AutoInclude(); + modelBuilder.Entity().Navigation(m => m.Modifier).AutoInclude(); + modelBuilder.Entity().Navigation(c => c.Kg).AutoInclude(); + modelBuilder.Entity().Navigation(c => c.Rd).AutoInclude(); + modelBuilder.Entity().Navigation(c => c.Contract).AutoInclude(); + modelBuilder.Entity().Navigation(c => c.WineCult).AutoInclude(); + modelBuilder.Entity().Navigation(c => c.AreaComType).AutoInclude(); + modelBuilder.Entity().Navigation(c => c.WineVar).AutoInclude(); + modelBuilder.Entity().Navigation(c => c.WineAttr).AutoInclude(); + modelBuilder.Entity().Navigation(c => c.Credit).AutoInclude(); + modelBuilder.Entity().Navigation(c => c.Member).AutoInclude(); + modelBuilder.Entity().Navigation(c => c.Variant).AutoInclude(); + modelBuilder.Entity().Navigation(a => a.Member).AutoInclude(); + modelBuilder.Entity().Navigation(a => a.Schedule).AutoInclude(); + modelBuilder.Entity().Navigation(a => a.Variety).AutoInclude(); + modelBuilder.Entity().Navigation(s => s.Branch).AutoInclude(); + } + public override void Dispose() { base.Dispose(); LogFile?.Dispose(); @@ -399,10 +443,12 @@ namespace Elwig.Helpers { var paymentBuckets = await GetMemberPaymentBuckets(year, mgnr, cnx); if (ownCnx) await cnx.DisposeAsync(); + var varieties = await WineVarieties.ToDictionaryAsync(v => v.SortId); + var attributes = await WineAttributes.ToDictionaryAsync(a => a.AttrId); var buckets = new Dictionary(); foreach (var id in rightsAndObligations.Keys.Union(deliveryBuckets.Keys).Union(paymentBuckets.Keys)) { - var variety = await WineVarieties.FindAsync(id[..2]); - var attribute = await WineAttributes.FindAsync(id[2..]); + var variety = varieties.GetValueOrDefault(id[..2]); + var attribute = attributes.GetValueOrDefault(id[2..]); var name = (variety?.Name ?? "") + (id[2..] == "_" ? " (kein Qual.Wein)" : attribute != null ? $" ({attribute})" : ""); buckets[id] = new( name, diff --git a/Elwig/Helpers/Billing/Billing.cs b/Elwig/Helpers/Billing/Billing.cs index f322713..aa53d68 100644 --- a/Elwig/Helpers/Billing/Billing.cs +++ b/Elwig/Helpers/Billing/Billing.cs @@ -21,7 +21,7 @@ namespace Elwig.Helpers.Billing { using var ctx = new AppDbContext(); Season = ctx.Seasons.Find(Year)!; Attributes = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a.Name); - Modifiers = ctx.Modifiers.Where(m => m.Year == Year).Include(m => m.Season).ToDictionary(m => m.ModId, m => (m.Abs, m.Rel)); + Modifiers = ctx.Modifiers.Where(m => m.Year == Year).ToDictionary(m => m.ModId, m => (m.Abs, m.Rel)); AreaComTypes = ctx.AreaCommitmentTypes.ToDictionary(v => v.VtrgId, v => (v.SortId, v.AttrId, v.Discriminator, v.MinKgPerHa, v.PenaltyAmount)); } diff --git a/Elwig/Helpers/Billing/BillingVariant.cs b/Elwig/Helpers/Billing/BillingVariant.cs index da79005..a6613c8 100644 --- a/Elwig/Helpers/Billing/BillingVariant.cs +++ b/Elwig/Helpers/Billing/BillingVariant.cs @@ -16,7 +16,7 @@ namespace Elwig.Helpers.Billing { public BillingVariant(int year, int avnr) : base(year) { AvNr = avnr; using var ctx = new AppDbContext(); - PaymentVariant = ctx.PaymentVariants.Include(v => v.Season).Where(v => v.Year == Year && v.AvNr == AvNr).Single() ?? throw new ArgumentException("PaymentVar not found"); + PaymentVariant = ctx.PaymentVariants.Where(v => v.Year == Year && v.AvNr == AvNr).Single(); Data = PaymentBillingData.FromJson(PaymentVariant.Data, Utils.GetVaributes(ctx, Year, onlyDelivered: false)); } diff --git a/Elwig/Helpers/Export/ElwigData.cs b/Elwig/Helpers/Export/ElwigData.cs index 552b5cf..9a7191c 100644 --- a/Elwig/Helpers/Export/ElwigData.cs +++ b/Elwig/Helpers/Export/ElwigData.cs @@ -860,7 +860,7 @@ namespace Elwig.Helpers.Export { ["ried"] = p.Rd?.Name, ["net_weight"] = p.IsNetWeight, ["manual_weighing"] = p.IsManualWeighing, - ["modids"] = new JsonArray(p.Modifiers.Select(m => (JsonNode)m.ModId).ToArray()), + ["modids"] = new JsonArray(p.PartModifiers.Select(m => (JsonNode)m.ModId).ToArray()), ["comment"] = p.Comment, ["created_at"] = $"{p.CreatedAt:yyyy-MM-ddTHH:mm:ssK}", ["modified_at"] = $"{p.ModifiedAt:yyyy-MM-ddTHH:mm:ssK}", diff --git a/Elwig/Helpers/Utils.cs b/Elwig/Helpers/Utils.cs index f48a2ea..681ec3b 100644 --- a/Elwig/Helpers/Utils.cs +++ b/Elwig/Helpers/Utils.cs @@ -557,7 +557,9 @@ namespace Elwig.Helpers { "Vorläufiges Dokument", MessageBoxButton.OK, MessageBoxImage.Error); return; } - await doc.Generate(); + using (var ctx = new AppDbContext()) { + await doc.Generate(ctx); + } await doc.Print(); } else if (mode == ExportMode.Email && emailData is (Member, string, string) e) { if (doc.IsPreview) { @@ -565,7 +567,9 @@ namespace Elwig.Helpers { "Vorläufiges Dokument", MessageBoxButton.OK, MessageBoxImage.Error); return; } - await doc.Generate(); + using (var ctx = new AppDbContext()) { + await doc.Generate(ctx); + } var success = await SendEmail(e.Member, e.Subject, e.Text, [doc]); if (success) MessageBox.Show("Die E-Mail wurde erfolgreich verschickt!\n\nEs kann einige Minuten dauern, bis die E-Mail im Posteingang des Empfängers aufscheint.", "E-Mail verschickt", @@ -582,12 +586,16 @@ namespace Elwig.Helpers { Title = $"{doc.Title} speichern unter - Elwig" }; if (d.ShowDialog() == true) { - await doc.Generate(); + using (var ctx = new AppDbContext()) { + await doc.Generate(ctx); + } doc.SaveTo(d.FileName); Process.Start("explorer.exe", d.FileName); } } else { - await doc.Generate(); + using (var ctx = new AppDbContext()) { + await doc.Generate(ctx); + } doc.Show(); } } diff --git a/Elwig/Models/Dtos/CreditNoteDeliveryData.cs b/Elwig/Models/Dtos/CreditNoteDeliveryData.cs index eabff29..7ad0b3d 100644 --- a/Elwig/Models/Dtos/CreditNoteDeliveryData.cs +++ b/Elwig/Models/Dtos/CreditNoteDeliveryData.cs @@ -28,9 +28,9 @@ namespace Elwig.Models.Dtos { } public static async Task> ForPaymentVariant(DbSet table, DbSet paymentVariants, int year, int avnr) { - var variant = await paymentVariants.FindAsync(year, avnr); + var variant = await paymentVariants.Include(v => v.Season.Modifiers).SingleAsync(v => v.Year == year && v.AvNr == avnr); BillingData? varData = null; - try { varData = variant != null ? BillingData.FromJson(variant.Data) : null; } catch { } + try { varData = variant.Data != null ? BillingData.FromJson(variant.Data) : null; } catch { } return (await FromDbSet(table, year, avnr)) .GroupBy( r => new { r.Year, r.AvNr, r.MgNr, r.TgNr, r.DId, r.DPNr }, diff --git a/Elwig/Models/Dtos/DeliveryAncmtListData.cs b/Elwig/Models/Dtos/DeliveryAncmtListData.cs index 5165d12..bc43fbf 100644 --- a/Elwig/Models/Dtos/DeliveryAncmtListData.cs +++ b/Elwig/Models/Dtos/DeliveryAncmtListData.cs @@ -28,12 +28,7 @@ namespace Elwig.Models.Dtos { } public static async Task FromQuery(IQueryable query, List filterNames) { - return new((await query - .Include(a => a.Schedule.Branch) - .Include(a => a.Member) - .Include(a => a.Variety) - .AsSplitQuery() - .ToListAsync()).Select(d => new DeliveryAncmtListRow(d)), filterNames); + return new((await query.ToListAsync()).Select(d => new DeliveryAncmtListRow(d)), filterNames); } } diff --git a/Elwig/Models/Dtos/DeliveryConfirmationDeliveryData.cs b/Elwig/Models/Dtos/DeliveryConfirmationDeliveryData.cs index 4dac291..94357f5 100644 --- a/Elwig/Models/Dtos/DeliveryConfirmationDeliveryData.cs +++ b/Elwig/Models/Dtos/DeliveryConfirmationDeliveryData.cs @@ -52,12 +52,8 @@ namespace Elwig.Models.Dtos { if (mgnr != null) q = q.Where(p => p.Delivery.MgNr == mgnr); await q .Include(p => p.Delivery) - .Include(p => p.Variety) - .Include(p => p.Attribute) - .Include(p => p.Quality) .Include(p => p.Buckets) - .Include(p => p.PartModifiers) - .ThenInclude(m => m.Modifier) + .Include(p => p.PartModifiers).ThenInclude(m => m.Modifier) .LoadAsync(); return await table.FromSqlRaw($""" SELECT p.* @@ -65,7 +61,7 @@ namespace Elwig.Models.Dtos { JOIN delivery_part p ON (p.year, p.did, p.dpnr) = (v.year, v.did, v.dpnr) WHERE (p.year = {y} OR {y} IS NULL) AND (v.mgnr = {m} OR {m} IS NULL) ORDER BY p.year, v.mgnr, v.sortid, v.abgewertet ASC, v.attribute_prio DESC, COALESCE(v.attrid, '~'), v.kmw DESC, v.lsnr, v.dpnr - """).ToListAsync(); + """).IgnoreAutoIncludes().ToListAsync(); } } diff --git a/Elwig/Models/Dtos/DeliveryJournalData.cs b/Elwig/Models/Dtos/DeliveryJournalData.cs index 79a40aa..831c76c 100644 --- a/Elwig/Models/Dtos/DeliveryJournalData.cs +++ b/Elwig/Models/Dtos/DeliveryJournalData.cs @@ -40,12 +40,7 @@ namespace Elwig.Models.Dtos { .Include(p => p.Delivery.Member.Branch) .Include(p => p.Delivery.Branch) .Include(p => p.PartModifiers).ThenInclude(m => m.Modifier) - .Include(p => p.Variety) - .Include(p => p.Attribute) - .Include(p => p.Cultivation) .Include(p => p.Origin) - .Include(p => p.Quality) - .AsSplitQuery() .ToListAsync()).Select(d => new DeliveryJournalRow(d)), filterNames); } } diff --git a/Elwig/Models/Dtos/MemberListData.cs b/Elwig/Models/Dtos/MemberListData.cs index e276e67..f38f684 100644 --- a/Elwig/Models/Dtos/MemberListData.cs +++ b/Elwig/Models/Dtos/MemberListData.cs @@ -47,15 +47,11 @@ namespace Elwig.Models.Dtos { } public static async Task FromQuery(IQueryable query, List filterNames, IEnumerable filterAreaCom) { - var areaComs = await query.ToDictionaryAsync(m => m.MgNr, m => Utils.ActiveAreaCommitments(m.AreaCommitments)); + var areaComs = await query.Include(m => m.AreaCommitments).ToDictionaryAsync(m => m.MgNr, m => Utils.ActiveAreaCommitments(m.AreaCommitments)); return new((await query - .Include(m => m.DefaultWbKg!.AtKg) .Include(m => m.Branch) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort) .Include(m => m.TelephoneNumbers) .Include(m => m.EmailAddresses) - .AsSplitQuery() .ToListAsync()).Select(m => new MemberListRow(m, areaComs[m.MgNr].Sum(c => c.Area), areaComs[m.MgNr].Where(c => filterAreaCom.Contains(c.VtrgId)).GroupBy(c => c.VtrgId).ToDictionary(g => g.Key, g => g.Sum(c => c.Area)))), diff --git a/Elwig/Models/Entities/Delivery.cs b/Elwig/Models/Entities/Delivery.cs index 0abe63e..ef02575 100644 --- a/Elwig/Models/Entities/Delivery.cs +++ b/Elwig/Models/Entities/Delivery.cs @@ -106,21 +106,21 @@ namespace Elwig.Models.Entities { [InverseProperty(nameof(DeliveryPart.Delivery))] public virtual ICollection Parts { get; private set; } = null!; [NotMapped] - public IEnumerable FilteredParts => PartFilter == null ? Parts : Parts.Where(p => PartFilter(p)); + public IEnumerable FilteredParts => PartFilter == null ? Parts : Parts.Where(p => PartFilter(p)); [NotMapped] public Predicate? PartFilter { get; set; } - public int Weight => Parts.Select(p => p.Weight).Sum(); - public int FilteredWeight => FilteredParts.Select(p => p.Weight).Sum(); + public int Weight => Parts.Sum(p => p.Weight); + public int FilteredWeight => FilteredParts.Sum(p => p.Weight); public IEnumerable Vaributes => Parts .GroupBy(p => (p.SortId, p.AttrId, p.CultId)) - .OrderByDescending(g => g.Select(p => p.Weight).Sum()) + .OrderByDescending(g => g.Sum(p => p.Weight)) .Select(g => new RawVaribute(g.Key.SortId, g.Key.AttrId, g.Key.CultId)); public IEnumerable FilteredVaributes => FilteredParts .GroupBy(p => (p.SortId, p.AttrId, p.CultId)) - .OrderByDescending(g => g.Select(p => p.Weight).Sum()) + .OrderByDescending(g => g.Sum(p => p.Weight)) .Select(g => new RawVaribute(g.Key.SortId, g.Key.AttrId, g.Key.CultId)); public string VaributeString => string.Join(", ", Vaributes); public string FilteredVaributeString => string.Join(", ", FilteredVaributes); @@ -153,7 +153,7 @@ namespace Elwig.Models.Entities { Member.Name, Member.MiddleName, Member.GivenName, Member.BillingAddress?.FullName, Comment }.ToList(); - list.AddRange(Parts.Select(p => p.Comment).Distinct()); + list.AddRange(FilteredParts.Select(p => p.Comment).Distinct()); return Utils.GetSearchScore(list, keywords); } } diff --git a/Elwig/Models/Entities/WineOrigin.cs b/Elwig/Models/Entities/WineOrigin.cs index 6e52d1f..fd2e420 100644 --- a/Elwig/Models/Entities/WineOrigin.cs +++ b/Elwig/Models/Entities/WineOrigin.cs @@ -27,13 +27,15 @@ namespace Elwig.Models.Entities { public virtual ICollection Gems { get; private set; } = null!; [InverseProperty(nameof(Parent))] - public virtual ICollection Children { get; private set; } = null!; + public virtual ICollection RealChildren { get; private set; } = null!; + [NotMapped] + public List Children { get; private set; } = []; public int Level => (Parent?.Level + 1) ?? 0; public string HkIdLevel => $"{new string(' ', Level * 2)}{HkId}"; - public int TotalChildNum => 1 + Children.Select(c => c.TotalChildNum).Sum(); + public int TotalChildNum => 1 + Children.Sum(c => c.TotalChildNum); private int SortKey1 => (Parent?.SortKey1 ?? 0) | (TotalChildNum << ((3 - Level) * 8)); public int SortKey => SortKey1 | ((Level < 3) ? (-1 >>> (Level * 8 + 8)) : 0); diff --git a/Elwig/Services/DeliveryService.cs b/Elwig/Services/DeliveryService.cs index b1e5a55..75ece62 100644 --- a/Elwig/Services/DeliveryService.cs +++ b/Elwig/Services/DeliveryService.cs @@ -27,10 +27,7 @@ namespace Elwig.Services { public static async Task GetMemberAsync(int mgnr) { using var ctx = new AppDbContext(); - return await ctx.Members - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.DefaultWbKg!.AtKg) - .FirstOrDefaultAsync(m => m.MgNr == mgnr); + return await ctx.Members.FirstOrDefaultAsync(m => m.MgNr == mgnr); } public static Member? GetMember(int mgnr) { @@ -71,7 +68,7 @@ namespace Elwig.Services { vm.IsNetWeight = p.IsNetWeight; vm.Modifiers.Clear(); - foreach (var m in p.Modifiers) { + foreach (var m in p.PartModifiers) { vm.Modifiers.Add((Modifier)ControlUtils.GetItemFromSourceWithPk(vm.ModifiersSource, m.Year, m.ModId)!); } @@ -472,6 +469,7 @@ namespace Elwig.Services { DeliveryPart p; using var ctx = new AppDbContext(); + using var tx = await ctx.Database.BeginTransactionAsync(); int year = oldYear ?? Utils.CurrentYear; int did = oldDid ?? await ctx.NextDId(year); int dpnr = oldDpnr ?? await ctx.NextDPNr(year, did); @@ -556,13 +554,13 @@ namespace Elwig.Services { if (originalMgNr != null && originalMgNr.Value != d.MgNr) { // update origin (KgNr), if default is selected var newKgNr = (await ctx.Members.FindAsync(d.MgNr))?.DefaultKgNr; - foreach (var part in d.Parts.Where(part => part.DPNr != dpnr && part.KgNr == originalMemberKgNr)) { - part.KgNr = newKgNr; - ctx.Update(part); - } + await ctx.DeliveryParts + .Where(p => p.Year == d.Year && p.DId == d.DId && p.DPNr != dpnr && p.KgNr == originalMemberKgNr) + .ExecuteUpdateAsync(u => u.SetProperty(p => p.KgNr, newKgNr)); } await ctx.SaveChangesAsync(); + await tx.CommitAsync(); return p; }); @@ -574,7 +572,10 @@ namespace Elwig.Services { using var ctx = new AppDbContext(); bool anyLeft = false; - var d = (await ctx.Deliveries.FindAsync(year, did))!; + var d = await ctx.Deliveries + .Where(d => d.Year == year && d.DId == did) + .Include(d => d.Parts).ThenInclude(p => p.PartModifiers) + .SingleAsync(); var lnr = await ctx.NextLNr(d.Date, d.ZwstId); n = new Delivery { Year = year, @@ -601,7 +602,11 @@ namespace Elwig.Services { anyLeft = true; p.Weight -= w; ctx.Update(p); - var s = ctx.CreateProxy(); + var s = new DeliveryPart { + SortId = null!, + QualId = null!, + HkId = null!, + }; var values = ctx.Entry(p).CurrentValues; ctx.Entry(s).CurrentValues.SetValues(values); s.Year = n.Year; @@ -633,7 +638,10 @@ namespace Elwig.Services { using var ctx = new AppDbContext(); var anyLeft = false; n = (await ctx.Deliveries.FirstAsync(d => d.LsNr == lsnr))!; - var d = (await ctx.Deliveries.FindAsync(year, did))!; + var d = await ctx.Deliveries + .Where(d => d.Year == year && d.DId == did) + .Include(d => d.Parts).ThenInclude(p => p.PartModifiers) + .SingleAsync(); var dpnr = await ctx.NextDPNr(n.Year, n.DId); foreach (var (p, w) in d.Parts.ToList().Zip(weights)) { if (w <= 0) { @@ -645,7 +653,11 @@ namespace Elwig.Services { anyLeft = true; p.Weight -= w; ctx.Update(p); - var s = ctx.CreateProxy(); + var s = new DeliveryPart { + SortId = null!, + QualId = null!, + HkId = null!, + }; var values = ctx.Entry(p).CurrentValues; ctx.Entry(s).CurrentValues.SetValues(values); s.Year = n.Year; @@ -674,7 +686,10 @@ namespace Elwig.Services { public static async Task DepreciateDelivery(int year, int did, int[] weights) { await Task.Run(async () => { using var ctx = new AppDbContext(); - var d = (await ctx.Deliveries.FindAsync(year, did))!; + var d = await ctx.Deliveries + .Where(d => d.Year == year && d.DId == did) + .Include(d => d.Parts).ThenInclude(p => p.PartModifiers) + .SingleAsync(); var dpnr = await ctx.NextDPNr(year, did); foreach (var (p, w) in d.Parts.ToList().Zip(weights)) { if (w <= 0) { @@ -686,7 +701,11 @@ namespace Elwig.Services { } else { p.Weight -= w; ctx.Update(p); - var n = ctx.CreateProxy(); + var n = new DeliveryPart { + SortId = null!, + QualId = null!, + HkId = null!, + }; var values = ctx.Entry(p).CurrentValues; ctx.Entry(n).CurrentValues.SetValues(values); n.DPNr = dpnr++; @@ -711,10 +730,8 @@ namespace Elwig.Services { Mouse.OverrideCursor = Cursors.Wait; await Task.Run(async () => { try { - using var ctx = new AppDbContext(); - var d = (await ctx.Deliveries.FindAsync(year, did))!; - using var doc = new DeliveryNote(d, ctx); - await Utils.ExportDocument(doc, mode, d.LsNr, (d.Member, $"{DeliveryNote.Name} Nr. {d.LsNr}", $"Im Anhang finden Sie den {DeliveryNote.Name} Nr. {d.LsNr}")); + using var doc = await DeliveryNote.Initialize(year, did); + await Utils.ExportDocument(doc, mode, doc.Delivery.LsNr, (doc.Member, $"{DeliveryNote.Name} Nr. {doc.Delivery.LsNr}", $"Im Anhang finden Sie den {DeliveryNote.Name} Nr. {doc.Delivery.LsNr}")); } catch (Exception exc) { MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); } @@ -792,9 +809,6 @@ namespace Elwig.Services { .Select(p => p.Delivery) .Distinct() .Include(d => d.Parts).ThenInclude(p => p.PartModifiers) - .Include(d => d.Parts).ThenInclude(p => p.Rd) - .Include(d => d.Parts).ThenInclude(p => p.Kg!.Gl) - .AsSplitQuery() .ToListAsync(); var wbKgs = list .SelectMany(d => d.Parts) diff --git a/Elwig/Services/MemberService.cs b/Elwig/Services/MemberService.cs index 849c7cf..a71f52d 100644 --- a/Elwig/Services/MemberService.cs +++ b/Elwig/Services/MemberService.cs @@ -395,8 +395,7 @@ namespace Elwig.Services { Mouse.OverrideCursor = Cursors.Wait; await Task.Run(async () => { try { - using var ctx = new AppDbContext(); - using var doc = new MemberDataSheet(m, ctx); + using var doc = new MemberDataSheet(m); await Utils.ExportDocument(doc, mode, emailData: (m, MemberDataSheet.Name, "Im Anhang finden Sie das aktuelle Stammdatenblatt")); } catch (Exception exc) { MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); @@ -414,9 +413,7 @@ namespace Elwig.Services { await b.CalculateBuckets(); App.HintContextChange(); - using var ctx = new AppDbContext(); - var data = await DeliveryConfirmationDeliveryData.ForMember(ctx.DeliveryParts, year, m); - using var doc = new DeliveryConfirmation(ctx, year, m, data); + using var doc = new DeliveryConfirmation(year, m); await Utils.ExportDocument(doc, mode, emailData: (m, $"{DeliveryConfirmation.Name} {year}", $"Im Anhang finden Sie die Anlieferungsbestätigung {year}")); } catch (Exception exc) { MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); @@ -429,16 +426,8 @@ namespace Elwig.Services { Mouse.OverrideCursor = Cursors.Wait; await Task.Run(async () => { try { - using var ctx = new AppDbContext(); - var v = (await ctx.PaymentVariants.FindAsync(year, avnr))!; - var data = await CreditNoteDeliveryData.ForPaymentVariant(ctx.CreditNoteDeliveryRows, ctx.PaymentVariants, year, avnr); - var p = (await ctx.MemberPayments.FindAsync(year, avnr, m.MgNr))!; - var b = BillingData.FromJson((await ctx.PaymentVariants.FindAsync(year, avnr))!.Data); - - using var doc = new CreditNote(ctx, p, data[m.MgNr], - b.ConsiderContractPenalties, b.ConsiderTotalPenalty, b.ConsiderAutoBusinessShares, b.ConsiderCustomModifiers, - await ctx.GetMemberUnderDelivery(year, m.MgNr)); - await Utils.ExportDocument(doc, mode, emailData: (m, $"{CreditNote.Name} {v.Name}", $"Im Anhang finden Sie die Traubengutschrift {v.Name}")); + using var doc = await CreditNote.Initialize(year, avnr, m.MgNr); + await Utils.ExportDocument(doc, mode, emailData: (m, $"{CreditNote.Name} {doc.Payment.Variant.Name}", $"Im Anhang finden Sie die Traubengutschrift {doc.Payment.Variant.Name}")); } catch (Exception exc) { MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); } @@ -520,10 +509,8 @@ namespace Elwig.Services { try { var members = await query .OrderBy(m => m.MgNr) - .Include(m => m.BillingAddress) .Include(m => m.TelephoneNumbers) .Include(m => m.EmailAddresses) - .AsSplitQuery() .ToListAsync(); using var exporter = new VCard(d.FileName); await exporter.ExportAsync(members); @@ -548,17 +535,12 @@ namespace Elwig.Services { try { var members = await query .OrderBy(m => m.MgNr) - .Include(m => m.BillingAddress) .Include(m => m.TelephoneNumbers) .Include(m => m.EmailAddresses) - .Include(m => m.DefaultWbKg!.Gl) - .AsSplitQuery() .ToListAsync(); var areaComs = await query .SelectMany(m => m.AreaCommitments) .Select(c => c.Contract).Distinct() - .Include(c => c.Rd) - .Include(c => c.Kg.Gl) .Include(c => c.Revisions) .ToListAsync(); var wbKgs = members @@ -725,18 +707,20 @@ namespace Elwig.Services { public static async Task DeleteMember(int mgnr, bool deletePaymentData, bool deleteDeliveries, bool deleteAreaComs) { await Task.Run(async () => { using var ctx = new AppDbContext(); + using var tx = await ctx.Database.BeginTransactionAsync(); var l = (await ctx.Members.FindAsync(mgnr))!; if (deletePaymentData) { - ctx.RemoveRange(l.Credits); + await ctx.Credits.Where(c => c.MgNr == mgnr).ExecuteDeleteAsync(); } if (deleteDeliveries) { - ctx.RemoveRange(l.Deliveries); + await ctx.Deliveries.Where(c => c.MgNr == mgnr).ExecuteDeleteAsync(); } if (deleteAreaComs) { - ctx.RemoveRange(l.AreaCommitments); + await ctx.AreaCommitments.Where(c => c.MgNr == mgnr).ExecuteDeleteAsync(); } ctx.Remove(l); await ctx.SaveChangesAsync(); + await tx.CommitAsync(); }); } } diff --git a/Elwig/Services/PaymentVariantService.cs b/Elwig/Services/PaymentVariantService.cs index c6cd7b6..4e17014 100644 --- a/Elwig/Services/PaymentVariantService.cs +++ b/Elwig/Services/PaymentVariantService.cs @@ -214,9 +214,7 @@ namespace Elwig.Services { Mouse.OverrideCursor = Cursors.Wait; await Task.Run(async () => { try { - using var ctx = new AppDbContext(); - var data = await PaymentVariantSummaryData.ForPaymentVariant(v, ctx.PaymentVariantSummaryRows); - using var doc = new PaymentVariantSummary((await ctx.PaymentVariants.FindAsync(v.Year, v.AvNr))!, data); + using var doc = await PaymentVariantSummary.Initialize(v.Year, v.AvNr); await Utils.ExportDocument(doc, mode); } catch (Exception exc) { MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); diff --git a/Elwig/Services/SyncService.cs b/Elwig/Services/SyncService.cs index c06c9cf..3eb76ec 100644 --- a/Elwig/Services/SyncService.cs +++ b/Elwig/Services/SyncService.cs @@ -25,18 +25,13 @@ namespace Elwig.Services { var path = Path.Combine(App.TempPath, filename); var members = await query .OrderBy(m => m.MgNr) - .Include(m => m.BillingAddress) .Include(m => m.TelephoneNumbers) .Include(m => m.EmailAddresses) - .Include(m => m.DefaultWbKg!.Gl) - .AsSplitQuery() .ToListAsync(); var areaComs = await query .SelectMany(m => m.AreaCommitments) .Select(c => c.Contract).Distinct() .OrderBy(c => c.FbNr) - .Include(c => c.Rd) - .Include(c => c.Kg.Gl) .Include(c => c.Revisions) .ToListAsync(); var wbKgs = members @@ -73,10 +68,7 @@ namespace Elwig.Services { var list = await query .Select(p => p.Delivery) .Distinct() - .Include(d => d.Parts).ThenInclude(p => p.PartModifiers).ThenInclude(m => m.Modifier) - .Include(d => d.Parts).ThenInclude(p => p.Rd) - .Include(d => d.Parts).ThenInclude(p => p.Kg!.Gl) - .AsSplitQuery() + .Include(d => d.Parts).ThenInclude(p => p.PartModifiers) .ToListAsync(); var wbKgs = list .SelectMany(d => d.Parts) @@ -114,27 +106,19 @@ namespace Elwig.Services { using (var ctx = new AppDbContext()) { members = await ctx.Members .Where(ChangedMembers) - .Include(m => m.BillingAddress) .Include(m => m.TelephoneNumbers) .Include(m => m.EmailAddresses) - .Include(m => m.DefaultWbKg!.Gl) .OrderBy(m => m.MgNr) - .AsSplitQuery() .ToListAsync(); areaComs = await ctx.AreaCommitmentContracts .Where(ChangedAreaComContracts) - .Include(c => c.Rd) - .Include(c => c.Kg.Gl) .Include(c => c.Revisions) .OrderBy(c => c.FbNr) .ToListAsync(); deliveries = await ctx.Deliveries .Where(ChangedDeliveries) - .Include(d => d.Parts).ThenInclude(p => p.PartModifiers).ThenInclude(m => m.Modifier) - .Include(d => d.Parts).ThenInclude(p => p.Rd) - .Include(d => d.Parts).ThenInclude(p => p.Kg).ThenInclude(k => k!.Gl) + .Include(d => d.Parts).ThenInclude(p => p.PartModifiers) .OrderBy(d => d.DateString).ThenBy(d => d.TimeString).ThenBy(d => d.LsNr) - .AsSplitQuery() .ToListAsync(); } var wbKgs = members @@ -179,11 +163,8 @@ namespace Elwig.Services { using var ctx = new AppDbContext(); var deliveries = await ctx.Deliveries .Where(d => d.Year == year && d.ZwstId == App.ZwstId) - .Include(d => d.Parts).ThenInclude(p => p.PartModifiers).ThenInclude(m => m.Modifier) - .Include(d => d.Parts).ThenInclude(p => p.Rd) - .Include(d => d.Parts).ThenInclude(p => p.Kg).ThenInclude(k => k!.Gl) + .Include(d => d.Parts).ThenInclude(p => p.PartModifiers) .OrderBy(d => d.DateString).ThenBy(d => d.TimeString).ThenBy(d => d.LsNr) - .AsSplitQuery() .ToListAsync(); var wbKgs = deliveries .SelectMany(d => d.Parts) diff --git a/Elwig/ViewModels/MemberAdminViewModel.cs b/Elwig/ViewModels/MemberAdminViewModel.cs index 8064cd0..bd453b0 100644 --- a/Elwig/ViewModels/MemberAdminViewModel.cs +++ b/Elwig/ViewModels/MemberAdminViewModel.cs @@ -20,7 +20,7 @@ namespace Elwig.ViewModels { public List TextFilter => [.. SearchQuery?.ToLower().Split(' ').ToList().FindAll(e => e.Length > 0) ?? []]; [ObservableProperty] - private bool _showOnlyActiveMembers; + private bool _showOnlyActiveMembers = true; [ObservableProperty] private Member? _selectedMember; diff --git a/Elwig/Windows/AdministrationWindow.cs b/Elwig/Windows/AdministrationWindow.cs index 09efc36..379a7f1 100644 --- a/Elwig/Windows/AdministrationWindow.cs +++ b/Elwig/Windows/AdministrationWindow.cs @@ -349,7 +349,6 @@ namespace Elwig.Windows { using var ctx = new AppDbContext(); list = await ctx.PlzDestinations .Where(p => p.Plz == plz) - .Include(p => p.Ort) .ToListAsync(); } diff --git a/Elwig/Windows/AreaComAdminWindow.xaml.cs b/Elwig/Windows/AreaComAdminWindow.xaml.cs index f7acdb7..bbe50b9 100644 --- a/Elwig/Windows/AreaComAdminWindow.xaml.cs +++ b/Elwig/Windows/AreaComAdminWindow.xaml.cs @@ -59,20 +59,9 @@ namespace Elwig.Windows { using var ctx = new AppDbContext(); var (_, contractQuery, areaComQuery, filter) = await vm.GetFilters(ctx); var contracts = await contractQuery - .Include(c => c.Kg.AtKg) - .Include(c => c.Rd!.Kg.AtKg) - .Include(c => c.Revisions).ThenInclude(a => a.WineCult) - .Include(c => c.Revisions).ThenInclude(a => a.AreaComType.WineAttr) - .Include(c => c.Revisions).ThenInclude(a => a.AreaComType.WineVar) .Include(c => c.Revisions).ThenInclude(a => a.Member) .ToListAsync(); - var areaComs = await areaComQuery - .Include(c => c.Contract.Kg.AtKg) - .Include(c => c.Contract.Rd!.Kg.AtKg) - .Include(a => a.WineCult) - .Include(a => a.AreaComType.WineAttr) - .Include(a => a.AreaComType.WineVar) - .ToListAsync(); + var areaComs = await areaComQuery.ToListAsync(); if (filter.Count > 0 && contracts.Count > 0) { var dict = contracts.AsParallel() diff --git a/Elwig/Windows/BaseDataWindow.xaml.AreaCom.cs b/Elwig/Windows/BaseDataWindow.xaml.AreaCom.cs index 9f62fe2..e4ba93a 100644 --- a/Elwig/Windows/BaseDataWindow.xaml.AreaCom.cs +++ b/Elwig/Windows/BaseDataWindow.xaml.AreaCom.cs @@ -21,8 +21,6 @@ namespace Elwig.Windows { private async Task AreaCommitmentTypesInitEditing(AppDbContext ctx) { _actList = new(await ctx.AreaCommitmentTypes .OrderBy(v => v.VtrgId) - .Include(t => t.WineVar) - .Include(t => t.WineAttr) .ToListAsync()); _acts = _actList.ToDictionary(v => v.VtrgId, v => (string?)v.VtrgId); _actIds = _actList.ToDictionary(v => v, v => v.VtrgId); diff --git a/Elwig/Windows/BaseDataWindow.xaml.Branch.cs b/Elwig/Windows/BaseDataWindow.xaml.Branch.cs index ef7f562..cb1ed3b 100644 --- a/Elwig/Windows/BaseDataWindow.xaml.Branch.cs +++ b/Elwig/Windows/BaseDataWindow.xaml.Branch.cs @@ -21,7 +21,7 @@ namespace Elwig.Windows { private async Task BranchesInitEditing(AppDbContext ctx) { _branchList = new(await ctx.Branches .OrderBy(b => b.Name) - .Include(b => b.PostalDest!.AtPlz) + .Include(b => b.PostalDest) .ToListAsync()); _branches = _branchList.ToDictionary(b => b.ZwstId, b => (string?)b.ZwstId); _branchIds = _branchList.ToDictionary(b => b, b => b.ZwstId); @@ -32,7 +32,7 @@ namespace Elwig.Windows { private async Task BranchesFinishEditing(AppDbContext ctx) { ControlUtils.RenewItemsSource(BranchList, await ctx.Branches .OrderBy(b => b.Name) - .Include(b => b.PostalDest!.AtPlz) + .Include(b => b.PostalDest) .ToListAsync()); _branchList = null; _branches = null; diff --git a/Elwig/Windows/BaseDataWindow.xaml.Season.cs b/Elwig/Windows/BaseDataWindow.xaml.Season.cs index dd19c4a..718a8b4 100644 --- a/Elwig/Windows/BaseDataWindow.xaml.Season.cs +++ b/Elwig/Windows/BaseDataWindow.xaml.Season.cs @@ -22,7 +22,6 @@ namespace Elwig.Windows { ControlUtils.RenewItemsSource(SeasonList, await ctx.Seasons .OrderByDescending(s => s.Year) .Include(s => s.Modifiers) - .Include(s => s.Currency) .ToListAsync()); SeasonList_SelectionChanged(null, null); } @@ -33,7 +32,6 @@ namespace Elwig.Windows { ControlUtils.RenewItemsSource(SeasonList, await ctx.Seasons .OrderByDescending(s => s.Year) .Include(s => s.Modifiers) - .Include(s => s.Currency) .ToListAsync()); _seasonChanged = false; } diff --git a/Elwig/Windows/BaseDataWindow.xaml.cs b/Elwig/Windows/BaseDataWindow.xaml.cs index a96e448..679b35b 100644 --- a/Elwig/Windows/BaseDataWindow.xaml.cs +++ b/Elwig/Windows/BaseDataWindow.xaml.cs @@ -163,12 +163,11 @@ namespace Elwig.Windows { ControlUtils.RenewItemsSource(SeasonList, await ctx.Seasons .OrderByDescending(s => s.Year) .Include(s => s.Modifiers) - .Include(s => s.Currency) .ToListAsync(), null, ControlUtils.RenewSourceDefault.First); var year = (SeasonList.SelectedItem as Season)?.Year; ControlUtils.RenewItemsSource(BranchList, await ctx.Branches .OrderBy(b => b.Name) - .Include(b => b.PostalDest!.AtPlz) + .Include(b => b.PostalDest) .ToListAsync(), null, ControlUtils.RenewSourceDefault.First); ControlUtils.RenewItemsSource(WineAttributeList, await ctx.WineAttributes .OrderBy(a => a.Name) @@ -181,8 +180,6 @@ namespace Elwig.Windows { ControlUtils.RenewItemsSource(AreaCommitmentTypeWineAttributeInput, attrList); ControlUtils.RenewItemsSource(AreaCommitmentTypeList, await ctx.AreaCommitmentTypes .OrderBy(t => t.VtrgId) - .Include(t => t.WineVar) - .Include(t => t.WineAttr) .ToListAsync(), null, ControlUtils.RenewSourceDefault.First); ControlUtils.RenewItemsSource(WineCultivationList, await ctx.WineCultivations .OrderBy(c => c.Name) diff --git a/Elwig/Windows/DeliveryAdminWindow.xaml.cs b/Elwig/Windows/DeliveryAdminWindow.xaml.cs index f9fbd1e..f98379c 100644 --- a/Elwig/Windows/DeliveryAdminWindow.xaml.cs +++ b/Elwig/Windows/DeliveryAdminWindow.xaml.cs @@ -429,10 +429,9 @@ namespace Elwig.Windows { var (_, deliveryQuery, deliveryPartsQuery, predicate, filter) = await vm.GetFilters(ctx); var deliveries = await deliveryQuery .Include(d => d.Parts).ThenInclude(p => p.PartModifiers).ThenInclude(m => m.Modifier) - .Include(d => d.Parts).ThenInclude(p => p.Attribute) - .Include(d => d.Parts).ThenInclude(p => p.Cultivation) .Include(d => d.Parts).ThenInclude(p => p.Variety) .Include(d => d.Member.EmailAddresses) + .IgnoreAutoIncludes() .AsSplitQuery() .ToListAsync(); deliveries.Reverse(); @@ -442,7 +441,7 @@ namespace Elwig.Windows { .ToDictionary(d => d, d => d.SearchScore(vm.TextFilter)) .OrderByDescending(a => a.Value) .ThenBy(a => a.Key.DateTime); - var threshold = dict.Select(a => a.Value).Max() * 3 / 4; + var threshold = dict.Max(a => a.Value) * 3 / 4; deliveries = [.. dict .Where(a => a.Value > threshold) .Select(a => a.Key)]; @@ -452,7 +451,7 @@ namespace Elwig.Windows { var deliveryPartsNum = await deliveryPartsQuery.CountAsync(); var varieties = await deliveryPartsQuery.Select(d => d.SortId).Distinct().ToListAsync(); - var members = await deliveryQuery.Select(d => d.Member).Distinct().ToListAsync(); + var members = await deliveryQuery.Select(d => d.Member).Distinct().IgnoreAutoIncludes().ToListAsync(); var stat = await DeliveryService.GenerateToolTipData(deliveryPartsQuery); return (filter, deliveries, deliveryPartsNum, varieties, members, stat); @@ -498,7 +497,7 @@ namespace Elwig.Windows { int year = 0; Menu_Bki_SaveList.Items.Clear(); - foreach (var s in await ctx.Seasons.OrderByDescending(s => s.Year).ToListAsync()) { + foreach (var s in await ctx.Seasons.OrderByDescending(s => s.Year).IgnoreAutoIncludes().ToListAsync()) { if (s.Year > year) year = s.Year; var i = new MenuItem { Header = $"Saison {s.Year}", @@ -515,7 +514,7 @@ namespace Elwig.Windows { }; noAttr.Click += Menu_BulkAction_SetAttribute_Click; Menu_BulkAction_SetAttribute.Items.Add(noAttr); - foreach (var attr in await ctx.WineAttributes.OrderBy(a => a.AttrId).ToListAsync()) { + foreach (var attr in await ctx.WineAttributes.OrderBy(a => a.AttrId).IgnoreAutoIncludes().ToListAsync()) { var i = new MenuItem { Header = attr.Name, }; @@ -525,7 +524,7 @@ namespace Elwig.Windows { Menu_BulkAction_AddModifier.Items.Clear(); Menu_BulkAction_RemoveModifier.Items.Clear(); - foreach (var mod in await ctx.Modifiers.Where(m => m.Year == year).OrderBy(m => m.ModId).ToListAsync()) { + foreach (var mod in await ctx.Modifiers.Where(m => m.Year == year).OrderBy(m => m.ModId).IgnoreAutoIncludes().ToListAsync()) { var i1 = new MenuItem { Header = mod.Name, }; @@ -543,8 +542,6 @@ namespace Elwig.Windows { var y = d?.Year ?? ViewModel.FilterSeason; ControlUtils.RenewItemsSource(MemberInput, await ctx.Members .Where(m => m.IsActive || !IsCreating) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.DefaultWbKg!.AtKg) .OrderBy(m => m.Name) .ThenBy(m => m.GivenName) .ToListAsync()); @@ -561,15 +558,16 @@ namespace Elwig.Windows { ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers .Where(m => m.Year == y && (!IsCreating || m.IsActive)) .OrderBy(m => m.Ordering) - .Include(m => m.Season.Currency) .ToListAsync()); - ControlUtils.RenewItemsSource(WineOriginInput, (await ctx.WineOrigins.ToListAsync()).OrderByDescending(o => o.SortKey).ThenBy(o => o.HkId)); + var origins = await ctx.WineOrigins.ToListAsync(); + origins.ForEach(o => { origins.FirstOrDefault(p => p.HkId == o.ParentHkId)?.Children.Add(o); }); + origins = [.. origins.OrderByDescending(o => o.SortKey).ThenBy(o => o.HkId)]; + ControlUtils.RenewItemsSource(WineOriginInput, origins); var kgList = (await ctx.Katastralgemeinden .Where(k => k.WbKg != null) .Include(k => k.WbKg) .Include(k => k.Gem.WbGem) .OrderBy(k => k.Name) - .AsSplitQuery() .ToListAsync()).Cast().ToList(); kgList.Insert(0, new NullItem()); ControlUtils.RenewItemsSource(WineKgInput, kgList); @@ -592,14 +590,12 @@ namespace Elwig.Windows { ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers .Where(m => m.Year == d.Year && (!IsCreating || m.IsActive)) .OrderBy(m => m.Ordering) - .Include(m => m.Season.Currency) .ToListAsync()); - ControlUtils.RenewItemsSource(DeliveryPartList, d.FilteredParts.OrderBy(p => p.DPNr).ToList(), DeliveryPartList_SelectionChanged, ControlUtils.RenewSourceDefault.First); + ControlUtils.RenewItemsSource(DeliveryPartList, d.Parts, DeliveryPartList_SelectionChanged, ControlUtils.RenewSourceDefault.First); } else { ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers .Where(m => m.Year == ViewModel.FilterSeason && (!IsCreating || m.IsActive)) .OrderBy(m => m.Ordering) - .Include(m => m.Season.Currency) .ToListAsync()); DeliveryPartList.ItemsSource = null; } @@ -607,16 +603,17 @@ namespace Elwig.Windows { private void RefreshInputs(bool validate = false) { ClearInputStates(); - if (DeliveryPartList.SelectedItem is DeliveryPart p) { - FillInputs(p); - } else if (DeliveryList.SelectedItem is Delivery d) { + if (DeliveryList.SelectedItem is Delivery d) { FillInputs(d); + if (DeliveryPartList.SelectedItem is DeliveryPart p) { + FillInputs(p); + } } else { ClearOriginalValues(); ClearDefaultValues(); ClearInputs(validate); ClearInputStates(); - } + } GC.Collect(); } @@ -628,7 +625,6 @@ namespace Elwig.Windows { } private void FillInputs(DeliveryPart p) { - FillInputs(p.Delivery); ClearOriginalValues(); ClearDefaultValues(); ViewModel.FillInputs(p); @@ -863,9 +859,10 @@ namespace Elwig.Windows { EmptyScale(); Utils.RunBackground("Lieferschein drucken", async () => { - using var ctx = new AppDbContext(); - using var doc = new DeliveryNote((await ctx.Deliveries.FindAsync(p.Year, p.DId))!, ctx); - await doc.Generate(); + using var doc = await DeliveryNote.Initialize(p.Year, p.DId); + using (var ctx = new AppDbContext()) { + await doc.Generate(ctx); + } if (App.Config.Debug) { doc.Show(); } else { @@ -892,8 +889,6 @@ namespace Elwig.Windows { ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First); ControlUtils.RenewItemsSource(MemberInput, await ctx.Members .Where(m => m.IsActive || !ViewModel.IsReceipt) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.DefaultWbKg!.AtKg) .OrderBy(m => m.Name) .ThenBy(m => m.GivenName) .ToListAsync()); @@ -934,12 +929,9 @@ namespace Elwig.Windows { ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers .Where(m => m.Year == ViewModel.FilterSeason && m.IsActive) .OrderBy(m => m.Ordering) - .Include(m => m.Season.Currency) .ToListAsync()); ControlUtils.RenewItemsSource(MemberInput, await ctx.Members .Where(m => m.IsActive || !ViewModel.IsReceipt) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.DefaultWbKg!.AtKg) .OrderBy(m => m.Name) .ThenBy(m => m.GivenName) .ToListAsync()); diff --git a/Elwig/Windows/DeliveryAncmtAdminWindow.xaml.cs b/Elwig/Windows/DeliveryAncmtAdminWindow.xaml.cs index 3b242a3..70f1635 100644 --- a/Elwig/Windows/DeliveryAncmtAdminWindow.xaml.cs +++ b/Elwig/Windows/DeliveryAncmtAdminWindow.xaml.cs @@ -85,7 +85,6 @@ namespace Elwig.Windows { using var ctx = new AppDbContext(); var list = await ctx.DeliverySchedules .Where(s => s.Year == ViewModel.FilterSeason) - .Include(s => s.Branch) .OrderBy(s => s.DateString) .ThenBy(s => s.Branch.Name) .ThenBy(s => s.Description) @@ -110,12 +109,7 @@ namespace Elwig.Windows { var (filter, deliveryAncmts, stat) = await Task.Run(async () => { using var ctx = new AppDbContext(); var (_, deliveryAncmtQuery, filter) = await vm.GetFilters(ctx); - var deliveryAncmts = await deliveryAncmtQuery - .Include(a => a.Member.BillingAddress) - .Include(a => a.Schedule) - .Include(a => a.Variety) - .AsSplitQuery() - .ToListAsync(); + var deliveryAncmts = await deliveryAncmtQuery.ToListAsync(); if (filter.Count > 0 && deliveryAncmts.Count > 0) { var dict = deliveryAncmts.AsParallel() @@ -189,8 +183,6 @@ namespace Elwig.Windows { ControlUtils.RenewItemsSource(MemberInput, await ctx.Members .Where(m => m.IsActive || !IsCreating) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.DefaultWbKg!.AtKg) .OrderBy(m => m.Name) .ThenBy(m => m.GivenName) .ThenBy(m => m.MgNr) @@ -286,8 +278,6 @@ namespace Elwig.Windows { using var ctx = new AppDbContext(); ControlUtils.RenewItemsSource(MemberInput, await ctx.Members .Where(m => m.IsActive || !IsCreating) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.DefaultWbKg!.AtKg) .OrderBy(m => m.Name) .ThenBy(m => m.GivenName) .ThenBy(m => m.MgNr) @@ -415,8 +405,6 @@ namespace Elwig.Windows { using var ctx = new AppDbContext(); ControlUtils.RenewItemsSource(MemberInput, await ctx.Members .Where(m => m.IsActive || !IsCreating) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.DefaultWbKg!.AtKg) .OrderBy(m => m.Name) .ThenBy(m => m.GivenName) .ThenBy(m => m.MgNr) diff --git a/Elwig/Windows/DeliveryScheduleAdminWindow.xaml.cs b/Elwig/Windows/DeliveryScheduleAdminWindow.xaml.cs index cd491d5..bfe299d 100644 --- a/Elwig/Windows/DeliveryScheduleAdminWindow.xaml.cs +++ b/Elwig/Windows/DeliveryScheduleAdminWindow.xaml.cs @@ -47,8 +47,6 @@ namespace Elwig.Windows { var (_, deliveryScheduleQuery, filter) = await vm.GetFilters(ctx); var deliverySchedules = await deliveryScheduleQuery .Include(s => s.Varieties) - .Include(s => s.Branch) - .AsSplitQuery() .ToListAsync(); if (filter.Count > 0 && deliverySchedules.Count > 0) { diff --git a/Elwig/Windows/MailWindow.xaml.cs b/Elwig/Windows/MailWindow.xaml.cs index cbaa424..91534ad 100644 --- a/Elwig/Windows/MailWindow.xaml.cs +++ b/Elwig/Windows/MailWindow.xaml.cs @@ -155,7 +155,7 @@ namespace Elwig.Windows { } protected override async Task OnRenewContext(AppDbContext ctx) { - var season = await ctx.Seasons.FindAsync(Year); + var season = await ctx.Seasons.Include(s => s.PaymentVariants).SingleAsync(s => s.Year == Year); var l = new List { MemberDataSheet.Name }; @@ -207,13 +207,8 @@ namespace Elwig.Windows { .OrderBy(m => m.Name) .ThenBy(m => m.GivenName) .Include(m => m.Branch) - .Include(m => m.DefaultWbKg!.AtKg) .Include(m => m.EmailAddresses) .Include(m => m.TelephoneNumbers) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.PostalDest.AtPlz!.Country) - .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort) - .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Country) .ToListAsync(), MemberInput_SelectionChanged); if (MemberCustomInput.SelectedItems.Count == 0) { MemberCustomInput.SelectionChanged -= MemberInput_SelectionChanged; @@ -492,13 +487,8 @@ namespace Elwig.Windows { } Recipients = await query .Include(m => m.Branch) - .Include(m => m.DefaultWbKg!.AtKg) .Include(m => m.EmailAddresses) .Include(m => m.TelephoneNumbers) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.PostalDest.AtPlz!.Country) - .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort) - .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Country) .ToListAsync(); } UpdatePostalEmailRecipients(); @@ -758,7 +748,7 @@ namespace Elwig.Windows { if (doc.Type == DocType.Custom) { return [new GeneratedDoc((string)doc.Details!)]; } else if (doc.Type == DocType.MemberDataSheet) { - return [new GeneratedDoc(new MemberDataSheet(m, ctx) { Date = postalDate })]; + return [new GeneratedDoc(new MemberDataSheet(m) { Date = postalDate })]; } else if (doc.Type == DocType.DeliveryConfirmation) { var year = (int)doc.Details!; DeliveryConfirmationDeliveryData data; @@ -769,21 +759,14 @@ namespace Elwig.Windows { } else { return []; } - return [new GeneratedDoc(new DeliveryConfirmation(ctx, year, m, data) { Date = postalDate })]; + return [new GeneratedDoc(new DeliveryConfirmation(year, m, data) { Date = postalDate })]; } else if (doc.Type == DocType.CreditNote) { var details = ((int, int))doc.Details!; var year = details.Item1; var avnr = details.Item2; var data = cnData[(year, avnr)]; try { - return [new GeneratedDoc(new CreditNote( - ctx, data.Item2[m.MgNr], data.Item1[m.MgNr], - data.Item3.ConsiderContractPenalties, - data.Item3.ConsiderTotalPenalty, - data.Item3.ConsiderAutoBusinessShares, - data.Item3.ConsiderCustomModifiers, - ctx.GetMemberUnderDelivery(year, m.MgNr).GetAwaiter().GetResult() - ) { Date = postalDate })]; + return [new GeneratedDoc(new CreditNote(data.Item2[m.MgNr], data.Item3, data.Item1[m.MgNr]) { Date = postalDate })]; } catch (Exception) { return []; } @@ -827,7 +810,7 @@ namespace Elwig.Windows { var emailRecipients = email.Select(d => d.Key.MgNr).ToHashSet(); foreach (var item1 in email.Select((e, i) => new { Index = i, e.Key, e.Value })) { foreach (var item2 in item1.Value.Select((d, i) => new { Index = i, Doc = d })) { - await item2.Doc.Generate(CancelGeneration?.Token, new Progress(v => App.MainDispatcher.Invoke(() => { + await item2.Doc.Generate(ctx, CancelGeneration?.Token, new Progress(v => App.MainDispatcher.Invoke(() => { ProgressBar.Value = offset + v * (item2.Index + 1) / item1.Value.Count / totalNum + 100.0 * item1.Index / totalNum; }))); } @@ -861,7 +844,7 @@ namespace Elwig.Windows { if (printDocs.Count > 0) { var print = Document.Merge(printDocs); - await print.Generate(CancelGeneration?.Token, new Progress(v => App.MainDispatcher.Invoke(() => { + await print.Generate(ctx, CancelGeneration?.Token, new Progress(v => App.MainDispatcher.Invoke(() => { ProgressBar.Value = offset + v * printNum / totalNum; }))); PrintDocument = print; diff --git a/Elwig/Windows/MemberAdminWindow.xaml.cs b/Elwig/Windows/MemberAdminWindow.xaml.cs index c07dd92..9aef452 100644 --- a/Elwig/Windows/MemberAdminWindow.xaml.cs +++ b/Elwig/Windows/MemberAdminWindow.xaml.cs @@ -121,14 +121,9 @@ namespace Elwig.Windows { using var ctx = new AppDbContext(); var (_, memberQuery, filter) = await vm.GetFilters(ctx); var members = await memberQuery - .Include(m => m.Branch) - .Include(m => m.DefaultWbKg!.AtKg) .Include(m => m.EmailAddresses) .Include(m => m.TelephoneNumbers) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.PostalDest.AtPlz!.Country) - .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort) - .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Country) + .AsSplitQuery() .ToListAsync(); if (filter.Count > 0 && members.Count > 0) { @@ -200,7 +195,7 @@ namespace Elwig.Windows { var font = new System.Windows.Media.FontFamily("Segoe MDL2 Assets"); MenuItem? temp = null; - var seasons = await ctx.Seasons.OrderByDescending(s => s.Year).ToListAsync(); + var seasons = await ctx.Seasons.Include(s => s.PaymentVariants).OrderByDescending(s => s.Year).ToListAsync(); Menu_DeliveryConfirmation.Items.Clear(); foreach (var s in seasons) { var i = new MenuItem { @@ -339,6 +334,7 @@ namespace Elwig.Windows { } private async void ActiveMemberInput_Changed(object sender, RoutedEventArgs evt) { + if (!IsInitialized) return; await RefreshList(); } @@ -509,7 +505,9 @@ namespace Elwig.Windows { try { await Task.Run(async () => { using var doc = new Letterhead(m); - await doc.Generate(); + using (var ctx = new AppDbContext()) { + await doc.Generate(ctx); + } if (!App.Config.Debug) { await doc.Print(); } else { diff --git a/Elwig/Windows/OriginHierarchyWindow.xaml.cs b/Elwig/Windows/OriginHierarchyWindow.xaml.cs index f445bbf..24a17cc 100644 --- a/Elwig/Windows/OriginHierarchyWindow.xaml.cs +++ b/Elwig/Windows/OriginHierarchyWindow.xaml.cs @@ -21,12 +21,11 @@ namespace Elwig.Windows { } protected override async Task OnRenewContext(AppDbContext ctx) { - var origins = (await ctx.WineOrigins - .Include("Gems.AtGem.Kgs.WbKg.Gl") - .AsSplitQuery() - .ToListAsync()) - .OrderByDescending(o => o.SortKey) - .ThenBy(o => o.HkId); + var origins = await ctx.WineOrigins + .Include(o => o.Gems).ThenInclude(g => g.AtGem.Kgs).ThenInclude(k => k.WbKg!.Gl) + .ToListAsync(); + origins.ForEach(o => { origins.FirstOrDefault(p => p.HkId == o.ParentHkId)?.Children.Add(o); }); + origins = [.. origins.OrderByDescending(o => o.SortKey).ThenBy(o => o.HkId)]; ControlUtils.RenewItemsSource(WineOrigins, origins, WineOrigins_SelectionChanged); if (WineOrigins.SelectedItem == null) { var hkid = await ctx.WbKgs @@ -39,8 +38,7 @@ namespace Elwig.Windows { } var gls = await ctx.WbGls .OrderBy(g => g.GlNr) - .Include("Kgs.Rds") - .AsSplitQuery() + .Include(g => g.Kgs).ThenInclude(k => k.Rds) .ToListAsync(); ControlUtils.RenewItemsSource(WbGls, gls, WbGls_SelectionChanged, ControlUtils.RenewSourceDefault.First); UpdateWbGems(); diff --git a/Elwig/Windows/PaymentVariantsWindow.xaml.cs b/Elwig/Windows/PaymentVariantsWindow.xaml.cs index bcd0411..56991d5 100644 --- a/Elwig/Windows/PaymentVariantsWindow.xaml.cs +++ b/Elwig/Windows/PaymentVariantsWindow.xaml.cs @@ -48,7 +48,6 @@ namespace Elwig.Windows { ControlUtils.RenewItemsSource(PaymentVariantList, await ctx.PaymentVariants .Where(v => v.Year == Year) .OrderBy(v => v.AvNr) - .Include(v => v.Season.Currency) .ToListAsync()); if (PaymentVariantList.SelectedItem == null && PaymentVariantList.Items.Count > 0) { PaymentVariantList.SelectedIndex = PaymentVariantList.Items.Count - 1; diff --git a/Tests/DatabaseSetup.cs b/Tests/DatabaseSetup.cs index 1111881..7026aca 100644 --- a/Tests/DatabaseSetup.cs +++ b/Tests/DatabaseSetup.cs @@ -2,6 +2,7 @@ using Elwig; using Elwig.Helpers; using Elwig.Helpers.Billing; using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; using System.Reflection; namespace Tests { @@ -22,7 +23,7 @@ namespace Tests { public void Setup_2_Client() { using var ctx = new AppDbContext(); App.Client = new ClientParameters(ctx); - App.SetBranch(ctx.Branches.Single()); + App.SetBranch(ctx.Branches.Include(b => b.PostalDest).Single()); } [OneTimeSetUp] diff --git a/Tests/Resources/Sql/DocumentInsert.sql b/Tests/Resources/Sql/DocumentInsert.sql index 543dab4..76490cd 100644 --- a/Tests/Resources/Sql/DocumentInsert.sql +++ b/Tests/Resources/Sql/DocumentInsert.sql @@ -64,6 +64,10 @@ INSERT INTO delivery_part (year, did, dpnr, sortid, attrid, cultid, weight, kmw, (2020, 12, 1, 'BP', NULL, NULL, 2410, 18.0, 'KAB', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL), (2020, 12, 2, 'BP', NULL, NULL, 2313, 18.1, 'KAB', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL); +INSERT INTO delivery_part_modifier (year, did, dpnr, modid) VALUES +(2020, 2, 1, 'S'), +(2020, 2, 2, 'A'); + INSERT INTO delivery_part_bucket (year, did, dpnr, bktnr, discr, value) VALUES (2020, 1, 1, 0, '_', 3219), (2020, 3, 1, 0, '_', 2561), diff --git a/Tests/UnitTests/DocumentTests/CreditNoteTest.cs b/Tests/UnitTests/DocumentTests/CreditNoteTest.cs index 996fe1e..1cf4db4 100644 --- a/Tests/UnitTests/DocumentTests/CreditNoteTest.cs +++ b/Tests/UnitTests/DocumentTests/CreditNoteTest.cs @@ -1,7 +1,4 @@ using Elwig.Documents; -using Elwig.Helpers; -using Elwig.Models.Dtos; -using Microsoft.EntityFrameworkCore; namespace Tests.UnitTests.DocumentTests { [TestFixture] @@ -9,12 +6,7 @@ namespace Tests.UnitTests.DocumentTests { [Test] public async Task Test_01_VirtualCreditNote() { - using var ctx = new AppDbContext(); - var m = await ctx.Members.FindAsync(101); - var p = await ctx.MemberPayments.Where(p => p.Year == 2020 && p.AvNr == 1).SingleAsync(); - var data = await CreditNoteDeliveryData.ForPaymentVariant(ctx.CreditNoteDeliveryRows, ctx.PaymentVariants, 2020, 1); - using var doc = new CreditNote(ctx, p, data[m!.MgNr], false, false, false, false, - ctx.GetMemberUnderDelivery(2020, m!.MgNr).GetAwaiter().GetResult()); + using var doc = await CreditNote.Initialize(2020, 1, 101); var text = await Utils.GeneratePdfText(doc); Assert.Multiple(() => { Assert.That(text, Contains.Substring(""" diff --git a/Tests/UnitTests/DocumentTests/DeliveryConfirmationTest.cs b/Tests/UnitTests/DocumentTests/DeliveryConfirmationTest.cs index e8af381..f87bb81 100644 --- a/Tests/UnitTests/DocumentTests/DeliveryConfirmationTest.cs +++ b/Tests/UnitTests/DocumentTests/DeliveryConfirmationTest.cs @@ -11,7 +11,7 @@ namespace Tests.UnitTests.DocumentTests { using var ctx = new AppDbContext(); var m = await ctx.Members.FindAsync(101); var data = await DeliveryConfirmationDeliveryData.ForMember(ctx.DeliveryParts, 2020, m!); - using var doc = new DeliveryConfirmation(ctx, 2020, m!, data); + using var doc = new DeliveryConfirmation(2020, m!, data); var text = await Utils.GeneratePdfText(doc); Assert.Multiple(() => { Assert.That(text, Contains.Substring(""" diff --git a/Tests/UnitTests/DocumentTests/DeliveryNoteTest.cs b/Tests/UnitTests/DocumentTests/DeliveryNoteTest.cs index 722ef13..55c06ad 100644 --- a/Tests/UnitTests/DocumentTests/DeliveryNoteTest.cs +++ b/Tests/UnitTests/DocumentTests/DeliveryNoteTest.cs @@ -1,5 +1,4 @@ using Elwig.Documents; -using Elwig.Helpers; namespace Tests.UnitTests.DocumentTests { [TestFixture] @@ -7,9 +6,7 @@ namespace Tests.UnitTests.DocumentTests { [Test] public async Task Test_01_OneDeliveryPart() { - using var ctx = new AppDbContext(); - var d = await ctx.Deliveries.FindAsync(2020, 1); - using var doc = new DeliveryNote(d!, ctx); + using var doc = await DeliveryNote.Initialize(2020, 1); var text = await Utils.GeneratePdfText(doc); Assert.Multiple(() => { Assert.That(text, Contains.Substring(""" @@ -19,7 +16,7 @@ namespace Tests.UnitTests.DocumentTests { """)); Assert.That(text, Contains.Substring("0123463")); // Betriebsnummer Assert.That(text, Contains.Substring("pauschaliert")); - Assert.That(text, Contains.Substring($"Wolkersdorf, am {Elwig.Helpers.Utils.Today:dd.MM.yyyy}")); + Assert.That(text, Contains.Substring($"Wolkersdorf, am {DateTime.Now:dd.MM.yyyy}")); Assert.That(text, Contains.Substring("Traubenübernahmeschein Nr. 20201001X001")); Assert.That(text, Contains.Substring("Das Mitglied erklärt, dass die gelieferte Ware dem österreichischen Weingesetz entspricht")); Assert.That(text, Contains.Substring(""" @@ -34,9 +31,7 @@ namespace Tests.UnitTests.DocumentTests { [Test] public async Task Test_02_TwoDeliveryParts() { - using var ctx = new AppDbContext(); - var d = await ctx.Deliveries.FindAsync(2020, 4); - using var doc = new DeliveryNote(d!, ctx); + using var doc = await DeliveryNote.Initialize(2020, 4); var text = await Utils.GeneratePdfText(doc); Assert.Multiple(() => { Assert.That(text, Contains.Substring(""" @@ -47,7 +42,7 @@ namespace Tests.UnitTests.DocumentTests { """)); Assert.That(text, Contains.Substring("0123471")); // Betriebsnummer Assert.That(text, Contains.Substring("pauschaliert")); - Assert.That(text, Contains.Substring($"Wolkersdorf, am {Elwig.Helpers.Utils.Today:dd.MM.yyyy}")); + Assert.That(text, Contains.Substring($"Wolkersdorf, am {DateTime.Now:dd.MM.yyyy}")); Assert.That(text, Contains.Substring("Traubenübernahmeschein Nr. 20201001X004")); Assert.That(text, Contains.Substring("Das Mitglied erklärt, dass die gelieferte Ware dem österreichischen Weingesetz entspricht")); Assert.That(text, Contains.Substring(""" @@ -68,9 +63,7 @@ namespace Tests.UnitTests.DocumentTests { [Test] public async Task Test_03_DeliveryPartsWithAttribute() { - using var ctx = new AppDbContext(); - var d = await ctx.Deliveries.FindAsync(2020, 3); - using var doc = new DeliveryNote(d!, ctx); + using var doc = await DeliveryNote.Initialize(2020, 3); var text = await Utils.GeneratePdfText(doc); Assert.Multiple(() => { Assert.That(text, Contains.Substring(""" @@ -80,7 +73,7 @@ namespace Tests.UnitTests.DocumentTests { """)); Assert.That(text, Contains.Substring("0123463")); // Betriebsnummer Assert.That(text, Contains.Substring("pauschaliert")); - Assert.That(text, Contains.Substring($"Wolkersdorf, am {Elwig.Helpers.Utils.Today:dd.MM.yyyy}")); + Assert.That(text, Contains.Substring($"Wolkersdorf, am {DateTime.Now:dd.MM.yyyy}")); Assert.That(text, Contains.Substring("Traubenübernahmeschein Nr. 20201001X003")); Assert.That(text, Contains.Substring("Das Mitglied erklärt, dass die gelieferte Ware dem österreichischen Weingesetz entspricht")); Assert.That(text, Contains.Substring(""" @@ -107,9 +100,7 @@ namespace Tests.UnitTests.DocumentTests { [Test] public async Task Test_04_DeliveryPartsWithCultivation() { - using var ctx = new AppDbContext(); - var d = await ctx.Deliveries.FindAsync(2020, 7); - using var doc = new DeliveryNote(d!, ctx); + using var doc = await DeliveryNote.Initialize(2020, 7); var text = await Utils.GeneratePdfText(doc); Assert.Multiple(() => { Assert.That(text, Contains.Substring(""" @@ -119,7 +110,7 @@ namespace Tests.UnitTests.DocumentTests { """)); Assert.That(text, Contains.Substring("0123480")); // Betriebsnummer Assert.That(text, Contains.Substring("pauschaliert")); - Assert.That(text, Contains.Substring($"Wolkersdorf, am {Elwig.Helpers.Utils.Today:dd.MM.yyyy}")); + Assert.That(text, Contains.Substring($"Wolkersdorf, am {DateTime.Now:dd.MM.yyyy}")); Assert.That(text, Contains.Substring("Traubenübernahmeschein Nr. 20201002X001")); Assert.That(text, Contains.Substring("Das Mitglied erklärt, dass die gelieferte Ware dem österreichischen Weingesetz entspricht")); Assert.That(text, Contains.Substring(""" @@ -139,5 +130,37 @@ namespace Tests.UnitTests.DocumentTests { Assert.That(text, Contains.Substring("Gesamt: 78 15,9 5 332")); }); } + + [Test] + public async Task Test_05_DeliveryPartsWithModifier() { + using var doc = await DeliveryNote.Initialize(2020, 2); + var text = await Utils.GeneratePdfText(doc); + Assert.Multiple(() => { + Assert.That(text, Contains.Substring(""" + W&B Weinbauer GesbR + WEINBAUER Wernhardt + Winzerstraße 2 + 2223 Hohenruppersdorf + """)); + Assert.That(text, Contains.Substring("0123471")); // Betriebsnummer + Assert.That(text, Contains.Substring("pauschaliert")); + Assert.That(text, Contains.Substring($"Wolkersdorf, am {DateTime.Now:dd.MM.yyyy}")); + Assert.That(text, Contains.Substring("Traubenübernahmeschein Nr. 20201001X002")); + Assert.That(text, Contains.Substring("Das Mitglied erklärt, dass die gelieferte Ware dem österreichischen Weingesetz entspricht")); + Assert.That(text, Contains.Substring(""" + 1 Grüner Veltliner Kabinett Kabinett 86 17,5 2 987 + Herkunft: Österreich / Weinland / Niederösterreich + / Matzner Hügel / Hohenruppersdorf / KG Hohenruppersdorf + Zu-/Abschläge: Geschädigte Trauben −10,00 % + Waage: ?, ID: ? (gerebelt gewogen) + 2 Grüner Veltliner Kabinett Kabinett 87 17,7 1 873 + Herkunft: Österreich / Weinland / Niederösterreich + / Matzner Hügel / Hohenruppersdorf / KG Hohenruppersdorf + Zu-/Abschläge: Keine Voranmeldung −0,1000 €/kg + Waage: ?, ID: ? (gerebelt gewogen) + Gesamt: 87 17,6 4 860 + """)); + }); + } } } diff --git a/Tests/UnitTests/DocumentTests/MemberDataSheetTest.cs b/Tests/UnitTests/DocumentTests/MemberDataSheetTest.cs index 379239d..f3a3fe9 100644 --- a/Tests/UnitTests/DocumentTests/MemberDataSheetTest.cs +++ b/Tests/UnitTests/DocumentTests/MemberDataSheetTest.cs @@ -1,5 +1,4 @@ using Elwig.Documents; -using Elwig.Helpers; namespace Tests.UnitTests.DocumentTests { [TestFixture] @@ -7,9 +6,7 @@ namespace Tests.UnitTests.DocumentTests { [Test] public async Task Test_01_SimpleMember() { - using var ctx = new AppDbContext(); - var m = await ctx.Members.FindAsync(104); - using var doc = new MemberDataSheet(m!, ctx); + using var doc = await MemberDataSheet.Initialize(104); var text = await Utils.GeneratePdfText(doc); Assert.Multiple(() => { Assert.That(text, Contains.Substring(""" diff --git a/Tests/UnitTests/DocumentTests/PaymentVariantSummaryTest.cs b/Tests/UnitTests/DocumentTests/PaymentVariantSummaryTest.cs index 385fa32..92ec95e 100644 --- a/Tests/UnitTests/DocumentTests/PaymentVariantSummaryTest.cs +++ b/Tests/UnitTests/DocumentTests/PaymentVariantSummaryTest.cs @@ -1,6 +1,4 @@ using Elwig.Documents; -using Elwig.Helpers; -using Elwig.Models.Dtos; namespace Tests.UnitTests.DocumentTests { [TestFixture] @@ -8,16 +6,13 @@ namespace Tests.UnitTests.DocumentTests { [Test] public async Task Test_01_PaymentVariant2020() { - using var ctx = new AppDbContext(); - var v = (await ctx.PaymentVariants.FindAsync(2020, 1))!; - var data = await PaymentVariantSummaryData.ForPaymentVariant(v, ctx.PaymentVariantSummaryRows); - using var doc = new PaymentVariantSummary(v, data); + using var doc = await PaymentVariantSummary.Initialize(2020, 1); var text = await Utils.GeneratePdfText(doc, true); var table = Utils.ExtractTable(text); Assert.Multiple(() => { Assert.That(text, Contains.Substring("Auszahlungsvariante")); - Assert.That(text, Contains.Substring(v.Name)); - Assert.That(table.Skip(17).ToArray(), Is.EqualTo(new string[][] { + Assert.That(text, Contains.Substring(doc.Variant.Name)); + Assert.That(table.Skip(19).ToArray(), Is.EqualTo(new string[][] { ["Sorte/Attr./Bewirt.", "Gradation", "ungebunden", "attributlos gebunden", "gebunden", "Gesamt" ], ["Qualitätsstufe", "[°Oe]", "[kg]", "[€/kg]", "[kg]", "[€/kg]", "[kg]", "[€/kg]", "[€]" ], ["Grüner Veltliner", "3 219", "0", "0", "1 609,50"], diff --git a/Tests/UnitTests/DocumentTests/Utils.cs b/Tests/UnitTests/DocumentTests/Utils.cs index 9bc84b2..f60a447 100644 --- a/Tests/UnitTests/DocumentTests/Utils.cs +++ b/Tests/UnitTests/DocumentTests/Utils.cs @@ -1,4 +1,5 @@ using Elwig.Documents; +using Elwig.Helpers; using NReco.PdfRenderer; using System.Text.RegularExpressions; @@ -8,7 +9,9 @@ namespace Tests.UnitTests.DocumentTests { private static readonly string FileName = Path.Combine(Path.GetTempPath(), "test_document.pdf"); public static async Task GeneratePdfText(Document doc, bool preserveLayout = false) { - await doc.Generate(); + using (var ctx = new AppDbContext()) { + await doc.Generate(ctx); + } try { doc.SaveTo(FileName); var conv = new PdfToTextConverter { CustomArgs = preserveLayout ? "-layout " : "-raw " }; diff --git a/Tests/UnitTests/ServiceTests/DeliveryServiceTest.cs b/Tests/UnitTests/ServiceTests/DeliveryServiceTest.cs index 768e46b..a5504f2 100644 --- a/Tests/UnitTests/ServiceTests/DeliveryServiceTest.cs +++ b/Tests/UnitTests/ServiceTests/DeliveryServiceTest.cs @@ -32,7 +32,6 @@ namespace Tests.UnitTests.ServiceTests { .Include(d => d.Parts) .ThenInclude(p => p.PartModifiers) .ThenInclude(m => m.Modifier) - .AsSplitQuery() .FirstOrDefaultAsync(); } diff --git a/Tests/UnitTests/ServiceTests/MemberServiceTest.cs b/Tests/UnitTests/ServiceTests/MemberServiceTest.cs index c92e531..8a4dfd2 100644 --- a/Tests/UnitTests/ServiceTests/MemberServiceTest.cs +++ b/Tests/UnitTests/ServiceTests/MemberServiceTest.cs @@ -12,8 +12,8 @@ namespace Tests.UnitTests.ServiceTests { using var ctx = new AppDbContext(); vm.BranchSource = await ctx.Branches.ToListAsync(); vm.DefaultKgSource = await ctx.Katastralgemeinden.ToListAsync(); - vm.OrtSource = await ctx.PlzDestinations.Include(p => p.Ort).ToListAsync(); - vm.BillingOrtSource = await ctx.PlzDestinations.Include(p => p.Ort).ToListAsync(); + vm.OrtSource = await ctx.PlzDestinations.ToListAsync(); + vm.BillingOrtSource = await ctx.PlzDestinations.ToListAsync(); } [Test] @@ -36,17 +36,13 @@ namespace Tests.UnitTests.ServiceTests { Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(null)); - Member? m; + Member m; using (var ctx = new AppDbContext()) { m = await ctx.Members .Where(m => m.MgNr == vm.MgNr) - .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.DefaultWbKg!.AtKg) .Include(m => m.EmailAddresses) .Include(m => m.TelephoneNumbers) - .AsSplitQuery() - .FirstOrDefaultAsync(); + .SingleAsync(); } Assert.That(m, Is.Not.Null); @@ -124,17 +120,13 @@ namespace Tests.UnitTests.ServiceTests { Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(null)); - Member? m; + Member m; using (var ctx = new AppDbContext()) { m = await ctx.Members .Where(m => m.MgNr == vm.MgNr) - .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.DefaultWbKg!.AtKg) .Include(m => m.EmailAddresses) .Include(m => m.TelephoneNumbers) - .AsSplitQuery() - .FirstOrDefaultAsync(); + .SingleAsync(); } Assert.That(m, Is.Not.Null); @@ -236,13 +228,9 @@ namespace Tests.UnitTests.ServiceTests { using (var ctx = new AppDbContext()) { vm.FillInputs(await ctx.Members .Where(m => m.MgNr == 202) - .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.DefaultWbKg!.AtKg) .Include(m => m.EmailAddresses) .Include(m => m.TelephoneNumbers) - .AsSplitQuery() - .FirstAsync()); + .SingleAsync()); } Assert.That(vm.IsActive, Is.True); @@ -253,17 +241,13 @@ namespace Tests.UnitTests.ServiceTests { Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(202)); - Member? m; + Member m; using (var ctx = new AppDbContext()) { m = await ctx.Members .Where(m => m.MgNr == 202) - .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.DefaultWbKg!.AtKg) .Include(m => m.EmailAddresses) .Include(m => m.TelephoneNumbers) - .AsSplitQuery() - .FirstOrDefaultAsync(); + .SingleAsync(); } Assert.That(m, Is.Not.Null); @@ -288,13 +272,9 @@ namespace Tests.UnitTests.ServiceTests { using (var ctx = new AppDbContext()) { vm.FillInputs(await ctx.Members .Where(m => m.MgNr == 203) - .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.DefaultWbKg!.AtKg) .Include(m => m.EmailAddresses) .Include(m => m.TelephoneNumbers) - .AsSplitQuery() - .FirstAsync()); + .SingleAsync()); } Assert.Multiple(() => { @@ -306,17 +286,13 @@ namespace Tests.UnitTests.ServiceTests { vm.MgNr = 210; Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(203)); - Member? m; + Member m; using (var ctx = new AppDbContext()) { m = await ctx.Members .Where(m => m.MgNr == 210) - .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort) - .Include(m => m.PostalDest.AtPlz!.Ort) - .Include(m => m.DefaultWbKg!.AtKg) .Include(m => m.EmailAddresses) .Include(m => m.TelephoneNumbers) - .AsSplitQuery() - .FirstOrDefaultAsync(); + .SingleAsync(); } Assert.That(m, Is.Not.Null);