[#79] Entities: Remove EF proxies

This commit is contained in:
2026-04-01 16:24:03 +02:00
parent 4460de9975
commit 9c39a2f820
50 changed files with 471 additions and 413 deletions

View File

@@ -6,6 +6,7 @@ using Elwig.Helpers.Printing;
using Elwig.Helpers.Weighing; using Elwig.Helpers.Weighing;
using Elwig.Models.Entities; using Elwig.Models.Entities;
using Elwig.Windows; using Elwig.Windows;
using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
@@ -104,7 +105,9 @@ namespace Elwig {
Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = []; Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = [];
using (var ctx = new AppDbContext()) { 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 { try {
Client = new(ctx); Client = new(ctx);
} catch (Exception e) { } catch (Exception e) {

View File

@@ -52,7 +52,6 @@ namespace Elwig.Dialogs {
ControlUtils.RenewItemsSource(DeliveryInput, await ctx.Deliveries ControlUtils.RenewItemsSource(DeliveryInput, await ctx.Deliveries
.Where(d => d.DateString == $"{_delivery.Date:yyyy-MM-dd}" && d.ZwstId == _delivery.ZwstId) .Where(d => d.DateString == $"{_delivery.Date:yyyy-MM-dd}" && d.ZwstId == _delivery.ZwstId)
.OrderBy(d => d.LsNr) .OrderBy(d => d.LsNr)
.Include(d => d.Member)
.Include(d => d.Parts) .Include(d => d.Parts)
.ToListAsync()); .ToListAsync());
if (DeliveryInput.SelectedItem == null) if (DeliveryInput.SelectedItem == null)

View File

@@ -261,7 +261,7 @@ namespace Elwig.Documents {
} }
protected Table NewBucketTable( protected Table NewBucketTable(
Season season, Dictionary<string, MemberBucket> buckets, Season season, Dictionary<string, MemberBucket> buckets, int deliveredWeight,
bool includeDelivery = true, bool includePayment = false, bool includeDelivery = true, bool includePayment = false,
bool isTiny = false, IEnumerable<string>? filter = null bool isTiny = false, IEnumerable<string>? filter = null
) { ) {
@@ -315,10 +315,8 @@ namespace Elwig.Documents {
.OrderBy(b => b.Value.Name); .OrderBy(b => b.Value.Name);
tbl.AddCell(NewBucketTh("Gesamtlieferung lt. gez. GA", isTiny: isTiny)); tbl.AddCell(NewBucketTh("Gesamtlieferung lt. gez. GA", isTiny: isTiny));
tbl.AddCells(FormatRow(Member.BusinessShares * season.MinKgPerBusinessShare, tbl.AddCells(FormatRow(Member.BusinessShares * season.MinKgPerBusinessShare, Member.BusinessShares * season.MaxKgPerBusinessShare,
Member.BusinessShares * season.MaxKgPerBusinessShare, deliveredWeight, isGa: true, showPayment: includePayment, showArea: !includeDelivery, isTiny: isTiny));
season.Deliveries.Where(d => d.MgNr == Member.MgNr).Sum(d => d.Weight),
isGa: true, showPayment: includePayment, showArea: !includeDelivery, isTiny: isTiny));
if (fbs.Any()) { if (fbs.Any()) {
tbl.AddCell(NewBucketSubHdr("Flächenbindungen" + (vtr.Any() ? " (inkl. Verträge)" : "") + ":", includePayment ? 8 : 7, isTiny: isTiny)); tbl.AddCell(NewBucketSubHdr("Flächenbindungen" + (vtr.Any() ? " (inkl. Verträge)" : "") + ":", includePayment ? 8 : 7, isTiny: isTiny));

View File

@@ -1,55 +1,82 @@
using Elwig.Helpers; using Elwig.Helpers;
using Elwig.Helpers.Billing;
using Elwig.Models.Dtos; using Elwig.Models.Dtos;
using Elwig.Models.Entities; using Elwig.Models.Entities;
using iText.Kernel.Pdf; using iText.Kernel.Pdf;
using iText.Layout.Borders; using iText.Layout.Borders;
using iText.Layout.Element; using iText.Layout.Element;
using iText.Layout.Properties; using iText.Layout.Properties;
using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
namespace Elwig.Documents { namespace Elwig.Documents {
public class CreditNote : BusinessDocument { public class CreditNote : BusinessDocument {
public new static string Name => "Traubengutschrift"; public new static string Name => "Traubengutschrift";
public PaymentMember? Payment; public PaymentMember Payment;
public Credit? Credit; public Credit? Credit;
public CreditNoteDeliveryData Data;
public string? Text; public string? Text;
public string CurrencySymbol; public string CurrencySymbol;
public int Precision; public int Precision;
public string MemberModifier; public string? MemberModifier;
public List<(string Name, int Kg, decimal Amount)>? MemberUnderDeliveries; public List<(string Name, int Kg, decimal Amount)>? MemberUnderDeliveries;
public decimal MemberTotalUnderDelivery; public decimal MemberTotalUnderDelivery;
public int MemberAutoBusinessShares; public int MemberAutoBusinessShares;
public decimal MemberAutoBusinessSharesAmount; public decimal MemberAutoBusinessSharesAmount;
public PaymentCustom? CustomPayment; public PaymentCustom? CustomPayment;
public CreditNote( protected bool ConsiderContractPenalties;
AppDbContext ctx, protected bool ConsiderTotalPenalty;
PaymentMember p, protected bool ConsiderAutoBusinessShares;
CreditNoteDeliveryData data, protected bool ConsiderCustomModifiers;
bool considerContractPenalties,
bool considerTotalPenalty, private CreditNoteDeliveryData? _data;
bool considerAutoBusinessShares, private Dictionary<string, UnderDelivery>? _underDeliveries;
bool considerCustomModifiers,
Dictionary<string, UnderDelivery>? underDeliveries = null public CreditNote(PaymentMember p, BillingData? billingData = null, CreditNoteDeliveryData? data = null, Dictionary<string, UnderDelivery>? underDeliveries = null) :
) :
base($"{Name} {(p.Credit != null ? $"Nr. {p.Credit.Year}/{p.Credit.TgNr:000}" : p.Member.FullName)} {p.Variant.Name}", p.Member) { base($"{Name} {(p.Credit != null ? $"Nr. {p.Credit.Year}/{p.Credit.TgNr:000}" : p.Member.FullName)} {p.Variant.Name}", p.Member) {
UseBillingAddress = true; UseBillingAddress = true;
ShowDateAndLocation = true; ShowDateAndLocation = true;
Data = data;
Payment = p; Payment = p;
Credit = p.Credit; Credit = p.Credit;
IsPreview = Payment == null || Credit == null; Text = App.Client.TextCreditNote;
var season = p.Variant.Season; DocumentId = $"Tr.-Gutschr. " + (Credit != null ? $"{Credit.Year}/{Credit.TgNr:000}" : Payment.MgNr);
if (considerCustomModifiers) { IsPreview = Credit == null;
CustomPayment = ctx.CustomPayments.Find(p.Year, p.MgNr); _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<CreditNote> Initialize(int year, int avnr, int mgnr, BillingData? billingData = null, CreditNoteDeliveryData? data = null, Dictionary<string, UnderDelivery>? 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) { if (CustomPayment?.ModComment != null) {
MemberModifier = CustomPayment.ModComment; MemberModifier = CustomPayment.ModComment;
} else if (mod != null) { } else if (mod != null) {
@@ -57,32 +84,28 @@ namespace Elwig.Documents {
} else { } else {
MemberModifier = "Sonstige Zu-/Abschläge"; 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) { if (ConsiderTotalPenalty) {
var total = data.Rows.SelectMany(r => r.Buckets).Sum(b => b.Value); var total = _data.Rows.SelectMany(r => r.Buckets).Sum(b => b.Value);
var totalUnderDelivery = total - p.Member.BusinessShares * season.MinKgPerBusinessShare; 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; MemberTotalUnderDelivery = totalUnderDelivery < 0 ? totalUnderDelivery * (season.PenaltyPerKg ?? 0) - (season.PenaltyAmount ?? 0) - (season.PenaltyPerBsAmount * Math.Floor(-(decimal)totalUnderDelivery / season.MinKgPerBusinessShare) ?? 0) : 0;
if (total == 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 fromDate = $"{season.Year}-01-01";
var toDate = $"{season.Year}-12-31"; var toDate = $"{season.Year}-12-31";
MemberAutoBusinessShares = ctx.MemberHistory MemberAutoBusinessShares = await ctx.MemberHistory
.Where(h => h.MgNr == p.Member.MgNr && h.Type == "auto") .Where(h => h.MgNr == Member.MgNr && h.Type == "auto")
.Where(h => h.DateString.CompareTo(fromDate) >= 0 && h.DateString.CompareTo(toDate) <= 0) .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); MemberAutoBusinessSharesAmount = MemberAutoBusinessShares * (-season.BusinessShareValue ?? 0);
} }
if (considerContractPenalties) { if (ConsiderContractPenalties) {
var varieties = ctx.WineVarieties.ToDictionary(v => v.SortId, v => v); var varieties = await ctx.WineVarieties.ToDictionaryAsync(v => v.SortId, v => v);
var attributes = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a); var attributes = await ctx.WineAttributes.ToDictionaryAsync(a => a.AttrId, a => a);
var comTypes = ctx.AreaCommitmentTypes.ToDictionary(t => t.VtrgId, t => t); var comTypes = await ctx.AreaCommitmentTypes.ToDictionaryAsync(t => t.VtrgId, t => t);
MemberUnderDeliveries = underDeliveries? MemberUnderDeliveries = _underDeliveries?
.OrderBy(u => u.Key) .OrderBy(u => u.Key)
.Select(u => ( .Select(u => (
varieties[u.Key[..2]].Name + (u.Key.Length > 2 ? " " + attributes[u.Key[2..]].Name : ""), 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) { protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
if (_data == null) throw new Exception("Call LoadData before RenderBody");
base.RenderBody(doc, pdf); base.RenderBody(doc, pdf);
doc.Add(NewCreditTable(Data)); doc.Add(NewCreditTable(_data));
var div = new Table(ColsMM(60, 105)) var div = new Table(ColsMM(60, 105))
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout() .SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
@@ -131,7 +155,7 @@ namespace Elwig.Documents {
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE) .SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
.SetKeepTogether(true); .SetKeepTogether(true);
var sum = Data.Rows.Sum(p => p.Amount); var sum = _data.Rows.Sum(p => p.Amount);
if (Payment == null) { if (Payment == null) {
tbl1.AddCells(FormatRow("Gesamt", sum, bold: true, noTopBorder: true)); tbl1.AddCells(FormatRow("Gesamt", sum, bold: true, noTopBorder: true));
} else { } else {
@@ -139,7 +163,7 @@ namespace Elwig.Documents {
if (Payment.NetAmount != Payment.Amount) { if (Payment.NetAmount != Payment.Amount) {
tbl1.AddCells(FormatRow("Zwischensumme", Payment.NetAmount, noTopBorder: noBorder)); tbl1.AddCells(FormatRow("Zwischensumme", Payment.NetAmount, noTopBorder: noBorder));
noBorder = false; 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) { if (Credit == null) {
tbl1.AddCells(FormatRow("Gesamtbetrag", Payment.Amount, bold: true, noTopBorder: noBorder)); tbl1.AddCells(FormatRow("Gesamtbetrag", Payment.Amount, bold: true, noTopBorder: noBorder));

View File

@@ -5,33 +5,48 @@ using iText.Kernel.Pdf;
using iText.Layout.Borders; using iText.Layout.Borders;
using iText.Layout.Element; using iText.Layout.Element;
using iText.Layout.Properties; using iText.Layout.Properties;
using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
namespace Elwig.Documents { namespace Elwig.Documents {
public class DeliveryConfirmation : BusinessDocument { public class DeliveryConfirmation : BusinessDocument {
public new static string Name => "Anlieferungsbestätigung"; public new static string Name => "Anlieferungsbestätigung";
public Season Season; private readonly int _year;
public DeliveryConfirmationDeliveryData Data; public Season? Season;
public int MemberDeliveredWeight;
public DeliveryConfirmationDeliveryData? Data;
public string? Text = App.Client.TextDeliveryConfirmation; public string? Text = App.Client.TextDeliveryConfirmation;
public Dictionary<string, MemberBucket> MemberBuckets; public Dictionary<string, MemberBucket> MemberBuckets = [];
public List<MemberStat> MemberStats; public List<MemberStat> MemberStats = [];
public DeliveryConfirmation(AppDbContext ctx, int year, Member m, DeliveryConfirmationDeliveryData data) : public DeliveryConfirmation(int year, Member m, DeliveryConfirmationDeliveryData? data = null) :
base($"{Name} {year}", m) { base($"{Name} {year}", m) {
Season = ctx.Seasons.Find(year) ?? throw new ArgumentException("invalid season"); _year = year;
ShowDateAndLocation = true; ShowDateAndLocation = true;
UseBillingAddress = true; UseBillingAddress = true;
DocumentId = $"Anl.-Best. {Season.Year}/{m.MgNr}"; DocumentId = $"Anl.-Best. {_year}/{m.MgNr}";
Data = data; 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) { protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) {
if (Data == null) throw new Exception("Call LoadData before BeforeRenderBody");
base.BeforeRenderBody(doc, pdf); base.BeforeRenderBody(doc, pdf);
var firstDay = Data.Rows.MinBy(r => r.Date)?.Date; var firstDay = Data.Rows.MinBy(r => r.Date)?.Date;
var lastDay = Data.Rows.MaxBy(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) { 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); base.RenderBody(doc, pdf);
doc.Add(NewDeliveryListTable(Data)); doc.Add(NewDeliveryListTable(Data));
doc.Add(NewWeightsTable(MemberStats) doc.Add(NewWeightsTable(MemberStats)
.SetMarginTopMM(10).SetKeepTogether(true)); .SetMarginTopMM(10).SetKeepTogether(true));
doc.Add(NewBucketTable(Season, MemberBuckets, includePayment: true) doc.Add(NewBucketTable(Season, MemberBuckets, MemberDeliveredWeight, includePayment: true)
.SetMarginTopMM(10).SetKeepTogether(true)); .SetMarginTopMM(10).SetKeepTogether(true));
if (Text != null) { if (Text != null) {

View File

@@ -5,10 +5,12 @@ using iText.Layout.Borders;
using iText.Layout.Element; using iText.Layout.Element;
using iText.Layout.Layout; using iText.Layout.Layout;
using iText.Layout.Properties; using iText.Layout.Properties;
using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Elwig.Documents { namespace Elwig.Documents {
public class DeliveryNote : BusinessDocument { public class DeliveryNote : BusinessDocument {
@@ -17,7 +19,8 @@ namespace Elwig.Documents {
public Delivery Delivery; public Delivery Delivery;
public string? Text; public string? Text;
public Dictionary<string, MemberBucket> MemberBuckets; public int MemberDeliveredWeight;
public Dictionary<string, MemberBucket> MemberBuckets = [];
// 0 - none // 0 - none
// 1 - GA only // 1 - GA only
@@ -25,7 +28,7 @@ namespace Elwig.Documents {
// 3 - full // 3 - full
public int DisplayStats = App.Client.ModeDeliveryNoteStats; public int DisplayStats = App.Client.ModeDeliveryNoteStats;
public DeliveryNote(Delivery d, AppDbContext? ctx = null) : public DeliveryNote(Delivery d) :
base($"{Name} Nr. {d.LsNr}", d.Member) { base($"{Name} Nr. {d.LsNr}", d.Member) {
UseBillingAddress = true; UseBillingAddress = true;
ShowDateAndLocation = true; ShowDateAndLocation = true;
@@ -34,7 +37,34 @@ namespace Elwig.Documents {
DocumentId = d.LsNr; DocumentId = d.LsNr;
Date = DateOnly.FromDateTime(d.ModifiedAt); Date = DateOnly.FromDateTime(d.ModifiedAt);
IsDoublePaged = true; IsDoublePaged = true;
MemberBuckets = ctx?.GetMemberBuckets(d.Year, d.Member.MgNr).GetAwaiter().GetResult() ?? []; }
public static async Task<DeliveryNote> 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<DeliveryNote> 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) { 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)); doc.Add(new KernedParagraph($"Anmerkung zur Lieferung: {Delivery.Comment}", 10).SetMarginsMM(5, 0, 0, 0));
} }
if (DisplayStats > 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()) filter: DisplayStats > 2 ? null : DisplayStats == 1 ? [] : Delivery.Parts.Select(p => p.SortId).Distinct().ToList())
.SetKeepTogether(true) .SetKeepTogether(true)
.SetMarginsMM(5, 0, 0, 0)); .SetMarginsMM(5, 0, 0, 0));

View File

@@ -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 BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) { }
protected virtual void RenderBody(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); return new KernedParagraph(App.Client.NameFull, 10);
} }
public async Task Generate(CancellationToken? cancelToken = null, IProgress<double>? progress = null) { public async Task Generate(AppDbContext ctx, CancellationToken? cancelToken = null, IProgress<double>? progress = null) {
if (_pdfFile != null) if (_pdfFile != null)
return; return;
progress?.Report(0.0); progress?.Report(0.0);
@@ -181,6 +183,7 @@ namespace Elwig.Documents {
merger.Merge(src, 1, src.GetNumberOfPages()); merger.Merge(src, 1, src.GetNumberOfPages());
p += src.GetNumberOfPages(); p += src.GetNumberOfPages();
} else { } else {
await doc.LoadData(ctx);
int pageNum = doc.Render(tmpPdf.FilePath); int pageNum = doc.Render(tmpPdf.FilePath);
if (IsDoublePaged && doc is Letterhead) { if (IsDoublePaged && doc is Letterhead) {
using var reader = new PdfReader(tmpPdf.FilePath); using var reader = new PdfReader(tmpPdf.FilePath);
@@ -233,6 +236,7 @@ namespace Elwig.Documents {
throw new OperationCanceledException("Dokumentenerzeugung abgebrochen!"); throw new OperationCanceledException("Dokumentenerzeugung abgebrochen!");
var pdf = new TempFile("pdf"); var pdf = new TempFile("pdf");
try { try {
await LoadData(ctx);
TotalPages = Render(pdf.FilePath); TotalPages = Render(pdf.FilePath);
} catch { } catch {
pdf.Dispose(); pdf.Dispose();

View File

@@ -5,32 +5,55 @@ using iText.Kernel.Pdf;
using iText.Layout.Borders; using iText.Layout.Borders;
using iText.Layout.Element; using iText.Layout.Element;
using iText.Layout.Properties; using iText.Layout.Properties;
using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Elwig.Documents { namespace Elwig.Documents {
public class MemberDataSheet : BusinessDocument { public class MemberDataSheet : BusinessDocument {
public new static string Name => "Stammdatenblatt"; public new static string Name => "Stammdatenblatt";
public Season Season; public Season? Season;
public Dictionary<string, MemberBucket> MemberBuckets; public int MemberDeliveredWeight;
public List<AreaCom> ActiveAreaCommitments; public Dictionary<string, MemberBucket> MemberBuckets = [];
public List<AreaCom> ActiveAreaCommitments = [];
public MemberDataSheet(Member m, AppDbContext ctx) : public MemberDataSheet(Member m) :
base($"{Name} {m.AdministrativeName}", m) { base($"{Name} {m.AdministrativeName}", m) {
DocumentId = $"{Name} {m.MgNr}"; 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<MemberDataSheet> 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) { protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
if (Season == null) throw new Exception("Call LoadData before RenderBody");
base.RenderBody(doc, pdf); base.RenderBody(doc, pdf);
doc.Add(NewMemberData().SetMarginBottomMM(5)); doc.Add(NewMemberData(Season).SetMarginBottomMM(5));
doc.Add(NewBucketTable(Season, MemberBuckets, includeDelivery: false)); doc.Add(NewBucketTable(Season, MemberBuckets, MemberDeliveredWeight, includeDelivery: false));
if (ActiveAreaCommitments.Count != 0) { if (ActiveAreaCommitments.Count != 0) {
bool firstOnPage = false; bool firstOnPage = false;
if (pdf.GetNumberOfPages() == 1) { if (pdf.GetNumberOfPages() == 1) {
@@ -38,7 +61,7 @@ namespace Elwig.Documents {
firstOnPage = true; 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(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); .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)) var tbl = new Table(ColsMM(30.0, 51.5, 20.0, 12.0, 18.0, 31.5))
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout() .SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE) .SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
@@ -117,7 +140,7 @@ namespace Elwig.Documents {
.AddCell(NewDataTh("UID:", colspan: 2)).AddCell(NewTd(Member.UstIdNr, colspan: 2)) .AddCell(NewDataTh("UID:", colspan: 2)).AddCell(NewTd(Member.UstIdNr, colspan: 2))
.AddCell(NewDataTh("Stammgemeinde:")).AddCell(NewTd(Member.DefaultKg?.Name)) .AddCell(NewDataTh("Stammgemeinde:")).AddCell(NewTd(Member.DefaultKg?.Name))
.AddCell(NewDataTh("Buchführend:", colspan: 2)).AddCell(NewTd(new KernedParagraph(Member.IsBuchführend ? "Ja " : "Nein ", 10) .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("(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(NewDataTh("Bio:", colspan: 2)).AddCell(NewTd(Member.IsOrganic ? "Ja" : "Nein", colspan: 2))
.AddCell(NewDataHdr("Genossenschaft", colspan: 6)) .AddCell(NewDataHdr("Genossenschaft", colspan: 6))
@@ -134,8 +157,8 @@ namespace Elwig.Documents {
return tbl; return tbl;
} }
protected Table NewAreaComTable() { protected Table NewAreaComTable(IEnumerable<AreaCom> activeAreaComs) {
var areaComs = ActiveAreaCommitments.GroupBy(a => a.AreaComType).Select(group => new { var areaComs = activeAreaComs.GroupBy(a => a.AreaComType).Select(group => new {
Type = group.Key, Type = group.Key,
AreaComs = group.OrderBy(c => c.Contract.Kg.AtKg.Name).ToList(), AreaComs = group.OrderBy(c => c.Contract.Kg.AtKg.Name).ToList(),
Size = group.Sum(c => c.Area) 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("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)); tbl.AddCell(NewTd(colspan: 2, borderTop: true).SetPaddingsMM(1, 1, 1, 1));
return tbl; return tbl;

View File

@@ -7,40 +7,60 @@ using iText.Kernel.Pdf;
using iText.Layout.Borders; using iText.Layout.Borders;
using iText.Layout.Element; using iText.Layout.Element;
using iText.Layout.Properties; using iText.Layout.Properties;
using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
namespace Elwig.Documents { namespace Elwig.Documents {
public class PaymentVariantSummary : Document { public class PaymentVariantSummary : Document {
public new static string Name => "Auszahlungsvariante"; public new static string Name => "Auszahlungsvariante";
public PaymentVariantSummaryData Data; public PaymentVariantSummaryData? Data;
public PaymentVar Variant; public PaymentVar Variant;
public BillingData BillingData; public BillingData BillingData;
public string CurrencySymbol; public string CurrencySymbol;
public int MemberNum; public int MemberNum;
public int DeliveryNum; public int DeliveryNum;
public int DeliveryPartNum; public int DeliveryPartNum;
public List<ModifierStat> ModifierStat; public List<ModifierStat>? ModifierStat;
public Dictionary<string, Modifier> Modifiers; public Dictionary<string, Modifier>? Modifiers;
public PaymentVariantSummary(PaymentVar v, PaymentVariantSummaryData data) : private List<Credit> _credits = [];
private List<PaymentDeliveryPart> _parts = [];
public PaymentVariantSummary(PaymentVar v, PaymentVariantSummaryData? data = null) :
base($"{Name} {v.Year} - {v.Name}") { base($"{Name} {v.Year} - {v.Name}") {
Variant = v; Variant = v;
BillingData = BillingData.FromJson(v.Data); BillingData = BillingData.FromJson(v.Data);
Data = data; Data = data;
CurrencySymbol = v.Season.Currency.Symbol ?? v.Season.Currency.Code; CurrencySymbol = v.Season.Currency.Symbol ?? v.Season.Currency.Code;
MemberNum = v.Credits.Count; }
public static async Task<PaymentVariantSummary> 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; IsPreview = MemberNum == 0;
DeliveryNum = v.DeliveryPartPayments.DistinctBy(p => p.DeliveryPart.Delivery).Count(); DeliveryNum = await ctx.Deliveries.Where(d => d.Year == Variant.Year).CountAsync();
DeliveryPartNum = v.DeliveryPartPayments.Count; DeliveryPartNum = await ctx.DeliveryParts.Where(d => d.Year == Variant.Year).CountAsync();
ModifierStat = AppDbContext.GetModifierStats(v.Year, v.AvNr).GetAwaiter().GetResult(); Data ??= await PaymentVariantSummaryData.ForPaymentVariant(Variant, ctx.PaymentVariantSummaryRows);
Modifiers = v.Season.Modifiers.ToDictionary(m => m.ModId); 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) { 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); base.RenderBody(doc, pdf);
doc.Add(new KernedParagraph($"{Name} Lese {Variant.Year}", 24) doc.Add(new KernedParagraph($"{Name} Lese {Variant.Year}", 24)
.SetTextAlignment(TextAlignment.CENTER).SetFont(BF) .SetTextAlignment(TextAlignment.CENTER).SetFont(BF)
@@ -48,10 +68,10 @@ namespace Elwig.Documents {
doc.Add(new KernedParagraph(Variant.Name, 14) doc.Add(new KernedParagraph(Variant.Name, 14)
.SetTextAlignment(TextAlignment.CENTER).SetFont(BF) .SetTextAlignment(TextAlignment.CENTER).SetFont(BF)
.SetMarginsMM(0, 0, 10, 0)); .SetMarginsMM(0, 0, 10, 0));
doc.Add(NewVariantStatTable().SetMarginBottomMM(10)); doc.Add(NewVariantStatTable(Data).SetMarginBottomMM(10));
doc.Add(NewModifierStatTable()); doc.Add(NewModifierStatTable(Modifiers, ModifierStat));
doc.Add(new AreaBreak(AreaBreakType.NEXT_PAGE)); 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) { 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); .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)) var tbl = new Table(ColsMM(20, 30, 4.5, 4.5, 23.5, 47.5, 15, 20))
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout() .SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE) .SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
.SetBorder(new SolidBorder(BorderThickness)); .SetBorder(new SolidBorder(BorderThickness));
//var sum1 = Variant.DeliveryPartPayments.Sum(p => p.NetAmount); //var sum1 = _parts.Sum(p => p.NetAmount);
//var sum2 = Variant.Credits.Sum(p => p.); //Variant.MemberPayments.Sum(p => p.Amount); //var sum2 = _credits.Sum(p => p.); //Variant.MemberPayments.Sum(p => p.Amount);
var deliveryModifiers = Variant.DeliveryPartPayments.Sum(p => p.Amount - p.NetAmount); var deliveryModifiers = _parts.Sum(p => p.Amount - p.NetAmount);
var memberModifiers = Variant.Credits.Sum(c => c.Payment.Amount - c.Payment.NetAmount); var memberModifiers = _credits.Sum(c => c.Payment.Amount - c.Payment.NetAmount);
var sum2 = Variant.Credits.Sum(p => p.NetAmount); var sum2 = _credits.Sum(p => p.NetAmount);
var sum1 = sum2 - deliveryModifiers - memberModifiers; var sum1 = sum2 - deliveryModifiers - memberModifiers;
var payed = -Variant.Credits.Sum(p => p.PrevNetAmount ?? 0m); var payed = -_credits.Sum(p => p.PrevNetAmount ?? 0m);
var netSum = Variant.Credits.Sum(p => p.NetAmount) - Variant.Credits.Sum(p => p.PrevNetAmount ?? 0m); var netSum = _credits.Sum(p => p.NetAmount) - _credits.Sum(p => p.PrevNetAmount ?? 0m);
var vat = Variant.Credits.Sum(p => p.VatAmount); var vat = _credits.Sum(p => p.VatAmount);
var grossSum = Variant.Credits.Sum(p => p.GrossAmount); var grossSum = _credits.Sum(p => p.GrossAmount);
var totalMods = Variant.Credits.Sum(p => p.Modifiers ?? 0m); var totalMods = _credits.Sum(p => p.Modifiers ?? 0m);
var considered = -Variant.Credits.Sum(p => p.PrevModifiers ?? 0m); var considered = -_credits.Sum(p => p.PrevModifiers ?? 0m);
var totalSum = Variant.Credits.Sum(p => p.Amount); 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 minWei = weiRows.Min(r => r.Ungeb.MinPrice);
var maxWei = weiRows.Max(r => r.Ungeb.MaxPrice); 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 minPrice = quwRows.Min(r => r.Ungeb.MinPrice);
var maxPrice = quwRows.Max(r => r.Ungeb.MaxPrice); 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) .Where(r => r.Geb.MaxPrice != null && r.Ungeb.MinPrice != null)
.Select(r => r.Geb.MaxPrice - r.Ungeb.MinPrice); .Select(r => r.Geb.MaxPrice - r.Ungeb.MinPrice);
var minGeb = gebRows.Min(); var minGeb = gebRows.Min();
@@ -191,26 +211,26 @@ namespace Elwig.Documents {
.AddCell(NewTd(CurrencySymbol)) .AddCell(NewTd(CurrencySymbol))
.AddCell(NewTd($"{Math.Abs(totalMods):N2}", right: true)) .AddCell(NewTd($"{Math.Abs(totalMods):N2}", right: true))
.AddCell(NewSectionTh("Menge (ungebunden):", borderLeft: true, borderTop: 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(NewSectionTh("Bereits berücksichtigte Abzüge:", colspan: 2))
.AddCell(NewTd(Utils.GetSign(considered))) .AddCell(NewTd(Utils.GetSign(considered)))
.AddCell(NewTd(CurrencySymbol)) .AddCell(NewTd(CurrencySymbol))
.AddCell(NewTd($"{Math.Abs(considered):N2}", right: true)) .AddCell(NewTd($"{Math.Abs(considered):N2}", right: true))
.AddCell(NewSectionTh("Menge (gebunden):", borderLeft: 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(NewSectionTh("Auszahlungsbetrag:", colspan: 2))
.AddCell(NewTd(borderTop: true)) .AddCell(NewTd(borderTop: true))
.AddCell(NewTd(CurrencySymbol, borderTop: true)) .AddCell(NewTd(CurrencySymbol, borderTop: true))
.AddCell(NewTd($"{totalSum:N2}", right: true, borderTop: true)) .AddCell(NewTd($"{totalSum:N2}", right: true, borderTop: true))
.AddCell(NewSectionTh("Gesamtmenge:", borderLeft: 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; return tbl;
} }
protected Table NewModifierStatTable() { protected Table NewModifierStatTable(Dictionary<string, Modifier> modifiers, IEnumerable<ModifierStat> modStat) {
var tbl = new Table(ColsMM(35, 30, 25, 25, 25, 25)) var tbl = new Table(ColsMM(35, 30, 25, 25, 25, 25))
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout() .SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE) .SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
@@ -228,8 +248,8 @@ namespace Elwig.Documents {
.AddCell(NewTh($"[{CurrencySymbol}]")) .AddCell(NewTh($"[{CurrencySymbol}]"))
.AddCell(NewTh($"[{CurrencySymbol}]")); .AddCell(NewTh($"[{CurrencySymbol}]"));
foreach (var m in ModifierStat) { foreach (var m in modStat) {
var mod = Modifiers[m.ModId]; var mod = modifiers[m.ModId];
tbl.AddCell(NewTd(mod.Name, italic: true)) tbl.AddCell(NewTd(mod.Name, italic: true))
.AddCell(NewTd(mod.ValueStr, right: true)) .AddCell(NewTd(mod.ValueStr, right: true))
.AddCell(NewTd($"{m.Count:N0}", right: true)) .AddCell(NewTd($"{m.Count:N0}", right: true))
@@ -241,7 +261,7 @@ namespace Elwig.Documents {
return tbl; return tbl;
} }
protected Table NewPriceTable() { protected Table NewPriceTable(PaymentVariantSummaryData data) {
var tbl = new Table(ColsMM(25, 19, 18, 15, 18, 15, 18, 15, 22)) var tbl = new Table(ColsMM(25, 19, 18, 15, 18, 15, 18, 15, 22))
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout() .SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE); .SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE);
@@ -262,10 +282,10 @@ namespace Elwig.Documents {
.AddHeaderCell(NewTh($"[{CurrencySymbol}]")); .AddHeaderCell(NewTh($"[{CurrencySymbol}]"));
string? lastHdr = null; 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}"; var hdr = $"{row.Variety}{(row.Attribute != null ? " / " : "")}{row.Attribute}{(row.Cultivation != null ? " / " : "")}{row.Cultivation}";
if (lastHdr != hdr) { 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) .Where(r => r.Variety == row.Variety && r.Attribute == row.Attribute && r.Cultivation == row.Cultivation)
.ToList(); .ToList();
var border = lastHdr != null; var border = lastHdr != null;

View File

@@ -29,7 +29,6 @@
<PackageReference Include="itext.bouncy-castle-adapter" Version="9.5.0" /> <PackageReference Include="itext.bouncy-castle-adapter" Version="9.5.0" />
<PackageReference Include="LinqKit" Version="1.3.11" /> <PackageReference Include="LinqKit" Version="1.3.11" />
<PackageReference Include="MailKit" Version="4.15.1" /> <PackageReference Include="MailKit" Version="4.15.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="10.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.5" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="10.0.5" /> <PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="10.0.5" />
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3856.49" /> <PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3856.49" />

View File

@@ -119,11 +119,55 @@ namespace Elwig.Helpers {
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
optionsBuilder.UseSqlite(ConnectionString); optionsBuilder.UseSqlite(ConnectionString);
optionsBuilder.UseLazyLoadingProxies();
optionsBuilder.LogTo(Log, LogLevel.Information); optionsBuilder.LogTo(Log, LogLevel.Information);
base.OnConfiguring(optionsBuilder); base.OnConfiguring(optionsBuilder);
} }
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder.Entity<WbKg>().Navigation(k => k.AtKg).AutoInclude();
modelBuilder.Entity<WbKg>().Navigation(k => k.Gl).AutoInclude();
modelBuilder.Entity<AT_Kg>().Navigation(k => k.Gem).AutoInclude();
modelBuilder.Entity<PostalDest>().Navigation(p => p.Country).AutoInclude();
modelBuilder.Entity<PostalDest>().Navigation(p => p.AtPlz).AutoInclude();
modelBuilder.Entity<AT_PlzDest>().Navigation(p => p.AtPlz).AutoInclude();
modelBuilder.Entity<AT_PlzDest>().Navigation(p => p.Ort).AutoInclude();
modelBuilder.Entity<Member>().Navigation(m => m.DefaultWbKg).AutoInclude();
modelBuilder.Entity<Member>().Navigation(m => m.Country).AutoInclude();
modelBuilder.Entity<Member>().Navigation(m => m.PostalDest).AutoInclude();
modelBuilder.Entity<Member>().Navigation(m => m.BillingAddress).AutoInclude();
modelBuilder.Entity<BillingAddr>().Navigation(a => a.Country).AutoInclude();
modelBuilder.Entity<BillingAddr>().Navigation(a => a.PostalDest).AutoInclude();
modelBuilder.Entity<Modifier>().Navigation(m => m.Season).AutoInclude();
modelBuilder.Entity<Season>().Navigation(s => s.Currency).AutoInclude();
modelBuilder.Entity<PaymentVar>().Navigation(v => v.Season).AutoInclude();
modelBuilder.Entity<PaymentDeliveryPart>().Navigation(p => p.Variant).AutoInclude();
modelBuilder.Entity<Credit>().Navigation(c => c.Payment).AutoInclude();
modelBuilder.Entity<Delivery>().Navigation(d => d.Member).AutoInclude();
modelBuilder.Entity<Delivery>().Navigation(d => d.Season).AutoInclude();
modelBuilder.Entity<Delivery>().Navigation(d => d.Branch).AutoInclude();
modelBuilder.Entity<DeliveryPart>().Navigation(p => p.Quality).AutoInclude();
modelBuilder.Entity<DeliveryPart>().Navigation(p => p.Variety).AutoInclude();
modelBuilder.Entity<DeliveryPart>().Navigation(p => p.Attribute).AutoInclude();
modelBuilder.Entity<DeliveryPart>().Navigation(p => p.Cultivation).AutoInclude();
modelBuilder.Entity<DeliveryPart>().Navigation(p => p.Kg).AutoInclude();
modelBuilder.Entity<DeliveryPart>().Navigation(p => p.Rd).AutoInclude();
modelBuilder.Entity<DeliveryPartModifier>().Navigation(m => m.Modifier).AutoInclude();
modelBuilder.Entity<AreaComContract>().Navigation(c => c.Kg).AutoInclude();
modelBuilder.Entity<AreaComContract>().Navigation(c => c.Rd).AutoInclude();
modelBuilder.Entity<AreaCom>().Navigation(c => c.Contract).AutoInclude();
modelBuilder.Entity<AreaCom>().Navigation(c => c.WineCult).AutoInclude();
modelBuilder.Entity<AreaCom>().Navigation(c => c.AreaComType).AutoInclude();
modelBuilder.Entity<AreaComType>().Navigation(c => c.WineVar).AutoInclude();
modelBuilder.Entity<AreaComType>().Navigation(c => c.WineAttr).AutoInclude();
modelBuilder.Entity<PaymentMember>().Navigation(c => c.Credit).AutoInclude();
modelBuilder.Entity<PaymentMember>().Navigation(c => c.Member).AutoInclude();
modelBuilder.Entity<PaymentMember>().Navigation(c => c.Variant).AutoInclude();
modelBuilder.Entity<DeliveryAncmt>().Navigation(a => a.Member).AutoInclude();
modelBuilder.Entity<DeliveryAncmt>().Navigation(a => a.Schedule).AutoInclude();
modelBuilder.Entity<DeliveryAncmt>().Navigation(a => a.Variety).AutoInclude();
modelBuilder.Entity<DeliverySchedule>().Navigation(s => s.Branch).AutoInclude();
}
public override void Dispose() { public override void Dispose() {
base.Dispose(); base.Dispose();
LogFile?.Dispose(); LogFile?.Dispose();
@@ -399,10 +443,12 @@ namespace Elwig.Helpers {
var paymentBuckets = await GetMemberPaymentBuckets(year, mgnr, cnx); var paymentBuckets = await GetMemberPaymentBuckets(year, mgnr, cnx);
if (ownCnx) await cnx.DisposeAsync(); 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<string, MemberBucket>(); var buckets = new Dictionary<string, MemberBucket>();
foreach (var id in rightsAndObligations.Keys.Union(deliveryBuckets.Keys).Union(paymentBuckets.Keys)) { foreach (var id in rightsAndObligations.Keys.Union(deliveryBuckets.Keys).Union(paymentBuckets.Keys)) {
var variety = await WineVarieties.FindAsync(id[..2]); var variety = varieties.GetValueOrDefault(id[..2]);
var attribute = await WineAttributes.FindAsync(id[2..]); var attribute = attributes.GetValueOrDefault(id[2..]);
var name = (variety?.Name ?? "") + (id[2..] == "_" ? " (kein Qual.Wein)" : attribute != null ? $" ({attribute})" : ""); var name = (variety?.Name ?? "") + (id[2..] == "_" ? " (kein Qual.Wein)" : attribute != null ? $" ({attribute})" : "");
buckets[id] = new( buckets[id] = new(
name, name,

View File

@@ -21,7 +21,7 @@ namespace Elwig.Helpers.Billing {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
Season = ctx.Seasons.Find(Year)!; Season = ctx.Seasons.Find(Year)!;
Attributes = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a.Name); 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)); AreaComTypes = ctx.AreaCommitmentTypes.ToDictionary(v => v.VtrgId, v => (v.SortId, v.AttrId, v.Discriminator, v.MinKgPerHa, v.PenaltyAmount));
} }

View File

@@ -16,7 +16,7 @@ namespace Elwig.Helpers.Billing {
public BillingVariant(int year, int avnr) : base(year) { public BillingVariant(int year, int avnr) : base(year) {
AvNr = avnr; AvNr = avnr;
using var ctx = new AppDbContext(); 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)); Data = PaymentBillingData.FromJson(PaymentVariant.Data, Utils.GetVaributes(ctx, Year, onlyDelivered: false));
} }

View File

@@ -860,7 +860,7 @@ namespace Elwig.Helpers.Export {
["ried"] = p.Rd?.Name, ["ried"] = p.Rd?.Name,
["net_weight"] = p.IsNetWeight, ["net_weight"] = p.IsNetWeight,
["manual_weighing"] = p.IsManualWeighing, ["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, ["comment"] = p.Comment,
["created_at"] = $"{p.CreatedAt:yyyy-MM-ddTHH:mm:ssK}", ["created_at"] = $"{p.CreatedAt:yyyy-MM-ddTHH:mm:ssK}",
["modified_at"] = $"{p.ModifiedAt:yyyy-MM-ddTHH:mm:ssK}", ["modified_at"] = $"{p.ModifiedAt:yyyy-MM-ddTHH:mm:ssK}",

View File

@@ -557,7 +557,9 @@ namespace Elwig.Helpers {
"Vorläufiges Dokument", MessageBoxButton.OK, MessageBoxImage.Error); "Vorläufiges Dokument", MessageBoxButton.OK, MessageBoxImage.Error);
return; return;
} }
await doc.Generate(); using (var ctx = new AppDbContext()) {
await doc.Generate(ctx);
}
await doc.Print(); await doc.Print();
} else if (mode == ExportMode.Email && emailData is (Member, string, string) e) { } else if (mode == ExportMode.Email && emailData is (Member, string, string) e) {
if (doc.IsPreview) { if (doc.IsPreview) {
@@ -565,7 +567,9 @@ namespace Elwig.Helpers {
"Vorläufiges Dokument", MessageBoxButton.OK, MessageBoxImage.Error); "Vorläufiges Dokument", MessageBoxButton.OK, MessageBoxImage.Error);
return; return;
} }
await doc.Generate(); using (var ctx = new AppDbContext()) {
await doc.Generate(ctx);
}
var success = await SendEmail(e.Member, e.Subject, e.Text, [doc]); var success = await SendEmail(e.Member, e.Subject, e.Text, [doc]);
if (success) 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", 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" Title = $"{doc.Title} speichern unter - Elwig"
}; };
if (d.ShowDialog() == true) { if (d.ShowDialog() == true) {
await doc.Generate(); using (var ctx = new AppDbContext()) {
await doc.Generate(ctx);
}
doc.SaveTo(d.FileName); doc.SaveTo(d.FileName);
Process.Start("explorer.exe", d.FileName); Process.Start("explorer.exe", d.FileName);
} }
} else { } else {
await doc.Generate(); using (var ctx = new AppDbContext()) {
await doc.Generate(ctx);
}
doc.Show(); doc.Show();
} }
} }

View File

@@ -28,9 +28,9 @@ namespace Elwig.Models.Dtos {
} }
public static async Task<IDictionary<int, CreditNoteDeliveryData>> ForPaymentVariant(DbSet<CreditNoteDeliveryRowSingle> table, DbSet<PaymentVar> paymentVariants, int year, int avnr) { public static async Task<IDictionary<int, CreditNoteDeliveryData>> ForPaymentVariant(DbSet<CreditNoteDeliveryRowSingle> table, DbSet<PaymentVar> 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; 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)) return (await FromDbSet(table, year, avnr))
.GroupBy( .GroupBy(
r => new { r.Year, r.AvNr, r.MgNr, r.TgNr, r.DId, r.DPNr }, r => new { r.Year, r.AvNr, r.MgNr, r.TgNr, r.DId, r.DPNr },

View File

@@ -28,12 +28,7 @@ namespace Elwig.Models.Dtos {
} }
public static async Task<DeliveryAncmtListData> FromQuery(IQueryable<DeliveryAncmt> query, List<string> filterNames) { public static async Task<DeliveryAncmtListData> FromQuery(IQueryable<DeliveryAncmt> query, List<string> filterNames) {
return new((await query return new((await query.ToListAsync()).Select(d => new DeliveryAncmtListRow(d)), filterNames);
.Include(a => a.Schedule.Branch)
.Include(a => a.Member)
.Include(a => a.Variety)
.AsSplitQuery()
.ToListAsync()).Select(d => new DeliveryAncmtListRow(d)), filterNames);
} }
} }

View File

@@ -52,12 +52,8 @@ namespace Elwig.Models.Dtos {
if (mgnr != null) q = q.Where(p => p.Delivery.MgNr == mgnr); if (mgnr != null) q = q.Where(p => p.Delivery.MgNr == mgnr);
await q await q
.Include(p => p.Delivery) .Include(p => p.Delivery)
.Include(p => p.Variety)
.Include(p => p.Attribute)
.Include(p => p.Quality)
.Include(p => p.Buckets) .Include(p => p.Buckets)
.Include(p => p.PartModifiers) .Include(p => p.PartModifiers).ThenInclude(m => m.Modifier)
.ThenInclude(m => m.Modifier)
.LoadAsync(); .LoadAsync();
return await table.FromSqlRaw($""" return await table.FromSqlRaw($"""
SELECT p.* 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) 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) 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 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();
} }
} }

View File

@@ -40,12 +40,7 @@ namespace Elwig.Models.Dtos {
.Include(p => p.Delivery.Member.Branch) .Include(p => p.Delivery.Member.Branch)
.Include(p => p.Delivery.Branch) .Include(p => p.Delivery.Branch)
.Include(p => p.PartModifiers).ThenInclude(m => m.Modifier) .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.Origin)
.Include(p => p.Quality)
.AsSplitQuery()
.ToListAsync()).Select(d => new DeliveryJournalRow(d)), filterNames); .ToListAsync()).Select(d => new DeliveryJournalRow(d)), filterNames);
} }
} }

View File

@@ -47,15 +47,11 @@ namespace Elwig.Models.Dtos {
} }
public static async Task<MemberListData> FromQuery(IQueryable<Member> query, List<string> filterNames, IEnumerable<string> filterAreaCom) { public static async Task<MemberListData> FromQuery(IQueryable<Member> query, List<string> filterNames, IEnumerable<string> 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 return new((await query
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.Branch) .Include(m => m.Branch)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
.Include(m => m.TelephoneNumbers) .Include(m => m.TelephoneNumbers)
.Include(m => m.EmailAddresses) .Include(m => m.EmailAddresses)
.AsSplitQuery()
.ToListAsync()).Select(m => new MemberListRow(m, .ToListAsync()).Select(m => new MemberListRow(m,
areaComs[m.MgNr].Sum(c => c.Area), 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)))), areaComs[m.MgNr].Where(c => filterAreaCom.Contains(c.VtrgId)).GroupBy(c => c.VtrgId).ToDictionary(g => g.Key, g => g.Sum(c => c.Area)))),

View File

@@ -106,21 +106,21 @@ namespace Elwig.Models.Entities {
[InverseProperty(nameof(DeliveryPart.Delivery))] [InverseProperty(nameof(DeliveryPart.Delivery))]
public virtual ICollection<DeliveryPart> Parts { get; private set; } = null!; public virtual ICollection<DeliveryPart> Parts { get; private set; } = null!;
[NotMapped] [NotMapped]
public IEnumerable<DeliveryPart> FilteredParts => PartFilter == null ? Parts : Parts.Where(p => PartFilter(p)); public IEnumerable<DeliveryPart> FilteredParts => PartFilter == null ? Parts : Parts.Where(p => PartFilter(p));
[NotMapped] [NotMapped]
public Predicate<DeliveryPart>? PartFilter { get; set; } public Predicate<DeliveryPart>? PartFilter { get; set; }
public int Weight => Parts.Select(p => p.Weight).Sum(); public int Weight => Parts.Sum(p => p.Weight);
public int FilteredWeight => FilteredParts.Select(p => p.Weight).Sum(); public int FilteredWeight => FilteredParts.Sum(p => p.Weight);
public IEnumerable<RawVaribute> Vaributes => Parts public IEnumerable<RawVaribute> Vaributes => Parts
.GroupBy(p => (p.SortId, p.AttrId, p.CultId)) .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)); .Select(g => new RawVaribute(g.Key.SortId, g.Key.AttrId, g.Key.CultId));
public IEnumerable<RawVaribute> FilteredVaributes => FilteredParts public IEnumerable<RawVaribute> FilteredVaributes => FilteredParts
.GroupBy(p => (p.SortId, p.AttrId, p.CultId)) .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)); .Select(g => new RawVaribute(g.Key.SortId, g.Key.AttrId, g.Key.CultId));
public string VaributeString => string.Join(", ", Vaributes); public string VaributeString => string.Join(", ", Vaributes);
public string FilteredVaributeString => string.Join(", ", FilteredVaributes); public string FilteredVaributeString => string.Join(", ", FilteredVaributes);
@@ -153,7 +153,7 @@ namespace Elwig.Models.Entities {
Member.Name, Member.MiddleName, Member.GivenName, Member.BillingAddress?.FullName, Member.Name, Member.MiddleName, Member.GivenName, Member.BillingAddress?.FullName,
Comment Comment
}.ToList(); }.ToList();
list.AddRange(Parts.Select(p => p.Comment).Distinct()); list.AddRange(FilteredParts.Select(p => p.Comment).Distinct());
return Utils.GetSearchScore(list, keywords); return Utils.GetSearchScore(list, keywords);
} }
} }

View File

@@ -27,13 +27,15 @@ namespace Elwig.Models.Entities {
public virtual ICollection<WbGem> Gems { get; private set; } = null!; public virtual ICollection<WbGem> Gems { get; private set; } = null!;
[InverseProperty(nameof(Parent))] [InverseProperty(nameof(Parent))]
public virtual ICollection<WineOrigin> Children { get; private set; } = null!; public virtual ICollection<WineOrigin> RealChildren { get; private set; } = null!;
[NotMapped]
public List<WineOrigin> Children { get; private set; } = [];
public int Level => (Parent?.Level + 1) ?? 0; public int Level => (Parent?.Level + 1) ?? 0;
public string HkIdLevel => $"{new string(' ', Level * 2)}{HkId}"; 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)); private int SortKey1 => (Parent?.SortKey1 ?? 0) | (TotalChildNum << ((3 - Level) * 8));
public int SortKey => SortKey1 | ((Level < 3) ? (-1 >>> (Level * 8 + 8)) : 0); public int SortKey => SortKey1 | ((Level < 3) ? (-1 >>> (Level * 8 + 8)) : 0);

View File

@@ -27,10 +27,7 @@ namespace Elwig.Services {
public static async Task<Member?> GetMemberAsync(int mgnr) { public static async Task<Member?> GetMemberAsync(int mgnr) {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
return await ctx.Members return await ctx.Members.FirstOrDefaultAsync(m => m.MgNr == mgnr);
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.DefaultWbKg!.AtKg)
.FirstOrDefaultAsync(m => m.MgNr == mgnr);
} }
public static Member? GetMember(int mgnr) { public static Member? GetMember(int mgnr) {
@@ -71,7 +68,7 @@ namespace Elwig.Services {
vm.IsNetWeight = p.IsNetWeight; vm.IsNetWeight = p.IsNetWeight;
vm.Modifiers.Clear(); 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)!); vm.Modifiers.Add((Modifier)ControlUtils.GetItemFromSourceWithPk(vm.ModifiersSource, m.Year, m.ModId)!);
} }
@@ -472,6 +469,7 @@ namespace Elwig.Services {
DeliveryPart p; DeliveryPart p;
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
using var tx = await ctx.Database.BeginTransactionAsync();
int year = oldYear ?? Utils.CurrentYear; int year = oldYear ?? Utils.CurrentYear;
int did = oldDid ?? await ctx.NextDId(year); int did = oldDid ?? await ctx.NextDId(year);
int dpnr = oldDpnr ?? await ctx.NextDPNr(year, did); int dpnr = oldDpnr ?? await ctx.NextDPNr(year, did);
@@ -556,13 +554,13 @@ namespace Elwig.Services {
if (originalMgNr != null && originalMgNr.Value != d.MgNr) { if (originalMgNr != null && originalMgNr.Value != d.MgNr) {
// update origin (KgNr), if default is selected // update origin (KgNr), if default is selected
var newKgNr = (await ctx.Members.FindAsync(d.MgNr))?.DefaultKgNr; var newKgNr = (await ctx.Members.FindAsync(d.MgNr))?.DefaultKgNr;
foreach (var part in d.Parts.Where(part => part.DPNr != dpnr && part.KgNr == originalMemberKgNr)) { await ctx.DeliveryParts
part.KgNr = newKgNr; .Where(p => p.Year == d.Year && p.DId == d.DId && p.DPNr != dpnr && p.KgNr == originalMemberKgNr)
ctx.Update(part); .ExecuteUpdateAsync(u => u.SetProperty(p => p.KgNr, newKgNr));
}
} }
await ctx.SaveChangesAsync(); await ctx.SaveChangesAsync();
await tx.CommitAsync();
return p; return p;
}); });
@@ -574,7 +572,10 @@ namespace Elwig.Services {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
bool anyLeft = false; 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); var lnr = await ctx.NextLNr(d.Date, d.ZwstId);
n = new Delivery { n = new Delivery {
Year = year, Year = year,
@@ -601,7 +602,11 @@ namespace Elwig.Services {
anyLeft = true; anyLeft = true;
p.Weight -= w; p.Weight -= w;
ctx.Update(p); ctx.Update(p);
var s = ctx.CreateProxy<DeliveryPart>(); var s = new DeliveryPart {
SortId = null!,
QualId = null!,
HkId = null!,
};
var values = ctx.Entry(p).CurrentValues; var values = ctx.Entry(p).CurrentValues;
ctx.Entry(s).CurrentValues.SetValues(values); ctx.Entry(s).CurrentValues.SetValues(values);
s.Year = n.Year; s.Year = n.Year;
@@ -633,7 +638,10 @@ namespace Elwig.Services {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
var anyLeft = false; var anyLeft = false;
n = (await ctx.Deliveries.FirstAsync(d => d.LsNr == lsnr))!; 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); var dpnr = await ctx.NextDPNr(n.Year, n.DId);
foreach (var (p, w) in d.Parts.ToList().Zip(weights)) { foreach (var (p, w) in d.Parts.ToList().Zip(weights)) {
if (w <= 0) { if (w <= 0) {
@@ -645,7 +653,11 @@ namespace Elwig.Services {
anyLeft = true; anyLeft = true;
p.Weight -= w; p.Weight -= w;
ctx.Update(p); ctx.Update(p);
var s = ctx.CreateProxy<DeliveryPart>(); var s = new DeliveryPart {
SortId = null!,
QualId = null!,
HkId = null!,
};
var values = ctx.Entry(p).CurrentValues; var values = ctx.Entry(p).CurrentValues;
ctx.Entry(s).CurrentValues.SetValues(values); ctx.Entry(s).CurrentValues.SetValues(values);
s.Year = n.Year; s.Year = n.Year;
@@ -674,7 +686,10 @@ namespace Elwig.Services {
public static async Task DepreciateDelivery(int year, int did, int[] weights) { public static async Task DepreciateDelivery(int year, int did, int[] weights) {
await Task.Run(async () => { await Task.Run(async () => {
using var ctx = new AppDbContext(); 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); var dpnr = await ctx.NextDPNr(year, did);
foreach (var (p, w) in d.Parts.ToList().Zip(weights)) { foreach (var (p, w) in d.Parts.ToList().Zip(weights)) {
if (w <= 0) { if (w <= 0) {
@@ -686,7 +701,11 @@ namespace Elwig.Services {
} else { } else {
p.Weight -= w; p.Weight -= w;
ctx.Update(p); ctx.Update(p);
var n = ctx.CreateProxy<DeliveryPart>(); var n = new DeliveryPart {
SortId = null!,
QualId = null!,
HkId = null!,
};
var values = ctx.Entry(p).CurrentValues; var values = ctx.Entry(p).CurrentValues;
ctx.Entry(n).CurrentValues.SetValues(values); ctx.Entry(n).CurrentValues.SetValues(values);
n.DPNr = dpnr++; n.DPNr = dpnr++;
@@ -711,10 +730,8 @@ namespace Elwig.Services {
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => { await Task.Run(async () => {
try { try {
using var ctx = new AppDbContext(); using var doc = await DeliveryNote.Initialize(year, did);
var d = (await ctx.Deliveries.FindAsync(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}"));
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}"));
} catch (Exception exc) { } catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
} }
@@ -792,9 +809,6 @@ namespace Elwig.Services {
.Select(p => p.Delivery) .Select(p => p.Delivery)
.Distinct() .Distinct()
.Include(d => d.Parts).ThenInclude(p => p.PartModifiers) .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(); .ToListAsync();
var wbKgs = list var wbKgs = list
.SelectMany(d => d.Parts) .SelectMany(d => d.Parts)

View File

@@ -395,8 +395,7 @@ namespace Elwig.Services {
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => { await Task.Run(async () => {
try { try {
using var ctx = new AppDbContext(); using var doc = new MemberDataSheet(m);
using var doc = new MemberDataSheet(m, ctx);
await Utils.ExportDocument(doc, mode, emailData: (m, MemberDataSheet.Name, "Im Anhang finden Sie das aktuelle Stammdatenblatt")); await Utils.ExportDocument(doc, mode, emailData: (m, MemberDataSheet.Name, "Im Anhang finden Sie das aktuelle Stammdatenblatt"));
} catch (Exception exc) { } catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
@@ -414,9 +413,7 @@ namespace Elwig.Services {
await b.CalculateBuckets(); await b.CalculateBuckets();
App.HintContextChange(); App.HintContextChange();
using var ctx = new AppDbContext(); using var doc = new DeliveryConfirmation(year, m);
var data = await DeliveryConfirmationDeliveryData.ForMember(ctx.DeliveryParts, year, m);
using var doc = new DeliveryConfirmation(ctx, year, m, data);
await Utils.ExportDocument(doc, mode, emailData: (m, $"{DeliveryConfirmation.Name} {year}", $"Im Anhang finden Sie die Anlieferungsbestätigung {year}")); await Utils.ExportDocument(doc, mode, emailData: (m, $"{DeliveryConfirmation.Name} {year}", $"Im Anhang finden Sie die Anlieferungsbestätigung {year}"));
} catch (Exception exc) { } catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
@@ -429,16 +426,8 @@ namespace Elwig.Services {
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => { await Task.Run(async () => {
try { try {
using var ctx = new AppDbContext(); using var doc = await CreditNote.Initialize(year, avnr, m.MgNr);
var v = (await ctx.PaymentVariants.FindAsync(year, avnr))!; await Utils.ExportDocument(doc, mode, emailData: (m, $"{CreditNote.Name} {doc.Payment.Variant.Name}", $"Im Anhang finden Sie die Traubengutschrift {doc.Payment.Variant.Name}"));
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}"));
} catch (Exception exc) { } catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
} }
@@ -520,10 +509,8 @@ namespace Elwig.Services {
try { try {
var members = await query var members = await query
.OrderBy(m => m.MgNr) .OrderBy(m => m.MgNr)
.Include(m => m.BillingAddress)
.Include(m => m.TelephoneNumbers) .Include(m => m.TelephoneNumbers)
.Include(m => m.EmailAddresses) .Include(m => m.EmailAddresses)
.AsSplitQuery()
.ToListAsync(); .ToListAsync();
using var exporter = new VCard(d.FileName); using var exporter = new VCard(d.FileName);
await exporter.ExportAsync(members); await exporter.ExportAsync(members);
@@ -548,17 +535,12 @@ namespace Elwig.Services {
try { try {
var members = await query var members = await query
.OrderBy(m => m.MgNr) .OrderBy(m => m.MgNr)
.Include(m => m.BillingAddress)
.Include(m => m.TelephoneNumbers) .Include(m => m.TelephoneNumbers)
.Include(m => m.EmailAddresses) .Include(m => m.EmailAddresses)
.Include(m => m.DefaultWbKg!.Gl)
.AsSplitQuery()
.ToListAsync(); .ToListAsync();
var areaComs = await query var areaComs = await query
.SelectMany(m => m.AreaCommitments) .SelectMany(m => m.AreaCommitments)
.Select(c => c.Contract).Distinct() .Select(c => c.Contract).Distinct()
.Include(c => c.Rd)
.Include(c => c.Kg.Gl)
.Include(c => c.Revisions) .Include(c => c.Revisions)
.ToListAsync(); .ToListAsync();
var wbKgs = members var wbKgs = members
@@ -725,18 +707,20 @@ namespace Elwig.Services {
public static async Task DeleteMember(int mgnr, bool deletePaymentData, bool deleteDeliveries, bool deleteAreaComs) { public static async Task DeleteMember(int mgnr, bool deletePaymentData, bool deleteDeliveries, bool deleteAreaComs) {
await Task.Run(async () => { await Task.Run(async () => {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
using var tx = await ctx.Database.BeginTransactionAsync();
var l = (await ctx.Members.FindAsync(mgnr))!; var l = (await ctx.Members.FindAsync(mgnr))!;
if (deletePaymentData) { if (deletePaymentData) {
ctx.RemoveRange(l.Credits); await ctx.Credits.Where(c => c.MgNr == mgnr).ExecuteDeleteAsync();
} }
if (deleteDeliveries) { if (deleteDeliveries) {
ctx.RemoveRange(l.Deliveries); await ctx.Deliveries.Where(c => c.MgNr == mgnr).ExecuteDeleteAsync();
} }
if (deleteAreaComs) { if (deleteAreaComs) {
ctx.RemoveRange(l.AreaCommitments); await ctx.AreaCommitments.Where(c => c.MgNr == mgnr).ExecuteDeleteAsync();
} }
ctx.Remove(l); ctx.Remove(l);
await ctx.SaveChangesAsync(); await ctx.SaveChangesAsync();
await tx.CommitAsync();
}); });
} }
} }

View File

@@ -214,9 +214,7 @@ namespace Elwig.Services {
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => { await Task.Run(async () => {
try { try {
using var ctx = new AppDbContext(); using var doc = await PaymentVariantSummary.Initialize(v.Year, v.AvNr);
var data = await PaymentVariantSummaryData.ForPaymentVariant(v, ctx.PaymentVariantSummaryRows);
using var doc = new PaymentVariantSummary((await ctx.PaymentVariants.FindAsync(v.Year, v.AvNr))!, data);
await Utils.ExportDocument(doc, mode); await Utils.ExportDocument(doc, mode);
} catch (Exception exc) { } catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);

View File

@@ -25,18 +25,13 @@ namespace Elwig.Services {
var path = Path.Combine(App.TempPath, filename); var path = Path.Combine(App.TempPath, filename);
var members = await query var members = await query
.OrderBy(m => m.MgNr) .OrderBy(m => m.MgNr)
.Include(m => m.BillingAddress)
.Include(m => m.TelephoneNumbers) .Include(m => m.TelephoneNumbers)
.Include(m => m.EmailAddresses) .Include(m => m.EmailAddresses)
.Include(m => m.DefaultWbKg!.Gl)
.AsSplitQuery()
.ToListAsync(); .ToListAsync();
var areaComs = await query var areaComs = await query
.SelectMany(m => m.AreaCommitments) .SelectMany(m => m.AreaCommitments)
.Select(c => c.Contract).Distinct() .Select(c => c.Contract).Distinct()
.OrderBy(c => c.FbNr) .OrderBy(c => c.FbNr)
.Include(c => c.Rd)
.Include(c => c.Kg.Gl)
.Include(c => c.Revisions) .Include(c => c.Revisions)
.ToListAsync(); .ToListAsync();
var wbKgs = members var wbKgs = members
@@ -73,10 +68,7 @@ namespace Elwig.Services {
var list = await query var list = await query
.Select(p => p.Delivery) .Select(p => p.Delivery)
.Distinct() .Distinct()
.Include(d => d.Parts).ThenInclude(p => p.PartModifiers).ThenInclude(m => m.Modifier) .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(); .ToListAsync();
var wbKgs = list var wbKgs = list
.SelectMany(d => d.Parts) .SelectMany(d => d.Parts)
@@ -114,27 +106,19 @@ namespace Elwig.Services {
using (var ctx = new AppDbContext()) { using (var ctx = new AppDbContext()) {
members = await ctx.Members members = await ctx.Members
.Where(ChangedMembers) .Where(ChangedMembers)
.Include(m => m.BillingAddress)
.Include(m => m.TelephoneNumbers) .Include(m => m.TelephoneNumbers)
.Include(m => m.EmailAddresses) .Include(m => m.EmailAddresses)
.Include(m => m.DefaultWbKg!.Gl)
.OrderBy(m => m.MgNr) .OrderBy(m => m.MgNr)
.AsSplitQuery()
.ToListAsync(); .ToListAsync();
areaComs = await ctx.AreaCommitmentContracts areaComs = await ctx.AreaCommitmentContracts
.Where(ChangedAreaComContracts) .Where(ChangedAreaComContracts)
.Include(c => c.Rd)
.Include(c => c.Kg.Gl)
.Include(c => c.Revisions) .Include(c => c.Revisions)
.OrderBy(c => c.FbNr) .OrderBy(c => c.FbNr)
.ToListAsync(); .ToListAsync();
deliveries = await ctx.Deliveries deliveries = await ctx.Deliveries
.Where(ChangedDeliveries) .Where(ChangedDeliveries)
.Include(d => d.Parts).ThenInclude(p => p.PartModifiers).ThenInclude(m => m.Modifier) .Include(d => d.Parts).ThenInclude(p => p.PartModifiers)
.Include(d => d.Parts).ThenInclude(p => p.Rd)
.Include(d => d.Parts).ThenInclude(p => p.Kg).ThenInclude(k => k!.Gl)
.OrderBy(d => d.DateString).ThenBy(d => d.TimeString).ThenBy(d => d.LsNr) .OrderBy(d => d.DateString).ThenBy(d => d.TimeString).ThenBy(d => d.LsNr)
.AsSplitQuery()
.ToListAsync(); .ToListAsync();
} }
var wbKgs = members var wbKgs = members
@@ -179,11 +163,8 @@ namespace Elwig.Services {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
var deliveries = await ctx.Deliveries var deliveries = await ctx.Deliveries
.Where(d => d.Year == year && d.ZwstId == App.ZwstId) .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.PartModifiers)
.Include(d => d.Parts).ThenInclude(p => p.Rd)
.Include(d => d.Parts).ThenInclude(p => p.Kg).ThenInclude(k => k!.Gl)
.OrderBy(d => d.DateString).ThenBy(d => d.TimeString).ThenBy(d => d.LsNr) .OrderBy(d => d.DateString).ThenBy(d => d.TimeString).ThenBy(d => d.LsNr)
.AsSplitQuery()
.ToListAsync(); .ToListAsync();
var wbKgs = deliveries var wbKgs = deliveries
.SelectMany(d => d.Parts) .SelectMany(d => d.Parts)

View File

@@ -20,7 +20,7 @@ namespace Elwig.ViewModels {
public List<string> TextFilter => [.. SearchQuery?.ToLower().Split(' ').ToList().FindAll(e => e.Length > 0) ?? []]; public List<string> TextFilter => [.. SearchQuery?.ToLower().Split(' ').ToList().FindAll(e => e.Length > 0) ?? []];
[ObservableProperty] [ObservableProperty]
private bool _showOnlyActiveMembers; private bool _showOnlyActiveMembers = true;
[ObservableProperty] [ObservableProperty]
private Member? _selectedMember; private Member? _selectedMember;

View File

@@ -349,7 +349,6 @@ namespace Elwig.Windows {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
list = await ctx.PlzDestinations list = await ctx.PlzDestinations
.Where(p => p.Plz == plz) .Where(p => p.Plz == plz)
.Include(p => p.Ort)
.ToListAsync(); .ToListAsync();
} }

View File

@@ -59,20 +59,9 @@ namespace Elwig.Windows {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
var (_, contractQuery, areaComQuery, filter) = await vm.GetFilters(ctx); var (_, contractQuery, areaComQuery, filter) = await vm.GetFilters(ctx);
var contracts = await contractQuery 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) .Include(c => c.Revisions).ThenInclude(a => a.Member)
.ToListAsync(); .ToListAsync();
var areaComs = await areaComQuery var areaComs = await areaComQuery.ToListAsync();
.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();
if (filter.Count > 0 && contracts.Count > 0) { if (filter.Count > 0 && contracts.Count > 0) {
var dict = contracts.AsParallel() var dict = contracts.AsParallel()

View File

@@ -21,8 +21,6 @@ namespace Elwig.Windows {
private async Task AreaCommitmentTypesInitEditing(AppDbContext ctx) { private async Task AreaCommitmentTypesInitEditing(AppDbContext ctx) {
_actList = new(await ctx.AreaCommitmentTypes _actList = new(await ctx.AreaCommitmentTypes
.OrderBy(v => v.VtrgId) .OrderBy(v => v.VtrgId)
.Include(t => t.WineVar)
.Include(t => t.WineAttr)
.ToListAsync()); .ToListAsync());
_acts = _actList.ToDictionary(v => v.VtrgId, v => (string?)v.VtrgId); _acts = _actList.ToDictionary(v => v.VtrgId, v => (string?)v.VtrgId);
_actIds = _actList.ToDictionary(v => v, v => v.VtrgId); _actIds = _actList.ToDictionary(v => v, v => v.VtrgId);

View File

@@ -21,7 +21,7 @@ namespace Elwig.Windows {
private async Task BranchesInitEditing(AppDbContext ctx) { private async Task BranchesInitEditing(AppDbContext ctx) {
_branchList = new(await ctx.Branches _branchList = new(await ctx.Branches
.OrderBy(b => b.Name) .OrderBy(b => b.Name)
.Include(b => b.PostalDest!.AtPlz) .Include(b => b.PostalDest)
.ToListAsync()); .ToListAsync());
_branches = _branchList.ToDictionary(b => b.ZwstId, b => (string?)b.ZwstId); _branches = _branchList.ToDictionary(b => b.ZwstId, b => (string?)b.ZwstId);
_branchIds = _branchList.ToDictionary(b => b, b => b.ZwstId); _branchIds = _branchList.ToDictionary(b => b, b => b.ZwstId);
@@ -32,7 +32,7 @@ namespace Elwig.Windows {
private async Task BranchesFinishEditing(AppDbContext ctx) { private async Task BranchesFinishEditing(AppDbContext ctx) {
ControlUtils.RenewItemsSource(BranchList, await ctx.Branches ControlUtils.RenewItemsSource(BranchList, await ctx.Branches
.OrderBy(b => b.Name) .OrderBy(b => b.Name)
.Include(b => b.PostalDest!.AtPlz) .Include(b => b.PostalDest)
.ToListAsync()); .ToListAsync());
_branchList = null; _branchList = null;
_branches = null; _branches = null;

View File

@@ -22,7 +22,6 @@ namespace Elwig.Windows {
ControlUtils.RenewItemsSource(SeasonList, await ctx.Seasons ControlUtils.RenewItemsSource(SeasonList, await ctx.Seasons
.OrderByDescending(s => s.Year) .OrderByDescending(s => s.Year)
.Include(s => s.Modifiers) .Include(s => s.Modifiers)
.Include(s => s.Currency)
.ToListAsync()); .ToListAsync());
SeasonList_SelectionChanged(null, null); SeasonList_SelectionChanged(null, null);
} }
@@ -33,7 +32,6 @@ namespace Elwig.Windows {
ControlUtils.RenewItemsSource(SeasonList, await ctx.Seasons ControlUtils.RenewItemsSource(SeasonList, await ctx.Seasons
.OrderByDescending(s => s.Year) .OrderByDescending(s => s.Year)
.Include(s => s.Modifiers) .Include(s => s.Modifiers)
.Include(s => s.Currency)
.ToListAsync()); .ToListAsync());
_seasonChanged = false; _seasonChanged = false;
} }

View File

@@ -163,12 +163,11 @@ namespace Elwig.Windows {
ControlUtils.RenewItemsSource(SeasonList, await ctx.Seasons ControlUtils.RenewItemsSource(SeasonList, await ctx.Seasons
.OrderByDescending(s => s.Year) .OrderByDescending(s => s.Year)
.Include(s => s.Modifiers) .Include(s => s.Modifiers)
.Include(s => s.Currency)
.ToListAsync(), null, ControlUtils.RenewSourceDefault.First); .ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
var year = (SeasonList.SelectedItem as Season)?.Year; var year = (SeasonList.SelectedItem as Season)?.Year;
ControlUtils.RenewItemsSource(BranchList, await ctx.Branches ControlUtils.RenewItemsSource(BranchList, await ctx.Branches
.OrderBy(b => b.Name) .OrderBy(b => b.Name)
.Include(b => b.PostalDest!.AtPlz) .Include(b => b.PostalDest)
.ToListAsync(), null, ControlUtils.RenewSourceDefault.First); .ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
ControlUtils.RenewItemsSource(WineAttributeList, await ctx.WineAttributes ControlUtils.RenewItemsSource(WineAttributeList, await ctx.WineAttributes
.OrderBy(a => a.Name) .OrderBy(a => a.Name)
@@ -181,8 +180,6 @@ namespace Elwig.Windows {
ControlUtils.RenewItemsSource(AreaCommitmentTypeWineAttributeInput, attrList); ControlUtils.RenewItemsSource(AreaCommitmentTypeWineAttributeInput, attrList);
ControlUtils.RenewItemsSource(AreaCommitmentTypeList, await ctx.AreaCommitmentTypes ControlUtils.RenewItemsSource(AreaCommitmentTypeList, await ctx.AreaCommitmentTypes
.OrderBy(t => t.VtrgId) .OrderBy(t => t.VtrgId)
.Include(t => t.WineVar)
.Include(t => t.WineAttr)
.ToListAsync(), null, ControlUtils.RenewSourceDefault.First); .ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
ControlUtils.RenewItemsSource(WineCultivationList, await ctx.WineCultivations ControlUtils.RenewItemsSource(WineCultivationList, await ctx.WineCultivations
.OrderBy(c => c.Name) .OrderBy(c => c.Name)

View File

@@ -429,10 +429,9 @@ namespace Elwig.Windows {
var (_, deliveryQuery, deliveryPartsQuery, predicate, filter) = await vm.GetFilters(ctx); var (_, deliveryQuery, deliveryPartsQuery, predicate, filter) = await vm.GetFilters(ctx);
var deliveries = await deliveryQuery var deliveries = await deliveryQuery
.Include(d => d.Parts).ThenInclude(p => p.PartModifiers).ThenInclude(m => m.Modifier) .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.Parts).ThenInclude(p => p.Variety)
.Include(d => d.Member.EmailAddresses) .Include(d => d.Member.EmailAddresses)
.IgnoreAutoIncludes()
.AsSplitQuery() .AsSplitQuery()
.ToListAsync(); .ToListAsync();
deliveries.Reverse(); deliveries.Reverse();
@@ -442,7 +441,7 @@ namespace Elwig.Windows {
.ToDictionary(d => d, d => d.SearchScore(vm.TextFilter)) .ToDictionary(d => d, d => d.SearchScore(vm.TextFilter))
.OrderByDescending(a => a.Value) .OrderByDescending(a => a.Value)
.ThenBy(a => a.Key.DateTime); .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 deliveries = [.. dict
.Where(a => a.Value > threshold) .Where(a => a.Value > threshold)
.Select(a => a.Key)]; .Select(a => a.Key)];
@@ -452,7 +451,7 @@ namespace Elwig.Windows {
var deliveryPartsNum = await deliveryPartsQuery.CountAsync(); var deliveryPartsNum = await deliveryPartsQuery.CountAsync();
var varieties = await deliveryPartsQuery.Select(d => d.SortId).Distinct().ToListAsync(); 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); var stat = await DeliveryService.GenerateToolTipData(deliveryPartsQuery);
return (filter, deliveries, deliveryPartsNum, varieties, members, stat); return (filter, deliveries, deliveryPartsNum, varieties, members, stat);
@@ -498,7 +497,7 @@ namespace Elwig.Windows {
int year = 0; int year = 0;
Menu_Bki_SaveList.Items.Clear(); 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; if (s.Year > year) year = s.Year;
var i = new MenuItem { var i = new MenuItem {
Header = $"Saison {s.Year}", Header = $"Saison {s.Year}",
@@ -515,7 +514,7 @@ namespace Elwig.Windows {
}; };
noAttr.Click += Menu_BulkAction_SetAttribute_Click; noAttr.Click += Menu_BulkAction_SetAttribute_Click;
Menu_BulkAction_SetAttribute.Items.Add(noAttr); 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 { var i = new MenuItem {
Header = attr.Name, Header = attr.Name,
}; };
@@ -525,7 +524,7 @@ namespace Elwig.Windows {
Menu_BulkAction_AddModifier.Items.Clear(); Menu_BulkAction_AddModifier.Items.Clear();
Menu_BulkAction_RemoveModifier.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 { var i1 = new MenuItem {
Header = mod.Name, Header = mod.Name,
}; };
@@ -543,8 +542,6 @@ namespace Elwig.Windows {
var y = d?.Year ?? ViewModel.FilterSeason; var y = d?.Year ?? ViewModel.FilterSeason;
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
.Where(m => m.IsActive || !IsCreating) .Where(m => m.IsActive || !IsCreating)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.DefaultWbKg!.AtKg)
.OrderBy(m => m.Name) .OrderBy(m => m.Name)
.ThenBy(m => m.GivenName) .ThenBy(m => m.GivenName)
.ToListAsync()); .ToListAsync());
@@ -561,15 +558,16 @@ namespace Elwig.Windows {
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers
.Where(m => m.Year == y && (!IsCreating || m.IsActive)) .Where(m => m.Year == y && (!IsCreating || m.IsActive))
.OrderBy(m => m.Ordering) .OrderBy(m => m.Ordering)
.Include(m => m.Season.Currency)
.ToListAsync()); .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 var kgList = (await ctx.Katastralgemeinden
.Where(k => k.WbKg != null) .Where(k => k.WbKg != null)
.Include(k => k.WbKg) .Include(k => k.WbKg)
.Include(k => k.Gem.WbGem) .Include(k => k.Gem.WbGem)
.OrderBy(k => k.Name) .OrderBy(k => k.Name)
.AsSplitQuery()
.ToListAsync()).Cast<object>().ToList(); .ToListAsync()).Cast<object>().ToList();
kgList.Insert(0, new NullItem()); kgList.Insert(0, new NullItem());
ControlUtils.RenewItemsSource(WineKgInput, kgList); ControlUtils.RenewItemsSource(WineKgInput, kgList);
@@ -592,14 +590,12 @@ namespace Elwig.Windows {
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers
.Where(m => m.Year == d.Year && (!IsCreating || m.IsActive)) .Where(m => m.Year == d.Year && (!IsCreating || m.IsActive))
.OrderBy(m => m.Ordering) .OrderBy(m => m.Ordering)
.Include(m => m.Season.Currency)
.ToListAsync()); .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 { } else {
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers
.Where(m => m.Year == ViewModel.FilterSeason && (!IsCreating || m.IsActive)) .Where(m => m.Year == ViewModel.FilterSeason && (!IsCreating || m.IsActive))
.OrderBy(m => m.Ordering) .OrderBy(m => m.Ordering)
.Include(m => m.Season.Currency)
.ToListAsync()); .ToListAsync());
DeliveryPartList.ItemsSource = null; DeliveryPartList.ItemsSource = null;
} }
@@ -607,10 +603,11 @@ namespace Elwig.Windows {
private void RefreshInputs(bool validate = false) { private void RefreshInputs(bool validate = false) {
ClearInputStates(); ClearInputStates();
if (DeliveryPartList.SelectedItem is DeliveryPart p) { if (DeliveryList.SelectedItem is Delivery d) {
FillInputs(p);
} else if (DeliveryList.SelectedItem is Delivery d) {
FillInputs(d); FillInputs(d);
if (DeliveryPartList.SelectedItem is DeliveryPart p) {
FillInputs(p);
}
} else { } else {
ClearOriginalValues(); ClearOriginalValues();
ClearDefaultValues(); ClearDefaultValues();
@@ -628,7 +625,6 @@ namespace Elwig.Windows {
} }
private void FillInputs(DeliveryPart p) { private void FillInputs(DeliveryPart p) {
FillInputs(p.Delivery);
ClearOriginalValues(); ClearOriginalValues();
ClearDefaultValues(); ClearDefaultValues();
ViewModel.FillInputs(p); ViewModel.FillInputs(p);
@@ -863,9 +859,10 @@ namespace Elwig.Windows {
EmptyScale(); EmptyScale();
Utils.RunBackground("Lieferschein drucken", async () => { Utils.RunBackground("Lieferschein drucken", async () => {
using var ctx = new AppDbContext(); using var doc = await DeliveryNote.Initialize(p.Year, p.DId);
using var doc = new DeliveryNote((await ctx.Deliveries.FindAsync(p.Year, p.DId))!, ctx); using (var ctx = new AppDbContext()) {
await doc.Generate(); await doc.Generate(ctx);
}
if (App.Config.Debug) { if (App.Config.Debug) {
doc.Show(); doc.Show();
} else { } else {
@@ -892,8 +889,6 @@ namespace Elwig.Windows {
ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First); ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First);
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
.Where(m => m.IsActive || !ViewModel.IsReceipt) .Where(m => m.IsActive || !ViewModel.IsReceipt)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.DefaultWbKg!.AtKg)
.OrderBy(m => m.Name) .OrderBy(m => m.Name)
.ThenBy(m => m.GivenName) .ThenBy(m => m.GivenName)
.ToListAsync()); .ToListAsync());
@@ -934,12 +929,9 @@ namespace Elwig.Windows {
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers
.Where(m => m.Year == ViewModel.FilterSeason && m.IsActive) .Where(m => m.Year == ViewModel.FilterSeason && m.IsActive)
.OrderBy(m => m.Ordering) .OrderBy(m => m.Ordering)
.Include(m => m.Season.Currency)
.ToListAsync()); .ToListAsync());
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
.Where(m => m.IsActive || !ViewModel.IsReceipt) .Where(m => m.IsActive || !ViewModel.IsReceipt)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.DefaultWbKg!.AtKg)
.OrderBy(m => m.Name) .OrderBy(m => m.Name)
.ThenBy(m => m.GivenName) .ThenBy(m => m.GivenName)
.ToListAsync()); .ToListAsync());

View File

@@ -85,7 +85,6 @@ namespace Elwig.Windows {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
var list = await ctx.DeliverySchedules var list = await ctx.DeliverySchedules
.Where(s => s.Year == ViewModel.FilterSeason) .Where(s => s.Year == ViewModel.FilterSeason)
.Include(s => s.Branch)
.OrderBy(s => s.DateString) .OrderBy(s => s.DateString)
.ThenBy(s => s.Branch.Name) .ThenBy(s => s.Branch.Name)
.ThenBy(s => s.Description) .ThenBy(s => s.Description)
@@ -110,12 +109,7 @@ namespace Elwig.Windows {
var (filter, deliveryAncmts, stat) = await Task.Run(async () => { var (filter, deliveryAncmts, stat) = await Task.Run(async () => {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
var (_, deliveryAncmtQuery, filter) = await vm.GetFilters(ctx); var (_, deliveryAncmtQuery, filter) = await vm.GetFilters(ctx);
var deliveryAncmts = await deliveryAncmtQuery var deliveryAncmts = await deliveryAncmtQuery.ToListAsync();
.Include(a => a.Member.BillingAddress)
.Include(a => a.Schedule)
.Include(a => a.Variety)
.AsSplitQuery()
.ToListAsync();
if (filter.Count > 0 && deliveryAncmts.Count > 0) { if (filter.Count > 0 && deliveryAncmts.Count > 0) {
var dict = deliveryAncmts.AsParallel() var dict = deliveryAncmts.AsParallel()
@@ -189,8 +183,6 @@ namespace Elwig.Windows {
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
.Where(m => m.IsActive || !IsCreating) .Where(m => m.IsActive || !IsCreating)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.DefaultWbKg!.AtKg)
.OrderBy(m => m.Name) .OrderBy(m => m.Name)
.ThenBy(m => m.GivenName) .ThenBy(m => m.GivenName)
.ThenBy(m => m.MgNr) .ThenBy(m => m.MgNr)
@@ -286,8 +278,6 @@ namespace Elwig.Windows {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
.Where(m => m.IsActive || !IsCreating) .Where(m => m.IsActive || !IsCreating)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.DefaultWbKg!.AtKg)
.OrderBy(m => m.Name) .OrderBy(m => m.Name)
.ThenBy(m => m.GivenName) .ThenBy(m => m.GivenName)
.ThenBy(m => m.MgNr) .ThenBy(m => m.MgNr)
@@ -415,8 +405,6 @@ namespace Elwig.Windows {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
.Where(m => m.IsActive || !IsCreating) .Where(m => m.IsActive || !IsCreating)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.DefaultWbKg!.AtKg)
.OrderBy(m => m.Name) .OrderBy(m => m.Name)
.ThenBy(m => m.GivenName) .ThenBy(m => m.GivenName)
.ThenBy(m => m.MgNr) .ThenBy(m => m.MgNr)

View File

@@ -47,8 +47,6 @@ namespace Elwig.Windows {
var (_, deliveryScheduleQuery, filter) = await vm.GetFilters(ctx); var (_, deliveryScheduleQuery, filter) = await vm.GetFilters(ctx);
var deliverySchedules = await deliveryScheduleQuery var deliverySchedules = await deliveryScheduleQuery
.Include(s => s.Varieties) .Include(s => s.Varieties)
.Include(s => s.Branch)
.AsSplitQuery()
.ToListAsync(); .ToListAsync();
if (filter.Count > 0 && deliverySchedules.Count > 0) { if (filter.Count > 0 && deliverySchedules.Count > 0) {

View File

@@ -155,7 +155,7 @@ namespace Elwig.Windows {
} }
protected override async Task OnRenewContext(AppDbContext ctx) { 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<string> { var l = new List<string> {
MemberDataSheet.Name MemberDataSheet.Name
}; };
@@ -207,13 +207,8 @@ namespace Elwig.Windows {
.OrderBy(m => m.Name) .OrderBy(m => m.Name)
.ThenBy(m => m.GivenName) .ThenBy(m => m.GivenName)
.Include(m => m.Branch) .Include(m => m.Branch)
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.EmailAddresses) .Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers) .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); .ToListAsync(), MemberInput_SelectionChanged);
if (MemberCustomInput.SelectedItems.Count == 0) { if (MemberCustomInput.SelectedItems.Count == 0) {
MemberCustomInput.SelectionChanged -= MemberInput_SelectionChanged; MemberCustomInput.SelectionChanged -= MemberInput_SelectionChanged;
@@ -492,13 +487,8 @@ namespace Elwig.Windows {
} }
Recipients = await query Recipients = await query
.Include(m => m.Branch) .Include(m => m.Branch)
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.EmailAddresses) .Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers) .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(); .ToListAsync();
} }
UpdatePostalEmailRecipients(); UpdatePostalEmailRecipients();
@@ -758,7 +748,7 @@ namespace Elwig.Windows {
if (doc.Type == DocType.Custom) { if (doc.Type == DocType.Custom) {
return [new GeneratedDoc((string)doc.Details!)]; return [new GeneratedDoc((string)doc.Details!)];
} else if (doc.Type == DocType.MemberDataSheet) { } 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) { } else if (doc.Type == DocType.DeliveryConfirmation) {
var year = (int)doc.Details!; var year = (int)doc.Details!;
DeliveryConfirmationDeliveryData data; DeliveryConfirmationDeliveryData data;
@@ -769,21 +759,14 @@ namespace Elwig.Windows {
} else { } else {
return []; 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) { } else if (doc.Type == DocType.CreditNote) {
var details = ((int, int))doc.Details!; var details = ((int, int))doc.Details!;
var year = details.Item1; var year = details.Item1;
var avnr = details.Item2; var avnr = details.Item2;
var data = cnData[(year, avnr)]; var data = cnData[(year, avnr)];
try { try {
return [new GeneratedDoc(new CreditNote( return [new GeneratedDoc(new CreditNote(data.Item2[m.MgNr], data.Item3, data.Item1[m.MgNr]) { Date = postalDate })];
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 })];
} catch (Exception) { } catch (Exception) {
return []; return [];
} }
@@ -827,7 +810,7 @@ namespace Elwig.Windows {
var emailRecipients = email.Select(d => d.Key.MgNr).ToHashSet(); 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 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 })) { foreach (var item2 in item1.Value.Select((d, i) => new { Index = i, Doc = d })) {
await item2.Doc.Generate(CancelGeneration?.Token, new Progress<double>(v => App.MainDispatcher.Invoke(() => { await item2.Doc.Generate(ctx, CancelGeneration?.Token, new Progress<double>(v => App.MainDispatcher.Invoke(() => {
ProgressBar.Value = offset + v * (item2.Index + 1) / item1.Value.Count / totalNum + 100.0 * item1.Index / totalNum; 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) { if (printDocs.Count > 0) {
var print = Document.Merge(printDocs); var print = Document.Merge(printDocs);
await print.Generate(CancelGeneration?.Token, new Progress<double>(v => App.MainDispatcher.Invoke(() => { await print.Generate(ctx, CancelGeneration?.Token, new Progress<double>(v => App.MainDispatcher.Invoke(() => {
ProgressBar.Value = offset + v * printNum / totalNum; ProgressBar.Value = offset + v * printNum / totalNum;
}))); })));
PrintDocument = print; PrintDocument = print;

View File

@@ -121,14 +121,9 @@ namespace Elwig.Windows {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
var (_, memberQuery, filter) = await vm.GetFilters(ctx); var (_, memberQuery, filter) = await vm.GetFilters(ctx);
var members = await memberQuery var members = await memberQuery
.Include(m => m.Branch)
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.EmailAddresses) .Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers) .Include(m => m.TelephoneNumbers)
.Include(m => m.PostalDest.AtPlz!.Ort) .AsSplitQuery()
.Include(m => m.PostalDest.AtPlz!.Country)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Country)
.ToListAsync(); .ToListAsync();
if (filter.Count > 0 && members.Count > 0) { if (filter.Count > 0 && members.Count > 0) {
@@ -200,7 +195,7 @@ namespace Elwig.Windows {
var font = new System.Windows.Media.FontFamily("Segoe MDL2 Assets"); var font = new System.Windows.Media.FontFamily("Segoe MDL2 Assets");
MenuItem? temp = null; 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(); Menu_DeliveryConfirmation.Items.Clear();
foreach (var s in seasons) { foreach (var s in seasons) {
var i = new MenuItem { var i = new MenuItem {
@@ -339,6 +334,7 @@ namespace Elwig.Windows {
} }
private async void ActiveMemberInput_Changed(object sender, RoutedEventArgs evt) { private async void ActiveMemberInput_Changed(object sender, RoutedEventArgs evt) {
if (!IsInitialized) return;
await RefreshList(); await RefreshList();
} }
@@ -509,7 +505,9 @@ namespace Elwig.Windows {
try { try {
await Task.Run(async () => { await Task.Run(async () => {
using var doc = new Letterhead(m); using var doc = new Letterhead(m);
await doc.Generate(); using (var ctx = new AppDbContext()) {
await doc.Generate(ctx);
}
if (!App.Config.Debug) { if (!App.Config.Debug) {
await doc.Print(); await doc.Print();
} else { } else {

View File

@@ -21,12 +21,11 @@ namespace Elwig.Windows {
} }
protected override async Task OnRenewContext(AppDbContext ctx) { protected override async Task OnRenewContext(AppDbContext ctx) {
var origins = (await ctx.WineOrigins var origins = await ctx.WineOrigins
.Include("Gems.AtGem.Kgs.WbKg.Gl") .Include(o => o.Gems).ThenInclude(g => g.AtGem.Kgs).ThenInclude(k => k.WbKg!.Gl)
.AsSplitQuery() .ToListAsync();
.ToListAsync()) origins.ForEach(o => { origins.FirstOrDefault(p => p.HkId == o.ParentHkId)?.Children.Add(o); });
.OrderByDescending(o => o.SortKey) origins = [.. origins.OrderByDescending(o => o.SortKey).ThenBy(o => o.HkId)];
.ThenBy(o => o.HkId);
ControlUtils.RenewItemsSource(WineOrigins, origins, WineOrigins_SelectionChanged); ControlUtils.RenewItemsSource(WineOrigins, origins, WineOrigins_SelectionChanged);
if (WineOrigins.SelectedItem == null) { if (WineOrigins.SelectedItem == null) {
var hkid = await ctx.WbKgs var hkid = await ctx.WbKgs
@@ -39,8 +38,7 @@ namespace Elwig.Windows {
} }
var gls = await ctx.WbGls var gls = await ctx.WbGls
.OrderBy(g => g.GlNr) .OrderBy(g => g.GlNr)
.Include("Kgs.Rds") .Include(g => g.Kgs).ThenInclude(k => k.Rds)
.AsSplitQuery()
.ToListAsync(); .ToListAsync();
ControlUtils.RenewItemsSource(WbGls, gls, WbGls_SelectionChanged, ControlUtils.RenewSourceDefault.First); ControlUtils.RenewItemsSource(WbGls, gls, WbGls_SelectionChanged, ControlUtils.RenewSourceDefault.First);
UpdateWbGems(); UpdateWbGems();

View File

@@ -48,7 +48,6 @@ namespace Elwig.Windows {
ControlUtils.RenewItemsSource(PaymentVariantList, await ctx.PaymentVariants ControlUtils.RenewItemsSource(PaymentVariantList, await ctx.PaymentVariants
.Where(v => v.Year == Year) .Where(v => v.Year == Year)
.OrderBy(v => v.AvNr) .OrderBy(v => v.AvNr)
.Include(v => v.Season.Currency)
.ToListAsync()); .ToListAsync());
if (PaymentVariantList.SelectedItem == null && PaymentVariantList.Items.Count > 0) { if (PaymentVariantList.SelectedItem == null && PaymentVariantList.Items.Count > 0) {
PaymentVariantList.SelectedIndex = PaymentVariantList.Items.Count - 1; PaymentVariantList.SelectedIndex = PaymentVariantList.Items.Count - 1;

View File

@@ -2,6 +2,7 @@ using Elwig;
using Elwig.Helpers; using Elwig.Helpers;
using Elwig.Helpers.Billing; using Elwig.Helpers.Billing;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using System.Reflection; using System.Reflection;
namespace Tests { namespace Tests {
@@ -22,7 +23,7 @@ namespace Tests {
public void Setup_2_Client() { public void Setup_2_Client() {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
App.Client = new ClientParameters(ctx); App.Client = new ClientParameters(ctx);
App.SetBranch(ctx.Branches.Single()); App.SetBranch(ctx.Branches.Include(b => b.PostalDest).Single());
} }
[OneTimeSetUp] [OneTimeSetUp]

View File

@@ -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, 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); (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 INSERT INTO delivery_part_bucket (year, did, dpnr, bktnr, discr, value) VALUES
(2020, 1, 1, 0, '_', 3219), (2020, 1, 1, 0, '_', 3219),
(2020, 3, 1, 0, '_', 2561), (2020, 3, 1, 0, '_', 2561),

View File

@@ -1,7 +1,4 @@
using Elwig.Documents; using Elwig.Documents;
using Elwig.Helpers;
using Elwig.Models.Dtos;
using Microsoft.EntityFrameworkCore;
namespace Tests.UnitTests.DocumentTests { namespace Tests.UnitTests.DocumentTests {
[TestFixture] [TestFixture]
@@ -9,12 +6,7 @@ namespace Tests.UnitTests.DocumentTests {
[Test] [Test]
public async Task Test_01_VirtualCreditNote() { public async Task Test_01_VirtualCreditNote() {
using var ctx = new AppDbContext(); using var doc = await CreditNote.Initialize(2020, 1, 101);
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());
var text = await Utils.GeneratePdfText(doc); var text = await Utils.GeneratePdfText(doc);
Assert.Multiple(() => { Assert.Multiple(() => {
Assert.That(text, Contains.Substring(""" Assert.That(text, Contains.Substring("""

View File

@@ -11,7 +11,7 @@ namespace Tests.UnitTests.DocumentTests {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
var m = await ctx.Members.FindAsync(101); var m = await ctx.Members.FindAsync(101);
var data = await DeliveryConfirmationDeliveryData.ForMember(ctx.DeliveryParts, 2020, m!); 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); var text = await Utils.GeneratePdfText(doc);
Assert.Multiple(() => { Assert.Multiple(() => {
Assert.That(text, Contains.Substring(""" Assert.That(text, Contains.Substring("""

View File

@@ -1,5 +1,4 @@
using Elwig.Documents; using Elwig.Documents;
using Elwig.Helpers;
namespace Tests.UnitTests.DocumentTests { namespace Tests.UnitTests.DocumentTests {
[TestFixture] [TestFixture]
@@ -7,9 +6,7 @@ namespace Tests.UnitTests.DocumentTests {
[Test] [Test]
public async Task Test_01_OneDeliveryPart() { public async Task Test_01_OneDeliveryPart() {
using var ctx = new AppDbContext(); using var doc = await DeliveryNote.Initialize(2020, 1);
var d = await ctx.Deliveries.FindAsync(2020, 1);
using var doc = new DeliveryNote(d!, ctx);
var text = await Utils.GeneratePdfText(doc); var text = await Utils.GeneratePdfText(doc);
Assert.Multiple(() => { Assert.Multiple(() => {
Assert.That(text, Contains.Substring(""" 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("0123463")); // Betriebsnummer
Assert.That(text, Contains.Substring("pauschaliert")); 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("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("Das Mitglied erklärt, dass die gelieferte Ware dem österreichischen Weingesetz entspricht"));
Assert.That(text, Contains.Substring(""" Assert.That(text, Contains.Substring("""
@@ -34,9 +31,7 @@ namespace Tests.UnitTests.DocumentTests {
[Test] [Test]
public async Task Test_02_TwoDeliveryParts() { public async Task Test_02_TwoDeliveryParts() {
using var ctx = new AppDbContext(); using var doc = await DeliveryNote.Initialize(2020, 4);
var d = await ctx.Deliveries.FindAsync(2020, 4);
using var doc = new DeliveryNote(d!, ctx);
var text = await Utils.GeneratePdfText(doc); var text = await Utils.GeneratePdfText(doc);
Assert.Multiple(() => { Assert.Multiple(() => {
Assert.That(text, Contains.Substring(""" 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("0123471")); // Betriebsnummer
Assert.That(text, Contains.Substring("pauschaliert")); 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("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("Das Mitglied erklärt, dass die gelieferte Ware dem österreichischen Weingesetz entspricht"));
Assert.That(text, Contains.Substring(""" Assert.That(text, Contains.Substring("""
@@ -68,9 +63,7 @@ namespace Tests.UnitTests.DocumentTests {
[Test] [Test]
public async Task Test_03_DeliveryPartsWithAttribute() { public async Task Test_03_DeliveryPartsWithAttribute() {
using var ctx = new AppDbContext(); using var doc = await DeliveryNote.Initialize(2020, 3);
var d = await ctx.Deliveries.FindAsync(2020, 3);
using var doc = new DeliveryNote(d!, ctx);
var text = await Utils.GeneratePdfText(doc); var text = await Utils.GeneratePdfText(doc);
Assert.Multiple(() => { Assert.Multiple(() => {
Assert.That(text, Contains.Substring(""" 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("0123463")); // Betriebsnummer
Assert.That(text, Contains.Substring("pauschaliert")); 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("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("Das Mitglied erklärt, dass die gelieferte Ware dem österreichischen Weingesetz entspricht"));
Assert.That(text, Contains.Substring(""" Assert.That(text, Contains.Substring("""
@@ -107,9 +100,7 @@ namespace Tests.UnitTests.DocumentTests {
[Test] [Test]
public async Task Test_04_DeliveryPartsWithCultivation() { public async Task Test_04_DeliveryPartsWithCultivation() {
using var ctx = new AppDbContext(); using var doc = await DeliveryNote.Initialize(2020, 7);
var d = await ctx.Deliveries.FindAsync(2020, 7);
using var doc = new DeliveryNote(d!, ctx);
var text = await Utils.GeneratePdfText(doc); var text = await Utils.GeneratePdfText(doc);
Assert.Multiple(() => { Assert.Multiple(() => {
Assert.That(text, Contains.Substring(""" 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("0123480")); // Betriebsnummer
Assert.That(text, Contains.Substring("pauschaliert")); 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("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("Das Mitglied erklärt, dass die gelieferte Ware dem österreichischen Weingesetz entspricht"));
Assert.That(text, Contains.Substring(""" Assert.That(text, Contains.Substring("""
@@ -139,5 +130,37 @@ namespace Tests.UnitTests.DocumentTests {
Assert.That(text, Contains.Substring("Gesamt: 78 15,9 5 332")); 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
"""));
});
}
} }
} }

View File

@@ -1,5 +1,4 @@
using Elwig.Documents; using Elwig.Documents;
using Elwig.Helpers;
namespace Tests.UnitTests.DocumentTests { namespace Tests.UnitTests.DocumentTests {
[TestFixture] [TestFixture]
@@ -7,9 +6,7 @@ namespace Tests.UnitTests.DocumentTests {
[Test] [Test]
public async Task Test_01_SimpleMember() { public async Task Test_01_SimpleMember() {
using var ctx = new AppDbContext(); using var doc = await MemberDataSheet.Initialize(104);
var m = await ctx.Members.FindAsync(104);
using var doc = new MemberDataSheet(m!, ctx);
var text = await Utils.GeneratePdfText(doc); var text = await Utils.GeneratePdfText(doc);
Assert.Multiple(() => { Assert.Multiple(() => {
Assert.That(text, Contains.Substring(""" Assert.That(text, Contains.Substring("""

View File

@@ -1,6 +1,4 @@
using Elwig.Documents; using Elwig.Documents;
using Elwig.Helpers;
using Elwig.Models.Dtos;
namespace Tests.UnitTests.DocumentTests { namespace Tests.UnitTests.DocumentTests {
[TestFixture] [TestFixture]
@@ -8,16 +6,13 @@ namespace Tests.UnitTests.DocumentTests {
[Test] [Test]
public async Task Test_01_PaymentVariant2020() { public async Task Test_01_PaymentVariant2020() {
using var ctx = new AppDbContext(); using var doc = await PaymentVariantSummary.Initialize(2020, 1);
var v = (await ctx.PaymentVariants.FindAsync(2020, 1))!;
var data = await PaymentVariantSummaryData.ForPaymentVariant(v, ctx.PaymentVariantSummaryRows);
using var doc = new PaymentVariantSummary(v, data);
var text = await Utils.GeneratePdfText(doc, true); var text = await Utils.GeneratePdfText(doc, true);
var table = Utils.ExtractTable(text); var table = Utils.ExtractTable(text);
Assert.Multiple(() => { Assert.Multiple(() => {
Assert.That(text, Contains.Substring("Auszahlungsvariante")); Assert.That(text, Contains.Substring("Auszahlungsvariante"));
Assert.That(text, Contains.Substring(v.Name)); Assert.That(text, Contains.Substring(doc.Variant.Name));
Assert.That(table.Skip(17).ToArray(), Is.EqualTo(new string[][] { Assert.That(table.Skip(19).ToArray(), Is.EqualTo(new string[][] {
["Sorte/Attr./Bewirt.", "Gradation", "ungebunden", "attributlos gebunden", "gebunden", "Gesamt" ], ["Sorte/Attr./Bewirt.", "Gradation", "ungebunden", "attributlos gebunden", "gebunden", "Gesamt" ],
["Qualitätsstufe", "[°Oe]", "[kg]", "[/kg]", "[kg]", "[/kg]", "[kg]", "[/kg]", "[]" ], ["Qualitätsstufe", "[°Oe]", "[kg]", "[/kg]", "[kg]", "[/kg]", "[kg]", "[/kg]", "[]" ],
["Grüner Veltliner", "3 219", "0", "0", "1 609,50"], ["Grüner Veltliner", "3 219", "0", "0", "1 609,50"],

View File

@@ -1,4 +1,5 @@
using Elwig.Documents; using Elwig.Documents;
using Elwig.Helpers;
using NReco.PdfRenderer; using NReco.PdfRenderer;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@@ -8,7 +9,9 @@ namespace Tests.UnitTests.DocumentTests {
private static readonly string FileName = Path.Combine(Path.GetTempPath(), "test_document.pdf"); private static readonly string FileName = Path.Combine(Path.GetTempPath(), "test_document.pdf");
public static async Task<string> GeneratePdfText(Document doc, bool preserveLayout = false) { public static async Task<string> GeneratePdfText(Document doc, bool preserveLayout = false) {
await doc.Generate(); using (var ctx = new AppDbContext()) {
await doc.Generate(ctx);
}
try { try {
doc.SaveTo(FileName); doc.SaveTo(FileName);
var conv = new PdfToTextConverter { CustomArgs = preserveLayout ? "-layout " : "-raw " }; var conv = new PdfToTextConverter { CustomArgs = preserveLayout ? "-layout " : "-raw " };

View File

@@ -32,7 +32,6 @@ namespace Tests.UnitTests.ServiceTests {
.Include(d => d.Parts) .Include(d => d.Parts)
.ThenInclude(p => p.PartModifiers) .ThenInclude(p => p.PartModifiers)
.ThenInclude(m => m.Modifier) .ThenInclude(m => m.Modifier)
.AsSplitQuery()
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
} }

View File

@@ -12,8 +12,8 @@ namespace Tests.UnitTests.ServiceTests {
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
vm.BranchSource = await ctx.Branches.ToListAsync(); vm.BranchSource = await ctx.Branches.ToListAsync();
vm.DefaultKgSource = await ctx.Katastralgemeinden.ToListAsync(); vm.DefaultKgSource = await ctx.Katastralgemeinden.ToListAsync();
vm.OrtSource = await ctx.PlzDestinations.Include(p => p.Ort).ToListAsync(); vm.OrtSource = await ctx.PlzDestinations.ToListAsync();
vm.BillingOrtSource = await ctx.PlzDestinations.Include(p => p.Ort).ToListAsync(); vm.BillingOrtSource = await ctx.PlzDestinations.ToListAsync();
} }
[Test] [Test]
@@ -36,17 +36,13 @@ namespace Tests.UnitTests.ServiceTests {
Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(null)); Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(null));
Member? m; Member m;
using (var ctx = new AppDbContext()) { using (var ctx = new AppDbContext()) {
m = await ctx.Members m = await ctx.Members
.Where(m => m.MgNr == vm.MgNr) .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.EmailAddresses)
.Include(m => m.TelephoneNumbers) .Include(m => m.TelephoneNumbers)
.AsSplitQuery() .SingleAsync();
.FirstOrDefaultAsync();
} }
Assert.That(m, Is.Not.Null); Assert.That(m, Is.Not.Null);
@@ -124,17 +120,13 @@ namespace Tests.UnitTests.ServiceTests {
Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(null)); Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(null));
Member? m; Member m;
using (var ctx = new AppDbContext()) { using (var ctx = new AppDbContext()) {
m = await ctx.Members m = await ctx.Members
.Where(m => m.MgNr == vm.MgNr) .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.EmailAddresses)
.Include(m => m.TelephoneNumbers) .Include(m => m.TelephoneNumbers)
.AsSplitQuery() .SingleAsync();
.FirstOrDefaultAsync();
} }
Assert.That(m, Is.Not.Null); Assert.That(m, Is.Not.Null);
@@ -236,13 +228,9 @@ namespace Tests.UnitTests.ServiceTests {
using (var ctx = new AppDbContext()) { using (var ctx = new AppDbContext()) {
vm.FillInputs(await ctx.Members vm.FillInputs(await ctx.Members
.Where(m => m.MgNr == 202) .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.EmailAddresses)
.Include(m => m.TelephoneNumbers) .Include(m => m.TelephoneNumbers)
.AsSplitQuery() .SingleAsync());
.FirstAsync());
} }
Assert.That(vm.IsActive, Is.True); Assert.That(vm.IsActive, Is.True);
@@ -253,17 +241,13 @@ namespace Tests.UnitTests.ServiceTests {
Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(202)); Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(202));
Member? m; Member m;
using (var ctx = new AppDbContext()) { using (var ctx = new AppDbContext()) {
m = await ctx.Members m = await ctx.Members
.Where(m => m.MgNr == 202) .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.EmailAddresses)
.Include(m => m.TelephoneNumbers) .Include(m => m.TelephoneNumbers)
.AsSplitQuery() .SingleAsync();
.FirstOrDefaultAsync();
} }
Assert.That(m, Is.Not.Null); Assert.That(m, Is.Not.Null);
@@ -288,13 +272,9 @@ namespace Tests.UnitTests.ServiceTests {
using (var ctx = new AppDbContext()) { using (var ctx = new AppDbContext()) {
vm.FillInputs(await ctx.Members vm.FillInputs(await ctx.Members
.Where(m => m.MgNr == 203) .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.EmailAddresses)
.Include(m => m.TelephoneNumbers) .Include(m => m.TelephoneNumbers)
.AsSplitQuery() .SingleAsync());
.FirstAsync());
} }
Assert.Multiple(() => { Assert.Multiple(() => {
@@ -306,17 +286,13 @@ namespace Tests.UnitTests.ServiceTests {
vm.MgNr = 210; vm.MgNr = 210;
Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(203)); Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(203));
Member? m; Member m;
using (var ctx = new AppDbContext()) { using (var ctx = new AppDbContext()) {
m = await ctx.Members m = await ctx.Members
.Where(m => m.MgNr == 210) .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.EmailAddresses)
.Include(m => m.TelephoneNumbers) .Include(m => m.TelephoneNumbers)
.AsSplitQuery() .SingleAsync();
.FirstOrDefaultAsync();
} }
Assert.That(m, Is.Not.Null); Assert.That(m, Is.Not.Null);