Compare commits
27 Commits
dd6f18117e
...
v1.0.5.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 61bdb2f3b5 | |||
| 2915f08a6b | |||
| 5c2fae1855 | |||
| 95fabe3633 | |||
| 7861a15e2e | |||
| 20fd5d5826 | |||
| 2b3c293730 | |||
| a852dbb242 | |||
| 7edf395497 | |||
| ea2b6db1fc | |||
| cf48f005e2 | |||
| 4eac8cd629 | |||
| 360856585a | |||
| cc6e31a006 | |||
| ce1a55df86 | |||
| 07d93dd384 | |||
| f6e9d429d5 | |||
| 7b78f9d6b9 | |||
| 22fbb0772f | |||
| 0a9c800116 | |||
| 278d79429b | |||
| e5e5e10cd7 | |||
| d051a2bfcf | |||
| 9c39a2f820 | |||
| 4460de9975 | |||
| f96ebdcf60 | |||
| e593175e72 |
@@ -23,6 +23,16 @@ jobs:
|
|||||||
echo "No files with BOM found"
|
echo "No files with BOM found"
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
- name: Check for code smells
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
git grep -IEn "\.(Single|First|Min|Max|Any)(OrDefault)?Async\([^)]|^using System.Data.Entity;"
|
||||||
|
if ( $lastexitcode -ne 1 ) {
|
||||||
|
exit 1
|
||||||
|
} else {
|
||||||
|
echo "No files with code smells found"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
- name: Setup MSBuild
|
- name: Setup MSBuild
|
||||||
uses: microsoft/setup-msbuild@v1.1
|
uses: microsoft/setup-msbuild@v1.1
|
||||||
- name: Setup NuGet
|
- name: Setup NuGet
|
||||||
|
|||||||
55
CHANGELOG.md
55
CHANGELOG.md
@@ -2,6 +2,61 @@
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
[v1.0.5.2][v1.0.5.2] (2026-04-24) {#v1.0.5.2}
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
### Behobene Fehler {#v1.0.5.2-bugfixes}
|
||||||
|
|
||||||
|
* Im Lieferungen-Fenster (`DeliveryAdminWindow`) sind Attribut/Bewirtschaftungsart in der Liste für Teil-Lieferungen nicht angezeigt worden. (5c2fae1855)
|
||||||
|
|
||||||
|
### Sonstiges {#v1.0.5.2-misc}
|
||||||
|
|
||||||
|
* Abhängigkeiten aktualisiert. (2915f08a6b)
|
||||||
|
|
||||||
|
[v1.0.5.2]: https://git.necronda.net/winzer/elwig/releases/tag/v1.0.5.2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[v1.0.5.1][v1.0.5.1] (2026-04-20) {#v1.0.5.1}
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
### Behobene Fehler {#v1.0.5.1-bugfixes}
|
||||||
|
|
||||||
|
* Zu-/Abschläge mit absolutem Wert (z.B. `€/kg`) wurden bei der Auszahlung nie mit der Menge multipliziert. (ea2b6db1fc)
|
||||||
|
* Massenaktionen im Lieferungen-Fenster (`DeliveryAdminWindow`) haben für Zu-/Abschläge nicht funktioniert. (4eac8cd629, cf48f005e2)
|
||||||
|
|
||||||
|
### Sonstiges {#v1.0.5.1-misc}
|
||||||
|
|
||||||
|
* Behebung von Kleinigkeiten im Layout bei Dokumenten (`CreditNote`, `PaymentVariantSummary`). (7edf395497, a852dbb242)
|
||||||
|
* Zuordnung von zwei Gemeinden vom Weinbaugebiet Neusiedlersee (`WLNS`) zu Leithaberg (`WLLB`). (2b3c293730)
|
||||||
|
* Abhängigkeiten aktualisiert. (20fd5d5826, 7861a15e2e)
|
||||||
|
|
||||||
|
[v1.0.5.1]: https://git.necronda.net/winzer/elwig/releases/tag/v1.0.5.1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[v1.0.5.0][v1.0.5.0] (2026-04-08) {#v1.0.5.0}
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
### Neue Funktionen {#v1.0.5.0-features}
|
||||||
|
|
||||||
|
* Flächenbindungen werden nun in _Verträgen_ zusammengefasst um bessere Übersicht und historische Nachvollziehbarkeit zu gewährleisten. ([#77][i77])
|
||||||
|
|
||||||
|
### Sonstiges {#v1.0.5.0-misc}
|
||||||
|
|
||||||
|
* Erhebliche Verbesserung der Leistung/Geschwindigkeit. ([#79][i79], e5e5e10cd7, 22fbb0772f)
|
||||||
|
* Am Stammdatenblatt (`MemberDataSheet`) wird nun als Datum das Datum der letzten Bearbeitung angegeben. (0a9c800116)
|
||||||
|
* Abhängigkeiten aktualisiert. (07d93dd384, ce1a55df86, cc6e31a006)
|
||||||
|
|
||||||
|
[v1.0.5.0]: https://git.necronda.net/winzer/elwig/releases/tag/v1.0.5.0
|
||||||
|
[i77]: https://git.necronda.net/winzer/elwig/issues/77
|
||||||
|
[i79]: https://git.necronda.net/winzer/elwig/issues/79
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[v1.0.4.1][v1.0.4.1] (2026-03-27) {#v1.0.4.1}
|
[v1.0.4.1][v1.0.4.1] (2026-03-27) {#v1.0.4.1}
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -105,9 +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
|
branches = ctx.FetchBranches()
|
||||||
.Include(b => b.PostalDest)
|
.ToDictionaryAsync(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))
|
||||||
.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));
|
.GetAwaiter().GetResult();
|
||||||
try {
|
try {
|
||||||
Client = new(ctx);
|
Client = new(ctx);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -201,6 +201,7 @@ namespace Elwig {
|
|||||||
BranchName = entry.Item2;
|
BranchName = entry.Item2;
|
||||||
BranchPlz = entry.Item3;
|
BranchPlz = entry.Item3;
|
||||||
BranchLocation = entry.Item4?
|
BranchLocation = entry.Item4?
|
||||||
|
.Split(",")[0]
|
||||||
.Split(" in ")[0]
|
.Split(" in ")[0]
|
||||||
.Split(" im ")[0]
|
.Split(" im ")[0]
|
||||||
.Split(" an ")[0]
|
.Split(" an ")[0]
|
||||||
@@ -221,7 +222,8 @@ namespace Elwig {
|
|||||||
MainDispatcher.Invoke(() => {
|
MainDispatcher.Invoke(() => {
|
||||||
foreach (Window w in CurrentApp.Windows) {
|
foreach (Window w in CurrentApp.Windows) {
|
||||||
if (w is not ContextWindow c) continue;
|
if (w is not ContextWindow c) continue;
|
||||||
MainDispatcher.BeginInvoke(c.HintContextChange);
|
MainDispatcher.Invoke(c.HintContextChange);
|
||||||
|
MainDispatcher.BeginInvoke(c.TryContextReload);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,15 +47,15 @@ namespace Elwig.Controls {
|
|||||||
private void UpdateButtons() {
|
private void UpdateButtons() {
|
||||||
var incButton = GetTemplateChild("IncrementButton") as RepeatButton;
|
var incButton = GetTemplateChild("IncrementButton") as RepeatButton;
|
||||||
var decButton = GetTemplateChild("DecrementButton") as RepeatButton;
|
var decButton = GetTemplateChild("DecrementButton") as RepeatButton;
|
||||||
incButton?.IsEnabled = Maximum != null && Value < Maximum;
|
incButton?.IsEnabled = Maximum == null || Value < Maximum;
|
||||||
decButton?.IsEnabled = Minimum != null && Value > Minimum;
|
decButton?.IsEnabled = Minimum == null || Value > Minimum;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void IntegerUpDown_TextChanged(object sender, TextChangedEventArgs evt) {
|
private void IntegerUpDown_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||||
var idx = CaretIndex;
|
var idx = CaretIndex;
|
||||||
Text = new string([.. Text.Where(char.IsAsciiDigit).Take(4)]);
|
Text = new string([.. Text.Where(char.IsAsciiDigit).Take(4)]);
|
||||||
CaretIndex = idx;
|
CaretIndex = idx;
|
||||||
evt.Handled = !(Value >= Minimum && Value <= Maximum);
|
evt.Handled = !((!Minimum.HasValue || Value >= Minimum) && (!Maximum.HasValue || Value <= Maximum));
|
||||||
if (idx >= 4) {
|
if (idx >= 4) {
|
||||||
if (Value < Minimum) {
|
if (Value < Minimum) {
|
||||||
Value = Minimum;
|
Value = Minimum;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Elwig.Helpers;
|
using Elwig.Helpers;
|
||||||
|
using System;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ namespace Elwig.Dialogs {
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Title = delete ? "Flächenbindung löschen" : "Flächenbindung bearbeiten";
|
Title = delete ? "Flächenbindung löschen" : "Flächenbindung bearbeiten";
|
||||||
RetroactiveInput.Content = delete ? "Rückwirkend löschen" : "Rückwirkend bearbeiten";
|
RetroactiveInput.Content = delete ? "Rückwirkend löschen" : "Rückwirkend bearbeiten";
|
||||||
|
forceRetroactive = forceRetroactive || yearFrom.HasValue && yearTo.HasValue && yearFrom.Value == yearTo.Value;
|
||||||
RetroactiveInput.IsEnabled = !forceRetroactive;
|
RetroactiveInput.IsEnabled = !forceRetroactive;
|
||||||
if (delete) {
|
if (delete) {
|
||||||
QuestionBlock1.Visibility = Visibility.Hidden;
|
QuestionBlock1.Visibility = Visibility.Hidden;
|
||||||
@@ -26,7 +28,8 @@ namespace Elwig.Dialogs {
|
|||||||
DescBlock1.Visibility = Visibility.Hidden;
|
DescBlock1.Visibility = Visibility.Hidden;
|
||||||
DescBlock2.Visibility = Visibility.Visible;
|
DescBlock2.Visibility = Visibility.Visible;
|
||||||
}
|
}
|
||||||
SeasonInput.Minimum = yearFrom + 1;
|
SeasonInput.Minimum = yearFrom.HasValue ? yearFrom + 1 : null;
|
||||||
|
SeasonInput.Maximum = yearTo.HasValue ? yearTo : null;
|
||||||
if (forceRetroactive || (yearTo.HasValue && yearTo < Utils.CurrentYear) || (yearFrom.HasValue && yearFrom >= Utils.CurrentYear)) {
|
if (forceRetroactive || (yearTo.HasValue && yearTo < Utils.CurrentYear) || (yearFrom.HasValue && yearFrom >= Utils.CurrentYear)) {
|
||||||
RetroactiveInput.IsChecked = true;
|
RetroactiveInput.IsChecked = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -50,7 +53,7 @@ namespace Elwig.Dialogs {
|
|||||||
DescBlock2.Visibility = Visibility.Hidden;
|
DescBlock2.Visibility = Visibility.Hidden;
|
||||||
} else {
|
} else {
|
||||||
SeasonInput.IsEnabled = true;
|
SeasonInput.IsEnabled = true;
|
||||||
SeasonInput.Text = $"{Utils.CurrentYear}";
|
SeasonInput.Text = $"{Math.Max(SeasonInput.Minimum ?? Utils.CurrentYear, Utils.CurrentYear)}";
|
||||||
DescBlock1.Visibility = QuestionBlock1.Visibility;
|
DescBlock1.Visibility = QuestionBlock1.Visibility;
|
||||||
DescBlock2.Visibility = QuestionBlock2.Visibility;
|
DescBlock2.Visibility = QuestionBlock2.Visibility;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,15 +44,10 @@ namespace Elwig.Dialogs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task OnRenewContext(AppDbContext ctx) {
|
protected override async Task OnRenewContext(AppDbContext ctx) {
|
||||||
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
|
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers().ToListAsync());
|
||||||
.Where(m => m.IsActive)
|
|
||||||
.OrderBy(m => m.Name)
|
|
||||||
.ThenBy(m => m.GivenName)
|
|
||||||
.ToListAsync());
|
|
||||||
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)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ namespace Elwig.Documents {
|
|||||||
public bool IncludeSender = false;
|
public bool IncludeSender = false;
|
||||||
public bool UseBillingAddress = false;
|
public bool UseBillingAddress = false;
|
||||||
public bool ShowDateAndLocation = false;
|
public bool ShowDateAndLocation = false;
|
||||||
|
public DateOnly? DateFrom;
|
||||||
protected Table? Aside;
|
protected Table? Aside;
|
||||||
|
|
||||||
public string Address {
|
public string Address {
|
||||||
@@ -47,11 +48,12 @@ namespace Elwig.Documents {
|
|||||||
return NewAsideCell(new KernedParagraph(text, 10), colspan, isName);
|
return NewAsideCell(new KernedParagraph(text, 10), colspan, isName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BusinessDocument(string title, Member m, bool includeSender = false) :
|
public BusinessDocument(string title, Member m, DateOnly? dateFrom, bool includeSender = false) :
|
||||||
base(title) {
|
base(title) {
|
||||||
Member = m;
|
Member = m;
|
||||||
Location = App.BranchLocation;
|
Location = App.BranchLocation;
|
||||||
IncludeSender = includeSender;
|
IncludeSender = includeSender;
|
||||||
|
DateFrom = dateFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||||
@@ -105,7 +107,7 @@ namespace Elwig.Documents {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doc.Add(new KernedParagraph(ShowDateAndLocation ? $"{Location}, am {Date:dd.MM.yyyy}" : "", 12).SetTextAlignment(TextAlignment.RIGHT).SetVerticalAlignment(VerticalAlignment.MIDDLE).SetHeight(24).SetMargin(0));
|
doc.Add(new KernedParagraph(ShowDateAndLocation ? $"{Location}, am {DateFrom ?? Date:dd.MM.yyyy}" : "", 12).SetTextAlignment(TextAlignment.RIGHT).SetVerticalAlignment(VerticalAlignment.MIDDLE).SetHeight(24).SetMargin(0));
|
||||||
doc.Add(new KernedParagraph(Title, 12).SetFont(BF).SetMargins(0, 0, 12, 0));
|
doc.Add(new KernedParagraph(Title, 12).SetFont(BF).SetMargins(0, 0, 12, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ namespace Elwig.Documents {
|
|||||||
private CreditNoteDeliveryData? _data;
|
private CreditNoteDeliveryData? _data;
|
||||||
private Dictionary<string, UnderDelivery>? _underDeliveries;
|
private Dictionary<string, UnderDelivery>? _underDeliveries;
|
||||||
|
|
||||||
public CreditNote(PaymentMember p, BillingData? billingData = null, CreditNoteDeliveryData? data = null, Dictionary<string, UnderDelivery>? underDeliveries = null) :
|
public CreditNote(PaymentMember p, DateOnly? dateFrom, 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, dateFrom) {
|
||||||
UseBillingAddress = true;
|
UseBillingAddress = true;
|
||||||
ShowDateAndLocation = true;
|
ShowDateAndLocation = true;
|
||||||
Payment = p;
|
Payment = p;
|
||||||
@@ -58,12 +58,12 @@ namespace Elwig.Documents {
|
|||||||
ConsiderCustomModifiers = billingData.ConsiderCustomModifiers;
|
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) {
|
public static async Task<CreditNote> Initialize(int year, int avnr, int mgnr, DateOnly? dateFrom, BillingData? billingData = null, CreditNoteDeliveryData? data = null, Dictionary<string, UnderDelivery>? underDeliveries = null) {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var p = await ctx.MemberPayments
|
var p = await ctx.MemberPayments
|
||||||
.Where(p => p.Year == year && p.AvNr == avnr && p.MgNr == mgnr)
|
.Where(p => p.Year == year && p.AvNr == avnr && p.MgNr == mgnr)
|
||||||
.SingleAsync();
|
.SingleAsync();
|
||||||
return new CreditNote(p, billingData, data, underDeliveries);
|
return new CreditNote(p, dateFrom, billingData, data, underDeliveries);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task LoadData(AppDbContext ctx) {
|
protected override async Task LoadData(AppDbContext ctx) {
|
||||||
@@ -76,7 +76,7 @@ namespace Elwig.Documents {
|
|||||||
_data ??= (await CreditNoteDeliveryData.ForPaymentVariant(ctx.CreditNoteDeliveryRows, ctx.PaymentVariants, Payment.Year, Payment.AvNr))[Member.MgNr];
|
_data ??= (await CreditNoteDeliveryData.ForPaymentVariant(ctx.CreditNoteDeliveryRows, ctx.PaymentVariants, Payment.Year, Payment.AvNr))[Member.MgNr];
|
||||||
_underDeliveries ??= await ctx.GetMemberUnderDelivery(Payment.Year, 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;
|
var mod = App.Client.IsMatzen ? await ctx.FetchModifiers(season.Year).Where(m => 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) {
|
||||||
@@ -102,8 +102,8 @@ namespace Elwig.Documents {
|
|||||||
MemberAutoBusinessSharesAmount = MemberAutoBusinessShares * (-season.BusinessShareValue ?? 0);
|
MemberAutoBusinessSharesAmount = MemberAutoBusinessShares * (-season.BusinessShareValue ?? 0);
|
||||||
}
|
}
|
||||||
if (ConsiderContractPenalties) {
|
if (ConsiderContractPenalties) {
|
||||||
var varieties = await ctx.WineVarieties.ToDictionaryAsync(v => v.SortId, v => v);
|
var varieties = await ctx.FetchWineVarieties().ToDictionaryAsync(v => v.SortId, v => v);
|
||||||
var attributes = await ctx.WineAttributes.ToDictionaryAsync(a => a.AttrId, a => a);
|
var attributes = await ctx.FetchWineAttributes().ToDictionaryAsync(a => a.AttrId, a => a);
|
||||||
var comTypes = await ctx.AreaCommitmentTypes.ToDictionaryAsync(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)
|
||||||
@@ -321,7 +321,7 @@ namespace Elwig.Documents {
|
|||||||
var totalMod = p.TotalModifiers ?? 0;
|
var totalMod = p.TotalModifiers ?? 0;
|
||||||
var pad = i == 0 ? 0.5f : 0;
|
var pad = i == 0 ? 0.5f : 0;
|
||||||
sub.AddCell(NewTd(rebelMod == 0 ? "-" : (Utils.GetSign(rebelMod) + $"{Math.Abs(rebelMod):0.0##}"), 6, center: true)
|
sub.AddCell(NewTd(rebelMod == 0 ? "-" : (Utils.GetSign(rebelMod) + $"{Math.Abs(rebelMod):0.0##}"), 6, center: true)
|
||||||
.SetPaddingTopMM(pad))
|
.SetPaddingTopMM(pad).SetPaddingLeft(0).SetPaddingRight(0))
|
||||||
.AddCell(NewTd(totalMod == 0 ? "-" : Utils.GetSign(totalMod) + $"{Math.Abs(totalMod):N2}", center: totalMod == 0, right: true)
|
.AddCell(NewTd(totalMod == 0 ? "-" : Utils.GetSign(totalMod) + $"{Math.Abs(totalMod):N2}", center: totalMod == 0, right: true)
|
||||||
.SetPaddingTopMM(pad))
|
.SetPaddingTopMM(pad))
|
||||||
.AddCell(NewTd($"{p.Amount:N2}", right: true)
|
.AddCell(NewTd($"{p.Amount:N2}", right: true)
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ namespace Elwig.Documents {
|
|||||||
public Dictionary<string, MemberBucket> MemberBuckets = [];
|
public Dictionary<string, MemberBucket> MemberBuckets = [];
|
||||||
public List<MemberStat> MemberStats = [];
|
public List<MemberStat> MemberStats = [];
|
||||||
|
|
||||||
public DeliveryConfirmation(int year, Member m, DeliveryConfirmationDeliveryData? data = null) :
|
public DeliveryConfirmation(int year, Member m, DateOnly? dateFrom, DeliveryConfirmationDeliveryData? data = null) :
|
||||||
base($"{Name} {year}", m) {
|
base($"{Name} {year}", m, dateFrom) {
|
||||||
_year = year;
|
_year = year;
|
||||||
ShowDateAndLocation = true;
|
ShowDateAndLocation = true;
|
||||||
UseBillingAddress = true;
|
UseBillingAddress = true;
|
||||||
@@ -35,7 +35,7 @@ namespace Elwig.Documents {
|
|||||||
|
|
||||||
protected override async Task LoadData(AppDbContext ctx) {
|
protected override async Task LoadData(AppDbContext ctx) {
|
||||||
await base.LoadData(ctx);
|
await base.LoadData(ctx);
|
||||||
Season = ctx.Seasons.Find(_year) ?? throw new ArgumentException("invalid season");
|
Season = await ctx.FetchSeasons(_year).SingleOrDefaultAsync() ?? throw new ArgumentException("Invalid season");
|
||||||
MemberDeliveredWeight = await ctx.Deliveries
|
MemberDeliveredWeight = await ctx.Deliveries
|
||||||
.Where(d => d.Year == Season.Year && d.MgNr == Member.MgNr)
|
.Where(d => d.Year == Season.Year && d.MgNr == Member.MgNr)
|
||||||
.SelectMany(d => d.Parts)
|
.SelectMany(d => d.Parts)
|
||||||
|
|||||||
@@ -29,14 +29,12 @@ namespace Elwig.Documents {
|
|||||||
public int DisplayStats = App.Client.ModeDeliveryNoteStats;
|
public int DisplayStats = App.Client.ModeDeliveryNoteStats;
|
||||||
|
|
||||||
public DeliveryNote(Delivery d) :
|
public DeliveryNote(Delivery d) :
|
||||||
base($"{Name} Nr. {d.LsNr}", d.Member) {
|
base($"{Name} Nr. {d.LsNr}", d.Member, DateOnly.FromDateTime(d.ModifiedAt)) {
|
||||||
UseBillingAddress = true;
|
UseBillingAddress = true;
|
||||||
ShowDateAndLocation = true;
|
ShowDateAndLocation = true;
|
||||||
Delivery = d;
|
Delivery = d;
|
||||||
Text = App.Client.TextDeliveryNote;
|
Text = App.Client.TextDeliveryNote;
|
||||||
DocumentId = d.LsNr;
|
DocumentId = d.LsNr;
|
||||||
Date = DateOnly.FromDateTime(d.ModifiedAt);
|
|
||||||
IsDoublePaged = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<DeliveryNote> Initialize(int year, int did) {
|
public static async Task<DeliveryNote> Initialize(int year, int did) {
|
||||||
|
|||||||
@@ -49,14 +49,12 @@ namespace Elwig.Documents {
|
|||||||
public bool IsPreview = false;
|
public bool IsPreview = false;
|
||||||
private iText.Layout.Document? _doc;
|
private iText.Layout.Document? _doc;
|
||||||
|
|
||||||
public int CurrentNextSeason;
|
|
||||||
public string? DocumentId;
|
public string? DocumentId;
|
||||||
public string Title;
|
public string Title;
|
||||||
public string Author;
|
public string Author;
|
||||||
public DateOnly Date;
|
public DateOnly Date;
|
||||||
|
|
||||||
public Document(string title) {
|
public Document(string title) {
|
||||||
CurrentNextSeason = Utils.CurrentNextSeason;
|
|
||||||
Title = title;
|
Title = title;
|
||||||
Author = App.Client.NameFull;
|
Author = App.Client.NameFull;
|
||||||
Date = DateOnly.FromDateTime(Utils.Today);
|
Date = DateOnly.FromDateTime(Utils.Today);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using iText.Layout;
|
|||||||
namespace Elwig.Documents {
|
namespace Elwig.Documents {
|
||||||
public class Letterhead : BusinessDocument {
|
public class Letterhead : BusinessDocument {
|
||||||
public Letterhead(Member m) :
|
public Letterhead(Member m) :
|
||||||
base($"Briefkopf {m.FullName}", m, true) {
|
base($"Briefkopf {m.FullName}", m, null, includeSender: true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||||
|
|||||||
@@ -23,18 +23,19 @@ namespace Elwig.Documents {
|
|||||||
public List<AreaCom> ActiveAreaCommitments = [];
|
public List<AreaCom> ActiveAreaCommitments = [];
|
||||||
|
|
||||||
public MemberDataSheet(Member m) :
|
public MemberDataSheet(Member m) :
|
||||||
base($"{Name} {m.AdministrativeName}", m) {
|
base($"{Name} {m.AdministrativeName}", m, DateOnly.FromDateTime(m.ModifiedAt)) {
|
||||||
|
ShowDateAndLocation = true;
|
||||||
DocumentId = $"{Name} {m.MgNr}";
|
DocumentId = $"{Name} {m.MgNr}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<MemberDataSheet> Initialize(int mgnr) {
|
public static async Task<MemberDataSheet> Initialize(int mgnr) {
|
||||||
using var ctx = new AppDbContext();
|
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());
|
return new MemberDataSheet(await ctx.FetchMembers(mgnr, true, true).SingleAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task LoadData(AppDbContext ctx) {
|
protected override async Task LoadData(AppDbContext ctx) {
|
||||||
await base.LoadData(ctx);
|
await base.LoadData(ctx);
|
||||||
Season = await ctx.Seasons.OrderBy(s => s.Year).LastOrDefaultAsync() ?? throw new ArgumentException("invalid season");
|
Season = await ctx.FetchSeasons().FirstOrDefaultAsync() ?? throw new ArgumentException("Invalid season");
|
||||||
MemberBuckets = await ctx.GetMemberBuckets(Utils.CurrentYear, Member.MgNr);
|
MemberBuckets = await ctx.GetMemberBuckets(Utils.CurrentYear, Member.MgNr);
|
||||||
ActiveAreaCommitments = await Member.ActiveAreaCommitments(ctx)
|
ActiveAreaCommitments = await Member.ActiveAreaCommitments(ctx)
|
||||||
.Include(c => c.Contract).ThenInclude(c => c.Revisions)
|
.Include(c => c.Contract).ThenInclude(c => c.Revisions)
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ namespace Elwig.Documents {
|
|||||||
DeliveryPartNum = await ctx.DeliveryParts.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);
|
Data ??= await PaymentVariantSummaryData.ForPaymentVariant(Variant, ctx.PaymentVariantSummaryRows);
|
||||||
ModifierStat = await AppDbContext.GetModifierStats(Variant.Year, Variant.AvNr);
|
ModifierStat = await AppDbContext.GetModifierStats(Variant.Year, Variant.AvNr);
|
||||||
Modifiers = await ctx.Modifiers.Where(m => m.Year == Variant.Year).ToDictionaryAsync(m => m.ModId);
|
Modifiers = await ctx.FetchModifiers(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) {
|
||||||
@@ -183,21 +183,21 @@ namespace Elwig.Documents {
|
|||||||
.AddCell(NewTd(CurrencySymbol))
|
.AddCell(NewTd(CurrencySymbol))
|
||||||
.AddCell(NewTd($"{Math.Abs(payed):N2}", right: true))
|
.AddCell(NewTd($"{Math.Abs(payed):N2}", right: true))
|
||||||
.AddCell(NewSectionTh("Preis (abgewertet):", borderTop: true, borderLeft: true))
|
.AddCell(NewSectionTh("Preis (abgewertet):", borderTop: true, borderLeft: true))
|
||||||
.AddCell(NewTd((minWei != maxWei ? $"{minWei:N4}\u2013{maxWei:N4}" : $"{minWei:N4}") + $" {CurrencySymbol}/kg", colspan: 2, center: true, borderTop: true))
|
.AddCell(NewTd(minWei == null && maxWei == null ? "-" : (minWei != maxWei ? $"{minWei:N4}\u2013{maxWei:N4}" : $"{minWei:N4}") + $" {CurrencySymbol}/kg", colspan: 2, center: true, borderTop: true))
|
||||||
|
|
||||||
.AddCell(NewSectionTh("Nettosumme:", colspan: 2))
|
.AddCell(NewSectionTh("Nettosumme:", colspan: 2))
|
||||||
.AddCell(NewTd(borderTop: true))
|
.AddCell(NewTd(borderTop: true))
|
||||||
.AddCell(NewTd(CurrencySymbol, borderTop: true))
|
.AddCell(NewTd(CurrencySymbol, borderTop: true))
|
||||||
.AddCell(NewTd($"{netSum:N2}", right: true, borderTop: true))
|
.AddCell(NewTd($"{netSum:N2}", right: true, borderTop: true))
|
||||||
.AddCell(NewSectionTh("Preis (ungeb., nicht abgew.):", borderLeft: true))
|
.AddCell(NewSectionTh("Preis (ungeb., nicht abgew.):", borderLeft: true))
|
||||||
.AddCell(NewTd((minPrice != maxPrice ? $"{minPrice:N4}–{maxPrice:N4}" : $"{minPrice:N4}") + $" {CurrencySymbol}/kg", colspan: 2, center: true))
|
.AddCell(NewTd(minPrice == null && maxPrice == null ? "-" : (minPrice != maxPrice ? $"{minPrice:N4}–{maxPrice:N4}" : $"{minPrice:N4}") + $" {CurrencySymbol}/kg", colspan: 2, center: true))
|
||||||
|
|
||||||
.AddCell(NewSectionTh("Mehrwertsteuer:", colspan: 2))
|
.AddCell(NewSectionTh("Mehrwertsteuer:", colspan: 2))
|
||||||
.AddCell(NewTd(Utils.GetSign(vat), right: true))
|
.AddCell(NewTd(Utils.GetSign(vat), right: true))
|
||||||
.AddCell(NewTd(CurrencySymbol))
|
.AddCell(NewTd(CurrencySymbol))
|
||||||
.AddCell(NewTd($"{Math.Abs(vat):N2}", right: true))
|
.AddCell(NewTd($"{Math.Abs(vat):N2}", right: true))
|
||||||
.AddCell(NewSectionTh("Gebunden-Zuschlag:", borderLeft: true))
|
.AddCell(NewSectionTh("Gebunden-Zuschlag:", borderLeft: true))
|
||||||
.AddCell(NewTd(minGeb != maxGeb ? $"{minGeb:N4}\u2013{maxGeb:N4} {CurrencySymbol}/kg" : minGeb == 0 ? "-" : $"{minGeb:N4} {CurrencySymbol}/kg", colspan: 2, center: true))
|
.AddCell(NewTd(minGeb == null && maxGeb == null ? "-" : minGeb != maxGeb ? $"{minGeb:N4}\u2013{maxGeb:N4} {CurrencySymbol}/kg" : minGeb == 0 ? "-" : $"{minGeb:N4} {CurrencySymbol}/kg", colspan: 2, center: true))
|
||||||
|
|
||||||
.AddCell(NewSectionTh("Bruttosumme:", colspan: 2))
|
.AddCell(NewSectionTh("Bruttosumme:", colspan: 2))
|
||||||
.AddCell(NewTd(borderTop: true))
|
.AddCell(NewTd(borderTop: true))
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||||
<ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon>
|
<ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon>
|
||||||
<Version>1.0.4.1</Version>
|
<Version>1.0.5.2</Version>
|
||||||
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
@@ -23,21 +23,21 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="bblanchon.PDFium.Win32" Version="148.0.7749" />
|
<PackageReference Include="bblanchon.PDFium.Win32" Version="149.0.7802" />
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
|
||||||
<PackageReference Include="itext" Version="9.5.0" />
|
<PackageReference Include="itext" Version="9.6.0" />
|
||||||
<PackageReference Include="itext.bouncy-castle-adapter" Version="9.5.0" />
|
<PackageReference Include="itext.bouncy-castle-adapter" Version="9.6.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.16.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.5" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.7" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="10.0.5" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="10.0.7" />
|
||||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3856.49" />
|
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3912.50" />
|
||||||
<PackageReference Include="NJsonSchema" Version="11.5.2" />
|
<PackageReference Include="NJsonSchema" Version="11.6.1" />
|
||||||
<PackageReference Include="ScottPlot.WPF" Version="5.1.57" />
|
<PackageReference Include="ScottPlot.WPF" Version="5.1.58" />
|
||||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.0.2" />
|
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.0.2" />
|
||||||
<PackageReference Include="System.IO.Hashing" Version="10.0.5" />
|
<PackageReference Include="System.IO.Hashing" Version="10.0.7" />
|
||||||
<PackageReference Include="System.IO.Ports" Version="10.0.5" />
|
<PackageReference Include="System.IO.Ports" Version="10.0.7" />
|
||||||
<PackageReference Include="System.Management" Version="10.0.5" />
|
<PackageReference Include="System.Management" Version="10.0.7" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ using Elwig.Models.Entities;
|
|||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using ScottPlot.TickGenerators.Financial;
|
||||||
|
using ScottPlot.TickGenerators.TimeUnits;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
@@ -11,6 +13,7 @@ using System.Linq;
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Media.Converters;
|
||||||
|
|
||||||
namespace Elwig.Helpers {
|
namespace Elwig.Helpers {
|
||||||
|
|
||||||
@@ -82,6 +85,70 @@ namespace Elwig.Helpers {
|
|||||||
public static string? ConnectionStringOverride { get; set; } = null;
|
public static string? ConnectionStringOverride { get; set; } = null;
|
||||||
public static string ConnectionString => ConnectionStringOverride ?? $"Data Source=\"{App.Config.DatabaseFile}\"; Mode=ReadWrite; Foreign Keys=True; Cache=Default; Pooling=False";
|
public static string ConnectionString => ConnectionStringOverride ?? $"Data Source=\"{App.Config.DatabaseFile}\"; Mode=ReadWrite; Foreign Keys=True; Cache=Default; Pooling=False";
|
||||||
|
|
||||||
|
private static readonly Func<AppDbContext, string?, bool, IAsyncEnumerable<Branch>> _compiledQueryBranches =
|
||||||
|
EF.CompileAsyncQuery<AppDbContext, string?, bool, Branch>((ctx, zwstid, includeWithoutMembers) => ctx.Branches
|
||||||
|
.Where(b => includeWithoutMembers || b.Members.Count > 0)
|
||||||
|
.Where(b => zwstid == null || b.ZwstId == zwstid)
|
||||||
|
.Include(b => b.PostalDest)
|
||||||
|
.OrderBy(b => b.Name));
|
||||||
|
|
||||||
|
private static readonly Func<AppDbContext, string?, IAsyncEnumerable<WineVar>> _compiledQueryWineVarieties =
|
||||||
|
EF.CompileAsyncQuery<AppDbContext, string?, WineVar>((ctx, sortid) => ctx.WineVarieties
|
||||||
|
.Where(v => sortid == null || v.SortId == sortid)
|
||||||
|
.OrderBy(v => v.Name));
|
||||||
|
|
||||||
|
private static readonly Func<AppDbContext, string?, bool, IAsyncEnumerable<WineAttr>> _compiledQueryWineAttributes =
|
||||||
|
EF.CompileAsyncQuery<AppDbContext, string?, bool, WineAttr>((ctx, attrid, includeNotActive) => ctx.WineAttributes
|
||||||
|
.Where(a => includeNotActive || a.IsActive)
|
||||||
|
.Where(a => attrid == null || a.AttrId == attrid)
|
||||||
|
.OrderBy(a => a.Name));
|
||||||
|
|
||||||
|
private static readonly Func<AppDbContext, string?, IAsyncEnumerable<WineCult>> _compiledQueryWineCultivations =
|
||||||
|
EF.CompileAsyncQuery<AppDbContext, string?, WineCult>((ctx, cultid) => ctx.WineCultivations
|
||||||
|
.Where(c => cultid == null || c.CultId == cultid)
|
||||||
|
.OrderBy(v => v.Name));
|
||||||
|
|
||||||
|
private static readonly Func<AppDbContext, bool, IAsyncEnumerable<WineQualLevel>> _compiledQueryWineQualityLevels =
|
||||||
|
EF.CompileAsyncQuery<AppDbContext, bool, WineQualLevel>((ctx, includePredicate) => ctx.WineQualityLevels
|
||||||
|
.Where(l => includePredicate || !l.IsPredicate)
|
||||||
|
.OrderBy(l => l.MinKmw));
|
||||||
|
|
||||||
|
private static readonly Func<AppDbContext, int?, bool, IAsyncEnumerable<Modifier>> _compiledQueryModifiers =
|
||||||
|
EF.CompileAsyncQuery<AppDbContext, int?, bool, Modifier>((ctx, year, incudeNotActive) => ctx.Modifiers
|
||||||
|
.Where(m => (year == null || m.Year == year) && (incudeNotActive || m.IsActive))
|
||||||
|
.OrderBy(m => m.Year).ThenBy(m => m.Ordering).ThenBy(m => m.Name));
|
||||||
|
|
||||||
|
private static readonly Func<AppDbContext, int?, bool, IAsyncEnumerable<Member>> _compiledQueryMembers =
|
||||||
|
EF.CompileAsyncQuery<AppDbContext, int?, bool, Member>((ctx, mgnr, includeNotActive) => ctx.Members
|
||||||
|
.Where(m => includeNotActive || m.IsActive)
|
||||||
|
.Where(m => mgnr == null || m.MgNr == mgnr)
|
||||||
|
.OrderBy(m => m.Name).ThenBy(m => m.GivenName).ThenBy(m => m.MgNr));
|
||||||
|
|
||||||
|
private static readonly Func<AppDbContext, int?, bool, IAsyncEnumerable<Member>> _compiledQueryMembersContactInfo =
|
||||||
|
EF.CompileAsyncQuery<AppDbContext, int?, bool, Member>((ctx, mgnr, includeNotActive) => ctx.Members
|
||||||
|
.Where(m => includeNotActive || m.IsActive)
|
||||||
|
.Where(m => mgnr == null || m.MgNr == mgnr)
|
||||||
|
.Include(m => m.EmailAddresses)
|
||||||
|
.Include(m => m.TelephoneNumbers)
|
||||||
|
.OrderBy(m => m.Name).ThenBy(m => m.GivenName).ThenBy(m => m.MgNr)
|
||||||
|
.AsSplitQuery());
|
||||||
|
|
||||||
|
private static readonly Func<AppDbContext, int?, IAsyncEnumerable<AreaCom>> _compiledQueryAreaCommitments =
|
||||||
|
EF.CompileAsyncQuery<AppDbContext, int?, AreaCom>((ctx, fbnr) => ctx.AreaCommitments
|
||||||
|
.Where(c => fbnr == null || c.FbNr == fbnr)
|
||||||
|
.OrderBy(c => c.FbNr).ThenBy(c => c.RevNr));
|
||||||
|
|
||||||
|
private static readonly Func<AppDbContext, int?, IAsyncEnumerable<Season>> _compiledQuerySeasons =
|
||||||
|
EF.CompileAsyncQuery<AppDbContext, int?, Season>((ctx, year) => ctx.Seasons
|
||||||
|
.Where(s => year == null || s.Year == year)
|
||||||
|
.OrderByDescending(s => s.Year));
|
||||||
|
|
||||||
|
private static readonly Func<AppDbContext, int?, IAsyncEnumerable<Season>> _compiledQuerySeasonsModifiers =
|
||||||
|
EF.CompileAsyncQuery<AppDbContext, int?, Season>((ctx, year) => ctx.Seasons
|
||||||
|
.Where(s => year == null || s.Year == year)
|
||||||
|
.Include(s => s.Modifiers)
|
||||||
|
.OrderByDescending(s => s.Year));
|
||||||
|
|
||||||
private readonly Dictionary<int, Dictionary<int, Dictionary<string, AreaComBucket>>> _memberAreaCommitmentBuckets = [];
|
private readonly Dictionary<int, Dictionary<int, Dictionary<string, AreaComBucket>>> _memberAreaCommitmentBuckets = [];
|
||||||
private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _memberDeliveryBuckets = [];
|
private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _memberDeliveryBuckets = [];
|
||||||
private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _memberDeliveryBucketsStrict = [];
|
private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _memberDeliveryBucketsStrict = [];
|
||||||
@@ -162,6 +229,10 @@ namespace Elwig.Helpers {
|
|||||||
modelBuilder.Entity<PaymentMember>().Navigation(c => c.Credit).AutoInclude();
|
modelBuilder.Entity<PaymentMember>().Navigation(c => c.Credit).AutoInclude();
|
||||||
modelBuilder.Entity<PaymentMember>().Navigation(c => c.Member).AutoInclude();
|
modelBuilder.Entity<PaymentMember>().Navigation(c => c.Member).AutoInclude();
|
||||||
modelBuilder.Entity<PaymentMember>().Navigation(c => c.Variant).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() {
|
||||||
@@ -179,23 +250,23 @@ namespace Elwig.Helpers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> MgNrExists(int mgnr) {
|
public async Task<bool> MgNrExists(int mgnr) {
|
||||||
return await Members.FindAsync(mgnr) != null;
|
return await _compiledQueryMembers.Invoke(this, mgnr, true).AnyAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> FbNrExists(int fbnr) {
|
public async Task<bool> FbNrExists(int fbnr) {
|
||||||
return await AreaCommitmentContracts.FindAsync(fbnr) != null;
|
return await _compiledQueryAreaCommitments.Invoke(this, fbnr).AnyAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> SortIdExists(string sortId) {
|
public async Task<bool> SortIdExists(string sortId) {
|
||||||
return await WineVarieties.FindAsync(sortId) != null;
|
return await _compiledQueryWineVarieties.Invoke(this, sortId).AnyAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> AttrIdExists(string attrId) {
|
public async Task<bool> AttrIdExists(string attrId) {
|
||||||
return await WineAttributes.FindAsync(attrId) != null;
|
return await _compiledQueryWineAttributes.Invoke(this, attrId, true).AnyAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> CultIdExists(string cultId) {
|
public async Task<bool> CultIdExists(string cultId) {
|
||||||
return await WineCultivations.FindAsync(cultId) != null;
|
return await _compiledQueryWineCultivations.Invoke(this, cultId).AnyAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> NextMgNr() {
|
public async Task<int> NextMgNr() {
|
||||||
@@ -213,88 +284,107 @@ namespace Elwig.Helpers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> NextRevNr(int fbnr) {
|
public async Task<int> NextRevNr(int fbnr) {
|
||||||
int c = 0;
|
return (await AreaCommitments.Where(c => c.FbNr == fbnr).Select(c => (int?)c.RevNr).MaxAsync() ?? 0) + 1;
|
||||||
(await AreaCommitments.Where(c => c.FbNr == fbnr).Select(c => c.RevNr).ToListAsync())
|
|
||||||
.ForEach(a => { if (a <= c + 100) c = a; });
|
|
||||||
return c + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> NextLNr(DateOnly date, string zwstid) {
|
public async Task<int> NextLNr(DateOnly date, string zwstid) {
|
||||||
var dateStr = date.ToString("yyyy-MM-dd");
|
var dateStr = date.ToString("yyyy-MM-dd");
|
||||||
int c = 0;
|
return (await Deliveries.Where(d => d.DateString == dateStr && d.ZwstId == zwstid).Select(d => (int?)d.LNr).MaxAsync() ?? 0) + 1;
|
||||||
(await Deliveries.Where(d => d.DateString == dateStr && d.ZwstId == zwstid).Select(d => d.LNr).ToListAsync())
|
|
||||||
.ForEach(a => { if (a <= c + 100) c = a; });
|
|
||||||
return c + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> NextDId(int year) {
|
public async Task<int> NextDId(int year) {
|
||||||
int c = 0;
|
return (await Deliveries.Where(d => d.Year == year).Select(d => (int?)d.DId).MaxAsync() ?? 0) + 1;
|
||||||
(await Deliveries.Where(d => d.Year == year).Select(d => d.DId).ToListAsync())
|
|
||||||
.ForEach(a => { if (a <= c + 100) c = a; });
|
|
||||||
return c + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> NextDPNr(int year, int did) {
|
public async Task<int> NextDPNr(int year, int did) {
|
||||||
int c = 0;
|
return (await DeliveryParts.Where(p => p.Year == year && p.DId == did).Select(p => (int?)p.DPNr).MaxAsync() ?? 0) + 1;
|
||||||
(await DeliveryParts.Where(p => p.Year == year && p.DId == did).Select(d => d.DPNr).ToListAsync())
|
|
||||||
.ForEach(a => { if (a <= c + 100) c = a; });
|
|
||||||
return c + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> NextRdNr(int kgnr) {
|
public async Task<int> NextRdNr(int kgnr) {
|
||||||
int c = 0;
|
return (await WbRde.Where(r => r.KgNr == kgnr).Select(r => (int?)r.RdNr).MaxAsync() ?? 0) + 1;
|
||||||
(await WbRde.Where(r => r.KgNr == kgnr).Select(r => r.RdNr).ToListAsync())
|
|
||||||
.ForEach(a => { if (a <= c + 100) c = a; });
|
|
||||||
return c + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> NextAvNr(int year) {
|
public async Task<int> NextAvNr(int year) {
|
||||||
int c = 0;
|
return (await PaymentVariants.Where(v => v.Year == year).Select(v => (int?)v.AvNr).MaxAsync() ?? 0) + 1;
|
||||||
(await PaymentVariants.Where(v => v.Year == year).Select(v => v.AvNr).ToListAsync())
|
|
||||||
.ForEach(a => { if (a <= c + 100) c = a; });
|
|
||||||
return c + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> NextDsNr(int year) {
|
public async Task<int> NextDsNr(int year) {
|
||||||
int c = 0;
|
return (await DeliverySchedules.Where(s => s.Year == year).Select(v => (int?)v.DsNr).MaxAsync() ?? 0) + 1;
|
||||||
(await DeliverySchedules.Where(s => s.Year == year).Select(s => s.DsNr).ToListAsync())
|
|
||||||
.ForEach(a => { if (a <= c + 100) c = a; });
|
|
||||||
return c + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateDeliveryPartModifiers(DeliveryPart part, IEnumerable<Modifier> oldModifiers, IEnumerable<Modifier> newModifiers) {
|
public IAsyncEnumerable<Branch> FetchBranches(string? zwstid = null, bool includeWithoutMembers = true) {
|
||||||
foreach (var m in Modifiers.Where(m => m.Year == part.Year)) {
|
return _compiledQueryBranches.Invoke(this, zwstid, includeWithoutMembers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsyncEnumerable<WineVar> FetchWineVarieties() {
|
||||||
|
return _compiledQueryWineVarieties.Invoke(this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsyncEnumerable<WineAttr> FetchWineAttributes(bool incudeNotActive = true) {
|
||||||
|
return _compiledQueryWineAttributes.Invoke(this, null, incudeNotActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsyncEnumerable<WineCult> FetchWineCultivations() {
|
||||||
|
return _compiledQueryWineCultivations.Invoke(this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsyncEnumerable<WineQualLevel> FetchWineQualityLevels(bool includePredicate = true) {
|
||||||
|
return _compiledQueryWineQualityLevels.Invoke(this, includePredicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsyncEnumerable<Modifier> FetchModifiers(int? year, bool incudeNotActive = true) {
|
||||||
|
return _compiledQueryModifiers.Invoke(this, year, incudeNotActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsyncEnumerable<Member> FetchMembers(int? mgnr = null, bool includeNotActive = false, bool includeContactInfo = false) {
|
||||||
|
if (includeContactInfo) {
|
||||||
|
return _compiledQueryMembersContactInfo.Invoke(this, mgnr, includeNotActive);
|
||||||
|
} else {
|
||||||
|
return _compiledQueryMembers.Invoke(this, mgnr, includeNotActive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsyncEnumerable<Season> FetchSeasons(int? year = null, bool includeModifiers = false) {
|
||||||
|
if (includeModifiers) {
|
||||||
|
return _compiledQuerySeasonsModifiers.Invoke(this, year);
|
||||||
|
} else {
|
||||||
|
return _compiledQuerySeasons.Invoke(this, year);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateDeliveryPartModifiers(DeliveryPart part, IEnumerable<string> oldModIds, IEnumerable<string> newModIds) {
|
||||||
|
foreach (var m in await FetchModifiers(part.Year).ToListAsync()) {
|
||||||
var mod = new DeliveryPartModifier {
|
var mod = new DeliveryPartModifier {
|
||||||
Year = part.Year,
|
Year = part.Year,
|
||||||
DId = part.DId,
|
DId = part.DId,
|
||||||
DPNr = part.DPNr,
|
DPNr = part.DPNr,
|
||||||
ModId = m.ModId,
|
ModId = m.ModId,
|
||||||
};
|
};
|
||||||
var old = oldModifiers.Where(pa => pa.ModId == m.ModId).FirstOrDefault();
|
var old = oldModIds.Contains(m.ModId);
|
||||||
if (newModifiers.Any(md => md.ModId == m.ModId)) {
|
if (newModIds.Contains(m.ModId)) {
|
||||||
if (old == null) {
|
if (!old) {
|
||||||
Add(mod);
|
Add(mod);
|
||||||
} else {
|
} else {
|
||||||
Update(mod);
|
Update(mod);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (old != null) {
|
if (old) {
|
||||||
Remove(mod);
|
Remove(mod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateDeliveryScheduleWineVarieties(DeliverySchedule schedule, IEnumerable<(WineVar, int)> oldVarieties, IEnumerable<(WineVar, int)> newVarieties) {
|
public async Task UpdateDeliveryScheduleWineVarieties(DeliverySchedule schedule, IEnumerable<(string, int)> oldVarieties, IEnumerable<(string, int)> newVarieties) {
|
||||||
foreach (var v in WineVarieties) {
|
foreach (var v in await FetchWineVarieties().ToArrayAsync()) {
|
||||||
var e = new DeliveryScheduleWineVar {
|
var e = new DeliveryScheduleWineVar {
|
||||||
Year = schedule.Year,
|
Year = schedule.Year,
|
||||||
DsNr = schedule.DsNr,
|
DsNr = schedule.DsNr,
|
||||||
SortId = v.SortId,
|
SortId = v.SortId,
|
||||||
Priority = 1,
|
Priority = 1,
|
||||||
};
|
};
|
||||||
var o = oldVarieties.Where(x => x.Item1.SortId == e.SortId).Select(x => x.Item2).FirstOrDefault(-1);
|
var o = oldVarieties.Where(x => x.Item1 == e.SortId).Select(x => x.Item2).FirstOrDefault(-1);
|
||||||
var n = newVarieties.Where(x => x.Item1.SortId == e.SortId).Select(x => x.Item2).FirstOrDefault(-1);
|
var n = newVarieties.Where(x => x.Item1 == e.SortId).Select(x => x.Item2).FirstOrDefault(-1);
|
||||||
if (n != -1) {
|
if (n != -1) {
|
||||||
e.Priority = n;
|
e.Priority = n;
|
||||||
if (o == -1) {
|
if (o == -1) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Elwig.Helpers {
|
|||||||
public static class AppDbUpdater {
|
public static class AppDbUpdater {
|
||||||
|
|
||||||
// Don't forget to update value in Tests/fetch-resources.bat!
|
// Don't forget to update value in Tests/fetch-resources.bat!
|
||||||
public static readonly int RequiredSchemaVersion = 38;
|
public static readonly int RequiredSchemaVersion = 39;
|
||||||
|
|
||||||
private static int VersionOffset = 0;
|
private static int VersionOffset = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Elwig.Models.Entities;
|
using Elwig.Models.Entities;
|
||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@@ -16,13 +15,30 @@ namespace Elwig.Helpers.Billing {
|
|||||||
protected readonly Dictionary<string, (decimal?, decimal?)> Modifiers;
|
protected readonly Dictionary<string, (decimal?, decimal?)> Modifiers;
|
||||||
protected readonly Dictionary<string, (string, string?, string?, int?, decimal?)> AreaComTypes;
|
protected readonly Dictionary<string, (string, string?, string?, int?, decimal?)> AreaComTypes;
|
||||||
|
|
||||||
public Billing(int year) {
|
protected Billing(int year, Season season,
|
||||||
|
Dictionary<string, string> attributes,
|
||||||
|
Dictionary<string, (decimal?, decimal?)> modifiers,
|
||||||
|
Dictionary<string, (string, string?, string?, int?, decimal?)> areaComTypes
|
||||||
|
) {
|
||||||
Year = year;
|
Year = year;
|
||||||
|
Season = season;
|
||||||
|
Attributes = attributes;
|
||||||
|
Modifiers = modifiers;
|
||||||
|
AreaComTypes = areaComTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static async Task<(Season, Dictionary<string, string>, Dictionary<string, (decimal?, decimal?)>, Dictionary<string, (string, string?, string?, int?, decimal?)>)> LoadData(AppDbContext ctx, int year) {
|
||||||
|
var season = await ctx.FetchSeasons(year).SingleOrDefaultAsync() ?? throw new ArgumentException("Invalid season");
|
||||||
|
var attributes = await ctx.FetchWineAttributes().ToDictionaryAsync(a => a.AttrId, a => a.Name);
|
||||||
|
var modifiers = await ctx.FetchModifiers(year).ToDictionaryAsync(m => m.ModId, m => (m.Abs, m.Rel));
|
||||||
|
var areaComTypes = ctx.AreaCommitmentTypes.ToDictionary(v => v.VtrgId, v => (v.SortId, v.AttrId, v.Discriminator, v.MinKgPerHa, v.PenaltyAmount));
|
||||||
|
return (season, attributes, modifiers, areaComTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<Billing> Create(int year) {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
Season = ctx.Seasons.Find(Year)!;
|
var (season, attributes, modifiers, areaComTypes) = await LoadData(ctx, year);
|
||||||
Attributes = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a.Name);
|
return new Billing(year, season, attributes, modifiers, areaComTypes);
|
||||||
Modifiers = ctx.Modifiers.Where(m => m.Year == Year).Include(m => m.Season).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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task FinishSeason() {
|
public async Task FinishSeason() {
|
||||||
|
|||||||
@@ -10,17 +10,35 @@ namespace Elwig.Helpers.Billing {
|
|||||||
public class BillingVariant : Billing {
|
public class BillingVariant : Billing {
|
||||||
|
|
||||||
protected readonly int AvNr;
|
protected readonly int AvNr;
|
||||||
protected readonly PaymentVar PaymentVariant;
|
protected PaymentVar PaymentVariant;
|
||||||
protected readonly PaymentBillingData Data;
|
protected PaymentBillingData Data;
|
||||||
|
|
||||||
public BillingVariant(int year, int avnr) : base(year) {
|
protected BillingVariant(int year, int avnr, Season season,
|
||||||
|
Dictionary<string, string> attributes,
|
||||||
|
Dictionary<string, (decimal?, decimal?)> modifiers,
|
||||||
|
Dictionary<string, (string, string?, string?, int?, decimal?)> areaComTypes,
|
||||||
|
PaymentVar paymentVar, PaymentBillingData data) :
|
||||||
|
base(year, season, attributes, modifiers, areaComTypes) {
|
||||||
AvNr = avnr;
|
AvNr = avnr;
|
||||||
|
PaymentVariant = paymentVar;
|
||||||
|
Data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static async Task<(PaymentVar, PaymentBillingData)> LoadData(AppDbContext ctx, int year, int avnr) {
|
||||||
|
var paymentVar = await ctx.PaymentVariants.Where(v => v.Year == year && v.AvNr == avnr).SingleAsync();
|
||||||
|
var data = PaymentBillingData.FromJson(paymentVar.Data, await Utils.GetVaributes(ctx, year, onlyDelivered: false));
|
||||||
|
return (paymentVar, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<BillingVariant> Create(int year, int 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");
|
var (season, attributes, modifiers, areaComTypes) = await LoadData(ctx, year);
|
||||||
Data = PaymentBillingData.FromJson(PaymentVariant.Data, Utils.GetVaributes(ctx, Year, onlyDelivered: false));
|
var (paymentVar, data) = await LoadData(ctx, year, avnr);
|
||||||
|
return new BillingVariant(year, avnr, season, attributes, modifiers, areaComTypes, paymentVar, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Calculate(bool strictPrices = true, bool? honorGebunden = null, bool? allowAttrsIntoLower = null, bool? avoidUnderDeliveries = null) {
|
public async Task Calculate(bool strictPrices = true, bool? honorGebunden = null, bool? allowAttrsIntoLower = null, bool? avoidUnderDeliveries = null) {
|
||||||
|
if (PaymentVariant == null || Data == null) throw new Exception("Call Load before Calculate");
|
||||||
using var cnx = await AppDbContext.ConnectAsync();
|
using var cnx = await AppDbContext.ConnectAsync();
|
||||||
using var tx = await cnx.BeginTransactionAsync();
|
using var tx = await cnx.BeginTransactionAsync();
|
||||||
await CalculateBuckets(honorGebunden, allowAttrsIntoLower, avoidUnderDeliveries, cnx);
|
await CalculateBuckets(honorGebunden, allowAttrsIntoLower, avoidUnderDeliveries, cnx);
|
||||||
@@ -214,7 +232,7 @@ namespace Elwig.Helpers.Billing {
|
|||||||
SET mod_rel = mod_rel + excluded.mod_rel;
|
SET mod_rel = mod_rel + excluded.mod_rel;
|
||||||
|
|
||||||
INSERT INTO payment_delivery_part (year, did, dpnr, avnr, net_amount, mod_abs, mod_rel)
|
INSERT INTO payment_delivery_part (year, did, dpnr, avnr, net_amount, mod_abs, mod_rel)
|
||||||
SELECT d.year, d.did, d.dpnr, {AvNr}, 0, COALESCE(m.abs, 0), COALESCE(m.rel, 0)
|
SELECT d.year, d.did, d.dpnr, {AvNr}, 0, COALESCE(m.abs, 0) * d.weight, COALESCE(m.rel, 0)
|
||||||
FROM delivery_part d
|
FROM delivery_part d
|
||||||
LEFT JOIN delivery_part_modifier p ON (p.year, p.did, p.dpnr) = (d.year, d.did, d.dpnr)
|
LEFT JOIN delivery_part_modifier p ON (p.year, p.did, p.dpnr) = (d.year, d.did, d.dpnr)
|
||||||
LEFT JOIN modifier m ON (m.year, m.modid) = (d.year, p.modid)
|
LEFT JOIN modifier m ON (m.year, m.modid) = (d.year, p.modid)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.Json.Nodes;
|
using System.Text.Json.Nodes;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Elwig.Helpers.Billing {
|
namespace Elwig.Helpers.Billing {
|
||||||
public class EditBillingData : BillingData {
|
public class EditBillingData : BillingData {
|
||||||
@@ -70,14 +71,14 @@ namespace Elwig.Helpers.Billing {
|
|||||||
return (curves, dict3);
|
return (curves, dict3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<GraphEntry> CreateGraphEntries(
|
private static async Task<List<GraphEntry>> CreateGraphEntries(
|
||||||
AppDbContext ctx, int precision,
|
AppDbContext ctx, int precision,
|
||||||
Dictionary<int, Curve> curves,
|
Dictionary<int, Curve> curves,
|
||||||
Dictionary<int, List<RawVaribute>> entries
|
Dictionary<int, List<RawVaribute>> entries
|
||||||
) {
|
) {
|
||||||
var vars = ctx.WineVarieties.ToDictionary(v => v.SortId, v => v);
|
var vars = await ctx.FetchWineVarieties().ToDictionaryAsync(v => v.SortId, v => v);
|
||||||
var attrs = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a);
|
var attrs = await ctx.FetchWineAttributes().ToDictionaryAsync(a => a.AttrId, a => a);
|
||||||
var cults = ctx.WineCultivations.ToDictionary(c => c.CultId, c => c);
|
var cults = await ctx.FetchWineCultivations().ToDictionaryAsync(c => c.CultId, c => c);
|
||||||
return entries
|
return entries
|
||||||
.Select(e => new GraphEntry(e.Key, precision, curves[e.Key], e.Value
|
.Select(e => new GraphEntry(e.Key, precision, curves[e.Key], e.Value
|
||||||
.Select(s => new Varibute(s, vars, attrs, cults))
|
.Select(s => new Varibute(s, vars, attrs, cults))
|
||||||
@@ -85,18 +86,18 @@ namespace Elwig.Helpers.Billing {
|
|||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<GraphEntry> GetPaymentGraphEntries(AppDbContext ctx, Season season) {
|
public async Task<IEnumerable<GraphEntry>> GetPaymentGraphEntries(AppDbContext ctx, Season season) {
|
||||||
var root = GetPaymentEntry();
|
var root = GetPaymentEntry();
|
||||||
var (curves, entries) = GetGraphEntries(root);
|
var (curves, entries) = GetGraphEntries(root);
|
||||||
return CreateGraphEntries(ctx, season.Precision, curves, entries).Where(e => e.Vaributes.Count > 0);
|
return (await CreateGraphEntries(ctx, season.Precision, curves, entries)).Where(e => e.Vaributes.Count > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<GraphEntry> GetQualityGraphEntries(AppDbContext ctx, Season season, int idOffset = 0) {
|
public async Task<IEnumerable<GraphEntry>> GetQualityGraphEntries(AppDbContext ctx, Season season, int idOffset = 0) {
|
||||||
var root = GetQualityEntry();
|
var root = GetQualityEntry();
|
||||||
if (root == null || root["WEI"] is not JsonNode qualityWei)
|
if (root == null || root["WEI"] is not JsonNode qualityWei)
|
||||||
return [];
|
return [];
|
||||||
var (curves, entries) = GetGraphEntries(qualityWei);
|
var (curves, entries) = GetGraphEntries(qualityWei);
|
||||||
var list = CreateGraphEntries(ctx, season.Precision, curves, entries).Where(e => e.Vaributes.Count > 0);
|
var list = (await CreateGraphEntries(ctx, season.Precision, curves, entries)).Where(e => e.Vaributes.Count > 0);
|
||||||
foreach (var e in list) {
|
foreach (var e in list) {
|
||||||
e.Id += idOffset;
|
e.Id += idOffset;
|
||||||
e.Abgewertet = true;
|
e.Abgewertet = true;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace Elwig.Helpers.Export {
|
|||||||
List<WbGl> currentWbGls;
|
List<WbGl> currentWbGls;
|
||||||
|
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
branches = await ctx.Branches.ToDictionaryAsync(b => b.ZwstId);
|
branches = await ctx.FetchBranches().ToDictionaryAsync(b => b.ZwstId);
|
||||||
currentDids = await ctx.Deliveries
|
currentDids = await ctx.Deliveries
|
||||||
.GroupBy(d => d.Year)
|
.GroupBy(d => d.Year)
|
||||||
.ToDictionaryAsync(g => g.Key, g => g.Max(d => d.DId));
|
.ToDictionaryAsync(g => g.Key, g => g.Max(d => d.DId));
|
||||||
@@ -224,7 +224,7 @@ namespace Elwig.Helpers.Export {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var importedMembers = new List<(string FileName, string ZwstId, string Device, int New, int Overwritten, int NotImported, string? Filters)>();
|
var importedMembers = new List<(string FileName, string ZwstId, string Device, int New, int Overwritten, int NotImported, string? Filters)>();
|
||||||
var importedAreaComs = new List<(string FileName, string ZwstId, string Device, int Imported, int NotImported, string? Filters)>();
|
var importedAreaComs = new List<(string FileName, string ZwstId, string Device, int New, int Overwritten, int NotImported, string? Filters)>();
|
||||||
var importedDeliveries = new List<(string FileName, string ZwstId, string Device, int New, int Overwritten, int NotImported, string? Filters)>();
|
var importedDeliveries = new List<(string FileName, string ZwstId, string Device, int New, int Overwritten, int NotImported, string? Filters)>();
|
||||||
|
|
||||||
foreach (var ((members, billingAddresses, telephoneNumbers, emailAddresses, areaCommitments, contracts, riede, wbKgs, wbGls, deliveries, deliveryParts, modifiers, timestamps), meta) in data.Zip(metaData)) {
|
foreach (var ((members, billingAddresses, telephoneNumbers, emailAddresses, areaCommitments, contracts, riede, wbKgs, wbGls, deliveries, deliveryParts, modifiers, timestamps), meta) in data.Zip(metaData)) {
|
||||||
@@ -308,9 +308,9 @@ namespace Elwig.Helpers.Export {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (importDuplicateMembers) {
|
if (importDuplicateMembers) {
|
||||||
ctx.RemoveRange(ctx.BillingAddresses.Where(a => duplicateMgNrs.Contains(a.MgNr)));
|
ctx.RemoveRange(ctx.BillingAddresses.IgnoreAutoIncludes().Where(a => duplicateMgNrs.Contains(a.MgNr)));
|
||||||
ctx.RemoveRange(ctx.MemberTelephoneNrs.Where(n => duplicateMgNrs.Contains(n.MgNr)));
|
ctx.RemoveRange(ctx.MemberTelephoneNrs.IgnoreAutoIncludes().Where(n => duplicateMgNrs.Contains(n.MgNr)));
|
||||||
ctx.RemoveRange(ctx.MemberEmailAddrs.Where(a => duplicateMgNrs.Contains(a.MgNr)));
|
ctx.RemoveRange(ctx.MemberEmailAddrs.IgnoreAutoIncludes().Where(a => duplicateMgNrs.Contains(a.MgNr)));
|
||||||
ctx.UpdateRange(members.Where(m => duplicateMgNrs.Contains(m.MgNr)));
|
ctx.UpdateRange(members.Where(m => duplicateMgNrs.Contains(m.MgNr)));
|
||||||
ctx.AddRange(billingAddresses.Where(a => duplicateMgNrs.Contains(a.MgNr)));
|
ctx.AddRange(billingAddresses.Where(a => duplicateMgNrs.Contains(a.MgNr)));
|
||||||
ctx.AddRange(telephoneNumbers.Where(n => duplicateMgNrs.Contains(n.MgNr)));
|
ctx.AddRange(telephoneNumbers.Where(n => duplicateMgNrs.Contains(n.MgNr)));
|
||||||
@@ -329,7 +329,7 @@ namespace Elwig.Helpers.Export {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (importDuplicateContracts) {
|
if (importDuplicateContracts) {
|
||||||
ctx.RemoveRange(ctx.AreaCommitments.Where(c => duplicateFbNrs.Contains(c.FbNr)));
|
ctx.RemoveRange(ctx.AreaCommitments.IgnoreAutoIncludes().Where(c => duplicateFbNrs.Contains(c.FbNr)));
|
||||||
ctx.UpdateRange(contracts.Where(c => duplicateFbNrs.Contains(c.FbNr)));
|
ctx.UpdateRange(contracts.Where(c => duplicateFbNrs.Contains(c.FbNr)));
|
||||||
ctx.AddRange(areaCommitments.Where(c => duplicateFbNrs.Contains(c.FbNr)));
|
ctx.AddRange(areaCommitments.Where(c => duplicateFbNrs.Contains(c.FbNr)));
|
||||||
}
|
}
|
||||||
@@ -339,8 +339,9 @@ namespace Elwig.Helpers.Export {
|
|||||||
}
|
}
|
||||||
if (contracts.Count > 0) {
|
if (contracts.Count > 0) {
|
||||||
ctx.AddRange(riede);
|
ctx.AddRange(riede);
|
||||||
var imported = contracts.Where(c => (importNewContracts && !duplicateFbNrs.Contains(c.FbNr)) || (importDuplicateContracts && duplicateFbNrs.Contains(c.FbNr))).ToList();
|
var n = importNewContracts ? contracts.Count - duplicateFbNrs.Count : 0;
|
||||||
importedAreaComs.Add((meta.FileName, meta.ZwstId, meta.Device, imported.Count, areaCommitments.Count - imported.Count, meta.AreaComFilters));
|
var o = importDuplicateContracts ? duplicateFbNrs.Count : 0;
|
||||||
|
importedAreaComs.Add((meta.FileName, meta.ZwstId, meta.Device, n, o, contracts.Count - n - o, meta.AreaComFilters));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allowedDuplicateLsNrs.Count > 0) {
|
if (allowedDuplicateLsNrs.Count > 0) {
|
||||||
@@ -349,9 +350,10 @@ namespace Elwig.Helpers.Export {
|
|||||||
.Select(d => (d.Year, d.DId))
|
.Select(d => (d.Year, d.DId))
|
||||||
.ToList();
|
.ToList();
|
||||||
ctx.RemoveRange(ctx.DeliveryParts
|
ctx.RemoveRange(ctx.DeliveryParts
|
||||||
|
.IgnoreAutoIncludes()
|
||||||
.Where(p => allowedDuplicateLsNrs.Contains(p.Delivery.LsNr))
|
.Where(p => allowedDuplicateLsNrs.Contains(p.Delivery.LsNr))
|
||||||
.SelectMany(p => p.PartModifiers));
|
.SelectMany(p => p.PartModifiers));
|
||||||
ctx.RemoveRange(ctx.DeliveryParts.Where(p => allowedDuplicateLsNrs.Contains(p.Delivery.LsNr)));
|
ctx.RemoveRange(ctx.DeliveryParts.IgnoreAutoIncludes().Where(p => allowedDuplicateLsNrs.Contains(p.Delivery.LsNr)));
|
||||||
ctx.UpdateRange(deliveries.Where(d => dids.Contains((d.Year, d.DId))));
|
ctx.UpdateRange(deliveries.Where(d => dids.Contains((d.Year, d.DId))));
|
||||||
ctx.AddRange(deliveryParts.Where(p => dids.Contains((p.Year, p.DId))));
|
ctx.AddRange(deliveryParts.Where(p => dids.Contains((p.Year, p.DId))));
|
||||||
ctx.AddRange(modifiers.Where(m => dids.Contains((m.Year, m.DId))));
|
ctx.AddRange(modifiers.Where(m => dids.Contains((m.Year, m.DId))));
|
||||||
@@ -363,9 +365,10 @@ namespace Elwig.Helpers.Export {
|
|||||||
.Select(d => (d.Year, d.DId))
|
.Select(d => (d.Year, d.DId))
|
||||||
.ToList();
|
.ToList();
|
||||||
ctx.RemoveRange(ctx.DeliveryParts
|
ctx.RemoveRange(ctx.DeliveryParts
|
||||||
|
.IgnoreAutoIncludes()
|
||||||
.Where(p => l.Contains(p.Delivery.LsNr))
|
.Where(p => l.Contains(p.Delivery.LsNr))
|
||||||
.SelectMany(p => p.PartModifiers));
|
.SelectMany(p => p.PartModifiers));
|
||||||
ctx.RemoveRange(ctx.DeliveryParts.Where(p => l.Contains(p.Delivery.LsNr)));
|
ctx.RemoveRange(ctx.DeliveryParts.IgnoreAutoIncludes().Where(p => l.Contains(p.Delivery.LsNr)));
|
||||||
ctx.UpdateRange(deliveries.Where(d => dids.Contains((d.Year, d.DId))));
|
ctx.UpdateRange(deliveries.Where(d => dids.Contains((d.Year, d.DId))));
|
||||||
ctx.AddRange(deliveryParts.Where(p => dids.Contains((p.Year, p.DId))));
|
ctx.AddRange(deliveryParts.Where(p => dids.Contains((p.Year, p.DId))));
|
||||||
ctx.AddRange(modifiers.Where(m => dids.Contains((m.Year, m.DId))));
|
ctx.AddRange(modifiers.Where(m => dids.Contains((m.Year, m.DId))));
|
||||||
@@ -418,10 +421,10 @@ namespace Elwig.Helpers.Export {
|
|||||||
$" ({d.New} neu, {d.Overwritten} überschrieben, {d.NotImported} nicht importiert)\n" +
|
$" ({d.New} neu, {d.Overwritten} überschrieben, {d.NotImported} nicht importiert)\n" +
|
||||||
$" Zweigstelle: {branches[d.ZwstId].Name} (Gerät {d.Device})\n" +
|
$" Zweigstelle: {branches[d.ZwstId].Name} (Gerät {d.Device})\n" +
|
||||||
$" Filter: {d.Filters}"),
|
$" Filter: {d.Filters}"),
|
||||||
$"Flächenbindungen: {importedAreaComs.Sum(d => d.Imported)}",
|
$"Flächenbindungen: {importedAreaComs.Sum(d => d.New + d.Overwritten)}",
|
||||||
..importedAreaComs.Select(d =>
|
..importedAreaComs.Select(d =>
|
||||||
$" {d.FileName} ({d.Imported})\n" +
|
$" {d.FileName} ({d.New + d.Overwritten})\n" +
|
||||||
$" ({d.Imported} importiert, {d.NotImported} nicht importiert)\n" +
|
$" ({d.New} importiert, {d.Overwritten} überschreiben, {d.NotImported} nicht importiert)\n" +
|
||||||
$" Zweigstelle: {branches[d.ZwstId].Name} (Gerät {d.Device})\n" +
|
$" Zweigstelle: {branches[d.ZwstId].Name} (Gerät {d.Device})\n" +
|
||||||
$" Filter: {d.Filters}"),
|
$" Filter: {d.Filters}"),
|
||||||
$"Lieferungen: {importedDeliveries.Sum(d => d.New + d.Overwritten)}",
|
$"Lieferungen: {importedDeliveries.Sum(d => d.New + d.Overwritten)}",
|
||||||
@@ -860,7 +863,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}",
|
||||||
|
|||||||
@@ -413,8 +413,8 @@ namespace Elwig.Helpers {
|
|||||||
return output.OrderByDescending(l => l.Count());
|
return output.OrderByDescending(l => l.Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<RawVaribute> GetVaributes(AppDbContext ctx, int year, bool onlyDelivered = true) {
|
public static async Task<List<RawVaribute>> GetVaributes(AppDbContext ctx, int year, bool onlyDelivered = true) {
|
||||||
var varieties = ctx.WineVarieties.Select(v => new RawVaribute(v.SortId, "", null)).ToList();
|
var varieties = await ctx.FetchWineVarieties().Select(v => new RawVaribute(v.SortId, "", null)).ToListAsync();
|
||||||
var delivered = ctx.DeliveryParts
|
var delivered = ctx.DeliveryParts
|
||||||
.Where(d => d.Year == year)
|
.Where(d => d.Year == year)
|
||||||
.Select(d => new RawVaribute(d.SortId, d.AttrId ?? "", d.CultId ?? ""))
|
.Select(d => new RawVaribute(d.SortId, d.AttrId ?? "", d.CultId ?? ""))
|
||||||
@@ -423,13 +423,11 @@ namespace Elwig.Helpers {
|
|||||||
return [.. (onlyDelivered ? delivered : delivered.Union(varieties)).Order()];
|
return [.. (onlyDelivered ? delivered : delivered.Union(varieties)).Order()];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Varibute> GetVaributeList(AppDbContext ctx, int year, bool onlyDelivered = true) {
|
public static async Task<List<Varibute>> GetVaributeList(AppDbContext ctx, int year, bool onlyDelivered = true) {
|
||||||
var varieties = ctx.WineVarieties.ToDictionary(v => v.SortId, v => v);
|
var varieties = await ctx.FetchWineVarieties().ToDictionaryAsync(v => v.SortId, v => v);
|
||||||
var attributes = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a);
|
var attributes = await ctx.FetchWineAttributes().ToDictionaryAsync(a => a.AttrId, a => a);
|
||||||
var cultivations = ctx.WineCultivations.ToDictionary(c => c.CultId, c => c);
|
var cultivations = await ctx.FetchWineCultivations().ToDictionaryAsync(c => c.CultId, c => c);
|
||||||
return GetVaributes(ctx, year, onlyDelivered)
|
return [.. (await GetVaributes(ctx, year, onlyDelivered)).Select(s => new Varibute(s, varieties, attributes, cultivations))];
|
||||||
.Select(s => new Varibute(s, varieties, attributes, cultivations))
|
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[LibraryImport("wininet.dll")]
|
[LibraryImport("wininet.dll")]
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ 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.Include(v => v.Season.Modifiers).SingleAsync(v => v.Year == year && v.AvNr == avnr);
|
var variant = await paymentVariants.Include(v => v.Season.Modifiers).Where(v => v.Year == year && v.AvNr == avnr).SingleAsync();
|
||||||
BillingData? varData = null;
|
BillingData? varData = null;
|
||||||
try { varData = variant.Data != 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))
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.*
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,13 +49,9 @@ 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.Include(m => m.AreaCommitments).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)))),
|
||||||
|
|||||||
@@ -106,7 +106,10 @@ 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 { get; set; } = [];
|
public IEnumerable<DeliveryPart> FilteredParts => PartFilter == null ? Parts : Parts.Where(p => PartFilter(p));
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public Predicate<DeliveryPart>? PartFilter { get; set; }
|
||||||
|
|
||||||
public int Weight => Parts.Sum(p => p.Weight);
|
public int Weight => Parts.Sum(p => p.Weight);
|
||||||
public int FilteredWeight => FilteredParts.Sum(p => p.Weight);
|
public int FilteredWeight => FilteredParts.Sum(p => p.Weight);
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ 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;
|
||||||
|
|
||||||
|
|||||||
@@ -153,6 +153,27 @@ BEGIN
|
|||||||
UPDATE area_commitment_contract SET mtime = UNIXEPOCH() WHERE fbnr = OLD.fbnr;
|
UPDATE area_commitment_contract SET mtime = UNIXEPOCH() WHERE fbnr = OLD.fbnr;
|
||||||
END;
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER t_area_commitment_i_mtime_member
|
||||||
|
AFTER INSERT ON area_commitment FOR EACH ROW
|
||||||
|
WHEN (SELECT value FROM client_parameter WHERE param = 'ENABLE_TIME_TRIGGERS') = 1
|
||||||
|
BEGIN
|
||||||
|
UPDATE member SET mtime = UNIXEPOCH() WHERE mgnr = NEW.mgnr;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER t_area_commitment_u_mtime_member
|
||||||
|
AFTER UPDATE ON area_commitment FOR EACH ROW
|
||||||
|
WHEN (SELECT value FROM client_parameter WHERE param = 'ENABLE_TIME_TRIGGERS') = 1
|
||||||
|
BEGIN
|
||||||
|
UPDATE member SET mtime = UNIXEPOCH() WHERE mgnr = NEW.mgnr OR mgnr = OLD.mgnr;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER t_area_commitment_d_mtime_member
|
||||||
|
AFTER DELETE ON area_commitment FOR EACH ROW
|
||||||
|
WHEN (SELECT value FROM client_parameter WHERE param = 'ENABLE_TIME_TRIGGERS') = 1
|
||||||
|
BEGIN
|
||||||
|
UPDATE member SET mtime = UNIXEPOCH() WHERE mgnr = OLD.mgnr;
|
||||||
|
END;
|
||||||
|
|
||||||
-- fix user fiddling - set actual year_from
|
-- fix user fiddling - set actual year_from
|
||||||
UPDATE area_commitment AS b
|
UPDATE area_commitment AS b
|
||||||
SET fbnr = a.fbnr, revnr = b.fbnr, year_from = a.year_to + 1
|
SET fbnr = a.fbnr, revnr = b.fbnr, year_from = a.year_to + 1
|
||||||
|
|||||||
8
Elwig/Resources/Sql/38-39.sql
Normal file
8
Elwig/Resources/Sql/38-39.sql
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
-- schema version 38 to 39
|
||||||
|
|
||||||
|
PRAGMA writable_schema = ON;
|
||||||
|
UPDATE sqlite_schema SET sql = REPLACE(sql, '{2,}', '{2,64}')
|
||||||
|
WHERE type = 'table' AND name = 'member_email_address';
|
||||||
|
PRAGMA writable_schema = OFF;
|
||||||
|
|
||||||
|
UPDATE wb_gem SET hkid = 'WLLB' WHERE gkz IN (10710, 10723);
|
||||||
@@ -20,6 +20,7 @@ namespace Elwig.Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void ClearInputs(this AreaComAdminViewModel vm) {
|
public static void ClearInputs(this AreaComAdminViewModel vm) {
|
||||||
|
vm.Period = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void FillInputs(this AreaComAdminViewModel vm, AreaComContract c) {
|
public static void FillInputs(this AreaComAdminViewModel vm, AreaComContract c) {
|
||||||
@@ -55,9 +56,9 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
var filter = vm.TextFilter;
|
var filter = vm.TextFilter;
|
||||||
if (filter.Count > 0) {
|
if (filter.Count > 0) {
|
||||||
var var = await ctx.WineVarieties.ToDictionaryAsync(v => v.SortId, v => v);
|
var var = await ctx.FetchWineVarieties().ToDictionaryAsync(v => v.SortId, v => v);
|
||||||
var attr = await ctx.WineAttributes.ToDictionaryAsync(a => a.Name.ToLower().Split(" ")[0], a => a);
|
var attrId = await ctx.FetchWineAttributes().ToDictionaryAsync(a => a.AttrId, a => a);
|
||||||
var attrId = await ctx.WineAttributes.ToDictionaryAsync(a => a.AttrId, a => a);
|
var attr = attrId.Values.ToDictionary(a => a.Name.ToLower().Split(" ")[0], a => a);
|
||||||
|
|
||||||
for (int i = 0; i < filter.Count; i++) {
|
for (int i = 0; i < filter.Count; i++) {
|
||||||
var e = filter[i];
|
var e = filter[i];
|
||||||
|
|||||||
@@ -65,11 +65,11 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
var filter = vm.TextFilter;
|
var filter = vm.TextFilter;
|
||||||
if (filter.Count > 0) {
|
if (filter.Count > 0) {
|
||||||
var var = await ctx.WineVarieties.ToDictionaryAsync(v => v.SortId, v => v);
|
var var = await ctx.FetchWineVarieties().ToDictionaryAsync(v => v.SortId, v => v);
|
||||||
var mgnr = await ctx.Members.ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
|
var mgnr = await ctx.FetchMembers(includeNotActive: true).ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
|
||||||
var zwst = await ctx.Branches.ToDictionaryAsync(b => b.Name.ToLower().Split(' ')[0], b => b);
|
var zwst = await ctx.FetchBranches().ToDictionaryAsync(b => b.Name.ToLower().Split(' ')[0], b => b);
|
||||||
var attr = await ctx.WineAttributes.ToDictionaryAsync(a => a.Name.ToLower().Split(' ')[0], a => a);
|
var attr = await ctx.FetchWineAttributes().ToDictionaryAsync(a => a.Name.ToLower().Split(' ')[0], a => a);
|
||||||
var cult = await ctx.WineCultivations.ToDictionaryAsync(c => c.Name.ToLower().Split(' ')[0], c => c);
|
var cult = await ctx.FetchWineCultivations().ToDictionaryAsync(c => c.Name.ToLower().Split(' ')[0], c => c);
|
||||||
|
|
||||||
for (int i = 0; i < filter.Count; i++) {
|
for (int i = 0; i < filter.Count; i++) {
|
||||||
var e = filter[i];
|
var e = filter[i];
|
||||||
@@ -318,18 +318,13 @@ namespace Elwig.Services {
|
|||||||
AddToolTipCell(grid, $"{weight * 100.0 / total2:N1} %", row, 4, 1, bold, true);
|
AddToolTipCell(grid, $"{weight * 100.0 / total2:N1} %", row, 4, 1, bold, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<(string, Grid)> GenerateToolTip(IQueryable<DeliveryAncmt> deliveryAncmts) {
|
public static async Task<(string Text, (string?, string?, int, int?, int)[] Grid)> GenerateToolTipData(IQueryable<DeliveryAncmt> deliveryAncmts) {
|
||||||
var grid = new Grid();
|
var grid = new List<(string?, string?, int, int?, int)>();
|
||||||
grid.ColumnDefinitions.Add(new() { Width = new(10) });
|
|
||||||
grid.ColumnDefinitions.Add(new() { Width = new(60) });
|
|
||||||
grid.ColumnDefinitions.Add(new() { Width = new(80) });
|
|
||||||
grid.ColumnDefinitions.Add(new() { Width = new(50) });
|
|
||||||
grid.ColumnDefinitions.Add(new() { Width = new(50) });
|
|
||||||
var text = "-";
|
var text = "-";
|
||||||
|
|
||||||
var weight = await deliveryAncmts.SumAsync(p => p.Weight);
|
var weight = await deliveryAncmts.SumAsync(p => p.Weight);
|
||||||
text = $"{weight:N0} kg";
|
text = $"{weight:N0} kg";
|
||||||
AddToolTipRow(grid, 0, "Menge", null, weight, null, weight);
|
grid.Add(("Menge", null, weight, null, weight));
|
||||||
|
|
||||||
if (await deliveryAncmts.AnyAsync()) {
|
if (await deliveryAncmts.AnyAsync()) {
|
||||||
var attrGroups = await deliveryAncmts
|
var attrGroups = await deliveryAncmts
|
||||||
@@ -370,13 +365,11 @@ namespace Elwig.Services {
|
|||||||
.ThenBy(g => g.SortId)
|
.ThenBy(g => g.SortId)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
int rowNum = 1;
|
|
||||||
foreach (var attrG in attrGroups) {
|
foreach (var attrG in attrGroups) {
|
||||||
rowNum++;
|
|
||||||
var name = attrG.Attr == null && attrG.Cult == null ? null : attrG.Attr + (attrG.Attr != null && attrG.Cult != null ? " / " : "") + attrG.Cult;
|
var name = attrG.Attr == null && attrG.Cult == null ? null : attrG.Attr + (attrG.Attr != null && attrG.Cult != null ? " / " : "") + attrG.Cult;
|
||||||
AddToolTipRow(grid, rowNum++, name, null, attrG.Weight, attrG.Weight, weight);
|
grid.Add((name, null, attrG.Weight, attrG.Weight, weight));
|
||||||
foreach (var g in groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult).OrderByDescending(g => g.Weight).ThenBy(g => g.SortId)) {
|
foreach (var g in groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult).OrderByDescending(g => g.Weight).ThenBy(g => g.SortId)) {
|
||||||
AddToolTipRow(grid, rowNum++, null, g.SortId, g.Weight, attrG.Weight, weight);
|
grid.Add((null, g.SortId, g.Weight, attrG.Weight, weight));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,7 +388,22 @@ namespace Elwig.Services {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (text, grid);
|
return (text, grid.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Grid GenerateToolTip((string?, string?, int, int?, int)[] data) {
|
||||||
|
var grid = new Grid();
|
||||||
|
grid.ColumnDefinitions.Add(new() { Width = new(10) });
|
||||||
|
grid.ColumnDefinitions.Add(new() { Width = new(60) });
|
||||||
|
grid.ColumnDefinitions.Add(new() { Width = new(80) });
|
||||||
|
grid.ColumnDefinitions.Add(new() { Width = new(50) });
|
||||||
|
grid.ColumnDefinitions.Add(new() { Width = new(50) });
|
||||||
|
int rowNum = 0;
|
||||||
|
foreach (var row in data) {
|
||||||
|
if (rowNum != 0 && row.Item2 == null) rowNum++;
|
||||||
|
AddToolTipRow(grid, rowNum++, row.Item1, row.Item2, row.Item3, row.Item4, row.Item5);
|
||||||
|
}
|
||||||
|
return grid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
var filter = vm.TextFilter;
|
var filter = vm.TextFilter;
|
||||||
if (filter.Count > 0) {
|
if (filter.Count > 0) {
|
||||||
var var = await ctx.WineVarieties.ToDictionaryAsync(v => v.SortId, v => v);
|
var var = await ctx.FetchWineVarieties().ToDictionaryAsync(v => v.SortId, v => v);
|
||||||
var zwst = await ctx.Branches.ToDictionaryAsync(b => b.Name.ToLower().Split(" ")[0], b => b);
|
var zwst = await ctx.FetchBranches().ToDictionaryAsync(b => b.Name.ToLower().Split(" ")[0], b => b);
|
||||||
|
|
||||||
for (int i = 0; i < filter.Count; i++) {
|
for (int i = 0; i < filter.Count; i++) {
|
||||||
var e = filter[i];
|
var e = filter[i];
|
||||||
@@ -174,12 +174,12 @@ namespace Elwig.Services {
|
|||||||
ctx.Add(s);
|
ctx.Add(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.UpdateDeliveryScheduleWineVarieties(s, (await ctx.DeliveryScheduleWineVarieties
|
await ctx.UpdateDeliveryScheduleWineVarieties(s, (await ctx.DeliveryScheduleWineVarieties
|
||||||
.Where(v => v.Year == s.Year && v.DsNr == s.DsNr)
|
.Where(v => v.Year == s.Year && v.DsNr == s.DsNr)
|
||||||
.Select(v => new { v.Variety, v.Priority })
|
.Select(v => new { v.Variety, v.Priority })
|
||||||
.ToListAsync())
|
.ToListAsync())
|
||||||
.Select(v => (v.Variety, v.Priority))
|
.Select(v => (v.Variety.SortId, v.Priority))
|
||||||
.ToList(), vm.MainVarieties.Select(v => (v, 1)).Union(vm.OtherVarieties.Select(v => (v, 2))).ToList());
|
.ToList(), vm.MainVarieties.Select(v => (v.SortId, 1)).Union(vm.OtherVarieties.Select(v => (v.SortId, 2))).ToList());
|
||||||
|
|
||||||
await ctx.SaveChangesAsync();
|
await ctx.SaveChangesAsync();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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.FetchMembers(mgnr).SingleOrDefaultAsync();
|
||||||
.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)!);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,12 +126,12 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
var filter = vm.TextFilter;
|
var filter = vm.TextFilter;
|
||||||
if (filter.Count > 0) {
|
if (filter.Count > 0) {
|
||||||
var var = await ctx.WineVarieties.ToDictionaryAsync(v => v.SortId, v => v);
|
var var = await ctx.FetchWineVarieties().ToDictionaryAsync(v => v.SortId, v => v);
|
||||||
var qual = await ctx.WineQualityLevels.Where(q => !q.IsPredicate).ToDictionaryAsync(q => q.QualId, q => q);
|
var qual = await ctx.FetchWineQualityLevels(false).ToDictionaryAsync(q => q.QualId, q => q);
|
||||||
var mgnr = await ctx.Members.ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
|
var mgnr = await ctx.FetchMembers(includeNotActive: true).ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
|
||||||
var zwst = await ctx.Branches.ToDictionaryAsync(b => b.Name.ToLower().Split(' ')[0], b => b);
|
var zwst = await ctx.FetchBranches().ToDictionaryAsync(b => b.Name.ToLower().Split(' ')[0], b => b);
|
||||||
var attr = await ctx.WineAttributes.ToDictionaryAsync(a => a.Name.ToLower().Split(' ')[0], a => a);
|
var attr = await ctx.FetchWineAttributes().ToDictionaryAsync(a => a.Name.ToLower().Split(' ')[0], a => a);
|
||||||
var cult = await ctx.WineCultivations.ToDictionaryAsync(c => c.Name.ToLower().Split(' ')[0], c => c);
|
var cult = await ctx.FetchWineCultivations().ToDictionaryAsync(c => c.Name.ToLower().Split(' ')[0], c => c);
|
||||||
|
|
||||||
for (int i = 0; i < filter.Count; i++) {
|
for (int i = 0; i < filter.Count; i++) {
|
||||||
var e = filter[i];
|
var e = filter[i];
|
||||||
@@ -549,14 +546,14 @@ namespace Elwig.Services {
|
|||||||
ctx.Add(p);
|
ctx.Add(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.UpdateDeliveryPartModifiers(p, await ctx.DeliveryPartModifiers
|
await ctx.UpdateDeliveryPartModifiers(p, await ctx.DeliveryPartModifiers
|
||||||
.Where(m => m.Year == p.Year && m.DId == p.DId && m.DPNr == p.DPNr)
|
.Where(m => m.Year == p.Year && m.DId == p.DId && m.DPNr == p.DPNr)
|
||||||
.Select(m => m.Modifier)
|
.Select(m => m.ModId)
|
||||||
.ToListAsync(), vm.Modifiers);
|
.ToListAsync(), vm.Modifiers.Select(m => m.ModId).ToList());
|
||||||
|
|
||||||
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.FetchMembers(d.MgNr).SingleOrDefaultAsync())?.DefaultKgNr;
|
||||||
await ctx.DeliveryParts
|
await ctx.DeliveryParts
|
||||||
.Where(p => p.Year == d.Year && p.DId == d.DId && p.DPNr != dpnr && p.KgNr == originalMemberKgNr)
|
.Where(p => p.Year == d.Year && p.DId == d.DId && p.DPNr != dpnr && p.KgNr == originalMemberKgNr)
|
||||||
.ExecuteUpdateAsync(u => u.SetProperty(p => p.KgNr, newKgNr));
|
.ExecuteUpdateAsync(u => u.SetProperty(p => p.KgNr, newKgNr));
|
||||||
@@ -640,7 +637,7 @@ namespace Elwig.Services {
|
|||||||
Delivery n;
|
Delivery n;
|
||||||
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.Where(d => d.LsNr == lsnr).FirstAsync())!;
|
||||||
var d = await ctx.Deliveries
|
var d = await ctx.Deliveries
|
||||||
.Where(d => d.Year == year && d.DId == did)
|
.Where(d => d.Year == year && d.DId == did)
|
||||||
.Include(d => d.Parts).ThenInclude(p => p.PartModifiers)
|
.Include(d => d.Parts).ThenInclude(p => p.PartModifiers)
|
||||||
@@ -812,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)
|
||||||
@@ -957,7 +951,7 @@ namespace Elwig.Services {
|
|||||||
tblTotal.FullName = DeliveryDepreciationList.Name;
|
tblTotal.FullName = DeliveryDepreciationList.Name;
|
||||||
tblTotal.Name = "Gesamt";
|
tblTotal.Name = "Gesamt";
|
||||||
await ods.AddTable(tblTotal);
|
await ods.AddTable(tblTotal);
|
||||||
foreach (var branch in await ctx.Branches.OrderBy(b => b.Name).ToListAsync()) {
|
foreach (var branch in await ctx.FetchBranches().ToListAsync()) {
|
||||||
var tbl = await DeliveryJournalData.FromQuery(query.Where(p => p.Delivery.ZwstId == branch.ZwstId), filterNames);
|
var tbl = await DeliveryJournalData.FromQuery(query.Where(p => p.Delivery.ZwstId == branch.ZwstId), filterNames);
|
||||||
tbl.FullName = DeliveryDepreciationList.Name;
|
tbl.FullName = DeliveryDepreciationList.Name;
|
||||||
tbl.Name = branch.Name;
|
tbl.Name = branch.Name;
|
||||||
@@ -1068,16 +1062,23 @@ namespace Elwig.Services {
|
|||||||
var gGrid = new List<(string?, string?, double, double, double)>();
|
var gGrid = new List<(string?, string?, double, double, double)>();
|
||||||
var gText = "-";
|
var gText = "-";
|
||||||
|
|
||||||
var weight = await deliveryParts.SumAsync(p => p.Weight);
|
var stat = (await deliveryParts.GroupBy(p => 0)
|
||||||
wText = $"{weight:N0} kg";
|
.Select(g => new {
|
||||||
wGrid.Add(("Menge", null, weight, null, weight));
|
Weight = g.Sum(p => p.Weight),
|
||||||
|
Min = g.Select(p => (double?)p.Kmw).DefaultIfEmpty().Min(),
|
||||||
|
Avg = g.Sum(p => p.Kmw * p.Weight) / g.Sum(p => p.Weight),
|
||||||
|
Max = g.Select(p => (double?)p.Kmw).DefaultIfEmpty().Max(),
|
||||||
|
})
|
||||||
|
.ToListAsync())
|
||||||
|
.DefaultIfEmpty(new { Weight = 0, Min = (double?)null, Avg = (double)0, Max = (double?)null })
|
||||||
|
.Single();
|
||||||
|
|
||||||
if (await deliveryParts.AnyAsync()) {
|
wText = $"{stat.Weight:N0} kg";
|
||||||
var kmwMin = await deliveryParts.MinAsync(p => p.Kmw);
|
wGrid.Add(("Menge", null, stat.Weight, null, stat.Weight));
|
||||||
var kmwAvg = Utils.AggregateDeliveryPartsKmw(deliveryParts);
|
|
||||||
var kmwMax = await deliveryParts.MaxAsync(p => p.Kmw);
|
if (stat.Min != null && stat.Max != null) {
|
||||||
gText = $"{kmwMin:N1}° / {kmwAvg:N1}° / {kmwMax:N1}°";
|
gText = $"{stat.Min:N1}° / {stat.Avg:N1}° / {stat.Max:N1}°";
|
||||||
gGrid.Add(("Gradation", null, kmwMin, kmwAvg, kmwMax));
|
gGrid.Add(("Gradation", null, stat.Min.Value, stat.Avg, stat.Max.Value));
|
||||||
|
|
||||||
var attrGroups = await deliveryParts
|
var attrGroups = await deliveryParts
|
||||||
.GroupBy(p => new { Attr = p.Attribute!.Name, Cult = p.Cultivation!.Name })
|
.GroupBy(p => new { Attr = p.Attribute!.Name, Cult = p.Cultivation!.Name })
|
||||||
@@ -1128,9 +1129,9 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
foreach (var attrG in attrGroups) {
|
foreach (var attrG in attrGroups) {
|
||||||
var name = attrG.Attr == null && attrG.Cult == null ? null : attrG.Attr + (attrG.Attr != null && attrG.Cult != null ? " / " : "") + attrG.Cult;
|
var name = attrG.Attr == null && attrG.Cult == null ? null : attrG.Attr + (attrG.Attr != null && attrG.Cult != null ? " / " : "") + attrG.Cult;
|
||||||
wGrid.Add((name, null, attrG.Weight, attrG.Weight, weight));
|
wGrid.Add((name, null, attrG.Weight, attrG.Weight, stat.Weight));
|
||||||
foreach (var g in groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult).OrderByDescending(g => g.Weight).ThenBy(g => g.SortId)) {
|
foreach (var g in groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult).OrderByDescending(g => g.Weight).ThenBy(g => g.SortId)) {
|
||||||
wGrid.Add((null, g.SortId, g.Weight, attrG.Weight, weight));
|
wGrid.Add((null, g.SortId, g.Weight, attrG.Weight, stat.Weight));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (var attrG in attrGroups) {
|
foreach (var attrG in attrGroups) {
|
||||||
@@ -1149,12 +1150,12 @@ namespace Elwig.Services {
|
|||||||
gText += $" [{name}]";
|
gText += $" [{name}]";
|
||||||
}
|
}
|
||||||
if (sortGroups.Count > 1 && sortGroups.Count <= 4) {
|
if (sortGroups.Count > 1 && sortGroups.Count <= 4) {
|
||||||
wText += $" = {string.Join(" + ", sortGroups.Select(g => $"{g.Weight:N0} kg ({(double)g.Weight / weight:0%})" + (g.SortId == null ? "" : $" [{g.SortId}]")))}";
|
wText += $" = {string.Join(" + ", sortGroups.Select(g => $"{g.Weight:N0} kg ({(double)g.Weight / stat.Weight:0%})" + (g.SortId == null ? "" : $" [{g.SortId}]")))}";
|
||||||
gText += $" = {string.Join(" + ", sortGroups.Select(g => $"{g.Min:N1}/{g.Avg:N1}/{g.Max:N1}" + (g.SortId == null ? "" : $" [{g.SortId}]")))}";
|
gText += $" = {string.Join(" + ", sortGroups.Select(g => $"{g.Min:N1}/{g.Avg:N1}/{g.Max:N1}" + (g.SortId == null ? "" : $" [{g.SortId}]")))}";
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (attrGroups.Count <= 4) {
|
} else if (attrGroups.Count <= 4) {
|
||||||
wText += $" = {string.Join(" + ", attrGroups.Select(g => $"{g.Weight:N0} kg ({(double)g.Weight / weight:0%})" + (g.Attr == null && g.Cult == null ? "" : $" [{g.Attr}{(g.Attr != null && g.Cult != null ? " / " : "")}{g.Cult}]")))}";
|
wText += $" = {string.Join(" + ", attrGroups.Select(g => $"{g.Weight:N0} kg ({(double)g.Weight / stat.Weight:0%})" + (g.Attr == null && g.Cult == null ? "" : $" [{g.Attr}{(g.Attr != null && g.Cult != null ? " / " : "")}{g.Cult}]")))}";
|
||||||
gText += $" = {string.Join(" + ", attrGroups.Select(g => $"{g.Min:N1}/{g.Avg:N1}/{g.Max:N1}" + (g.Attr == null && g.Cult == null ? "" : $" [{g.Attr}{(g.Attr != null && g.Cult != null ? " / " : "")}{g.Cult}]")))}";
|
gText += $" = {string.Join(" + ", attrGroups.Select(g => $"{g.Min:N1}/{g.Avg:N1}/{g.Max:N1}" + (g.Attr == null && g.Cult == null ? "" : $" [{g.Attr}{(g.Attr != null && g.Cult != null ? " / " : "")}{g.Cult}]")))}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ namespace Elwig.Services {
|
|||||||
var c = m.ActiveAreaCommitments(ctx, Utils.CurrentLastSeason);
|
var c = m.ActiveAreaCommitments(ctx, Utils.CurrentLastSeason);
|
||||||
int maxKgPerHa = 10_000;
|
int maxKgPerHa = 10_000;
|
||||||
try {
|
try {
|
||||||
var s = await ctx.Seasons.FindAsync(await ctx.Seasons.MaxAsync(s => s.Year));
|
var s = await ctx.FetchSeasons().FirstOrDefaultAsync();
|
||||||
if (s != null) maxKgPerHa = s.MaxKgPerHa;
|
if (s != null) maxKgPerHa = s.MaxKgPerHa;
|
||||||
} catch { }
|
} catch { }
|
||||||
var (text, gridData) = await AreaComService.GenerateToolTipData(c, maxKgPerHa);
|
var (text, gridData) = await AreaComService.GenerateToolTipData(c, maxKgPerHa);
|
||||||
@@ -225,8 +225,8 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
var filter = vm.TextFilter;
|
var filter = vm.TextFilter;
|
||||||
if (filter.Count > 0) {
|
if (filter.Count > 0) {
|
||||||
var branches = await ctx.Branches.ToListAsync();
|
var branches = await ctx.FetchBranches().ToListAsync();
|
||||||
var mgnr = await ctx.Members.ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
|
var mgnr = await ctx.FetchMembers(includeNotActive: true).ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
|
||||||
var kgs = await ctx.WbKgs.ToDictionaryAsync(k => k.AtKg.Name.ToLower(), k => k.AtKg);
|
var kgs = await ctx.WbKgs.ToDictionaryAsync(k => k.AtKg.Name.ToLower(), k => k.AtKg);
|
||||||
var areaComs = await ctx.AreaCommitmentTypes.ToDictionaryAsync(t => $"{t.SortId}{t.AttrId}", t => t);
|
var areaComs = await ctx.AreaCommitmentTypes.ToDictionaryAsync(t => $"{t.SortId}{t.AttrId}", t => t);
|
||||||
|
|
||||||
@@ -408,12 +408,12 @@ namespace Elwig.Services {
|
|||||||
Mouse.OverrideCursor = Cursors.Wait;
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
try {
|
try {
|
||||||
var b = new Billing(year);
|
var b = await Billing.Create(year);
|
||||||
await b.FinishSeason();
|
await b.FinishSeason();
|
||||||
await b.CalculateBuckets();
|
await b.CalculateBuckets();
|
||||||
App.HintContextChange();
|
App.HintContextChange();
|
||||||
|
|
||||||
using var doc = new DeliveryConfirmation(year, m);
|
using var doc = new DeliveryConfirmation(year, m, null);
|
||||||
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);
|
||||||
@@ -426,7 +426,7 @@ namespace Elwig.Services {
|
|||||||
Mouse.OverrideCursor = Cursors.Wait;
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
try {
|
try {
|
||||||
using var doc = await CreditNote.Initialize(year, avnr, m.MgNr);
|
using var doc = await CreditNote.Initialize(year, avnr, m.MgNr, null);
|
||||||
await Utils.ExportDocument(doc, mode, emailData: (m, $"{CreditNote.Name} {doc.Payment.Variant.Name}", $"Im Anhang finden Sie die Traubengutschrift {doc.Payment.Variant.Name}"));
|
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) {
|
} catch (Exception exc) {
|
||||||
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
@@ -509,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);
|
||||||
@@ -537,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
|
||||||
@@ -715,7 +708,7 @@ namespace Elwig.Services {
|
|||||||
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();
|
using var tx = await ctx.Database.BeginTransactionAsync();
|
||||||
var l = (await ctx.Members.FindAsync(mgnr))!;
|
var l = await ctx.FetchMembers(mgnr).SingleAsync();
|
||||||
if (deletePaymentData) {
|
if (deletePaymentData) {
|
||||||
await ctx.Credits.Where(c => c.MgNr == mgnr).ExecuteDeleteAsync();
|
await ctx.Credits.Where(c => c.MgNr == mgnr).ExecuteDeleteAsync();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -363,21 +363,21 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
public static async Task Calculate(int year, int avnr) {
|
public static async Task Calculate(int year, int avnr) {
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
var b = new BillingVariant(year, avnr);
|
var b = await BillingVariant.Create(year, avnr);
|
||||||
await b.Calculate();
|
await b.Calculate();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task Commit(int year, int avnr) {
|
public static async Task Commit(int year, int avnr) {
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
var b = new BillingVariant(year, avnr);
|
var b = await BillingVariant.Create(year, avnr);
|
||||||
await b.Commit();
|
await b.Commit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task Revert(int year, int avnr) {
|
public static async Task Revert(int year, int avnr) {
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
var b = new BillingVariant(year, avnr);
|
var b = await BillingVariant.Create(year, avnr);
|
||||||
await b.Revert();
|
await b.Revert();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -277,7 +258,7 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
public static async Task<bool> ChangesAvailable(AppDbContext ctx, string url, string username, string password) {
|
public static async Task<bool> ChangesAvailable(AppDbContext ctx, string url, string username, string password) {
|
||||||
try {
|
try {
|
||||||
return await ctx.Members.AnyAsync(ChangedMembers) || await ctx.AreaCommitmentContracts.AnyAsync(ChangedAreaComContracts) || await ctx.Deliveries.AnyAsync(ChangedDeliveries) || (Utils.HasInternetConnectivity() && (await GetFilesToImport(url, username, password)).Count > 0);
|
return await ctx.Members.Where(ChangedMembers).AnyAsync() || await ctx.AreaCommitmentContracts.Where(ChangedAreaComContracts).AnyAsync() || await ctx.Deliveries.Where(ChangedDeliveries).AnyAsync() || (Utils.HasInternetConnectivity() && (await GetFilesToImport(url, username, password)).Count > 0);
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ namespace Elwig.Windows {
|
|||||||
cb.SelectionChanged += ComboBox_SelectionChanged;
|
cb.SelectionChanged += ComboBox_SelectionChanged;
|
||||||
foreach (var lb in ListBoxInputs)
|
foreach (var lb in ListBoxInputs)
|
||||||
lb.SelectionChanged += ComboBox_SelectionChanged;
|
lb.SelectionChanged += ComboBox_SelectionChanged;
|
||||||
|
LockInputs();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnClosing(object? sender, CancelEventArgs evt) {
|
private void OnClosing(object? sender, CancelEventArgs evt) {
|
||||||
@@ -349,7 +350,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
xmlns:local="clr-namespace:Elwig.Windows"
|
xmlns:local="clr-namespace:Elwig.Windows"
|
||||||
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
||||||
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
||||||
Title="{Binding Title}" Height="600" MinHeight="550" Width="1000" MinWidth="860"
|
Title="{Binding Title}" Height="600" MinHeight="550" Width="1000" MinWidth="860">
|
||||||
Loaded="Window_Loaded">
|
|
||||||
<Window.DataContext>
|
<Window.DataContext>
|
||||||
<vm:AreaComAdminViewModel/>
|
<vm:AreaComAdminViewModel/>
|
||||||
</Window.DataContext>
|
</Window.DataContext>
|
||||||
|
|||||||
@@ -39,10 +39,6 @@ namespace Elwig.Windows {
|
|||||||
ViewModel.FilterSeason = Utils.CurrentYear;
|
ViewModel.FilterSeason = Utils.CurrentYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs e) {
|
|
||||||
LockInputs();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FocusSearchInput(object sender, RoutedEventArgs evt) {
|
private void FocusSearchInput(object sender, RoutedEventArgs evt) {
|
||||||
if (!IsEditing && !IsCreating) {
|
if (!IsEditing && !IsCreating) {
|
||||||
SearchInput.Focus();
|
SearchInput.Focus();
|
||||||
@@ -51,42 +47,44 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task RefreshList(bool updateSort = false) {
|
private async Task RefreshList(bool updateSort = false) {
|
||||||
using var ctx = new AppDbContext();
|
var vm = ViewModel;
|
||||||
var (_, contractQuery, areaComQuery, filter) = await ViewModel.GetFilters(ctx);
|
var cursor = Mouse.OverrideCursor != null;
|
||||||
var contracts = await contractQuery
|
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
||||||
.Include(c => c.Kg.AtKg)
|
var query = (vm.SearchQuery, vm.FilterSeason);
|
||||||
.Include(c => c.Rd!.Kg.AtKg)
|
var (filter, contracts, areaComs, areaComCount, stat) = await Task.Run(async () => {
|
||||||
.Include(c => c.Revisions).ThenInclude(a => a.WineCult)
|
using var ctx = new AppDbContext();
|
||||||
.Include(c => c.Revisions).ThenInclude(a => a.AreaComType.WineAttr)
|
var (_, contractQuery, areaComQuery, filter) = await vm.GetFilters(ctx);
|
||||||
.Include(c => c.Revisions).ThenInclude(a => a.AreaComType.WineVar)
|
var contracts = await contractQuery
|
||||||
.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()
|
||||||
.ToDictionary(d => d, d => d.SearchScore(ViewModel.TextFilter))
|
.ToDictionary(d => d, d => d.SearchScore(vm.TextFilter))
|
||||||
.OrderByDescending(c => c.Value);
|
.OrderByDescending(c => c.Value);
|
||||||
var threshold = dict.Max(a => a.Value) * 3 / 4;
|
var threshold = dict.Max(a => a.Value) * 3 / 4;
|
||||||
contracts = [.. dict
|
contracts = [.. dict
|
||||||
.Where(a => a.Value > threshold)
|
.Where(a => a.Value > threshold)
|
||||||
.Select(a => a.Key)];
|
.Select(a => a.Key)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var areaComCount = await areaComQuery.CountAsync();
|
||||||
|
var season = await ctx.FetchSeasons().FirstOrDefaultAsync();
|
||||||
|
var stat = await AreaComService.GenerateToolTipData(areaComQuery, season?.MaxKgPerHa ?? 10_000);
|
||||||
|
|
||||||
|
return (filter, contracts, areaComs, areaComCount, stat);
|
||||||
|
});
|
||||||
|
if (!cursor) Mouse.OverrideCursor = null;
|
||||||
|
if (query != (ViewModel.SearchQuery, ViewModel.FilterSeason)) return;
|
||||||
|
|
||||||
ControlUtils.RenewItemsSource(AreaCommitmentList, contracts,
|
ControlUtils.RenewItemsSource(AreaCommitmentList, contracts,
|
||||||
AreaCommitmentList_SelectionChanged, filter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
AreaCommitmentList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
||||||
RefreshInputs();
|
RefreshInputs();
|
||||||
|
|
||||||
if (filter.Count == 0) {
|
if (filter.Count == 0) {
|
||||||
ViewModel.StatusAreaCommitments = $"{await areaComQuery.CountAsync():N0}";
|
ViewModel.StatusAreaCommitments = $"{areaComCount:N0}";
|
||||||
var s = await ctx.Seasons.FindAsync(await ctx.Seasons.MaxAsync(s => s.Year));
|
var (text, gridData) = stat;
|
||||||
var (text, gridData) = await AreaComService.GenerateToolTipData(areaComQuery, s?.MaxKgPerHa ?? 10_000);
|
|
||||||
ViewModel.StatusArea = text;
|
ViewModel.StatusArea = text;
|
||||||
ViewModel.StatusAreaToolTip = AreaComService.GenerateToolTip(gridData);
|
ViewModel.StatusAreaToolTip = AreaComService.GenerateToolTip(gridData);
|
||||||
} else {
|
} else {
|
||||||
@@ -153,10 +151,15 @@ namespace Elwig.Windows {
|
|||||||
ValidateRequiredInputs();
|
ValidateRequiredInputs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new protected void ClearInputs(bool validate = false) {
|
||||||
|
ViewModel.ClearInputs();
|
||||||
|
base.ClearInputs(validate);
|
||||||
|
}
|
||||||
|
|
||||||
protected override async Task OnRenewContext(AppDbContext ctx) {
|
protected override async Task OnRenewContext(AppDbContext ctx) {
|
||||||
await base.OnRenewContext(ctx);
|
await base.OnRenewContext(ctx);
|
||||||
|
|
||||||
if (await ctx.Members.FindAsync(ViewModel.FilterMember.MgNr) is not Member m) {
|
if (await ctx.FetchMembers(ViewModel.FilterMember.MgNr).SingleOrDefaultAsync() is not Member m) {
|
||||||
Close();
|
Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -173,12 +176,8 @@ namespace Elwig.Windows {
|
|||||||
.Include(c => c.WineAttr)
|
.Include(c => c.WineAttr)
|
||||||
.OrderBy(v => v.VtrgId)
|
.OrderBy(v => v.VtrgId)
|
||||||
.ToListAsync());
|
.ToListAsync());
|
||||||
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
|
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: true).ToListAsync());
|
||||||
.OrderBy(m => m.Name).ThenBy(m => m.GivenName).ThenBy(m => m.MgNr)
|
var cultList = await ctx.FetchWineCultivations().Cast<object>().ToListAsync();
|
||||||
.ToListAsync());
|
|
||||||
var cultList = await ctx.WineCultivations
|
|
||||||
.OrderBy(c => c.Name)
|
|
||||||
.Cast<object>().ToListAsync();
|
|
||||||
cultList.Insert(0, new NullItem());
|
cultList.Insert(0, new NullItem());
|
||||||
ControlUtils.RenewItemsSource(WineCultivationInput, cultList, null, ControlUtils.RenewSourceDefault.First);
|
ControlUtils.RenewItemsSource(WineCultivationInput, cultList, null, ControlUtils.RenewSourceDefault.First);
|
||||||
await RefreshList();
|
await RefreshList();
|
||||||
@@ -267,8 +266,10 @@ namespace Elwig.Windows {
|
|||||||
if (InputHasChanged(AreaInput) || InputHasChanged(AreaComTypeInput) || InputHasChanged(MgNrInput)) {
|
if (InputHasChanged(AreaInput) || InputHasChanged(AreaComTypeInput) || InputHasChanged(MgNrInput)) {
|
||||||
var a = (RevisionList.SelectedItem as AreaCom)!;
|
var a = (RevisionList.SelectedItem as AreaCom)!;
|
||||||
var d = new AreaComModifyDialog(a.YearFrom, a.YearTo, a.Area, false, RevisionList.ItemsSource.Cast<object>().FirstOrDefault() != a);
|
var d = new AreaComModifyDialog(a.YearFrom, a.YearTo, a.Area, false, RevisionList.ItemsSource.Cast<object>().FirstOrDefault() != a);
|
||||||
if (d.ShowDialog() != true)
|
if (d.ShowDialog() != true) {
|
||||||
|
SaveButton.IsEnabled = true;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
yearTo = d.YearTo;
|
yearTo = d.YearTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,17 +447,19 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async void ActiveAreaCommitmentInput_Changed(object sender, RoutedEventArgs evt) {
|
private async void ActiveAreaCommitmentInput_Changed(object sender, RoutedEventArgs evt) {
|
||||||
|
if (!HasContextLoaded) return;
|
||||||
await RefreshList();
|
await RefreshList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) {
|
private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||||
|
if (!HasContextLoaded) return;
|
||||||
var binding = ((TextBox)sender).GetBindingExpression(TextBox.TextProperty);
|
var binding = ((TextBox)sender).GetBindingExpression(TextBox.TextProperty);
|
||||||
binding?.UpdateSource();
|
binding?.UpdateSource();
|
||||||
await RefreshList(true);
|
await RefreshList(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||||
if (ViewModel.FilterSeason == null) return;
|
if (!HasContextLoaded || ViewModel.FilterSeason == null) return;
|
||||||
await RefreshList();
|
await RefreshList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
xmlns:local="clr-namespace:Elwig.Windows"
|
xmlns:local="clr-namespace:Elwig.Windows"
|
||||||
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="Stammdaten - Elwig" Height="520" MinHeight="400" Width="860" MinWidth="810"
|
Title="Stammdaten - Elwig" Height="520" MinHeight="400" Width="860" MinWidth="810">
|
||||||
Loaded="Window_Loaded">
|
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
<Style TargetType="Label">
|
<Style TargetType="Label">
|
||||||
<Setter Property="HorizontalAlignment" Value="Left"/>
|
<Setter Property="HorizontalAlignment" Value="Left"/>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -19,10 +19,7 @@ namespace Elwig.Windows {
|
|||||||
private bool _branchUpdate = false;
|
private bool _branchUpdate = false;
|
||||||
|
|
||||||
private async Task BranchesInitEditing(AppDbContext ctx) {
|
private async Task BranchesInitEditing(AppDbContext ctx) {
|
||||||
_branchList = new(await ctx.Branches
|
_branchList = new(await ctx.FetchBranches().ToListAsync());
|
||||||
.OrderBy(b => b.Name)
|
|
||||||
.Include(b => b.PostalDest!.AtPlz)
|
|
||||||
.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);
|
||||||
ControlUtils.RenewItemsSource(BranchList, _branchList);
|
ControlUtils.RenewItemsSource(BranchList, _branchList);
|
||||||
@@ -30,10 +27,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.FetchBranches().ToListAsync());
|
||||||
.OrderBy(b => b.Name)
|
|
||||||
.Include(b => b.PostalDest!.AtPlz)
|
|
||||||
.ToListAsync());
|
|
||||||
_branchList = null;
|
_branchList = null;
|
||||||
_branches = null;
|
_branches = null;
|
||||||
_branchIds = null;
|
_branchIds = null;
|
||||||
@@ -47,9 +41,10 @@ namespace Elwig.Windows {
|
|||||||
if (!_branchChanged || _branchList == null || _branches == null || _branchIds == null)
|
if (!_branchChanged || _branchList == null || _branches == null || _branchIds == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var (zwstid, _) in _branches.Where(b => b.Value == null)) {
|
var tx = await ctx.Database.BeginTransactionAsync();
|
||||||
ctx.Remove(ctx.Branches.Find(zwstid)!);
|
var deleteZwstIds = _branches.Where(b => b.Value == null).Select(b => b.Key).ToList();
|
||||||
}
|
await ctx.Branches.Where(b => deleteZwstIds.Contains(b.ZwstId)).ExecuteDeleteAsync();
|
||||||
|
|
||||||
foreach (var (branch, old) in _branchIds) {
|
foreach (var (branch, old) in _branchIds) {
|
||||||
branch.ZwstId = old;
|
branch.ZwstId = old;
|
||||||
}
|
}
|
||||||
@@ -61,13 +56,13 @@ namespace Elwig.Windows {
|
|||||||
foreach (var (old, zwstid) in _branches.Where(b => b.Value != null)) {
|
foreach (var (old, zwstid) in _branches.Where(b => b.Value != null)) {
|
||||||
await ctx.Database.ExecuteSqlAsync($"UPDATE branch SET zwstid = {zwstid} WHERE zwstid = {old}");
|
await ctx.Database.ExecuteSqlAsync($"UPDATE branch SET zwstid = {zwstid} WHERE zwstid = {old}");
|
||||||
}
|
}
|
||||||
await ctx.SaveChangesAsync();
|
|
||||||
|
|
||||||
foreach (var branch in _branchList.Where(b => !_branchIds.ContainsKey(b))) {
|
foreach (var branch in _branchList.Where(b => !_branchIds.ContainsKey(b))) {
|
||||||
if (branch.ZwstId == null) continue;
|
if (branch.ZwstId == null) continue;
|
||||||
ctx.Add(branch);
|
ctx.Add(branch);
|
||||||
}
|
}
|
||||||
await ctx.SaveChangesAsync();
|
await ctx.SaveChangesAsync();
|
||||||
|
await tx.CommitAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BranchList_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) {
|
private void BranchList_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) {
|
||||||
|
|||||||
@@ -22,10 +22,7 @@ namespace Elwig.Windows {
|
|||||||
private async Task ModifiersInitEditing(AppDbContext ctx) {
|
private async Task ModifiersInitEditing(AppDbContext ctx) {
|
||||||
SeasonList.IsEnabled = false;
|
SeasonList.IsEnabled = false;
|
||||||
var year = (SeasonList.SelectedItem as Season)?.Year;
|
var year = (SeasonList.SelectedItem as Season)?.Year;
|
||||||
_modList = new(await ctx.Modifiers
|
_modList = new(await ctx.FetchModifiers(year ?? 0).ToListAsync());
|
||||||
.Where(m => m.Year == year)
|
|
||||||
.OrderBy(m => m.Ordering)
|
|
||||||
.ToListAsync());
|
|
||||||
_mods = _modList.ToDictionary(m => m.ModId, m => (string?)m.ModId);
|
_mods = _modList.ToDictionary(m => m.ModId, m => (string?)m.ModId);
|
||||||
_modIds = _modList.ToDictionary(m => m, m => m.ModId);
|
_modIds = _modList.ToDictionary(m => m, m => m.ModId);
|
||||||
ControlUtils.RenewItemsSource(SeasonModifierList, _modList);
|
ControlUtils.RenewItemsSource(SeasonModifierList, _modList);
|
||||||
@@ -34,10 +31,7 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
private async Task ModifiersFinishEditing(AppDbContext ctx) {
|
private async Task ModifiersFinishEditing(AppDbContext ctx) {
|
||||||
var year = (SeasonList.SelectedItem as Season)?.Year;
|
var year = (SeasonList.SelectedItem as Season)?.Year;
|
||||||
ControlUtils.RenewItemsSource(SeasonModifierList, await ctx.Modifiers
|
ControlUtils.RenewItemsSource(SeasonModifierList, await ctx.FetchModifiers(year ?? 0).ToListAsync());
|
||||||
.Where(m => m.Year == year)
|
|
||||||
.OrderBy(m => m.Ordering)
|
|
||||||
.ToListAsync());
|
|
||||||
_modList = null;
|
_modList = null;
|
||||||
_mods = null;
|
_mods = null;
|
||||||
_modIds = null;
|
_modIds = null;
|
||||||
|
|||||||
@@ -19,22 +19,14 @@ namespace Elwig.Windows {
|
|||||||
private async Task SeasonsInitEditing(AppDbContext ctx) {
|
private async Task SeasonsInitEditing(AppDbContext ctx) {
|
||||||
SeasonAddButton.IsEnabled = false;
|
SeasonAddButton.IsEnabled = false;
|
||||||
SeasonRemoveButton.IsEnabled = false;
|
SeasonRemoveButton.IsEnabled = false;
|
||||||
ControlUtils.RenewItemsSource(SeasonList, await ctx.Seasons
|
ControlUtils.RenewItemsSource(SeasonList, await ctx.FetchSeasons(includeModifiers: true).ToListAsync());
|
||||||
.OrderByDescending(s => s.Year)
|
|
||||||
.Include(s => s.Modifiers)
|
|
||||||
.Include(s => s.Currency)
|
|
||||||
.ToListAsync());
|
|
||||||
SeasonList_SelectionChanged(null, null);
|
SeasonList_SelectionChanged(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SeasonsFinishEditing(AppDbContext ctx) {
|
private async Task SeasonsFinishEditing(AppDbContext ctx) {
|
||||||
SeasonAddButton.IsEnabled = true;
|
SeasonAddButton.IsEnabled = true;
|
||||||
SeasonRemoveButton.IsEnabled = true;
|
SeasonRemoveButton.IsEnabled = true;
|
||||||
ControlUtils.RenewItemsSource(SeasonList, await ctx.Seasons
|
ControlUtils.RenewItemsSource(SeasonList, await ctx.FetchSeasons(includeModifiers: true).ToListAsync());
|
||||||
.OrderByDescending(s => s.Year)
|
|
||||||
.Include(s => s.Modifiers)
|
|
||||||
.Include(s => s.Currency)
|
|
||||||
.ToListAsync());
|
|
||||||
_seasonChanged = false;
|
_seasonChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ namespace Elwig.Windows {
|
|||||||
private bool _attrUpdate = false;
|
private bool _attrUpdate = false;
|
||||||
|
|
||||||
private async Task WineAttributesInitEditing(AppDbContext ctx) {
|
private async Task WineAttributesInitEditing(AppDbContext ctx) {
|
||||||
_attrList = new(await ctx.WineAttributes
|
_attrList = new(await ctx.FetchWineAttributes().ToListAsync());
|
||||||
.OrderBy(a => a.Name)
|
|
||||||
.ToListAsync());
|
|
||||||
_attrs = _attrList.ToDictionary(a => a.AttrId, a => (string?)a.AttrId);
|
_attrs = _attrList.ToDictionary(a => a.AttrId, a => (string?)a.AttrId);
|
||||||
_attrIds = _attrList.ToDictionary(a => a, a => a.AttrId);
|
_attrIds = _attrList.ToDictionary(a => a, a => a.AttrId);
|
||||||
ControlUtils.RenewItemsSource(WineAttributeList, _attrList);
|
ControlUtils.RenewItemsSource(WineAttributeList, _attrList);
|
||||||
@@ -29,9 +27,7 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task WineAttributesFinishEditing(AppDbContext ctx) {
|
private async Task WineAttributesFinishEditing(AppDbContext ctx) {
|
||||||
ControlUtils.RenewItemsSource(WineAttributeList, await ctx.WineAttributes
|
ControlUtils.RenewItemsSource(WineAttributeList, await ctx.FetchWineAttributes().ToListAsync());
|
||||||
.OrderBy(a => a.Name)
|
|
||||||
.ToListAsync());
|
|
||||||
_attrList = null;
|
_attrList = null;
|
||||||
_attrs = null;
|
_attrs = null;
|
||||||
_attrIds = null;
|
_attrIds = null;
|
||||||
@@ -45,9 +41,9 @@ namespace Elwig.Windows {
|
|||||||
if (!_attrChanged || _attrList == null || _attrs == null || _attrIds == null)
|
if (!_attrChanged || _attrList == null || _attrs == null || _attrIds == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var (attrid, _) in _attrs.Where(a => a.Value == null)) {
|
using var tx = await ctx.Database.BeginTransactionAsync();
|
||||||
ctx.Remove(ctx.WineAttributes.Find(attrid)!);
|
var deleteAttrIds = _attrs.Where(a => a.Value == null).Select(a => a.Key).ToList();
|
||||||
}
|
await ctx.WineAttributes.Where(a => deleteAttrIds.Contains(a.AttrId)).ExecuteDeleteAsync();
|
||||||
foreach (var (attr, old) in _attrIds) {
|
foreach (var (attr, old) in _attrIds) {
|
||||||
attr.AttrId = old;
|
attr.AttrId = old;
|
||||||
}
|
}
|
||||||
@@ -61,13 +57,13 @@ namespace Elwig.Windows {
|
|||||||
await ctx.Database.ExecuteSqlAsync($"UPDATE area_commitment_type SET vtrgid = (sortid || COALESCE(attrid, '') || COALESCE(disc, '')) WHERE attrid = {attrid}");
|
await ctx.Database.ExecuteSqlAsync($"UPDATE area_commitment_type SET vtrgid = (sortid || COALESCE(attrid, '') || COALESCE(disc, '')) WHERE attrid = {attrid}");
|
||||||
await ctx.Database.ExecuteSqlRawAsync($"UPDATE payment_variant SET data = REPLACE(REPLACE(data, '/{old}\"', '/{attrid}\"'), '/{old}-', '/{attrid}-')");
|
await ctx.Database.ExecuteSqlRawAsync($"UPDATE payment_variant SET data = REPLACE(REPLACE(data, '/{old}\"', '/{attrid}\"'), '/{old}-', '/{attrid}-')");
|
||||||
}
|
}
|
||||||
await ctx.SaveChangesAsync();
|
|
||||||
|
|
||||||
foreach (var attr in _attrList.Where(a => !_attrIds.ContainsKey(a))) {
|
foreach (var attr in _attrList.Where(a => !_attrIds.ContainsKey(a))) {
|
||||||
if (attr.AttrId == null) continue;
|
if (attr.AttrId == null) continue;
|
||||||
ctx.Add(attr);
|
ctx.Add(attr);
|
||||||
}
|
}
|
||||||
await ctx.SaveChangesAsync();
|
await ctx.SaveChangesAsync();
|
||||||
|
await tx.CommitAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WineAttributeList_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) {
|
private void WineAttributeList_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) {
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ namespace Elwig.Windows {
|
|||||||
private bool _cultUpdate = false;
|
private bool _cultUpdate = false;
|
||||||
|
|
||||||
private async Task WineCultivationsInitEditing(AppDbContext ctx) {
|
private async Task WineCultivationsInitEditing(AppDbContext ctx) {
|
||||||
_cultList = new(await ctx.WineCultivations
|
_cultList = new(await ctx.FetchWineCultivations().ToListAsync());
|
||||||
.OrderBy(c => c.Name)
|
|
||||||
.ToListAsync());
|
|
||||||
_cults = _cultList.ToDictionary(c => c.CultId, c => (string?)c.CultId);
|
_cults = _cultList.ToDictionary(c => c.CultId, c => (string?)c.CultId);
|
||||||
_cultIds = _cultList.ToDictionary(c => c, c => c.CultId);
|
_cultIds = _cultList.ToDictionary(c => c, c => c.CultId);
|
||||||
ControlUtils.RenewItemsSource(WineCultivationList, _cultList);
|
ControlUtils.RenewItemsSource(WineCultivationList, _cultList);
|
||||||
@@ -29,9 +27,7 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task WineCultivationsFinishEditing(AppDbContext ctx) {
|
private async Task WineCultivationsFinishEditing(AppDbContext ctx) {
|
||||||
ControlUtils.RenewItemsSource(WineCultivationList, await ctx.WineCultivations
|
ControlUtils.RenewItemsSource(WineCultivationList, await ctx.FetchWineCultivations().ToListAsync());
|
||||||
.OrderBy(c => c.Name)
|
|
||||||
.ToListAsync());
|
|
||||||
_cultList = null;
|
_cultList = null;
|
||||||
_cults = null;
|
_cults = null;
|
||||||
_cultIds = null;
|
_cultIds = null;
|
||||||
@@ -45,9 +41,9 @@ namespace Elwig.Windows {
|
|||||||
if (!_cultChanged || _cultList == null || _cults == null || _cultIds == null)
|
if (!_cultChanged || _cultList == null || _cults == null || _cultIds == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var (cultid, _) in _cults.Where(c => c.Value == null)) {
|
using var tx = await ctx.Database.BeginTransactionAsync();
|
||||||
ctx.Remove(ctx.WineCultivations.Find(cultid)!);
|
var deleteCultIds = _cults.Where(c => c.Value == null).Select(c => c.Key).ToList();
|
||||||
}
|
await ctx.WineCultivations.Where(c => deleteCultIds.Contains(c.CultId)).ExecuteDeleteAsync();
|
||||||
foreach (var (cult, old) in _cultIds) {
|
foreach (var (cult, old) in _cultIds) {
|
||||||
cult.CultId = old;
|
cult.CultId = old;
|
||||||
}
|
}
|
||||||
@@ -60,13 +56,13 @@ namespace Elwig.Windows {
|
|||||||
await ctx.Database.ExecuteSqlAsync($"UPDATE wine_cultivation SET cultid = {cultid} WHERE cultid = {old}");
|
await ctx.Database.ExecuteSqlAsync($"UPDATE wine_cultivation SET cultid = {cultid} WHERE cultid = {old}");
|
||||||
await ctx.Database.ExecuteSqlRawAsync($"UPDATE payment_variant SET data = REPLACE(data, '-{old}\"', '-{cultid}\"')");
|
await ctx.Database.ExecuteSqlRawAsync($"UPDATE payment_variant SET data = REPLACE(data, '-{old}\"', '-{cultid}\"')");
|
||||||
}
|
}
|
||||||
await ctx.SaveChangesAsync();
|
|
||||||
|
|
||||||
foreach (var cult in _cultList.Where(c => !_cultIds.ContainsKey(c))) {
|
foreach (var cult in _cultList.Where(c => !_cultIds.ContainsKey(c))) {
|
||||||
if (cult.CultId == null) continue;
|
if (cult.CultId == null) continue;
|
||||||
ctx.Add(cult);
|
ctx.Add(cult);
|
||||||
}
|
}
|
||||||
await ctx.SaveChangesAsync();
|
await ctx.SaveChangesAsync();
|
||||||
|
await tx.CommitAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WineCultivationList_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) {
|
private void WineCultivationList_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) {
|
||||||
|
|||||||
@@ -153,44 +153,22 @@ namespace Elwig.Windows {
|
|||||||
ParameterExportEbicsAddress.IsEnabled = true;
|
ParameterExportEbicsAddress.IsEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs evt) {
|
|
||||||
LockInputs();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task OnRenewContext(AppDbContext ctx) {
|
protected override async Task OnRenewContext(AppDbContext ctx) {
|
||||||
await base.OnRenewContext(ctx);
|
await base.OnRenewContext(ctx);
|
||||||
FillInputs(App.Client, await ctx.Seasons.FindAsync(Utils.CurrentLastSeason));
|
FillInputs(App.Client, await ctx.FetchSeasons(Utils.CurrentLastSeason).SingleOrDefaultAsync());
|
||||||
ControlUtils.RenewItemsSource(SeasonList, await ctx.Seasons
|
ControlUtils.RenewItemsSource(SeasonList, await ctx.FetchSeasons(includeModifiers: true).ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
|
||||||
.OrderByDescending(s => s.Year)
|
|
||||||
.Include(s => s.Modifiers)
|
|
||||||
.Include(s => s.Currency)
|
|
||||||
.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.FetchBranches().ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
|
||||||
.OrderBy(b => b.Name)
|
ControlUtils.RenewItemsSource(WineAttributeList, await ctx.FetchWineAttributes().ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
|
||||||
.Include(b => b.PostalDest!.AtPlz)
|
ControlUtils.RenewItemsSource(AreaCommitmentTypeWineVariantInput, await ctx.FetchWineVarieties().ToListAsync());
|
||||||
.ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
|
var attrList = await ctx.FetchWineAttributes().Cast<object>().ToListAsync();
|
||||||
ControlUtils.RenewItemsSource(WineAttributeList, await ctx.WineAttributes
|
|
||||||
.OrderBy(a => a.Name)
|
|
||||||
.ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
|
|
||||||
ControlUtils.RenewItemsSource(AreaCommitmentTypeWineVariantInput, await ctx.WineVarieties
|
|
||||||
.OrderBy(s => s.Name)
|
|
||||||
.ToListAsync());
|
|
||||||
var attrList = await ctx.WineAttributes.OrderBy(a => a.Name).Cast<object>().ToListAsync();
|
|
||||||
attrList.Insert(0, new NullItem(""));
|
attrList.Insert(0, new NullItem(""));
|
||||||
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);
|
|
||||||
ControlUtils.RenewItemsSource(WineCultivationList, await ctx.WineCultivations
|
|
||||||
.OrderBy(c => c.Name)
|
|
||||||
.ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
|
|
||||||
ControlUtils.RenewItemsSource(SeasonModifierList, await ctx.Modifiers
|
|
||||||
.Where(m => m.Year == year)
|
|
||||||
.OrderBy(m => m.Ordering)
|
|
||||||
.ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
|
.ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
|
||||||
|
ControlUtils.RenewItemsSource(WineCultivationList, await ctx.FetchWineCultivations().ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
|
||||||
|
ControlUtils.RenewItemsSource(SeasonModifierList, await ctx.FetchModifiers(year ?? 0).ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateButtons() {
|
protected override void UpdateButtons() {
|
||||||
@@ -286,7 +264,7 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
ClearInputStates();
|
ClearInputStates();
|
||||||
FillInputs(App.Client, await ctx.Seasons.FindAsync(Utils.CurrentLastSeason));
|
FillInputs(App.Client, await ctx.FetchSeasons(Utils.CurrentLastSeason).SingleOrDefaultAsync());
|
||||||
LockInputs();
|
LockInputs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +284,7 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
ClearInputStates();
|
ClearInputStates();
|
||||||
FillInputs(App.Client, await ctx.Seasons.FindAsync(Utils.CurrentLastSeason));
|
FillInputs(App.Client, await ctx.FetchSeasons(Utils.CurrentLastSeason).SingleOrDefaultAsync());
|
||||||
UpdateButtons();
|
UpdateButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +320,7 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
ClearInputStates();
|
ClearInputStates();
|
||||||
FillInputs(App.Client, await ctx.Seasons.FindAsync(Utils.CurrentLastSeason));
|
FillInputs(App.Client, await ctx.FetchSeasons(Utils.CurrentLastSeason).SingleOrDefaultAsync());
|
||||||
LockInputs();
|
LockInputs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,7 +408,7 @@ namespace Elwig.Windows {
|
|||||||
private async Task UpdateParameters(int year) {
|
private async Task UpdateParameters(int year) {
|
||||||
try {
|
try {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
if (await ctx.Seasons.FindAsync(year) is not Season s)
|
if (await ctx.FetchSeasons(year).SingleOrDefaultAsync() is not Season s)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s.Billing_AllowAttrsIntoLower = ParameterAllowAttrIntoLowerInput.IsChecked ?? false;
|
s.Billing_AllowAttrsIntoLower = ParameterAllowAttrIntoLowerInput.IsChecked ?? false;
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
xmlns:ScottPlot="clr-namespace:ScottPlot.WPF;assembly=ScottPlot.WPF"
|
xmlns:ScottPlot="clr-namespace:ScottPlot.WPF;assembly=ScottPlot.WPF"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="Auszahlung - Elwig" Height="700" Width="1500" MinWidth="1000" MinHeight="500"
|
Title="Auszahlung - Elwig" Height="700" Width="1500" MinWidth="1000" MinHeight="500"
|
||||||
Loaded="Window_Loaded"
|
|
||||||
Closing="Window_Closing">
|
Closing="Window_Closing">
|
||||||
|
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
|
|||||||
@@ -80,9 +80,6 @@ namespace Elwig.Windows {
|
|||||||
LockContext = true;
|
LockContext = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs evt) {
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
|
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
|
||||||
if (HasChanged) {
|
if (HasChanged) {
|
||||||
var r = MessageBox.Show("Soll das Fenster wirklich geschlossen werden? Nicht gespeicherte Änderungen werden NICHT übernommen!", "Schließen bestätigen",
|
var r = MessageBox.Show("Soll das Fenster wirklich geschlossen werden? Nicht gespeicherte Änderungen werden NICHT übernommen!", "Schließen bestätigen",
|
||||||
@@ -101,17 +98,17 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
private async Task RefreshGraphList(AppDbContext ctx) {
|
private async Task RefreshGraphList(AppDbContext ctx) {
|
||||||
PaymentVar = await ctx.PaymentVariants.FindAsync(Year, AvNr) ?? throw new ArgumentException("PaymentVar not found");
|
PaymentVar = await ctx.PaymentVariants.FindAsync(Year, AvNr) ?? throw new ArgumentException("PaymentVar not found");
|
||||||
Season = await ctx.Seasons.FindAsync(Year) ?? throw new ArgumentException("Season not found");
|
Season = await ctx.FetchSeasons(Year).SingleOrDefaultAsync() ?? throw new ArgumentException("Season not found");
|
||||||
CurrencySymbol = Season.Currency.Symbol ?? Season.Currency.Code;
|
CurrencySymbol = Season.Currency.Symbol ?? Season.Currency.Code;
|
||||||
PriceInput.Unit = $"{CurrencySymbol}/kg";
|
PriceInput.Unit = $"{CurrencySymbol}/kg";
|
||||||
GebundenFlatBonus.Unit = $"{CurrencySymbol}/kg";
|
GebundenFlatBonus.Unit = $"{CurrencySymbol}/kg";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var data = EditBillingData.FromJson(PaymentVar.Data, Utils.GetVaributes(ctx, Year));
|
var data = EditBillingData.FromJson(PaymentVar.Data, await Utils.GetVaributes(ctx, Year));
|
||||||
var paymentEntries = data.GetPaymentGraphEntries(ctx, Season);
|
var paymentEntries = await data.GetPaymentGraphEntries(ctx, Season);
|
||||||
GraphEntries = [
|
GraphEntries = [
|
||||||
..paymentEntries,
|
..paymentEntries,
|
||||||
..data.GetQualityGraphEntries(ctx, Season, paymentEntries.Any() ? paymentEntries.Max(e => e.Id) : 0)
|
..await data.GetQualityGraphEntries(ctx, Season, paymentEntries.Any() ? paymentEntries.Max(e => e.Id) : 0)
|
||||||
];
|
];
|
||||||
} catch (KeyNotFoundException ex) {
|
} catch (KeyNotFoundException ex) {
|
||||||
var key = ex.Message.Split('\'')[1].Split('\'')[0];
|
var key = ex.Message.Split('\'')[1].Split('\'')[0];
|
||||||
@@ -126,7 +123,7 @@ namespace Elwig.Windows {
|
|||||||
MessageBox.Show("Fehler beim Laden der Auszahlungsvariante:\n\n" + ex.Message, "Fehler",
|
MessageBox.Show("Fehler beim Laden der Auszahlungsvariante:\n\n" + ex.Message, "Fehler",
|
||||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
}
|
}
|
||||||
Vaributes = Utils.GetVaributeList(ctx, Year);
|
Vaributes = await Utils.GetVaributeList(ctx, Year);
|
||||||
GraphEntries.ForEach(e => {
|
GraphEntries.ForEach(e => {
|
||||||
e.Vaributes.ForEach(v => {
|
e.Vaributes.ForEach(v => {
|
||||||
var found = Vaributes.Find(a => a.Variety?.SortId == v.Variety?.SortId && a.Attribute?.AttrId == v.Attribute?.AttrId && a.Cultivation?.CultId == v.Cultivation?.CultId);
|
var found = Vaributes.Find(a => a.Variety?.SortId == v.Variety?.SortId && a.Attribute?.AttrId == v.Attribute?.AttrId && a.Cultivation?.CultId == v.Cultivation?.CultId);
|
||||||
@@ -645,7 +642,7 @@ namespace Elwig.Windows {
|
|||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var origData = BillingData.FromJson(PaymentVar.Data);
|
var origData = BillingData.FromJson(PaymentVar.Data);
|
||||||
var data = BillingData.FromGraphEntries(GraphEntries, origData, Utils.GetVaributes(ctx, Year),
|
var data = BillingData.FromGraphEntries(GraphEntries, origData, await Utils.GetVaributes(ctx, Year),
|
||||||
AllVaributesAssigned, AllVaributesAssignedAbgew);
|
AllVaributesAssigned, AllVaributesAssignedAbgew);
|
||||||
|
|
||||||
PaymentVar.Data = data.ToJsonString();
|
PaymentVar.Data = data.ToJsonString();
|
||||||
@@ -663,7 +660,7 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
var b = new BillingVariant(PaymentVar.Year, PaymentVar.AvNr);
|
var b = await BillingVariant.Create(PaymentVar.Year, PaymentVar.AvNr);
|
||||||
await b.Calculate(false);
|
await b.Calculate(false);
|
||||||
});
|
});
|
||||||
} catch (KeyNotFoundException exc) {
|
} catch (KeyNotFoundException exc) {
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected bool HasContextLoaded { get; private set; }
|
||||||
|
|
||||||
private bool _renewPending = false;
|
private bool _renewPending = false;
|
||||||
|
|
||||||
private readonly RoutedCommand CtrlR = new("CtrlR", typeof(ContextWindow), [new KeyGesture(Key.R, ModifierKeys.Control)]);
|
private readonly RoutedCommand CtrlR = new("CtrlR", typeof(ContextWindow), [new KeyGesture(Key.R, ModifierKeys.Control)]);
|
||||||
@@ -30,27 +32,41 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async void ForceContextReload(object sender, EventArgs evt) {
|
public async void ForceContextReload(object sender, EventArgs evt) {
|
||||||
await HintContextChange();
|
await ForceContextReload();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task HintContextChange() {
|
public async Task ForceContextReload() {
|
||||||
|
HintContextChange();
|
||||||
|
await TryContextReload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HintContextChange() {
|
||||||
_renewPending = true;
|
_renewPending = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task TryContextReload() {
|
||||||
if (LockContext) return;
|
if (LockContext) return;
|
||||||
await EnsureContextRenewed();
|
await EnsureContextRenewed();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async void OnLoaded(object? sender, RoutedEventArgs? evt) {
|
protected async void OnLoaded(object? sender, RoutedEventArgs? evt) {
|
||||||
|
Mouse.OverrideCursor = Cursors.AppStarting;
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
await OnRenewContext(ctx);
|
await OnRenewContext(ctx);
|
||||||
|
HasContextLoaded = true;
|
||||||
|
await OnInit(ctx);
|
||||||
|
Mouse.OverrideCursor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task EnsureContextRenewed() {
|
protected async Task EnsureContextRenewed() {
|
||||||
if (!_renewPending) return;
|
if (!_renewPending) return;
|
||||||
|
_renewPending = false;
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
await OnRenewContext(ctx);
|
await OnRenewContext(ctx);
|
||||||
_renewPending = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual protected async Task OnInit(AppDbContext ctx) { }
|
||||||
|
|
||||||
abstract protected Task OnRenewContext(AppDbContext ctx);
|
abstract protected Task OnRenewContext(AppDbContext ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,7 @@
|
|||||||
xmlns:local="clr-namespace:Elwig.Windows"
|
xmlns:local="clr-namespace:Elwig.Windows"
|
||||||
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
||||||
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
||||||
Title="{Binding Title}" Height="720" Width="1150" MinHeight="720" MinWidth="1000"
|
Title="{Binding Title}" Height="720" Width="1150" MinHeight="720" MinWidth="1000">
|
||||||
Loaded="Window_Loaded">
|
|
||||||
<Window.DataContext>
|
<Window.DataContext>
|
||||||
<vm:DeliveryAdminViewModel/>
|
<vm:DeliveryAdminViewModel/>
|
||||||
</Window.DataContext>
|
</Window.DataContext>
|
||||||
@@ -530,12 +529,12 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Label Content="Gradation:" Margin="10,10,10,10"/>
|
<Label Content="Gradation:" Margin="10,10,10,10"/>
|
||||||
<ctrl:UnitTextBox x:Name="GradationOeInput" Unit="°Oe" Text="{Binding GradationOeString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
<ctrl:UnitTextBox x:Name="GradationOeInput" Unit="°Oe" Text="{Binding GradationOeString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
TextChanged="GradationOeInput_TextChanged" KeyUp="Input_KeyUp"
|
TextChanged="GradationOeInput_TextChanged" LostFocus="GradationOeInput_LostFocus" KeyUp="Input_KeyUp"
|
||||||
Grid.Column="1" Width="54" Margin="0,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
Grid.Column="1" Width="54" Margin="0,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||||
|
|
||||||
<Label Content="=" Margin="60,10,10,10" Grid.Column="1"/>
|
<Label Content="=" Margin="60,10,10,10" Grid.Column="1"/>
|
||||||
<ctrl:UnitTextBox x:Name="GradationKmwInput" Unit="°KMW" Text="{Binding GradationKmwString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
<ctrl:UnitTextBox x:Name="GradationKmwInput" Unit="°KMW" Text="{Binding GradationKmwString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
TextChanged="GradationKmwInput_TextChanged" KeyUp="Input_KeyUp"
|
TextChanged="GradationKmwInput_TextChanged" LostFocus="GradationKmwInput_LostFocus" KeyUp="Input_KeyUp"
|
||||||
Grid.Column="1" Width="68" Margin="78,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
Grid.Column="1" Width="68" Margin="78,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||||
|
|
||||||
<Label Content="Qualitätsstufe:" Margin="10,40,10,10"/>
|
<Label Content="Qualitätsstufe:" Margin="10,40,10,10"/>
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ namespace Elwig.Windows {
|
|||||||
private readonly Button[] WeighingButtons;
|
private readonly Button[] WeighingButtons;
|
||||||
|
|
||||||
private List<WineQualLevel> WineQualityLevels = [];
|
private List<WineQualLevel> WineQualityLevels = [];
|
||||||
|
private Dictionary<int, List<Modifier>> Modifiers = [];
|
||||||
|
|
||||||
public DeliveryAdminWindow(bool receipt = false) {
|
public DeliveryAdminWindow(bool receipt = false) {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -122,20 +123,20 @@ namespace Elwig.Windows {
|
|||||||
Menu_Export_UploadSeason.IsEnabled = App.Config.SyncUrl != null;
|
Menu_Export_UploadSeason.IsEnabled = App.Config.SyncUrl != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeliveryAdminWindow(int mgnr) : this() {
|
public DeliveryAdminWindow(int mgnr) :
|
||||||
|
this() {
|
||||||
ViewModel.FilterMember = DeliveryService.GetMember(mgnr) ?? throw new ArgumentException("MgNr argument has invalid value");
|
ViewModel.FilterMember = DeliveryService.GetMember(mgnr) ?? throw new ArgumentException("MgNr argument has invalid value");
|
||||||
ViewModel.Title = $"Lieferungen - {ViewModel.FilterMember.AdministrativeName} - Elwig";
|
ViewModel.Title = $"Lieferungen - {ViewModel.FilterMember.AdministrativeName} - Elwig";
|
||||||
ViewModel.EnableAllSeasons = true;
|
ViewModel.EnableAllSeasons = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs evt) {
|
protected override async Task OnInit(AppDbContext ctx) {
|
||||||
|
await base.OnInit(ctx);
|
||||||
OnSecondPassed(null, null);
|
OnSecondPassed(null, null);
|
||||||
SecondsTimer.Start();
|
SecondsTimer.Start();
|
||||||
LockInputs();
|
|
||||||
if (ViewModel.IsReceipt) {
|
if (ViewModel.IsReceipt) {
|
||||||
NewDeliveryButton_Click(null, null);
|
NewDeliveryButton_Click(null, null);
|
||||||
using var ctx = new AppDbContext();
|
if (await ctx.FetchSeasons(Utils.CurrentYear).SingleOrDefaultAsync() == null) {
|
||||||
if (ctx.Seasons.Find(Utils.CurrentYear) == null) {
|
|
||||||
MessageBox.Show("Die Saison für das aktuelle Jahr wurde noch nicht erstellt. Neue Lieferungen können nicht abgespeichert werden.\n\n(Stammdaten -> Saisons -> Neu anlegen...)",
|
MessageBox.Show("Die Saison für das aktuelle Jahr wurde noch nicht erstellt. Neue Lieferungen können nicht abgespeichert werden.\n\n(Stammdaten -> Saisons -> Neu anlegen...)",
|
||||||
"Saison noch nicht erstellt", MessageBoxButton.OK, MessageBoxImage.Warning);
|
"Saison noch nicht erstellt", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||||
}
|
}
|
||||||
@@ -420,43 +421,57 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task RefreshList(bool updateSort = false) {
|
private async Task RefreshList(bool updateSort = false) {
|
||||||
using var ctx = new AppDbContext();
|
var vm = ViewModel;
|
||||||
var (_, deliveryQuery, deliveryPartsQuery, predicate, filter) = await ViewModel.GetFilters(ctx);
|
var cursor = Mouse.OverrideCursor != null;
|
||||||
var deliveries = await deliveryQuery
|
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
||||||
.Include(d => d.Member.EmailAddresses)
|
var query = (vm.SearchQuery, vm.FilterSeason, vm.FilterAllSeasons, vm.FilterTodayOnly);
|
||||||
.ToListAsync();
|
var (filter, deliveries, deliveryPartsNum, varieties, members, stat) = await Task.Run(async () => {
|
||||||
deliveries.Reverse();
|
using var ctx = new AppDbContext();
|
||||||
|
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.Variety)
|
||||||
|
.Include(d => d.Parts).ThenInclude(p => p.Attribute)
|
||||||
|
.Include(d => d.Parts).ThenInclude(p => p.Cultivation)
|
||||||
|
.IgnoreAutoIncludes()
|
||||||
|
.AsSplitQuery()
|
||||||
|
.ToListAsync();
|
||||||
|
deliveries.Reverse();
|
||||||
|
|
||||||
if (filter.Count > 0 && deliveries.Count > 0) {
|
if (filter.Count > 0 && deliveries.Count > 0) {
|
||||||
var dict = deliveries.AsParallel()
|
var dict = deliveries.AsParallel()
|
||||||
.ToDictionary(d => d, d => d.SearchScore(ViewModel.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.Max(a => a.Value) * 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)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deliveries.ForEach(d => { d.PartFilter = predicate; });
|
||||||
|
|
||||||
|
var deliveryPartsNum = await deliveryPartsQuery.CountAsync();
|
||||||
|
var varieties = await deliveryPartsQuery.Select(d => d.SortId).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);
|
||||||
|
});
|
||||||
|
if (!cursor) Mouse.OverrideCursor = null;
|
||||||
|
if (query != (ViewModel.SearchQuery, ViewModel.FilterSeason, ViewModel.FilterAllSeasons, ViewModel.FilterTodayOnly)) return;
|
||||||
|
|
||||||
var filteredParts = await deliveryPartsQuery
|
|
||||||
.Include(p => p.PartModifiers).ThenInclude(p => p.Modifier)
|
|
||||||
.GroupBy(p => new { p.Year, p.DId })
|
|
||||||
.ToDictionaryAsync(g => (g.Key.Year, g.Key.DId), g => g.ToList());
|
|
||||||
deliveries.ForEach(d => { d.FilteredParts = filteredParts.GetValueOrDefault((d.Year, d.DId)) ?? []; });
|
|
||||||
ControlUtils.RenewItemsSource(DeliveryList, deliveries,
|
ControlUtils.RenewItemsSource(DeliveryList, deliveries,
|
||||||
DeliveryList_SelectionChanged, filter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
DeliveryList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
||||||
await RefreshDeliveryParts();
|
await RefreshDeliveryParts();
|
||||||
|
|
||||||
var members = await deliveryQuery.Select(d => d.Member).Distinct().IgnoreAutoIncludes().ToListAsync();
|
|
||||||
ViewModel.StatusMembers = $"{members.Count:N0}" + (members.Count > 0 && members.Count <= 4 ? $" ({string.Join(", ", members.Select(m => m.AdministrativeName))})" : "");
|
ViewModel.StatusMembers = $"{members.Count:N0}" + (members.Count > 0 && members.Count <= 4 ? $" ({string.Join(", ", members.Select(m => m.AdministrativeName))})" : "");
|
||||||
ViewModel.StatusDeliveries = $"{deliveries.Count:N0}";
|
ViewModel.StatusDeliveries = $"{deliveries.Count:N0}";
|
||||||
|
|
||||||
if (filter.Count == 0) {
|
if (filter.Count == 0) {
|
||||||
var deliveryParts = deliveryPartsQuery;
|
ViewModel.StatusDeliveries = $"{deliveries.Count:N0} ({deliveryPartsNum:N0})";
|
||||||
ViewModel.StatusDeliveries = $"{deliveries.Count:N0} ({await deliveryParts.CountAsync():N0})";
|
|
||||||
var varieties = await deliveryParts.Select(d => d.SortId).Distinct().ToListAsync();
|
|
||||||
ViewModel.StatusVarieties = $"{varieties.Count:N0}" + (varieties.Count > 0 && varieties.Count <= 10 ? $" ({string.Join(", ", varieties)})" : "");
|
ViewModel.StatusVarieties = $"{varieties.Count:N0}" + (varieties.Count > 0 && varieties.Count <= 10 ? $" ({string.Join(", ", varieties)})" : "");
|
||||||
var (wText, wData, gText, gData) = await DeliveryService.GenerateToolTipData(deliveryParts);
|
var (wText, wData, gText, gData) = stat;
|
||||||
ViewModel.StatusWeight = wText;
|
ViewModel.StatusWeight = wText;
|
||||||
ViewModel.StatusGradation = gText;
|
ViewModel.StatusGradation = gText;
|
||||||
(ViewModel.StatusWeightToolTip, ViewModel.StatusGradationToolTip) = DeliveryService.GenerateToolTip(wData, gData);
|
(ViewModel.StatusWeightToolTip, ViewModel.StatusGradationToolTip) = DeliveryService.GenerateToolTip(wData, gData);
|
||||||
@@ -484,7 +499,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).IgnoreAutoIncludes().ToListAsync()) {
|
foreach (var s in await ctx.FetchSeasons().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}",
|
||||||
@@ -493,6 +508,9 @@ namespace Elwig.Windows {
|
|||||||
Menu_Bki_SaveList.Items.Add(i);
|
Menu_Bki_SaveList.Items.Add(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var attributes = await ctx.FetchWineAttributes(!IsCreating).ToListAsync();
|
||||||
|
Modifiers = await ctx.FetchModifiers(null).GroupBy(m => m.Year).ToDictionaryAsync(g => g.Key, g => g.ToList());
|
||||||
|
|
||||||
var font = new FontFamily("Segoe MDL2 Assets");
|
var font = new FontFamily("Segoe MDL2 Assets");
|
||||||
Menu_BulkAction_SetAttribute.Items.Clear();
|
Menu_BulkAction_SetAttribute.Items.Clear();
|
||||||
var noAttr = new MenuItem {
|
var noAttr = new MenuItem {
|
||||||
@@ -501,7 +519,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).IgnoreAutoIncludes().ToListAsync()) {
|
foreach (var attr in attributes) {
|
||||||
var i = new MenuItem {
|
var i = new MenuItem {
|
||||||
Header = attr.Name,
|
Header = attr.Name,
|
||||||
};
|
};
|
||||||
@@ -511,7 +529,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).IgnoreAutoIncludes().ToListAsync()) {
|
foreach (var mod in Modifiers.GetValueOrDefault(ViewModel.SelectedDelivery?.Year ?? year, [])) {
|
||||||
var i1 = new MenuItem {
|
var i1 = new MenuItem {
|
||||||
Header = mod.Name,
|
Header = mod.Name,
|
||||||
};
|
};
|
||||||
@@ -525,44 +543,34 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await RefreshList();
|
await RefreshList();
|
||||||
var d = DeliveryList.SelectedItem as Delivery;
|
|
||||||
var y = d?.Year ?? ViewModel.FilterSeason;
|
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: !IsCreating, includeContactInfo: true).ToListAsync());
|
||||||
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
|
ControlUtils.RenewItemsSource(BranchInput, await ctx.FetchBranches().ToListAsync());
|
||||||
.Where(m => m.IsActive || !IsCreating)
|
ControlUtils.RenewItemsSource(WineVarietyInput, await ctx.FetchWineVarieties().ToListAsync());
|
||||||
.Include(m => m.PostalDest.AtPlz!.Ort)
|
var attrList = attributes.Cast<object>().ToList();
|
||||||
.Include(m => m.DefaultWbKg!.AtKg)
|
|
||||||
.OrderBy(m => m.Name)
|
|
||||||
.ThenBy(m => m.GivenName)
|
|
||||||
.ToListAsync());
|
|
||||||
ControlUtils.RenewItemsSource(BranchInput, await ctx.Branches.OrderBy(b => b.Name).ToListAsync());
|
|
||||||
ControlUtils.RenewItemsSource(WineVarietyInput, await ctx.WineVarieties.OrderBy(v => v.Name).ToListAsync());
|
|
||||||
var attrList = await ctx.WineAttributes.Where(a => !IsCreating || a.IsActive).OrderBy(a => a.Name).Cast<object>().ToListAsync();
|
|
||||||
attrList.Insert(0, new NullItem(""));
|
attrList.Insert(0, new NullItem(""));
|
||||||
ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First);
|
ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First);
|
||||||
var cultList = await ctx.WineCultivations.OrderBy(a => a.Name).Cast<object>().ToListAsync();
|
var cultList = await ctx.FetchWineCultivations().Cast<object>().ToListAsync();
|
||||||
cultList.Insert(0, new NullItem(""));
|
cultList.Insert(0, new NullItem(""));
|
||||||
ControlUtils.RenewItemsSource(CultivationInput, cultList, null, ControlUtils.RenewSourceDefault.First);
|
ControlUtils.RenewItemsSource(CultivationInput, cultList, null, ControlUtils.RenewSourceDefault.First);
|
||||||
WineQualityLevels = await ctx.WineQualityLevels.ToListAsync();
|
WineQualityLevels = await ctx.FetchWineQualityLevels().ToListAsync();
|
||||||
ControlUtils.RenewItemsSource(WineQualityLevelInput, WineQualityLevels);
|
ControlUtils.RenewItemsSource(WineQualityLevelInput, WineQualityLevels);
|
||||||
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers
|
ControlUtils.RenewItemsSource(ModifiersInput, Modifiers.GetValueOrDefault(year, []).Where(m => m.IsActive || !IsCreating).ToList());
|
||||||
.Where(m => m.Year == y && (!IsCreating || m.IsActive))
|
var origins = await ctx.WineOrigins.ToListAsync();
|
||||||
.OrderBy(m => m.Ordering)
|
origins.ForEach(o => { origins.FirstOrDefault(p => p.HkId == o.ParentHkId)?.Children.Add(o); });
|
||||||
.Include(m => m.Season.Currency)
|
origins = [.. origins.OrderByDescending(o => o.SortKey).ThenBy(o => o.HkId)];
|
||||||
.ToListAsync());
|
ControlUtils.RenewItemsSource(WineOriginInput, origins);
|
||||||
ControlUtils.RenewItemsSource(WineOriginInput, (await ctx.WineOrigins.Include(o => o.Parent).Include(o => o.Children).ToListAsync()).OrderByDescending(o => o.SortKey).ThenBy(o => o.HkId));
|
|
||||||
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);
|
||||||
UpdateRdInput();
|
UpdateRdInput();
|
||||||
if (IsCreating) await UpdateLsNr();
|
if (IsCreating) await UpdateLsNr();
|
||||||
|
|
||||||
await RefreshDeliveryParts();
|
|
||||||
RefreshInputs();
|
RefreshInputs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,22 +582,11 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task RefreshDeliveryParts() {
|
private async Task RefreshDeliveryParts() {
|
||||||
using var ctx = new AppDbContext();
|
|
||||||
if (DeliveryList.SelectedItem is Delivery d) {
|
if (DeliveryList.SelectedItem is Delivery d) {
|
||||||
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers
|
ControlUtils.RenewItemsSource(ModifiersInput, Modifiers.GetValueOrDefault(d.Year, []).Where(m => m.IsActive || !IsCreating).ToList());
|
||||||
.Where(m => m.Year == d.Year && (!IsCreating || m.IsActive))
|
ControlUtils.RenewItemsSource(DeliveryPartList, d.Parts, DeliveryPartList_SelectionChanged, ControlUtils.RenewSourceDefault.First);
|
||||||
.OrderBy(m => m.Ordering)
|
|
||||||
.ToListAsync());
|
|
||||||
ControlUtils.RenewItemsSource(DeliveryPartList, await ctx.DeliveryParts
|
|
||||||
.Where(p => p.Year == d.Year && p.DId == d.DId)
|
|
||||||
.OrderBy(p => p.DPNr)
|
|
||||||
.Include(p => p.PartModifiers)
|
|
||||||
.ToListAsync(), DeliveryPartList_SelectionChanged, ControlUtils.RenewSourceDefault.First);
|
|
||||||
} else {
|
} else {
|
||||||
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers
|
ControlUtils.RenewItemsSource(ModifiersInput, Modifiers.GetValueOrDefault(ViewModel.FilterSeason ?? 0, []).Where(m => m.IsActive || !IsCreating).ToList());
|
||||||
.Where(m => m.Year == ViewModel.FilterSeason && (!IsCreating || m.IsActive))
|
|
||||||
.OrderBy(m => m.Ordering)
|
|
||||||
.ToListAsync());
|
|
||||||
DeliveryPartList.ItemsSource = null;
|
DeliveryPartList.ItemsSource = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -681,17 +678,19 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) {
|
private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||||
|
if (!HasContextLoaded) return;
|
||||||
await RefreshList(true);
|
await RefreshList(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||||
if (ViewModel.FilterSeason == null || TodayOnlyInput == null || AllSeasonsInput == null) return;
|
if (!HasContextLoaded || ViewModel.FilterSeason == null || TodayOnlyInput == null || AllSeasonsInput == null) return;
|
||||||
TodayOnlyInput.IsChecked = false;
|
TodayOnlyInput.IsChecked = false;
|
||||||
AllSeasonsInput.IsChecked = false;
|
AllSeasonsInput.IsChecked = false;
|
||||||
await RefreshList();
|
await RefreshList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void TodayOnlyInput_Changed(object sender, RoutedEventArgs evt) {
|
private async void TodayOnlyInput_Changed(object sender, RoutedEventArgs evt) {
|
||||||
|
if (!HasContextLoaded) return;
|
||||||
if (TodayOnlyInput.IsChecked == true && AllSeasonsInput.IsChecked == false) {
|
if (TodayOnlyInput.IsChecked == true && AllSeasonsInput.IsChecked == false) {
|
||||||
ViewModel.FilterSeason = Utils.Today.Year;
|
ViewModel.FilterSeason = Utils.Today.Year;
|
||||||
ViewModel.FilterTodayOnly = true;
|
ViewModel.FilterTodayOnly = true;
|
||||||
@@ -700,6 +699,7 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async void AllSeasonsInput_Changed(object sender, RoutedEventArgs evt) {
|
private async void AllSeasonsInput_Changed(object sender, RoutedEventArgs evt) {
|
||||||
|
if (!HasContextLoaded) return;
|
||||||
if (AllSeasonsInput.IsChecked == true) {
|
if (AllSeasonsInput.IsChecked == true) {
|
||||||
SeasonInput.IsEnabled = false;
|
SeasonInput.IsEnabled = false;
|
||||||
ViewModel.FilterSeason = null;
|
ViewModel.FilterSeason = null;
|
||||||
@@ -719,7 +719,7 @@ namespace Elwig.Windows {
|
|||||||
Menu_DeliveryNote_Show.IsEnabled = !IsEditing && !IsCreating;
|
Menu_DeliveryNote_Show.IsEnabled = !IsEditing && !IsCreating;
|
||||||
Menu_DeliveryNote_SavePdf.IsEnabled = !IsEditing && !IsCreating;
|
Menu_DeliveryNote_SavePdf.IsEnabled = !IsEditing && !IsCreating;
|
||||||
Menu_DeliveryNote_Print.IsEnabled = !IsEditing && !IsCreating;
|
Menu_DeliveryNote_Print.IsEnabled = !IsEditing && !IsCreating;
|
||||||
Menu_DeliveryNote_Email.IsEnabled = !IsEditing && !IsCreating && App.Config.Smtp != null && d.Member.EmailAddresses.Count > 0;
|
Menu_DeliveryNote_Email.IsEnabled = !IsEditing && !IsCreating && App.Config.Smtp != null && ViewModel.Member?.EmailAddresses.Count > 0;
|
||||||
Menu_Export_ExportSelected.IsEnabled = !IsEditing && !IsCreating;
|
Menu_Export_ExportSelected.IsEnabled = !IsEditing && !IsCreating;
|
||||||
Menu_Export_UploadSelected.IsEnabled = !IsEditing && !IsCreating && App.Config.SyncUrl != null;
|
Menu_Export_UploadSelected.IsEnabled = !IsEditing && !IsCreating && App.Config.SyncUrl != null;
|
||||||
} else {
|
} else {
|
||||||
@@ -812,11 +812,12 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EmptyScale();
|
EmptyScale();
|
||||||
|
|
||||||
await EnsureContextRenewed();
|
await EnsureContextRenewed();
|
||||||
Mouse.OverrideCursor = null;
|
Mouse.OverrideCursor = null;
|
||||||
ControlUtils.SelectItem(DeliveryList, p?.Delivery);
|
ControlUtils.SelectItemWithPk(DeliveryList, p?.Year, p?.DId);
|
||||||
DeliveryPartList.SelectedItem = null;
|
DeliveryPartList.SelectedItem = null;
|
||||||
DeliveryPartList.ScrollIntoView(DeliveryPartList.ItemsSource.Cast<object>().Last());
|
DeliveryPartList.ScrollIntoView(DeliveryPartList.ItemsSource.Cast<object>().LastOrDefault());
|
||||||
InitialInputs();
|
InitialInputs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -849,26 +850,22 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EmptyScale();
|
EmptyScale();
|
||||||
await EnsureContextRenewed();
|
|
||||||
if (p?.Delivery != null) {
|
|
||||||
try {
|
|
||||||
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 {
|
|
||||||
await doc.Print(2);
|
|
||||||
}
|
|
||||||
} catch (Exception exc) {
|
|
||||||
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Utils.RunBackground("Lieferschein drucken", async () => {
|
||||||
|
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 {
|
||||||
|
await doc.Print(2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await EnsureContextRenewed();
|
||||||
Mouse.OverrideCursor = null;
|
Mouse.OverrideCursor = null;
|
||||||
DeliveryList.SelectedItem = null;
|
DeliveryList.SelectedItem = null;
|
||||||
await EnsureContextRenewed();
|
|
||||||
InitInputs();
|
InitInputs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -880,16 +877,10 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var attrList = await ctx.WineAttributes.OrderBy(a => a.Name).Cast<object>().ToListAsync();
|
var attrList = await ctx.FetchWineAttributes().Cast<object>().ToListAsync();
|
||||||
attrList.Insert(0, new NullItem(""));
|
attrList.Insert(0, new NullItem(""));
|
||||||
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.FetchMembers(includeNotActive: !ViewModel.IsReceipt, includeContactInfo: true).ToListAsync());
|
||||||
.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());
|
|
||||||
if (DeliveryList.SelectedItem is not Delivery d) {
|
if (DeliveryList.SelectedItem is not Delivery d) {
|
||||||
// switch away from creating mode
|
// switch away from creating mode
|
||||||
IsCreating = false;
|
IsCreating = false;
|
||||||
@@ -921,21 +912,11 @@ namespace Elwig.Windows {
|
|||||||
ViewModel.FilterTodayOnly = true;
|
ViewModel.FilterTodayOnly = true;
|
||||||
ViewModel.SearchQuery = "";
|
ViewModel.SearchQuery = "";
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var attrList = await ctx.WineAttributes.Where(a => a.IsActive).OrderBy(a => a.Name).Cast<object>().ToListAsync();
|
var attrList = await ctx.FetchWineAttributes(false).Cast<object>().ToListAsync();
|
||||||
attrList.Insert(0, new NullItem(""));
|
attrList.Insert(0, new NullItem(""));
|
||||||
ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First);
|
ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First);
|
||||||
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers
|
ControlUtils.RenewItemsSource(ModifiersInput, Modifiers.GetValueOrDefault(ViewModel.FilterSeason ?? 0, []).Where(m => m.IsActive).ToList());
|
||||||
.Where(m => m.Year == ViewModel.FilterSeason && m.IsActive)
|
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: !ViewModel.IsReceipt, includeContactInfo: true).ToListAsync());
|
||||||
.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());
|
|
||||||
IsCreating = true;
|
IsCreating = true;
|
||||||
DeliveryList.IsEnabled = false;
|
DeliveryList.IsEnabled = false;
|
||||||
DeliveryPartList.IsEnabled = false;
|
DeliveryPartList.IsEnabled = false;
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
xmlns:local="clr-namespace:Elwig.Windows"
|
xmlns:local="clr-namespace:Elwig.Windows"
|
||||||
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
||||||
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
||||||
Title="Anmeldungen - Elwig" Height="700" Width="980" MinWidth="600" MinHeight="400"
|
Title="Anmeldungen - Elwig" Height="700" Width="980" MinWidth="600" MinHeight="400">
|
||||||
Loaded="Window_Loaded">
|
|
||||||
<Window.DataContext>
|
<Window.DataContext>
|
||||||
<vm:DeliveryAncmtAdminViewModel/>
|
<vm:DeliveryAncmtAdminViewModel/>
|
||||||
</Window.DataContext>
|
</Window.DataContext>
|
||||||
|
|||||||
@@ -36,11 +36,7 @@ namespace Elwig.Windows {
|
|||||||
ControlUtils.InitializeDelayTimer(SearchInput, SearchInput_TextChanged);
|
ControlUtils.InitializeDelayTimer(SearchInput, SearchInput_TextChanged);
|
||||||
SearchInput.TextChanged -= SearchInput_TextChanged;
|
SearchInput.TextChanged -= SearchInput_TextChanged;
|
||||||
ViewModel.FilterSeason = Utils.CurrentLastSeason;
|
ViewModel.FilterSeason = Utils.CurrentLastSeason;
|
||||||
}
|
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs evt) {
|
|
||||||
ViewModel.FilterOnlyUpcoming = true;
|
ViewModel.FilterOnlyUpcoming = true;
|
||||||
LockInputs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Input_KeyUp(object sender, KeyEventArgs evt) {
|
private void Input_KeyUp(object sender, KeyEventArgs evt) {
|
||||||
@@ -85,7 +81,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)
|
||||||
@@ -103,36 +98,41 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task RefreshList(bool updateSort = false) {
|
private async Task RefreshList(bool updateSort = false) {
|
||||||
using var ctx = new AppDbContext();
|
var vm = ViewModel;
|
||||||
var (_, deliveryAncmtQuery, filter) = await ViewModel.GetFilters(ctx);
|
var cursor = Mouse.OverrideCursor != null;
|
||||||
var deliveryAncmts = await deliveryAncmtQuery
|
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
||||||
.Include(a => a.Member.BillingAddress)
|
var query = (vm.SearchQuery, vm.FilterSeason, vm.FilterOnlyUpcoming, vm.FilterOnlyUpcoming);
|
||||||
.Include(a => a.Schedule)
|
var (filter, deliveryAncmts, stat) = await Task.Run(async () => {
|
||||||
.Include(a => a.Variety)
|
using var ctx = new AppDbContext();
|
||||||
.AsSplitQuery()
|
var (_, deliveryAncmtQuery, filter) = await vm.GetFilters(ctx);
|
||||||
.ToListAsync();
|
var deliveryAncmts = await deliveryAncmtQuery.ToListAsync();
|
||||||
|
|
||||||
if (filter.Count > 0 && deliveryAncmts.Count > 0) {
|
if (filter.Count > 0 && deliveryAncmts.Count > 0) {
|
||||||
var dict = deliveryAncmts.AsParallel()
|
var dict = deliveryAncmts.AsParallel()
|
||||||
.ToDictionary(a => a, a => a.SearchScore(filter))
|
.ToDictionary(a => a, a => a.SearchScore(filter))
|
||||||
.OrderByDescending(a => a.Value)
|
.OrderByDescending(a => a.Value)
|
||||||
.ThenBy(a => a.Key.Schedule.DateString)
|
.ThenBy(a => a.Key.Schedule.DateString)
|
||||||
.ThenBy(a => a.Key.Member.Name)
|
.ThenBy(a => a.Key.Member.Name)
|
||||||
.ThenBy(a => a.Key.Member.GivenName)
|
.ThenBy(a => a.Key.Member.GivenName)
|
||||||
.ThenBy(a => a.Key.Member.MgNr);
|
.ThenBy(a => a.Key.Member.MgNr);
|
||||||
var threshold = dict.Select(a => a.Value).Max() * 3 / 4;
|
var threshold = dict.Max(a => a.Value) * 3 / 4;
|
||||||
deliveryAncmts = dict
|
deliveryAncmts = [.. dict
|
||||||
.Where(a => a.Value > threshold)
|
.Where(a => a.Value > threshold)
|
||||||
.Select(a => a.Key)
|
.Select(a => a.Key)];
|
||||||
.ToList();
|
} else {
|
||||||
} else {
|
deliveryAncmts = [.. deliveryAncmts
|
||||||
deliveryAncmts = deliveryAncmts
|
.OrderBy(a => a.Schedule.DateString)
|
||||||
.OrderBy(a => a.Schedule.DateString)
|
.ThenBy(a => a.Member.Name)
|
||||||
.ThenBy(a => a.Member.Name)
|
.ThenBy(a => a.Member.GivenName)
|
||||||
.ThenBy(a => a.Member.GivenName)
|
.ThenBy(a => a.Member.MgNr)];
|
||||||
.ThenBy(a => a.Member.MgNr)
|
}
|
||||||
.ToList();
|
|
||||||
}
|
var stat = await DeliveryAncmtService.GenerateToolTipData(deliveryAncmtQuery);
|
||||||
|
|
||||||
|
return (filter, deliveryAncmts, stat);
|
||||||
|
});
|
||||||
|
if (!cursor) Mouse.OverrideCursor = null;
|
||||||
|
if (query != (ViewModel.SearchQuery, ViewModel.FilterSeason, ViewModel.FilterOnlyUpcoming, ViewModel.FilterOnlyUpcoming)) return;
|
||||||
|
|
||||||
ControlUtils.RenewItemsSource(DeliveryAncmtList, deliveryAncmts,
|
ControlUtils.RenewItemsSource(DeliveryAncmtList, deliveryAncmts,
|
||||||
DeliveryAncmtList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
DeliveryAncmtList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
||||||
@@ -141,9 +141,9 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
ViewModel.StatusAncmts = $"{deliveryAncmts.Count:N0}";
|
ViewModel.StatusAncmts = $"{deliveryAncmts.Count:N0}";
|
||||||
if (filter.Count == 0) {
|
if (filter.Count == 0) {
|
||||||
var (text, grid) = await DeliveryAncmtService.GenerateToolTip(deliveryAncmtQuery);
|
var (text, data) = stat;
|
||||||
ViewModel.StatusWeight = text;
|
ViewModel.StatusWeight = text;
|
||||||
ViewModel.StatusWeightToolTip = grid;
|
ViewModel.StatusWeightToolTip = DeliveryAncmtService.GenerateToolTip(data);
|
||||||
} else {
|
} else {
|
||||||
ViewModel.StatusWeight = $"{deliveryAncmts.Sum(a => a.Weight):N0} kg";
|
ViewModel.StatusWeight = $"{deliveryAncmts.Sum(a => a.Weight):N0} kg";
|
||||||
ViewModel.StatusWeightToolTip = null;
|
ViewModel.StatusWeightToolTip = null;
|
||||||
@@ -177,15 +177,8 @@ namespace Elwig.Windows {
|
|||||||
protected override async Task OnRenewContext(AppDbContext ctx) {
|
protected override async Task OnRenewContext(AppDbContext ctx) {
|
||||||
await base.OnRenewContext(ctx);
|
await base.OnRenewContext(ctx);
|
||||||
|
|
||||||
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
|
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: !IsCreating).ToListAsync());
|
||||||
.Where(m => m.IsActive || !IsCreating)
|
ControlUtils.RenewItemsSource(WineVarietyInput, await ctx.FetchWineVarieties().ToListAsync());
|
||||||
.Include(m => m.PostalDest.AtPlz!.Ort)
|
|
||||||
.Include(m => m.DefaultWbKg!.AtKg)
|
|
||||||
.OrderBy(m => m.Name)
|
|
||||||
.ThenBy(m => m.GivenName)
|
|
||||||
.ThenBy(m => m.MgNr)
|
|
||||||
.ToListAsync());
|
|
||||||
ControlUtils.RenewItemsSource(WineVarietyInput, await ctx.WineVarieties.OrderBy(v => v.Name).ToListAsync());
|
|
||||||
|
|
||||||
await RefreshDeliveryScheduleList();
|
await RefreshDeliveryScheduleList();
|
||||||
await RefreshList();
|
await RefreshList();
|
||||||
@@ -196,6 +189,7 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async void DeliveryScheduleList_SelectionChanged(object sender, RoutedEventArgs evt) {
|
private async void DeliveryScheduleList_SelectionChanged(object sender, RoutedEventArgs evt) {
|
||||||
|
if (!HasContextLoaded) return;
|
||||||
await RefreshList();
|
await RefreshList();
|
||||||
if (DeliveryScheduleList.SelectedItem is DeliverySchedule s) {
|
if (DeliveryScheduleList.SelectedItem is DeliverySchedule s) {
|
||||||
Menu_DeliveryAncmtList_SaveSelected.IsEnabled = !IsEditing && !IsCreating;
|
Menu_DeliveryAncmtList_SaveSelected.IsEnabled = !IsEditing && !IsCreating;
|
||||||
@@ -217,11 +211,13 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async void OnlyUpcomingInput_Changed(object sender, RoutedEventArgs evt) {
|
private async void OnlyUpcomingInput_Changed(object sender, RoutedEventArgs evt) {
|
||||||
|
if (!HasContextLoaded) return;
|
||||||
await RefreshDeliveryScheduleList();
|
await RefreshDeliveryScheduleList();
|
||||||
await RefreshList(true);
|
await RefreshList(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void FromAllSchedulesInput_Changed(object sender, RoutedEventArgs evt) {
|
private async void FromAllSchedulesInput_Changed(object sender, RoutedEventArgs evt) {
|
||||||
|
if (!HasContextLoaded) return;
|
||||||
if (ViewModel.FilterFromAllSchedules) {
|
if (ViewModel.FilterFromAllSchedules) {
|
||||||
DeliveryScheduleList.SelectedItem = null;
|
DeliveryScheduleList.SelectedItem = null;
|
||||||
} else if (DeliveryScheduleList.SelectedItem == null) {
|
} else if (DeliveryScheduleList.SelectedItem == null) {
|
||||||
@@ -231,11 +227,12 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async void SearchInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
private async void SearchInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||||
|
if (!HasContextLoaded) return;
|
||||||
await RefreshList(true);
|
await RefreshList(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||||
if (ViewModel.FilterSeason == null) return;
|
if (!HasContextLoaded || ViewModel.FilterSeason == null) return;
|
||||||
ViewModel.FilterOnlyUpcoming = false;
|
ViewModel.FilterOnlyUpcoming = false;
|
||||||
await RefreshDeliveryScheduleList();
|
await RefreshDeliveryScheduleList();
|
||||||
await RefreshList();
|
await RefreshList();
|
||||||
@@ -274,14 +271,7 @@ namespace Elwig.Windows {
|
|||||||
ViewModel.SelectedDeliveryAncmt = null;
|
ViewModel.SelectedDeliveryAncmt = null;
|
||||||
|
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
|
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: !IsCreating).ToListAsync());
|
||||||
.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)
|
|
||||||
.ToListAsync());
|
|
||||||
|
|
||||||
HideNewEditDeleteButtons();
|
HideNewEditDeleteButtons();
|
||||||
ShowSaveResetCancelButtons();
|
ShowSaveResetCancelButtons();
|
||||||
@@ -403,14 +393,7 @@ namespace Elwig.Windows {
|
|||||||
DeliveryAncmtList.IsEnabled = true;
|
DeliveryAncmtList.IsEnabled = true;
|
||||||
|
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
|
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: !IsCreating).ToListAsync());
|
||||||
.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)
|
|
||||||
.ToListAsync());
|
|
||||||
|
|
||||||
HideSaveResetCancelButtons();
|
HideSaveResetCancelButtons();
|
||||||
ShowNewEditDeleteButtons();
|
ShowNewEditDeleteButtons();
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
xmlns:local="clr-namespace:Elwig.Windows"
|
xmlns:local="clr-namespace:Elwig.Windows"
|
||||||
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
||||||
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
||||||
Title="Leseplanung - Elwig" Height="600" Width="850" MinHeight="450" MinWidth="800"
|
Title="Leseplanung - Elwig" Height="600" Width="850" MinHeight="450" MinWidth="800">
|
||||||
Loaded="Window_Loaded">
|
|
||||||
<Window.DataContext>
|
<Window.DataContext>
|
||||||
<vm:DeliveryScheduleAdminViewModel/>
|
<vm:DeliveryScheduleAdminViewModel/>
|
||||||
</Window.DataContext>
|
</Window.DataContext>
|
||||||
|
|||||||
@@ -30,41 +30,43 @@ namespace Elwig.Windows {
|
|||||||
ControlUtils.InitializeDelayTimer(SearchInput, SearchInput_TextChanged);
|
ControlUtils.InitializeDelayTimer(SearchInput, SearchInput_TextChanged);
|
||||||
SearchInput.TextChanged -= SearchInput_TextChanged;
|
SearchInput.TextChanged -= SearchInput_TextChanged;
|
||||||
ViewModel.FilterSeason = Utils.CurrentLastSeason;
|
ViewModel.FilterSeason = Utils.CurrentLastSeason;
|
||||||
}
|
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs evt) {
|
|
||||||
ViewModel.FilterOnlyUpcoming = true;
|
ViewModel.FilterOnlyUpcoming = true;
|
||||||
LockInputs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RefreshList(bool updateSort = false) {
|
private async Task RefreshList(bool updateSort = false) {
|
||||||
using var ctx = new AppDbContext();
|
var vm = ViewModel;
|
||||||
var (_, deliveryScheduleQuery, filter) = await ViewModel.GetFilters(ctx);
|
var cursor = Mouse.OverrideCursor != null;
|
||||||
var deliverySchedules = await deliveryScheduleQuery
|
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
||||||
.Include(s => s.Varieties)
|
var query = (vm.SearchQuery, vm.FilterSeason, vm.FilterOnlyUpcoming);
|
||||||
.Include(s => s.Branch)
|
var deliverySchedules = await Task.Run(async () => {
|
||||||
.AsSplitQuery()
|
using var ctx = new AppDbContext();
|
||||||
.ToListAsync();
|
var (_, deliveryScheduleQuery, filter) = await vm.GetFilters(ctx);
|
||||||
|
var deliverySchedules = await deliveryScheduleQuery
|
||||||
|
.Include(s => s.Varieties)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
if (filter.Count > 0 && deliverySchedules.Count > 0) {
|
if (filter.Count > 0 && deliverySchedules.Count > 0) {
|
||||||
var dict = deliverySchedules.AsParallel()
|
var dict = deliverySchedules.AsParallel()
|
||||||
.ToDictionary(s => s, s => s.SearchScore(filter))
|
.ToDictionary(s => s, s => s.SearchScore(filter))
|
||||||
.OrderByDescending(a => a.Value)
|
.OrderByDescending(a => a.Value)
|
||||||
.ThenBy(a => a.Key.DateString)
|
.ThenBy(a => a.Key.DateString)
|
||||||
.ThenBy(a => a.Key.Branch.Name)
|
.ThenBy(a => a.Key.Branch.Name)
|
||||||
.ThenBy(a => a.Key.Description);
|
.ThenBy(a => a.Key.Description);
|
||||||
var threshold = dict.Select(a => a.Value).Max() * 3 / 4;
|
var threshold = dict.Max(a => a.Value) * 3 / 4;
|
||||||
deliverySchedules = dict
|
deliverySchedules = [.. dict
|
||||||
.Where(a => a.Value > threshold)
|
.Where(a => a.Value > threshold)
|
||||||
.Select(a => a.Key)
|
.Select(a => a.Key)];
|
||||||
.ToList();
|
} else {
|
||||||
} else {
|
deliverySchedules = [.. deliverySchedules
|
||||||
deliverySchedules = deliverySchedules
|
.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)
|
}
|
||||||
.ToList();
|
|
||||||
}
|
return deliverySchedules;
|
||||||
|
});
|
||||||
|
if (!cursor) Mouse.OverrideCursor = null;
|
||||||
|
if (query != ((ViewModel.SearchQuery, ViewModel.FilterSeason, ViewModel.FilterOnlyUpcoming))) return;
|
||||||
|
|
||||||
ControlUtils.RenewItemsSource(DeliveryScheduleList, deliverySchedules,
|
ControlUtils.RenewItemsSource(DeliveryScheduleList, deliverySchedules,
|
||||||
DeliveryScheduleList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
DeliveryScheduleList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
||||||
@@ -99,14 +101,14 @@ namespace Elwig.Windows {
|
|||||||
protected override async Task OnRenewContext(AppDbContext ctx) {
|
protected override async Task OnRenewContext(AppDbContext ctx) {
|
||||||
await base.OnRenewContext(ctx);
|
await base.OnRenewContext(ctx);
|
||||||
|
|
||||||
ControlUtils.RenewItemsSource(BranchInput, await ctx.Branches.OrderBy(b => b.Name).ToListAsync());
|
ControlUtils.RenewItemsSource(BranchInput, await ctx.FetchBranches().ToListAsync());
|
||||||
var varieties = await ctx.WineVarieties.OrderBy(v => v.Name).ToListAsync();
|
var varieties = await ctx.FetchWineVarieties().ToListAsync();
|
||||||
ControlUtils.RenewItemsSource(MainWineVarietiesInput, varieties);
|
ControlUtils.RenewItemsSource(MainWineVarietiesInput, varieties);
|
||||||
ControlUtils.RenewItemsSource(OtherWineVarietiesInput, varieties);
|
ControlUtils.RenewItemsSource(OtherWineVarietiesInput, varieties);
|
||||||
var attrList = await ctx.WineAttributes.OrderBy(a => a.Name).Cast<object>().ToListAsync();
|
var attrList = await ctx.FetchWineAttributes().Cast<object>().ToListAsync();
|
||||||
attrList.Insert(0, new NullItem("- Keine Angabe -"));
|
attrList.Insert(0, new NullItem("- Keine Angabe -"));
|
||||||
ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First);
|
ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First);
|
||||||
var cultList = await ctx.WineCultivations.OrderBy(a => a.Name).Cast<object>().ToListAsync();
|
var cultList = await ctx.FetchWineCultivations().Cast<object>().ToListAsync();
|
||||||
cultList.Insert(0, new NullItem("- Kein Angabe -"));
|
cultList.Insert(0, new NullItem("- Kein Angabe -"));
|
||||||
ControlUtils.RenewItemsSource(CultivationInput, cultList, null, ControlUtils.RenewSourceDefault.First);
|
ControlUtils.RenewItemsSource(CultivationInput, cultList, null, ControlUtils.RenewSourceDefault.First);
|
||||||
|
|
||||||
@@ -118,15 +120,17 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async void OnlyUpcomingInput_Changed(object sender, RoutedEventArgs evt) {
|
private async void OnlyUpcomingInput_Changed(object sender, RoutedEventArgs evt) {
|
||||||
|
if (!HasContextLoaded) return;
|
||||||
await RefreshList();
|
await RefreshList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SearchInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
private async void SearchInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||||
|
if (!HasContextLoaded) return;
|
||||||
await RefreshList(true);
|
await RefreshList(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||||
if (ViewModel.FilterSeason == null) return;
|
if (!HasContextLoaded || ViewModel.FilterSeason == null) return;
|
||||||
ViewModel.FilterOnlyUpcoming = false;
|
ViewModel.FilterOnlyUpcoming = false;
|
||||||
await RefreshList();
|
await RefreshList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ namespace Elwig.Windows {
|
|||||||
public MailWindow(int? year = null) {
|
public MailWindow(int? year = null) {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
Year = year ?? ctx.Seasons.OrderBy(s => s.Year).LastOrDefault()?.Year ?? Utils.Today.Year;
|
Year = year ?? ctx.Seasons.OrderByDescending(s => s.Year).FirstOrDefault()?.Year ?? Utils.Today.Year;
|
||||||
Title = $"Rundschreiben - Lese {Year} - Elwig";
|
Title = $"Rundschreiben - Lese {Year} - Elwig";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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.Include(s => s.PaymentVariants).SingleAsync(s => s.Year == Year);
|
var season = await ctx.Seasons.Include(s => s.PaymentVariants).Where(s => s.Year == Year).SingleOrDefaultAsync();
|
||||||
var l = new List<string> {
|
var l = new List<string> {
|
||||||
MemberDataSheet.Name
|
MemberDataSheet.Name
|
||||||
};
|
};
|
||||||
@@ -165,10 +165,7 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
AvaiableDocumentsList.ItemsSource = l;
|
AvaiableDocumentsList.ItemsSource = l;
|
||||||
|
|
||||||
ControlUtils.RenewItemsSource(MemberBranchInput, await ctx.Branches
|
ControlUtils.RenewItemsSource(MemberBranchInput, await ctx.FetchBranches(includeWithoutMembers: false).ToListAsync(), MemberInput_SelectionChanged);
|
||||||
.Where(b => b.Members.Count != 0)
|
|
||||||
.OrderBy(b => b.Name)
|
|
||||||
.ToListAsync(), MemberInput_SelectionChanged);
|
|
||||||
if (MemberBranchInput.SelectedItems.Count == 0) {
|
if (MemberBranchInput.SelectedItems.Count == 0) {
|
||||||
MemberBranchInput.SelectionChanged -= MemberInput_SelectionChanged;
|
MemberBranchInput.SelectionChanged -= MemberInput_SelectionChanged;
|
||||||
MemberBranchInput.SelectAll();
|
MemberBranchInput.SelectAll();
|
||||||
@@ -207,13 +204,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;
|
||||||
@@ -373,7 +365,7 @@ namespace Elwig.Windows {
|
|||||||
RecipientsDeliveryMembersInput.IsChecked = true;
|
RecipientsDeliveryMembersInput.IsChecked = true;
|
||||||
} else if (idx >= 2) {
|
} else if (idx >= 2) {
|
||||||
var name = s.Split(" – ")[^1];
|
var name = s.Split(" – ")[^1];
|
||||||
var pv = await ctx.PaymentVariants.SingleAsync(v => v.Year == Year && v.Name == name)!;
|
var pv = await ctx.PaymentVariants.Where(v => v.Year == Year && v.Name == name).SingleAsync();
|
||||||
SelectedDocs.Add(new(DocType.CreditNote, s, (pv.Year, pv.AvNr)));
|
SelectedDocs.Add(new(DocType.CreditNote, s, (pv.Year, pv.AvNr)));
|
||||||
RecipientsCreditMembersInput.IsChecked = true;
|
RecipientsCreditMembersInput.IsChecked = true;
|
||||||
}
|
}
|
||||||
@@ -492,13 +484,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();
|
||||||
@@ -703,7 +690,7 @@ namespace Elwig.Windows {
|
|||||||
PrintButton.IsEnabled = PrintDocument != null && !hasPreviewDocs;
|
PrintButton.IsEnabled = PrintDocument != null && !hasPreviewDocs;
|
||||||
EmailButton.IsEnabled = EmailDocuments != null && !hasPreviewDocs && App.Config.Smtp != null;
|
EmailButton.IsEnabled = EmailDocuments != null && !hasPreviewDocs && App.Config.Smtp != null;
|
||||||
} catch (Exception exc) {
|
} catch (Exception exc) {
|
||||||
MessageBox.Show(exc.ToString(), "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
} finally {
|
} finally {
|
||||||
UnlockInputs();
|
UnlockInputs();
|
||||||
GenerateButton.IsEnabled = true;
|
GenerateButton.IsEnabled = true;
|
||||||
@@ -725,7 +712,7 @@ namespace Elwig.Windows {
|
|||||||
foreach (var doc in docs) {
|
foreach (var doc in docs) {
|
||||||
if (doc.Type == DocType.DeliveryConfirmation) {
|
if (doc.Type == DocType.DeliveryConfirmation) {
|
||||||
var year = (int)doc.Details!;
|
var year = (int)doc.Details!;
|
||||||
var b = new Billing(year);
|
var b = await Billing.Create(year);
|
||||||
await b.FinishSeason();
|
await b.FinishSeason();
|
||||||
await b.CalculateBuckets();
|
await b.CalculateBuckets();
|
||||||
App.HintContextChange();
|
App.HintContextChange();
|
||||||
@@ -755,6 +742,9 @@ namespace Elwig.Windows {
|
|||||||
Member = m,
|
Member = m,
|
||||||
Docs = docs.SelectMany<SelectedDoc, GeneratedDoc>(doc => {
|
Docs = docs.SelectMany<SelectedDoc, GeneratedDoc>(doc => {
|
||||||
try {
|
try {
|
||||||
|
App.MainDispatcher.Invoke(() => {
|
||||||
|
ProgressBar.Value = offset + 100.0 * i / 2 / totalNum;
|
||||||
|
});
|
||||||
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) {
|
||||||
@@ -769,14 +759,14 @@ namespace Elwig.Windows {
|
|||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return [new GeneratedDoc(new DeliveryConfirmation(year, m, data) { Date = postalDate })];
|
return [new GeneratedDoc(new DeliveryConfirmation(year, m, postalDate, 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(data.Item2[m.MgNr], data.Item3, data.Item1[m.MgNr]) { Date = postalDate })];
|
return [new GeneratedDoc(new CreditNote(data.Item2[m.MgNr], postalDate, data.Item3, data.Item1[m.MgNr]) { Date = postalDate })];
|
||||||
} catch (Exception) {
|
} catch (Exception) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -1007,7 +997,7 @@ namespace Elwig.Windows {
|
|||||||
return;
|
return;
|
||||||
var name = s.Split(" – ")[^1];
|
var name = s.Split(" – ")[^1];
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var pv = ctx.PaymentVariants.Single(v => v.Year == Year && v.Name == name)!;
|
var pv = ctx.PaymentVariants.Where(v => v.Year == Year && v.Name == name).Single();
|
||||||
SelectedDocs.Add(new(DocType.CreditNote, s, (pv.Year, pv.AvNr)));
|
SelectedDocs.Add(new(DocType.CreditNote, s, (pv.Year, pv.AvNr)));
|
||||||
SelectedDocumentsList.SelectedIndex = SelectedDocs.Count - 1;
|
SelectedDocumentsList.SelectedIndex = SelectedDocs.Count - 1;
|
||||||
RecipientsCreditMembersInput.IsChecked = true;
|
RecipientsCreditMembersInput.IsChecked = true;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
xmlns:local="clr-namespace:Elwig.Windows"
|
xmlns:local="clr-namespace:Elwig.Windows"
|
||||||
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
||||||
Title="Elwig" Height="390" Width="520" ResizeMode="CanMinimize"
|
Title="Elwig" Height="390" Width="520" ResizeMode="CanMinimize"
|
||||||
Loaded="Window_Loaded" Closing="Window_Closing">
|
Closing="Window_Closing">
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
<Style TargetType="Button">
|
<Style TargetType="Button">
|
||||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||||
|
|||||||
@@ -37,11 +37,11 @@ namespace Elwig.Windows {
|
|||||||
SyncButton.Visibility = App.Config.SyncUrl != null ? Visibility.Visible : Visibility.Hidden;
|
SyncButton.Visibility = App.Config.SyncUrl != null ? Visibility.Visible : Visibility.Hidden;
|
||||||
Menu_Database_Upload.IsEnabled = App.Config.SyncUrl != null;
|
Menu_Database_Upload.IsEnabled = App.Config.SyncUrl != null;
|
||||||
Menu_Database_Download.IsEnabled = App.Config.SyncUrl != null;
|
Menu_Database_Download.IsEnabled = App.Config.SyncUrl != null;
|
||||||
|
SeasonInput.Value = Utils.CurrentLastSeason;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs evt) {
|
protected override async Task OnInit(AppDbContext ctx) {
|
||||||
SeasonInput.Value = Utils.CurrentLastSeason;
|
await base.OnInit(ctx);
|
||||||
|
|
||||||
if (Utils.HasInternetConnectivity()) {
|
if (Utils.HasInternetConnectivity()) {
|
||||||
CheckSync(200);
|
CheckSync(200);
|
||||||
}
|
}
|
||||||
@@ -405,7 +405,7 @@ namespace Elwig.Windows {
|
|||||||
private async void SeasonInput_TextChanged(object? sender, TextChangedEventArgs? evt) {
|
private async void SeasonInput_TextChanged(object? sender, TextChangedEventArgs? evt) {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var year = SeasonInput.Value;
|
var year = SeasonInput.Value;
|
||||||
var s0 = await ctx.Seasons.FindAsync(year);
|
var s0 = await ctx.FetchSeasons(year).SingleOrDefaultAsync();
|
||||||
var valid = (s0 != null);
|
var valid = (s0 != null);
|
||||||
DeliveryConfirmationButton.IsEnabled = valid;
|
DeliveryConfirmationButton.IsEnabled = valid;
|
||||||
PaymentButton.IsEnabled = valid;
|
PaymentButton.IsEnabled = valid;
|
||||||
@@ -469,7 +469,7 @@ namespace Elwig.Windows {
|
|||||||
Mouse.OverrideCursor = Cursors.Wait;
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
try {
|
try {
|
||||||
var b = new Billing(year);
|
var b = await Billing.Create(year);
|
||||||
await b.FinishSeason();
|
await b.FinishSeason();
|
||||||
await b.CalculateBuckets();
|
await b.CalculateBuckets();
|
||||||
App.HintContextChange();
|
App.HintContextChange();
|
||||||
@@ -502,7 +502,7 @@ namespace Elwig.Windows {
|
|||||||
Mouse.OverrideCursor = Cursors.Wait;
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
try {
|
try {
|
||||||
var b = new Billing(year);
|
var b = await Billing.Create(year);
|
||||||
await b.FinishSeason();
|
await b.FinishSeason();
|
||||||
await b.CalculateBuckets();
|
await b.CalculateBuckets();
|
||||||
App.HintContextChange();
|
App.HintContextChange();
|
||||||
@@ -511,7 +511,7 @@ namespace Elwig.Windows {
|
|||||||
using var ods = new OdsFile(d.FileName);
|
using var ods = new OdsFile(d.FileName);
|
||||||
var tblTotal = await WeightBreakdownData.ForSeason(ctx.WeightBreakDownRows, year);
|
var tblTotal = await WeightBreakdownData.ForSeason(ctx.WeightBreakDownRows, year);
|
||||||
await ods.AddTable(tblTotal);
|
await ods.AddTable(tblTotal);
|
||||||
foreach (var branch in await ctx.Branches.OrderBy(b => b.Name).ToListAsync()) {
|
foreach (var branch in await ctx.FetchBranches().ToListAsync()) {
|
||||||
var tbl = await WeightBreakdownData.ForSeason(ctx.WeightBreakDownRows, year, branch);
|
var tbl = await WeightBreakdownData.ForSeason(ctx.WeightBreakDownRows, year, branch);
|
||||||
await ods.AddTable(tbl);
|
await ods.AddTable(tbl);
|
||||||
}
|
}
|
||||||
@@ -537,7 +537,7 @@ namespace Elwig.Windows {
|
|||||||
Mouse.OverrideCursor = Cursors.Wait;
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
try {
|
try {
|
||||||
var b = new Billing(year);
|
var b = await Billing.Create(year);
|
||||||
await b.FinishSeason();
|
await b.FinishSeason();
|
||||||
await b.CalculateBuckets();
|
await b.CalculateBuckets();
|
||||||
App.HintContextChange();
|
App.HintContextChange();
|
||||||
@@ -568,7 +568,7 @@ namespace Elwig.Windows {
|
|||||||
Mouse.OverrideCursor = Cursors.Wait;
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
try {
|
try {
|
||||||
var b = new Billing(year);
|
var b = await Billing.Create(year);
|
||||||
await b.FinishSeason();
|
await b.FinishSeason();
|
||||||
await b.CalculateBuckets();
|
await b.CalculateBuckets();
|
||||||
App.HintContextChange();
|
App.HintContextChange();
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:Elwig.Windows"
|
xmlns:local="clr-namespace:Elwig.Windows"
|
||||||
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
||||||
Title="Mitglieder - Elwig" Height="700" Width="1250" MinHeight="650" MinWidth="1150"
|
Title="Mitglieder - Elwig" Height="700" Width="1250" MinHeight="650" MinWidth="1150">
|
||||||
Loaded="Window_Loaded">
|
|
||||||
<Window.DataContext>
|
<Window.DataContext>
|
||||||
<vm:MemberAdminViewModel/>
|
<vm:MemberAdminViewModel/>
|
||||||
</Window.DataContext>
|
</Window.DataContext>
|
||||||
|
|||||||
@@ -82,12 +82,9 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
Menu_Export_UploadFilters.IsEnabled = App.Config.SyncUrl != null;
|
Menu_Export_UploadFilters.IsEnabled = App.Config.SyncUrl != null;
|
||||||
Menu_Export_UploadAll.IsEnabled = App.Config.SyncUrl != null;
|
Menu_Export_UploadAll.IsEnabled = App.Config.SyncUrl != null;
|
||||||
}
|
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs evt) {
|
|
||||||
ViewModel.ShowOnlyActiveMembers = true;
|
ViewModel.ShowOnlyActiveMembers = true;
|
||||||
|
|
||||||
UpdateContactInfoVisibility();
|
UpdateContactInfoVisibility();
|
||||||
LockInputs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FocusMember(int mgnr) {
|
public void FocusMember(int mgnr) {
|
||||||
@@ -113,46 +110,52 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task RefreshList(bool updateSort = false) {
|
private async Task RefreshList(bool updateSort = false) {
|
||||||
using var ctx = new AppDbContext();
|
var vm = ViewModel;
|
||||||
var (_, memberQuery, filter) = await ViewModel.GetFilters(ctx);
|
var cursor = Mouse.OverrideCursor != null;
|
||||||
var members = await memberQuery
|
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
||||||
.Include(m => m.Branch)
|
var query = (vm.SearchQuery, vm.ShowOnlyActiveMembers);
|
||||||
.Include(m => m.DefaultWbKg!.AtKg)
|
var (members, totalMemberCount, totalBusinessShares) = await Task.Run(async () => {
|
||||||
.Include(m => m.EmailAddresses)
|
using var ctx = new AppDbContext();
|
||||||
.Include(m => m.TelephoneNumbers)
|
var (_, memberQuery, filter) = await vm.GetFilters(ctx);
|
||||||
.Include(m => m.PostalDest.AtPlz!.Ort)
|
var members = await memberQuery
|
||||||
.Include(m => m.PostalDest.AtPlz!.Country)
|
.Include(m => m.EmailAddresses)
|
||||||
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
|
.Include(m => m.TelephoneNumbers)
|
||||||
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Country)
|
.AsSplitQuery()
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
if (filter.Count > 0 && members.Count > 0) {
|
if (filter.Count > 0 && members.Count > 0) {
|
||||||
var dict = members.AsParallel()
|
var dict = members.AsParallel()
|
||||||
.ToDictionary(m => m, m => m.SearchScore(filter))
|
.ToDictionary(m => m, m => m.SearchScore(filter))
|
||||||
.OrderByDescending(a => a.Value)
|
.OrderByDescending(a => a.Value)
|
||||||
.ThenBy(a => a.Key.Name)
|
.ThenBy(a => a.Key.Name)
|
||||||
.ThenBy(a => a.Key.GivenName)
|
.ThenBy(a => a.Key.GivenName)
|
||||||
.ThenBy(a => a.Key.MgNr);
|
.ThenBy(a => a.Key.MgNr);
|
||||||
var threshold = dict.Select(a => a.Value).Max() * 3 / 4;
|
var threshold = dict.Select(a => a.Value).Max() * 3 / 4;
|
||||||
members = dict
|
members = [.. dict
|
||||||
.Where(a => a.Value > threshold)
|
.Where(a => a.Value > threshold)
|
||||||
.Select(a => a.Key)
|
.Select(a => a.Key)];
|
||||||
.ToList();
|
} else {
|
||||||
} else {
|
members = [.. members
|
||||||
members = members
|
.OrderBy(m => m.Name)
|
||||||
.OrderBy(m => m.Name)
|
.ThenBy(m => m.GivenName)
|
||||||
.ThenBy(m => m.GivenName)
|
.ThenBy(m => m.MgNr)];
|
||||||
.ThenBy(m => m.MgNr)
|
}
|
||||||
.ToList();
|
|
||||||
}
|
var totalMemberCount = await ctx.Members.CountAsync();
|
||||||
|
var totalBusinessShares = await ctx.Members.SumAsync(m => m.BusinessShares);
|
||||||
|
|
||||||
|
return (members, totalMemberCount, totalBusinessShares);
|
||||||
|
});
|
||||||
|
if (!cursor) Mouse.OverrideCursor = null;
|
||||||
|
if (query != (ViewModel.SearchQuery, ViewModel.ShowOnlyActiveMembers)) return;
|
||||||
|
|
||||||
ControlUtils.RenewItemsSource(MemberList, members,
|
ControlUtils.RenewItemsSource(MemberList, members,
|
||||||
MemberList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
MemberList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
||||||
if (updateSort && MemberList.SelectedItem != null)
|
if (updateSort && MemberList.SelectedItem != null)
|
||||||
MemberList.ScrollIntoView(MemberList.SelectedItem);
|
MemberList.ScrollIntoView(MemberList.SelectedItem);
|
||||||
|
|
||||||
ViewModel.StatusMembers = $"{members.Count:N0} ({await ctx.Members.CountAsync():N0})";
|
ViewModel.StatusMembers = $"{members.Count:N0} ({totalMemberCount:N0})";
|
||||||
ViewModel.StatusBusinessShares = $"{members.Sum(m => m.BusinessShares):N0} ({await ctx.Members.SumAsync(m => m.BusinessShares):N0})";
|
ViewModel.StatusBusinessShares = $"{members.Sum(m => m.BusinessShares):N0} ({totalBusinessShares:N0})";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefreshInputs(bool validate = false) {
|
private void RefreshInputs(bool validate = false) {
|
||||||
@@ -184,7 +187,7 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
protected override async Task OnRenewContext(AppDbContext ctx) {
|
protected override async Task OnRenewContext(AppDbContext ctx) {
|
||||||
await base.OnRenewContext(ctx);
|
await base.OnRenewContext(ctx);
|
||||||
ControlUtils.RenewItemsSource(BranchInput, await ctx.Branches.OrderBy(b => b.Name).ToListAsync());
|
ControlUtils.RenewItemsSource(BranchInput, await ctx.FetchBranches().ToListAsync());
|
||||||
ControlUtils.RenewItemsSource(DefaultKgInput, await ctx.WbKgs.Select(k => k.AtKg).OrderBy(k => k.Name).ToListAsync());
|
ControlUtils.RenewItemsSource(DefaultKgInput, await ctx.WbKgs.Select(k => k.AtKg).OrderBy(k => k.Name).ToListAsync());
|
||||||
|
|
||||||
var font = new System.Windows.Media.FontFamily("Segoe MDL2 Assets");
|
var font = new System.Windows.Media.FontFamily("Segoe MDL2 Assets");
|
||||||
@@ -328,7 +331,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;
|
if (!HasContextLoaded) return;
|
||||||
await RefreshList();
|
await RefreshList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,10 +388,9 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
int areaComs = 0, deliveries = 0, credits = 0;
|
int areaComs = 0, deliveries = 0, credits = 0;
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
var l = (await ctx.Members.FindAsync(m.MgNr))!;
|
areaComs = await ctx.AreaCommitments.Where(c => c.MgNr == m.MgNr).CountAsync();
|
||||||
areaComs = l.AreaCommitments.Count;
|
deliveries = await ctx.Deliveries.Where(d => d.MgNr == m.MgNr).CountAsync();
|
||||||
deliveries = l.Deliveries.Count;
|
credits = await ctx.Credits.Where(c => c.MgNr == m.MgNr).CountAsync();
|
||||||
credits = l.Credits.Count;
|
|
||||||
}
|
}
|
||||||
var d = new DeleteMemberDialog(m.MgNr, m.AdministrativeName, areaComs, deliveries, credits);
|
var d = new DeleteMemberDialog(m.MgNr, m.AdministrativeName, areaComs, deliveries, credits);
|
||||||
if (d.ShowDialog() == true) {
|
if (d.ShowDialog() == true) {
|
||||||
@@ -485,6 +487,7 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) {
|
private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||||
|
if (!HasContextLoaded) return;
|
||||||
await RefreshList(true);
|
await RefreshList(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -790,7 +793,7 @@ namespace Elwig.Windows {
|
|||||||
if (areaComs.Count == 0)
|
if (areaComs.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var oldMember = (await ctx.Members.FindAsync(mgnr))!;
|
var oldMember = await ctx.FetchMembers(mgnr).SingleAsync();
|
||||||
var newName = $"{ViewModel.Name?.Replace('ß', 'ẞ').ToUpper()} " +
|
var newName = $"{ViewModel.Name?.Replace('ß', 'ẞ').ToUpper()} " +
|
||||||
$"{ViewModel.Prefix}{(!string.IsNullOrEmpty(ViewModel.Prefix) ? " " : "")}" +
|
$"{ViewModel.Prefix}{(!string.IsNullOrEmpty(ViewModel.Prefix) ? " " : "")}" +
|
||||||
$"{ViewModel.GivenName}{(!string.IsNullOrEmpty(ViewModel.GivenName) ? " " : "")}" +
|
$"{ViewModel.GivenName}{(!string.IsNullOrEmpty(ViewModel.GivenName) ? " " : "")}" +
|
||||||
|
|||||||
@@ -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();
|
||||||
@@ -214,7 +212,7 @@ namespace Elwig.Windows {
|
|||||||
App.HintContextChange();
|
App.HintContextChange();
|
||||||
ControlUtils.SelectItemWithPk(WbKgs, k.KgNr);
|
ControlUtils.SelectItemWithPk(WbKgs, k.KgNr);
|
||||||
} catch (Exception exc) {
|
} catch (Exception exc) {
|
||||||
await HintContextChange();
|
await ForceContextReload();
|
||||||
var str = "Der Eintrag konnte nicht aus der Datenbank gelöscht werden!\n\n" + exc.Message;
|
var str = "Der Eintrag konnte nicht aus der Datenbank gelöscht werden!\n\n" + exc.Message;
|
||||||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||||||
MessageBox.Show(str, "Katastralgemeinde deaktivieren", MessageBoxButton.OK, MessageBoxImage.Error);
|
MessageBox.Show(str, "Katastralgemeinde deaktivieren", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task OnRenewContext(AppDbContext ctx) {
|
protected override async Task OnRenewContext(AppDbContext ctx) {
|
||||||
var members = await ctx.Members
|
var members = await ctx.FetchMembers(includeNotActive: true)
|
||||||
.Select(m => new {
|
.Select(m => new {
|
||||||
m.MgNr,
|
m.MgNr,
|
||||||
m.Name,
|
m.Name,
|
||||||
@@ -48,11 +48,8 @@ namespace Elwig.Windows {
|
|||||||
m.BusinessShares,
|
m.BusinessShares,
|
||||||
m.IsActive,
|
m.IsActive,
|
||||||
})
|
})
|
||||||
.OrderBy(m => m.Name)
|
|
||||||
.ThenBy(m => m.GivenName)
|
|
||||||
.ThenBy(m => m.MgNr)
|
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
var season = (await ctx.Seasons.FindAsync(Year))!;
|
var season = await ctx.FetchSeasons(Year).SingleAsync();
|
||||||
var contracts = await ctx.AreaCommitmentTypes.ToDictionaryAsync(t => t.VtrgId, t => t);
|
var contracts = await ctx.AreaCommitmentTypes.ToDictionaryAsync(t => t.VtrgId, t => t);
|
||||||
|
|
||||||
var tbl1 = await OverUnderDeliveryData.ForSeason(ctx.OverUnderDeliveryRows, Year);
|
var tbl1 = await OverUnderDeliveryData.ForSeason(ctx.OverUnderDeliveryRows, Year);
|
||||||
@@ -145,11 +142,7 @@ namespace Elwig.Windows {
|
|||||||
TotalModifiers.Text = $"{list.Count(r => r.Total != 0)} Mg. / {list.Sum(r => r.Total):N2} {sym}";
|
TotalModifiers.Text = $"{list.Count(r => r.Total != 0)} Mg. / {list.Sum(r => r.Total):N2} {sym}";
|
||||||
NonDeliveries.Text = $"{list.Count(r => r.Weight == 0):N0}";
|
NonDeliveries.Text = $"{list.Count(r => r.Weight == 0):N0}";
|
||||||
|
|
||||||
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
|
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: true).ToListAsync());
|
||||||
.OrderBy(m => m.Name)
|
|
||||||
.ThenBy(m => m.GivenName)
|
|
||||||
.ThenBy(m => m.MgNr)
|
|
||||||
.ToListAsync());
|
|
||||||
CustomAmountInput.Unit = sym;
|
CustomAmountInput.Unit = sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +163,7 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
await App.Client.UpdateValues();
|
await App.Client.UpdateValues();
|
||||||
var b = new Billing(Year);
|
var b = await Billing.Create(Year);
|
||||||
await b.AutoAdjustBusinessShares(new DateOnly(Year, 11, 30), kg ?? default, bs ?? default, kgPerBs ?? default, percent / 100.0 ?? default, minBs ?? default);
|
await b.AutoAdjustBusinessShares(new DateOnly(Year, 11, 30), kg ?? default, bs ?? default, kgPerBs ?? default, percent / 100.0 ?? default, minBs ?? default);
|
||||||
});
|
});
|
||||||
App.HintContextChange();
|
App.HintContextChange();
|
||||||
@@ -186,7 +179,7 @@ namespace Elwig.Windows {
|
|||||||
Mouse.OverrideCursor = Cursors.Wait;
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
try {
|
try {
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
var b = new Billing(Year);
|
var b = await Billing.Create(Year);
|
||||||
await b.UnAdjustBusinessShares();
|
await b.UnAdjustBusinessShares();
|
||||||
});
|
});
|
||||||
App.HintContextChange();
|
App.HintContextChange();
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -256,13 +255,13 @@ namespace Elwig.Windows {
|
|||||||
await ViewModel.UpdatePaymentVariant(v.Year, v.AvNr);
|
await ViewModel.UpdatePaymentVariant(v.Year, v.AvNr);
|
||||||
App.HintContextChange();
|
App.HintContextChange();
|
||||||
} catch (Exception exc) {
|
} catch (Exception exc) {
|
||||||
await HintContextChange();
|
await ForceContextReload();
|
||||||
var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message;
|
var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message;
|
||||||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||||||
MessageBox.Show(str, "Auszahlungsvariante aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
|
MessageBox.Show(str, "Auszahlungsvariante aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
}
|
}
|
||||||
Mouse.OverrideCursor = null;
|
Mouse.OverrideCursor = null;
|
||||||
await HintContextChange();
|
await EnsureContextRenewed();
|
||||||
CommentInput_TextChanged(null, null);
|
CommentInput_TextChanged(null, null);
|
||||||
DateInput_TextChanged(null, null);
|
DateInput_TextChanged(null, null);
|
||||||
TransferDateInput_TextChanged(null, null);
|
TransferDateInput_TextChanged(null, null);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="WixToolset.Sdk/6">
|
<Project Sdk="WixToolset.Sdk/7">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<HarvestFileSuppressUniqueIds>false</HarvestFileSuppressUniqueIds>
|
<HarvestFileSuppressUniqueIds>false</HarvestFileSuppressUniqueIds>
|
||||||
<HarvestFileGenerateGuidsNow>true</HarvestFileGenerateGuidsNow>
|
<HarvestFileGenerateGuidsNow>true</HarvestFileGenerateGuidsNow>
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
<BuildProjectReferences>False</BuildProjectReferences>
|
<BuildProjectReferences>False</BuildProjectReferences>
|
||||||
<OutputName>Elwig</OutputName>
|
<OutputName>Elwig</OutputName>
|
||||||
<Cultures>de-AT</Cultures>
|
<Cultures>de-AT</Cultures>
|
||||||
|
<AcceptEula>wix7</AcceptEula>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<UsingTask TaskName="GetFileVersion" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
<UsingTask TaskName="GetFileVersion" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
||||||
<ParameterGroup>
|
<ParameterGroup>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ About
|
|||||||
**Product:** Elwig
|
**Product:** Elwig
|
||||||
**Description:** Electronic Management for Vintners' Cooperatives
|
**Description:** Electronic Management for Vintners' Cooperatives
|
||||||
**Type:** ERP system
|
**Type:** ERP system
|
||||||
**Version:** 1.0.4.1 ([Changelog](./CHANGELOG.md))
|
**Version:** 1.0.5.2 ([Changelog](./CHANGELOG.md))
|
||||||
**License:** [GNU General Public License 3.0 (GPLv3)](./LICENSE)
|
**License:** [GNU General Public License 3.0 (GPLv3)](./LICENSE)
|
||||||
**Website:** https://elwig.at/
|
**Website:** https://elwig.at/
|
||||||
**Source code:** https://git.necronda.net/winzer/elwig
|
**Source code:** https://git.necronda.net/winzer/elwig
|
||||||
@@ -33,7 +33,7 @@ Packaging: [WiX Toolset](https://www.firegiant.com/wixtoolset/)
|
|||||||
**Produkt:** Elwig
|
**Produkt:** Elwig
|
||||||
**Beschreibung:** Elektronische Winzergenossenschaftsverwaltung
|
**Beschreibung:** Elektronische Winzergenossenschaftsverwaltung
|
||||||
**Typ:** Warenwirtschaftssystem (ERP-System)
|
**Typ:** Warenwirtschaftssystem (ERP-System)
|
||||||
**Version:** 1.0.4.1 ([Änderungsprotokoll](./CHANGELOG.md))
|
**Version:** 1.0.5.2 ([Änderungsprotokoll](./CHANGELOG.md))
|
||||||
**Lizenz:** [GNU General Public License 3.0 (GPLv3)](./LICENSE)
|
**Lizenz:** [GNU General Public License 3.0 (GPLv3)](./LICENSE)
|
||||||
**Website:** https://elwig.at/
|
**Website:** https://elwig.at/
|
||||||
**Quellcode:** https://git.necronda.net/winzer/elwig
|
**Quellcode:** https://git.necronda.net/winzer/elwig
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<Project Sdk="WixToolset.Sdk/6">
|
<Project Sdk="WixToolset.Sdk/7">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Bundle</OutputType>
|
<OutputType>Bundle</OutputType>
|
||||||
<OutputName>Elwig</OutputName>
|
<OutputName>Elwig</OutputName>
|
||||||
<Cultures>de-AT</Cultures>
|
<Cultures>de-AT</Cultures>
|
||||||
|
<AcceptEula>wix7</AcceptEula>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Target Name="CustomBeforeBuild" BeforeTargets="BeforeBuild">
|
<Target Name="CustomBeforeBuild" BeforeTargets="BeforeBuild">
|
||||||
<Exec Command="curl --fail -s -L "https://go.microsoft.com/fwlink/p/?LinkId=2124703" -z "$(ProjectDir)\Files\MicrosoftEdgeWebview2Setup.exe" -o "$(ProjectDir)\Files\MicrosoftEdgeWebview2Setup.exe"" />
|
<Exec Command="curl --fail -s -L "https://go.microsoft.com/fwlink/p/?LinkId=2124703" -z "$(ProjectDir)\Files\MicrosoftEdgeWebview2Setup.exe" -o "$(ProjectDir)\Files\MicrosoftEdgeWebview2Setup.exe"" />
|
||||||
@@ -13,7 +14,7 @@
|
|||||||
</Target>
|
</Target>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Installer\Installer.wixproj" />
|
<ProjectReference Include="..\Installer\Installer.wixproj" />
|
||||||
<PackageReference Include="WixToolset.Bal.wixext" Version="6.0.2" />
|
<PackageReference Include="WixToolset.Bal.wixext" Version="7.0.0" />
|
||||||
<PackageReference Include="WixToolset.Util.wixext" Version="6.0.2" />
|
<PackageReference Include="WixToolset.Util.wixext" Version="7.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -80,6 +80,7 @@ namespace Tests.E2ETests {
|
|||||||
|
|
||||||
Window.FindElement(By.WpfId("SaveButton")).Click();
|
Window.FindElement(By.WpfId("SaveButton")).Click();
|
||||||
|
|
||||||
|
Thread.Sleep(500);
|
||||||
Window.FindElement(By.WpfId("SearchInput")).SendKeys("9999");
|
Window.FindElement(By.WpfId("SearchInput")).SendKeys("9999");
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
var memberListRow = Window.FindElement(By.WpfId("MemberList")).FindElement(By.ClassName("DataGridRow"));
|
var memberListRow = Window.FindElement(By.WpfId("MemberList")).FindElement(By.ClassName("DataGridRow"));
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.4.0" />
|
||||||
<PackageReference Include="Appium.WebDriver" Version="4.4.5" />
|
<PackageReference Include="Appium.WebDriver" Version="4.4.5" />
|
||||||
<PackageReference Include="NReco.PdfRenderer" Version="1.6.0" />
|
<PackageReference Include="NReco.PdfRenderer" Version="1.6.0" />
|
||||||
<PackageReference Include="NUnit" Version="4.5.1" />
|
<PackageReference Include="NUnit" Version="4.5.1" />
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="8.0.1">
|
<PackageReference Include="coverlet.collector" Version="10.0.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Tests.UnitTests.DocumentTests {
|
|||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task Test_01_VirtualCreditNote() {
|
public async Task Test_01_VirtualCreditNote() {
|
||||||
using var doc = await CreditNote.Initialize(2020, 1, 101);
|
using var doc = await CreditNote.Initialize(2020, 1, 101, null);
|
||||||
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("""
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ namespace Tests.UnitTests.DocumentTests {
|
|||||||
[Test]
|
[Test]
|
||||||
public async Task Test_01_SimpleDeliveryConfirmation() {
|
public async Task Test_01_SimpleDeliveryConfirmation() {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var m = await ctx.Members.FindAsync(101);
|
var m = await ctx.FetchMembers(101).SingleAsync();
|
||||||
var data = await DeliveryConfirmationDeliveryData.ForMember(ctx.DeliveryParts, 2020, m!);
|
var data = await DeliveryConfirmationDeliveryData.ForMember(ctx.DeliveryParts, 2020, m!);
|
||||||
using var doc = new DeliveryConfirmation(2020, m!, data);
|
using var doc = new DeliveryConfirmation(2020, m!, null, 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("""
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Tests.UnitTests.DocumentTests {
|
|||||||
[Test]
|
[Test]
|
||||||
public async Task Test_01_SimpleLetterhead() {
|
public async Task Test_01_SimpleLetterhead() {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var m = await ctx.Members.FindAsync(104);
|
var m = await ctx.FetchMembers(104).SingleAsync();
|
||||||
using var doc = new Letterhead(m!);
|
using var doc = new Letterhead(m!);
|
||||||
var text = await Utils.GeneratePdfText(doc);
|
var text = await Utils.GeneratePdfText(doc);
|
||||||
Assert.Multiple(() => {
|
Assert.Multiple(() => {
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ namespace Tests.UnitTests.HelperTests {
|
|||||||
Assert.That(delivery["GVK"], Is.EqualTo( 4_000));
|
Assert.That(delivery["GVK"], Is.EqualTo( 4_000));
|
||||||
});
|
});
|
||||||
|
|
||||||
BillingVariant b = new(year, 1);
|
var b = await BillingVariant.Create(year, 1);
|
||||||
await b.CalculateBuckets(false, false, false);
|
await b.CalculateBuckets(false, false, false);
|
||||||
var payment = await GetMemberPaymentBuckets(year, mgnr);
|
var payment = await GetMemberPaymentBuckets(year, mgnr);
|
||||||
Assert.Multiple(() => {
|
Assert.Multiple(() => {
|
||||||
@@ -179,7 +179,7 @@ namespace Tests.UnitTests.HelperTests {
|
|||||||
Assert.That(delivery["GVK"], Is.EqualTo( 4_000));
|
Assert.That(delivery["GVK"], Is.EqualTo( 4_000));
|
||||||
});
|
});
|
||||||
|
|
||||||
BillingVariant b = new(year, 1);
|
var b = await BillingVariant.Create(year, 1);
|
||||||
await b.CalculateBuckets(false, false, false, Connection);
|
await b.CalculateBuckets(false, false, false, Connection);
|
||||||
var payment = await GetMemberPaymentBuckets(year, mgnr);
|
var payment = await GetMemberPaymentBuckets(year, mgnr);
|
||||||
Assert.Multiple(() => {
|
Assert.Multiple(() => {
|
||||||
@@ -225,7 +225,7 @@ namespace Tests.UnitTests.HelperTests {
|
|||||||
Assert.That(delivery["GVK"], Is.EqualTo( 4_000));
|
Assert.That(delivery["GVK"], Is.EqualTo( 4_000));
|
||||||
});
|
});
|
||||||
|
|
||||||
BillingVariant b = new(year, 1);
|
var b = await BillingVariant.Create(year, 1);
|
||||||
await b.CalculateBuckets(true, false, false, Connection);
|
await b.CalculateBuckets(true, false, false, Connection);
|
||||||
var payment = await GetMemberPaymentBuckets(year, mgnr);
|
var payment = await GetMemberPaymentBuckets(year, mgnr);
|
||||||
Assert.Multiple(() => {
|
Assert.Multiple(() => {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace Tests.UnitTests.HelperTests {
|
|||||||
DateString = "2021-01-31",
|
DateString = "2021-01-31",
|
||||||
};
|
};
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var members = ctx.Members.ToList();
|
var members = await ctx.FetchMembers().ToListAsync();
|
||||||
Assert.That(members, Has.Count.GreaterThan(0));
|
Assert.That(members, Has.Count.GreaterThan(0));
|
||||||
using var exporter = new Ebics(v, FileName, version, mode);
|
using var exporter = new Ebics(v, FileName, version, mode);
|
||||||
await exporter.ExportAsync(members.Select(m => new Transaction(m, 1234.56m, "EUR", m.MgNr % 100)));
|
await exporter.ExportAsync(members.Select(m => new Transaction(m, 1234.56m, "EUR", m.MgNr % 100)));
|
||||||
|
|||||||
@@ -10,19 +10,19 @@ namespace Tests.UnitTests.ServiceTests {
|
|||||||
|
|
||||||
private static async Task InitViewModel(DeliveryAdminViewModel vm) {
|
private static async Task InitViewModel(DeliveryAdminViewModel vm) {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
vm.MemberSource = await ctx.Members.ToListAsync();
|
vm.MemberSource = await ctx.FetchMembers(includeNotActive: true).ToListAsync();
|
||||||
vm.BranchSource = await ctx.Branches.ToListAsync();
|
vm.BranchSource = await ctx.FetchBranches().ToListAsync();
|
||||||
vm.WineVarSource = await ctx.WineVarieties.ToListAsync();
|
vm.WineVarSource = await ctx.FetchWineVarieties().ToListAsync();
|
||||||
List<object> attrs = (await ctx.WineAttributes.ToListAsync()).Cast<object>().ToList();
|
List<object> attrs = await ctx.FetchWineAttributes().Cast<object>().ToListAsync();
|
||||||
attrs.Insert(0, new NullItem());
|
attrs.Insert(0, new NullItem());
|
||||||
vm.WineAttrSource = attrs;
|
vm.WineAttrSource = attrs;
|
||||||
List<object> cults = (await ctx.WineCultivations.ToListAsync()).Cast<object>().ToList();
|
List<object> cults = await ctx.FetchWineCultivations().Cast<object>().ToListAsync();
|
||||||
cults.Insert(0, new NullItem());
|
cults.Insert(0, new NullItem());
|
||||||
vm.WineCultSource = cults;
|
vm.WineCultSource = cults;
|
||||||
vm.WineQualityLevelSource = await ctx.WineQualityLevels.ToListAsync();
|
vm.WineQualityLevelSource = await ctx.FetchWineQualityLevels().ToListAsync();
|
||||||
vm.WineOriginSource = await ctx.WineOrigins.ToListAsync();
|
vm.WineOriginSource = await ctx.WineOrigins.ToListAsync();
|
||||||
vm.WineKgSource = await ctx.Katastralgemeinden.ToListAsync();
|
vm.WineKgSource = await ctx.Katastralgemeinden.ToListAsync();
|
||||||
vm.ModifiersSource = await ctx.Modifiers.Where(m => m.Year == 2022).ToListAsync();
|
vm.ModifiersSource = await ctx.FetchModifiers(2022).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<Delivery?> GetDelivery(string lsnr) {
|
private static async Task<Delivery?> GetDelivery(string lsnr) {
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ namespace Tests.UnitTests.ServiceTests {
|
|||||||
|
|
||||||
private static async Task InitViewModel(MemberAdminViewModel vm) {
|
private static async Task InitViewModel(MemberAdminViewModel vm) {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
vm.BranchSource = await ctx.Branches.ToListAsync();
|
vm.BranchSource = await ctx.FetchBranches().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]
|
||||||
@@ -31,22 +31,14 @@ namespace Tests.UnitTests.ServiceTests {
|
|||||||
|
|
||||||
Assert.That(vm.MgNr, Is.EqualTo(205));
|
Assert.That(vm.MgNr, Is.EqualTo(205));
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
Assert.That(await ctx.Members.FindAsync(205), Is.Null);
|
Assert.That(await ctx.FetchMembers(205, includeNotActive: true).SingleOrDefaultAsync(), Is.Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
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.FetchMembers(vm.MgNr, includeNotActive: true, includeContactInfo: true).SingleAsync();
|
||||||
.Where(m => m.MgNr == vm.MgNr)
|
|
||||||
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
|
|
||||||
.Include(m => m.PostalDest.AtPlz!.Ort)
|
|
||||||
.Include(m => m.DefaultWbKg!.AtKg)
|
|
||||||
.Include(m => m.EmailAddresses)
|
|
||||||
.Include(m => m.TelephoneNumbers)
|
|
||||||
.AsSplitQuery()
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.That(m, Is.Not.Null);
|
Assert.That(m, Is.Not.Null);
|
||||||
@@ -119,22 +111,14 @@ namespace Tests.UnitTests.ServiceTests {
|
|||||||
vm.IsFunktionär = true;
|
vm.IsFunktionär = true;
|
||||||
|
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
Assert.That(await ctx.Members.FindAsync(999), Is.Null);
|
Assert.That(await ctx.FetchMembers(999, includeNotActive: true).SingleOrDefaultAsync(), Is.Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
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.FetchMembers(vm.MgNr, includeNotActive: true, includeContactInfo: true).SingleAsync();
|
||||||
.Where(m => m.MgNr == vm.MgNr)
|
|
||||||
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
|
|
||||||
.Include(m => m.PostalDest.AtPlz!.Ort)
|
|
||||||
.Include(m => m.DefaultWbKg!.AtKg)
|
|
||||||
.Include(m => m.EmailAddresses)
|
|
||||||
.Include(m => m.TelephoneNumbers)
|
|
||||||
.AsSplitQuery()
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.That(m, Is.Not.Null);
|
Assert.That(m, Is.Not.Null);
|
||||||
@@ -234,15 +218,7 @@ namespace Tests.UnitTests.ServiceTests {
|
|||||||
var vm = new MemberAdminViewModel();
|
var vm = new MemberAdminViewModel();
|
||||||
await InitViewModel(vm);
|
await InitViewModel(vm);
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
vm.FillInputs(await ctx.Members
|
vm.FillInputs(await ctx.FetchMembers(202, includeNotActive: true, includeContactInfo: true).SingleAsync());
|
||||||
.Where(m => m.MgNr == 202)
|
|
||||||
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
|
|
||||||
.Include(m => m.PostalDest.AtPlz!.Ort)
|
|
||||||
.Include(m => m.DefaultWbKg!.AtKg)
|
|
||||||
.Include(m => m.EmailAddresses)
|
|
||||||
.Include(m => m.TelephoneNumbers)
|
|
||||||
.AsSplitQuery()
|
|
||||||
.FirstAsync());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.That(vm.IsActive, Is.True);
|
Assert.That(vm.IsActive, Is.True);
|
||||||
@@ -253,17 +229,9 @@ 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.FetchMembers(202, includeNotActive: true, includeContactInfo: true).SingleAsync();
|
||||||
.Where(m => m.MgNr == 202)
|
|
||||||
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
|
|
||||||
.Include(m => m.PostalDest.AtPlz!.Ort)
|
|
||||||
.Include(m => m.DefaultWbKg!.AtKg)
|
|
||||||
.Include(m => m.EmailAddresses)
|
|
||||||
.Include(m => m.TelephoneNumbers)
|
|
||||||
.AsSplitQuery()
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.That(m, Is.Not.Null);
|
Assert.That(m, Is.Not.Null);
|
||||||
@@ -286,15 +254,7 @@ namespace Tests.UnitTests.ServiceTests {
|
|||||||
var vm = new MemberAdminViewModel();
|
var vm = new MemberAdminViewModel();
|
||||||
await InitViewModel(vm);
|
await InitViewModel(vm);
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
vm.FillInputs(await ctx.Members
|
vm.FillInputs(await ctx.FetchMembers(203, includeNotActive: true, includeContactInfo: true).SingleAsync());
|
||||||
.Where(m => m.MgNr == 203)
|
|
||||||
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
|
|
||||||
.Include(m => m.PostalDest.AtPlz!.Ort)
|
|
||||||
.Include(m => m.DefaultWbKg!.AtKg)
|
|
||||||
.Include(m => m.EmailAddresses)
|
|
||||||
.Include(m => m.TelephoneNumbers)
|
|
||||||
.AsSplitQuery()
|
|
||||||
.FirstAsync());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.Multiple(() => {
|
Assert.Multiple(() => {
|
||||||
@@ -306,17 +266,9 @@ 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.FetchMembers(210, includeNotActive: true, includeContactInfo: true).SingleAsync();
|
||||||
.Where(m => m.MgNr == 210)
|
|
||||||
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
|
|
||||||
.Include(m => m.PostalDest.AtPlz!.Ort)
|
|
||||||
.Include(m => m.DefaultWbKg!.AtKg)
|
|
||||||
.Include(m => m.EmailAddresses)
|
|
||||||
.Include(m => m.TelephoneNumbers)
|
|
||||||
.AsSplitQuery()
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.That(m, Is.Not.Null);
|
Assert.That(m, Is.Not.Null);
|
||||||
@@ -334,27 +286,27 @@ namespace Tests.UnitTests.ServiceTests {
|
|||||||
[Test]
|
[Test]
|
||||||
public async Task TestDelete_01_NoReferences() {
|
public async Task TestDelete_01_NoReferences() {
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
Assert.That(await ctx.Members.FindAsync(201), Is.Not.Null);
|
Assert.That(await ctx.FetchMembers(201, includeNotActive: true).SingleOrDefaultAsync(), Is.Not.Null);
|
||||||
}
|
}
|
||||||
Assert.DoesNotThrowAsync(async () => await MemberService.DeleteMember(201, false, false, false));
|
Assert.DoesNotThrowAsync(async () => await MemberService.DeleteMember(201, false, false, false));
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
Assert.That(await ctx.Members.FindAsync(201), Is.Null);
|
Assert.That(await ctx.FetchMembers(201, includeNotActive: true).SingleOrDefaultAsync(), Is.Null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task TestDelete_02_AllReferences() {
|
public async Task TestDelete_02_AllReferences() {
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
Assert.That(await ctx.Members.FindAsync(204), Is.Not.Null);
|
Assert.That(await ctx.FetchMembers(204, includeNotActive: true).SingleOrDefaultAsync(), Is.Not.Null);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 7; i++) {
|
for (int i = 0; i < 7; i++) {
|
||||||
Assert.ThrowsAsync<DbUpdateException>(async () => await MemberService.DeleteMember(204, (i & 1) != 0, (i & 2) != 0, (i & 4) != 0));
|
Assert.ThrowsAsync<DbUpdateException>(async () => await MemberService.DeleteMember(204, (i & 1) != 0, (i & 2) != 0, (i & 4) != 0));
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
Assert.That(await ctx.Members.FindAsync(204), Is.Not.Null);
|
Assert.That(await ctx.FetchMembers(204, includeNotActive: true).SingleOrDefaultAsync(), Is.Not.Null);
|
||||||
}
|
}
|
||||||
Assert.DoesNotThrowAsync(async () => await MemberService.DeleteMember(204, true, true, true));
|
Assert.DoesNotThrowAsync(async () => await MemberService.DeleteMember(204, true, true, true));
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
Assert.That(await ctx.Members.FindAsync(204), Is.Null);
|
Assert.That(await ctx.FetchMembers(204, includeNotActive: true).SingleOrDefaultAsync(), Is.Null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
curl --fail -s -L "https://elwig.at/files/create.sql?v=38" -u "elwig:ganzGeheim123!" -o "Resources\Sql\Create.sql"
|
curl --fail -s -L "https://elwig.at/files/create.sql?v=39" -u "elwig:ganzGeheim123!" -o "Resources\Sql\Create.sql"
|
||||||
|
|||||||
Reference in New Issue
Block a user