[#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.Models.Entities;
using Elwig.Windows;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Data;
@@ -104,7 +105,9 @@ namespace Elwig {
Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = [];
using (var ctx = new AppDbContext()) {
branches = ctx.Branches.ToDictionary(b => b.Name.ToLower(), b => (b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Ort.Name, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr));
branches = ctx.Branches
.Include(b => b.PostalDest)
.ToDictionary(b => b.Name.ToLower(), b => (b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Ort.Name, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr));
try {
Client = new(ctx);
} catch (Exception e) {

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

@@ -5,32 +5,55 @@ using iText.Kernel.Pdf;
using iText.Layout.Borders;
using iText.Layout.Element;
using iText.Layout.Properties;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Elwig.Documents {
public class MemberDataSheet : BusinessDocument {
public new static string Name => "Stammdatenblatt";
public Season Season;
public Dictionary<string, MemberBucket> MemberBuckets;
public List<AreaCom> ActiveAreaCommitments;
public Season? Season;
public int MemberDeliveredWeight;
public Dictionary<string, MemberBucket> MemberBuckets = [];
public List<AreaCom> ActiveAreaCommitments = [];
public MemberDataSheet(Member m, AppDbContext ctx) :
public MemberDataSheet(Member m) :
base($"{Name} {m.AdministrativeName}", m) {
DocumentId = $"{Name} {m.MgNr}";
Season = ctx.Seasons.ToList().MaxBy(s => s.Year) ?? throw new ArgumentException("invalid season");
MemberBuckets = ctx.GetMemberBuckets(Utils.CurrentYear, m.MgNr).GetAwaiter().GetResult();
ActiveAreaCommitments = [.. m.ActiveAreaCommitments(ctx)];
}
public static async Task<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) {
if (Season == null) throw new Exception("Call LoadData before RenderBody");
base.RenderBody(doc, pdf);
doc.Add(NewMemberData().SetMarginBottomMM(5));
doc.Add(NewBucketTable(Season, MemberBuckets, includeDelivery: false));
doc.Add(NewMemberData(Season).SetMarginBottomMM(5));
doc.Add(NewBucketTable(Season, MemberBuckets, MemberDeliveredWeight, includeDelivery: false));
if (ActiveAreaCommitments.Count != 0) {
bool firstOnPage = false;
if (pdf.GetNumberOfPages() == 1) {
@@ -38,7 +61,7 @@ namespace Elwig.Documents {
firstOnPage = true;
}
doc.Add(new KernedParagraph(12).Add(Bold($"Flächenbindungen per {Date:dd.MM.yyyy}")).SetMargins(firstOnPage ? 0 : 24, 0, 12, 0));
doc.Add(NewAreaComTable());
doc.Add(NewAreaComTable(ActiveAreaCommitments));
}
}
@@ -52,7 +75,7 @@ namespace Elwig.Documents {
.SetPaddingRightMM(0);
}
protected Table NewMemberData() {
protected Table NewMemberData(Season season) {
var tbl = new Table(ColsMM(30.0, 51.5, 20.0, 12.0, 18.0, 31.5))
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
@@ -117,7 +140,7 @@ namespace Elwig.Documents {
.AddCell(NewDataTh("UID:", colspan: 2)).AddCell(NewTd(Member.UstIdNr, colspan: 2))
.AddCell(NewDataTh("Stammgemeinde:")).AddCell(NewTd(Member.DefaultKg?.Name))
.AddCell(NewDataTh("Buchführend:", colspan: 2)).AddCell(NewTd(new KernedParagraph(Member.IsBuchführend ? "Ja " : "Nein ", 10)
.Add(Normal($"({(Member.IsBuchführend ? Season.VatNormal : Season.VatFlatrate) * 100:N0}% USt.)", 8)), colspan: 2))
.Add(Normal($"({(Member.IsBuchführend ? season.VatNormal : season.VatFlatrate) * 100:N0}% USt.)", 8)), colspan: 2))
.AddCell(NewDataTh("(Katastralgemeinde mit dem größten Anteil an Weinbauflächen)", 8, colspan: 2))
.AddCell(NewDataTh("Bio:", colspan: 2)).AddCell(NewTd(Member.IsOrganic ? "Ja" : "Nein", colspan: 2))
.AddCell(NewDataHdr("Genossenschaft", colspan: 6))
@@ -134,8 +157,8 @@ namespace Elwig.Documents {
return tbl;
}
protected Table NewAreaComTable() {
var areaComs = ActiveAreaCommitments.GroupBy(a => a.AreaComType).Select(group => new {
protected Table NewAreaComTable(IEnumerable<AreaCom> activeAreaComs) {
var areaComs = activeAreaComs.GroupBy(a => a.AreaComType).Select(group => new {
Type = group.Key,
AreaComs = group.OrderBy(c => c.Contract.Kg.AtKg.Name).ToList(),
Size = group.Sum(c => c.Area)
@@ -177,7 +200,7 @@ namespace Elwig.Documents {
}
tbl.AddCell(NewTd("Gesamt:", 12, colspan: 2, bold: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1));
tbl.AddCell(NewTd($"{ActiveAreaCommitments.Sum(a => a.Area):N0}", 12, colspan: 2, right: true, bold: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1));
tbl.AddCell(NewTd($"{activeAreaComs.Sum(a => a.Area):N0}", 12, colspan: 2, right: true, bold: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1));
tbl.AddCell(NewTd(colspan: 2, borderTop: true).SetPaddingsMM(1, 1, 1, 1));
return tbl;

View File

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

View File

@@ -29,7 +29,6 @@
<PackageReference Include="itext.bouncy-castle-adapter" Version="9.5.0" />
<PackageReference Include="LinqKit" Version="1.3.11" />
<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.Extensions.Configuration.Ini" Version="10.0.5" />
<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) {
optionsBuilder.UseSqlite(ConnectionString);
optionsBuilder.UseLazyLoadingProxies();
optionsBuilder.LogTo(Log, LogLevel.Information);
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() {
base.Dispose();
LogFile?.Dispose();
@@ -399,10 +443,12 @@ namespace Elwig.Helpers {
var paymentBuckets = await GetMemberPaymentBuckets(year, mgnr, cnx);
if (ownCnx) await cnx.DisposeAsync();
var varieties = await WineVarieties.ToDictionaryAsync(v => v.SortId);
var attributes = await WineAttributes.ToDictionaryAsync(a => a.AttrId);
var buckets = new Dictionary<string, MemberBucket>();
foreach (var id in rightsAndObligations.Keys.Union(deliveryBuckets.Keys).Union(paymentBuckets.Keys)) {
var variety = await WineVarieties.FindAsync(id[..2]);
var attribute = await WineAttributes.FindAsync(id[2..]);
var variety = varieties.GetValueOrDefault(id[..2]);
var attribute = attributes.GetValueOrDefault(id[2..]);
var name = (variety?.Name ?? "") + (id[2..] == "_" ? " (kein Qual.Wein)" : attribute != null ? $" ({attribute})" : "");
buckets[id] = new(
name,

View File

@@ -21,7 +21,7 @@ namespace Elwig.Helpers.Billing {
using var ctx = new AppDbContext();
Season = ctx.Seasons.Find(Year)!;
Attributes = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a.Name);
Modifiers = ctx.Modifiers.Where(m => m.Year == Year).Include(m => m.Season).ToDictionary(m => m.ModId, m => (m.Abs, m.Rel));
Modifiers = ctx.Modifiers.Where(m => m.Year == Year).ToDictionary(m => m.ModId, m => (m.Abs, m.Rel));
AreaComTypes = ctx.AreaCommitmentTypes.ToDictionary(v => v.VtrgId, v => (v.SortId, v.AttrId, v.Discriminator, v.MinKgPerHa, v.PenaltyAmount));
}

View File

@@ -16,7 +16,7 @@ namespace Elwig.Helpers.Billing {
public BillingVariant(int year, int avnr) : base(year) {
AvNr = avnr;
using var ctx = new AppDbContext();
PaymentVariant = ctx.PaymentVariants.Include(v => v.Season).Where(v => v.Year == Year && v.AvNr == AvNr).Single() ?? throw new ArgumentException("PaymentVar not found");
PaymentVariant = ctx.PaymentVariants.Where(v => v.Year == Year && v.AvNr == AvNr).Single();
Data = PaymentBillingData.FromJson(PaymentVariant.Data, Utils.GetVaributes(ctx, Year, onlyDelivered: false));
}

View File

@@ -860,7 +860,7 @@ namespace Elwig.Helpers.Export {
["ried"] = p.Rd?.Name,
["net_weight"] = p.IsNetWeight,
["manual_weighing"] = p.IsManualWeighing,
["modids"] = new JsonArray(p.Modifiers.Select(m => (JsonNode)m.ModId).ToArray()),
["modids"] = new JsonArray(p.PartModifiers.Select(m => (JsonNode)m.ModId).ToArray()),
["comment"] = p.Comment,
["created_at"] = $"{p.CreatedAt:yyyy-MM-ddTHH:mm:ssK}",
["modified_at"] = $"{p.ModifiedAt:yyyy-MM-ddTHH:mm:ssK}",

View File

@@ -557,7 +557,9 @@ namespace Elwig.Helpers {
"Vorläufiges Dokument", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
await doc.Generate();
using (var ctx = new AppDbContext()) {
await doc.Generate(ctx);
}
await doc.Print();
} else if (mode == ExportMode.Email && emailData is (Member, string, string) e) {
if (doc.IsPreview) {
@@ -565,7 +567,9 @@ namespace Elwig.Helpers {
"Vorläufiges Dokument", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
await doc.Generate();
using (var ctx = new AppDbContext()) {
await doc.Generate(ctx);
}
var success = await SendEmail(e.Member, e.Subject, e.Text, [doc]);
if (success)
MessageBox.Show("Die E-Mail wurde erfolgreich verschickt!\n\nEs kann einige Minuten dauern, bis die E-Mail im Posteingang des Empfängers aufscheint.", "E-Mail verschickt",
@@ -582,12 +586,16 @@ namespace Elwig.Helpers {
Title = $"{doc.Title} speichern unter - Elwig"
};
if (d.ShowDialog() == true) {
await doc.Generate();
using (var ctx = new AppDbContext()) {
await doc.Generate(ctx);
}
doc.SaveTo(d.FileName);
Process.Start("explorer.exe", d.FileName);
}
} else {
await doc.Generate();
using (var ctx = new AppDbContext()) {
await doc.Generate(ctx);
}
doc.Show();
}
}

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) {
var variant = await paymentVariants.FindAsync(year, avnr);
var variant = await paymentVariants.Include(v => v.Season.Modifiers).SingleAsync(v => v.Year == year && v.AvNr == avnr);
BillingData? varData = null;
try { varData = variant != null ? BillingData.FromJson(variant.Data) : null; } catch { }
try { varData = variant.Data != null ? BillingData.FromJson(variant.Data) : null; } catch { }
return (await FromDbSet(table, year, avnr))
.GroupBy(
r => new { r.Year, r.AvNr, r.MgNr, r.TgNr, r.DId, r.DPNr },

View File

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

View File

@@ -52,12 +52,8 @@ namespace Elwig.Models.Dtos {
if (mgnr != null) q = q.Where(p => p.Delivery.MgNr == mgnr);
await q
.Include(p => p.Delivery)
.Include(p => p.Variety)
.Include(p => p.Attribute)
.Include(p => p.Quality)
.Include(p => p.Buckets)
.Include(p => p.PartModifiers)
.ThenInclude(m => m.Modifier)
.Include(p => p.PartModifiers).ThenInclude(m => m.Modifier)
.LoadAsync();
return await table.FromSqlRaw($"""
SELECT p.*
@@ -65,7 +61,7 @@ namespace Elwig.Models.Dtos {
JOIN delivery_part p ON (p.year, p.did, p.dpnr) = (v.year, v.did, v.dpnr)
WHERE (p.year = {y} OR {y} IS NULL) AND (v.mgnr = {m} OR {m} IS NULL)
ORDER BY p.year, v.mgnr, v.sortid, v.abgewertet ASC, v.attribute_prio DESC, COALESCE(v.attrid, '~'), v.kmw DESC, v.lsnr, v.dpnr
""").ToListAsync();
""").IgnoreAutoIncludes().ToListAsync();
}
}

View File

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

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) {
var areaComs = await query.ToDictionaryAsync(m => m.MgNr, m => Utils.ActiveAreaCommitments(m.AreaCommitments));
var areaComs = await query.Include(m => m.AreaCommitments).ToDictionaryAsync(m => m.MgNr, m => Utils.ActiveAreaCommitments(m.AreaCommitments));
return new((await query
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.Branch)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
.Include(m => m.TelephoneNumbers)
.Include(m => m.EmailAddresses)
.AsSplitQuery()
.ToListAsync()).Select(m => new MemberListRow(m,
areaComs[m.MgNr].Sum(c => c.Area),
areaComs[m.MgNr].Where(c => filterAreaCom.Contains(c.VtrgId)).GroupBy(c => c.VtrgId).ToDictionary(g => g.Key, g => g.Sum(c => c.Area)))),

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -59,20 +59,9 @@ namespace Elwig.Windows {
using var ctx = new AppDbContext();
var (_, contractQuery, areaComQuery, filter) = await vm.GetFilters(ctx);
var contracts = await contractQuery
.Include(c => c.Kg.AtKg)
.Include(c => c.Rd!.Kg.AtKg)
.Include(c => c.Revisions).ThenInclude(a => a.WineCult)
.Include(c => c.Revisions).ThenInclude(a => a.AreaComType.WineAttr)
.Include(c => c.Revisions).ThenInclude(a => a.AreaComType.WineVar)
.Include(c => c.Revisions).ThenInclude(a => a.Member)
.ToListAsync();
var areaComs = await areaComQuery
.Include(c => c.Contract.Kg.AtKg)
.Include(c => c.Contract.Rd!.Kg.AtKg)
.Include(a => a.WineCult)
.Include(a => a.AreaComType.WineAttr)
.Include(a => a.AreaComType.WineVar)
.ToListAsync();
var areaComs = await areaComQuery.ToListAsync();
if (filter.Count > 0 && contracts.Count > 0) {
var dict = contracts.AsParallel()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -155,7 +155,7 @@ namespace Elwig.Windows {
}
protected override async Task OnRenewContext(AppDbContext ctx) {
var season = await ctx.Seasons.FindAsync(Year);
var season = await ctx.Seasons.Include(s => s.PaymentVariants).SingleAsync(s => s.Year == Year);
var l = new List<string> {
MemberDataSheet.Name
};
@@ -207,13 +207,8 @@ namespace Elwig.Windows {
.OrderBy(m => m.Name)
.ThenBy(m => m.GivenName)
.Include(m => m.Branch)
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.PostalDest.AtPlz!.Country)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Country)
.ToListAsync(), MemberInput_SelectionChanged);
if (MemberCustomInput.SelectedItems.Count == 0) {
MemberCustomInput.SelectionChanged -= MemberInput_SelectionChanged;
@@ -492,13 +487,8 @@ namespace Elwig.Windows {
}
Recipients = await query
.Include(m => m.Branch)
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.PostalDest.AtPlz!.Country)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Country)
.ToListAsync();
}
UpdatePostalEmailRecipients();
@@ -758,7 +748,7 @@ namespace Elwig.Windows {
if (doc.Type == DocType.Custom) {
return [new GeneratedDoc((string)doc.Details!)];
} else if (doc.Type == DocType.MemberDataSheet) {
return [new GeneratedDoc(new MemberDataSheet(m, ctx) { Date = postalDate })];
return [new GeneratedDoc(new MemberDataSheet(m) { Date = postalDate })];
} else if (doc.Type == DocType.DeliveryConfirmation) {
var year = (int)doc.Details!;
DeliveryConfirmationDeliveryData data;
@@ -769,21 +759,14 @@ namespace Elwig.Windows {
} else {
return [];
}
return [new GeneratedDoc(new DeliveryConfirmation(ctx, year, m, data) { Date = postalDate })];
return [new GeneratedDoc(new DeliveryConfirmation(year, m, data) { Date = postalDate })];
} else if (doc.Type == DocType.CreditNote) {
var details = ((int, int))doc.Details!;
var year = details.Item1;
var avnr = details.Item2;
var data = cnData[(year, avnr)];
try {
return [new GeneratedDoc(new CreditNote(
ctx, data.Item2[m.MgNr], data.Item1[m.MgNr],
data.Item3.ConsiderContractPenalties,
data.Item3.ConsiderTotalPenalty,
data.Item3.ConsiderAutoBusinessShares,
data.Item3.ConsiderCustomModifiers,
ctx.GetMemberUnderDelivery(year, m.MgNr).GetAwaiter().GetResult()
) { Date = postalDate })];
return [new GeneratedDoc(new CreditNote(data.Item2[m.MgNr], data.Item3, data.Item1[m.MgNr]) { Date = postalDate })];
} catch (Exception) {
return [];
}
@@ -827,7 +810,7 @@ namespace Elwig.Windows {
var emailRecipients = email.Select(d => d.Key.MgNr).ToHashSet();
foreach (var item1 in email.Select((e, i) => new { Index = i, e.Key, e.Value })) {
foreach (var item2 in item1.Value.Select((d, i) => new { Index = i, Doc = d })) {
await item2.Doc.Generate(CancelGeneration?.Token, new Progress<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;
})));
}
@@ -861,7 +844,7 @@ namespace Elwig.Windows {
if (printDocs.Count > 0) {
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;
})));
PrintDocument = print;

View File

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

View File

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

View File

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