Compare commits

..

3 Commits

Author SHA1 Message Date
lorenz.stechauner c3cf239cba [WIP] Use compiled queries
Test / Run tests (push) Successful in 3m0s
2026-04-04 15:29:47 +02:00
lorenz.stechauner bd1e579674 [WIP] Models/Entities: Remove EF proxies 2026-04-04 15:29:42 +02:00
lorenz.stechauner bf7c9532d1 [WIP] Entities: Add AreaComContract to group area commitments together 2026-04-02 21:02:25 +02:00
49 changed files with 214 additions and 288 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
- name: Check for code smells
shell: powershell
run: |
git grep -IEn "\.(Single|First|Min|Max|Any)(OrDefault)?Async\([^)]|^using System.Data.Entity;"
git grep -IEn "\.(Single|First|Min|Max)(OrDefault)?Async\([^)]|^using System.Data.Entity;"
if ( $lastexitcode -ne 1 ) {
exit 1
} else {
-55
View File
@@ -2,61 +2,6 @@
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}
---------------------------------------------
+3 -4
View File
@@ -105,9 +105,9 @@ namespace Elwig {
Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = [];
using (var ctx = new AppDbContext()) {
branches = ctx.FetchBranches()
.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))
.GetAwaiter().GetResult();
branches = ctx.Branches
.Include(b => b.PostalDest)
.ToDictionary(b => b.Name.ToLower(), b => (b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Ort.Name, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr));
try {
Client = new(ctx);
} catch (Exception e) {
@@ -201,7 +201,6 @@ namespace Elwig {
BranchName = entry.Item2;
BranchPlz = entry.Item3;
BranchLocation = entry.Item4?
.Split(",")[0]
.Split(" in ")[0]
.Split(" im ")[0]
.Split(" an ")[0]
+2 -4
View File
@@ -22,7 +22,6 @@ namespace Elwig.Documents {
public bool IncludeSender = false;
public bool UseBillingAddress = false;
public bool ShowDateAndLocation = false;
public DateOnly? DateFrom;
protected Table? Aside;
public string Address {
@@ -48,12 +47,11 @@ namespace Elwig.Documents {
return NewAsideCell(new KernedParagraph(text, 10), colspan, isName);
}
public BusinessDocument(string title, Member m, DateOnly? dateFrom, bool includeSender = false) :
public BusinessDocument(string title, Member m, bool includeSender = false) :
base(title) {
Member = m;
Location = App.BranchLocation;
IncludeSender = includeSender;
DateFrom = dateFrom;
}
protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) {
@@ -107,7 +105,7 @@ namespace Elwig.Documents {
}
}
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(ShowDateAndLocation ? $"{Location}, am {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));
}
+5 -5
View File
@@ -37,8 +37,8 @@ namespace Elwig.Documents {
private CreditNoteDeliveryData? _data;
private Dictionary<string, UnderDelivery>? _underDeliveries;
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, dateFrom) {
public CreditNote(PaymentMember p, BillingData? billingData = null, CreditNoteDeliveryData? data = null, Dictionary<string, UnderDelivery>? underDeliveries = null) :
base($"{Name} {(p.Credit != null ? $"Nr. {p.Credit.Year}/{p.Credit.TgNr:000}" : p.Member.FullName)} {p.Variant.Name}", p.Member) {
UseBillingAddress = true;
ShowDateAndLocation = true;
Payment = p;
@@ -58,12 +58,12 @@ namespace Elwig.Documents {
ConsiderCustomModifiers = billingData.ConsiderCustomModifiers;
}
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) {
public static async Task<CreditNote> Initialize(int year, int avnr, int mgnr, BillingData? billingData = null, CreditNoteDeliveryData? data = null, Dictionary<string, UnderDelivery>? underDeliveries = null) {
using var ctx = new AppDbContext();
var p = await ctx.MemberPayments
.Where(p => p.Year == year && p.AvNr == avnr && p.MgNr == mgnr)
.SingleAsync();
return new CreditNote(p, dateFrom, billingData, data, underDeliveries);
return new CreditNote(p, billingData, data, underDeliveries);
}
protected override async Task LoadData(AppDbContext ctx) {
@@ -321,7 +321,7 @@ namespace Elwig.Documents {
var totalMod = p.TotalModifiers ?? 0;
var pad = i == 0 ? 0.5f : 0;
sub.AddCell(NewTd(rebelMod == 0 ? "-" : (Utils.GetSign(rebelMod) + $"{Math.Abs(rebelMod):0.0##}"), 6, center: true)
.SetPaddingTopMM(pad).SetPaddingLeft(0).SetPaddingRight(0))
.SetPaddingTopMM(pad))
.AddCell(NewTd(totalMod == 0 ? "-" : Utils.GetSign(totalMod) + $"{Math.Abs(totalMod):N2}", center: totalMod == 0, right: true)
.SetPaddingTopMM(pad))
.AddCell(NewTd($"{p.Amount:N2}", right: true)
+2 -2
View File
@@ -24,8 +24,8 @@ namespace Elwig.Documents {
public Dictionary<string, MemberBucket> MemberBuckets = [];
public List<MemberStat> MemberStats = [];
public DeliveryConfirmation(int year, Member m, DateOnly? dateFrom, DeliveryConfirmationDeliveryData? data = null) :
base($"{Name} {year}", m, dateFrom) {
public DeliveryConfirmation(int year, Member m, DeliveryConfirmationDeliveryData? data = null) :
base($"{Name} {year}", m) {
_year = year;
ShowDateAndLocation = true;
UseBillingAddress = true;
+3 -1
View File
@@ -29,12 +29,14 @@ namespace Elwig.Documents {
public int DisplayStats = App.Client.ModeDeliveryNoteStats;
public DeliveryNote(Delivery d) :
base($"{Name} Nr. {d.LsNr}", d.Member, DateOnly.FromDateTime(d.ModifiedAt)) {
base($"{Name} Nr. {d.LsNr}", d.Member) {
UseBillingAddress = true;
ShowDateAndLocation = true;
Delivery = d;
Text = App.Client.TextDeliveryNote;
DocumentId = d.LsNr;
Date = DateOnly.FromDateTime(d.ModifiedAt);
IsDoublePaged = true;
}
public static async Task<DeliveryNote> Initialize(int year, int did) {
+2
View File
@@ -49,12 +49,14 @@ namespace Elwig.Documents {
public bool IsPreview = false;
private iText.Layout.Document? _doc;
public int CurrentNextSeason;
public string? DocumentId;
public string Title;
public string Author;
public DateOnly Date;
public Document(string title) {
CurrentNextSeason = Utils.CurrentNextSeason;
Title = title;
Author = App.Client.NameFull;
Date = DateOnly.FromDateTime(Utils.Today);
+1 -1
View File
@@ -6,7 +6,7 @@ using iText.Layout;
namespace Elwig.Documents {
public class Letterhead : BusinessDocument {
public Letterhead(Member m) :
base($"Briefkopf {m.FullName}", m, null, includeSender: true) {
base($"Briefkopf {m.FullName}", m, true) {
}
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
+6 -3
View File
@@ -23,14 +23,17 @@ namespace Elwig.Documents {
public List<AreaCom> ActiveAreaCommitments = [];
public MemberDataSheet(Member m) :
base($"{Name} {m.AdministrativeName}", m, DateOnly.FromDateTime(m.ModifiedAt)) {
ShowDateAndLocation = true;
base($"{Name} {m.AdministrativeName}", m) {
DocumentId = $"{Name} {m.MgNr}";
}
public static async Task<MemberDataSheet> Initialize(int mgnr) {
using var ctx = new AppDbContext();
return new MemberDataSheet(await ctx.FetchMembers(mgnr, true, true).SingleAsync());
return new MemberDataSheet(await ctx.Members
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.Where(m => m.MgNr == mgnr)
.SingleAsync());
}
protected override async Task LoadData(AppDbContext ctx) {
+3 -3
View File
@@ -183,21 +183,21 @@ namespace Elwig.Documents {
.AddCell(NewTd(CurrencySymbol))
.AddCell(NewTd($"{Math.Abs(payed):N2}", right: true))
.AddCell(NewSectionTh("Preis (abgewertet):", borderTop: true, borderLeft: 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(NewTd((minWei != maxWei ? $"{minWei:N4}\u2013{maxWei:N4}" : $"{minWei:N4}") + $" {CurrencySymbol}/kg", colspan: 2, center: true, borderTop: true))
.AddCell(NewSectionTh("Nettosumme:", colspan: 2))
.AddCell(NewTd(borderTop: true))
.AddCell(NewTd(CurrencySymbol, borderTop: true))
.AddCell(NewTd($"{netSum:N2}", right: true, borderTop: true))
.AddCell(NewSectionTh("Preis (ungeb., nicht abgew.):", borderLeft: true))
.AddCell(NewTd(minPrice == null && maxPrice == null ? "-" : (minPrice != maxPrice ? $"{minPrice:N4}{maxPrice:N4}" : $"{minPrice:N4}") + $" {CurrencySymbol}/kg", colspan: 2, center: true))
.AddCell(NewTd((minPrice != maxPrice ? $"{minPrice:N4}{maxPrice:N4}" : $"{minPrice:N4}") + $" {CurrencySymbol}/kg", colspan: 2, center: true))
.AddCell(NewSectionTh("Mehrwertsteuer:", colspan: 2))
.AddCell(NewTd(Utils.GetSign(vat), right: true))
.AddCell(NewTd(CurrencySymbol))
.AddCell(NewTd($"{Math.Abs(vat):N2}", right: true))
.AddCell(NewSectionTh("Gebunden-Zuschlag:", borderLeft: 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(NewTd(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(NewTd(borderTop: true))
+13 -13
View File
@@ -9,7 +9,7 @@
<UseWindowsForms>true</UseWindowsForms>
<PreserveCompilationContext>true</PreserveCompilationContext>
<ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon>
<Version>1.0.5.2</Version>
<Version>1.0.4.1</Version>
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ApplicationManifest>app.manifest</ApplicationManifest>
@@ -23,21 +23,21 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="bblanchon.PDFium.Win32" Version="149.0.7802" />
<PackageReference Include="bblanchon.PDFium.Win32" Version="148.0.7749" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
<PackageReference Include="itext" Version="9.6.0" />
<PackageReference Include="itext.bouncy-castle-adapter" Version="9.6.0" />
<PackageReference Include="itext" Version="9.5.0" />
<PackageReference Include="itext.bouncy-castle-adapter" Version="9.5.0" />
<PackageReference Include="LinqKit" Version="1.3.11" />
<PackageReference Include="MailKit" Version="4.16.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.7" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="10.0.7" />
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3912.50" />
<PackageReference Include="NJsonSchema" Version="11.6.1" />
<PackageReference Include="ScottPlot.WPF" Version="5.1.58" />
<PackageReference Include="MailKit" Version="4.15.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="10.0.5" />
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3856.49" />
<PackageReference Include="NJsonSchema" Version="11.5.2" />
<PackageReference Include="ScottPlot.WPF" Version="5.1.57" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.0.2" />
<PackageReference Include="System.IO.Hashing" Version="10.0.7" />
<PackageReference Include="System.IO.Ports" Version="10.0.7" />
<PackageReference Include="System.Management" Version="10.0.7" />
<PackageReference Include="System.IO.Hashing" Version="10.0.5" />
<PackageReference Include="System.IO.Ports" Version="10.0.5" />
<PackageReference Include="System.Management" Version="10.0.5" />
</ItemGroup>
</Project>
+14 -38
View File
@@ -85,11 +85,9 @@ namespace Elwig.Helpers {
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";
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)
private static readonly Func<AppDbContext, bool, IAsyncEnumerable<Branch>> _compiledQueryBranches =
EF.CompileAsyncQuery<AppDbContext, bool, Branch>((ctx, onlyWithMembers) => ctx.Branches
.Where(b => !onlyWithMembers || b.Members.Count > 0)
.OrderBy(b => b.Name));
private static readonly Func<AppDbContext, string?, IAsyncEnumerable<WineVar>> _compiledQueryWineVarieties =
@@ -113,10 +111,10 @@ namespace Elwig.Helpers {
.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<Modifier>> _compiledQueryModifiers =
EF.CompileAsyncQuery<AppDbContext, int, bool, Modifier>((ctx, year, incudeNotActive) => ctx.Modifiers
.Where(m => m.Year == year && (incudeNotActive || m.IsActive))
.OrderBy(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
@@ -124,26 +122,12 @@ namespace Elwig.Helpers {
.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)
@@ -312,8 +296,8 @@ namespace Elwig.Helpers {
return (await DeliverySchedules.Where(s => s.Year == year).Select(v => (int?)v.DsNr).MaxAsync() ?? 0) + 1;
}
public IAsyncEnumerable<Branch> FetchBranches(string? zwstid = null, bool includeWithoutMembers = true) {
return _compiledQueryBranches.Invoke(this, zwstid, includeWithoutMembers);
public IAsyncEnumerable<Branch> FetchBranches(bool onlyWithMembers = false) {
return _compiledQueryBranches.Invoke(this, onlyWithMembers);
}
public IAsyncEnumerable<WineVar> FetchWineVarieties() {
@@ -333,23 +317,15 @@ namespace Elwig.Helpers {
}
public IAsyncEnumerable<Modifier> FetchModifiers(int? year, bool incudeNotActive = true) {
return _compiledQueryModifiers.Invoke(this, year, incudeNotActive);
return _compiledQueryModifiers.Invoke(this, year ?? 0, 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<Member> FetchMembers(bool includeNotActive = false) {
return _compiledQueryMembers.Invoke(this, null, 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 IAsyncEnumerable<Season> FetchSeasons(int? year = null) {
return _compiledQuerySeasons.Invoke(this, year);
}
public async Task UpdateDeliveryPartModifiers(DeliveryPart part, IEnumerable<string> oldModIds, IEnumerable<string> newModIds) {
+1 -1
View File
@@ -9,7 +9,7 @@ namespace Elwig.Helpers {
public static class AppDbUpdater {
// Don't forget to update value in Tests/fetch-resources.bat!
public static readonly int RequiredSchemaVersion = 39;
public static readonly int RequiredSchemaVersion = 38;
private static int VersionOffset = 0;
+1 -1
View File
@@ -232,7 +232,7 @@ namespace Elwig.Helpers.Billing {
SET mod_rel = mod_rel + excluded.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) * d.weight, COALESCE(m.rel, 0)
SELECT d.year, d.did, d.dpnr, {AvNr}, 0, COALESCE(m.abs, 0), COALESCE(m.rel, 0)
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 modifier m ON (m.year, m.modid) = (d.year, p.modid)
+13 -16
View File
@@ -41,7 +41,7 @@ namespace Elwig.Helpers.Export {
List<WbGl> currentWbGls;
using (var ctx = new AppDbContext()) {
branches = await ctx.FetchBranches().ToDictionaryAsync(b => b.ZwstId);
branches = await ctx.Branches.ToDictionaryAsync(b => b.ZwstId);
currentDids = await ctx.Deliveries
.GroupBy(d => d.Year)
.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 importedAreaComs = 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 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)) {
@@ -308,9 +308,9 @@ namespace Elwig.Helpers.Export {
}
if (importDuplicateMembers) {
ctx.RemoveRange(ctx.BillingAddresses.IgnoreAutoIncludes().Where(a => duplicateMgNrs.Contains(a.MgNr)));
ctx.RemoveRange(ctx.MemberTelephoneNrs.IgnoreAutoIncludes().Where(n => duplicateMgNrs.Contains(n.MgNr)));
ctx.RemoveRange(ctx.MemberEmailAddrs.IgnoreAutoIncludes().Where(a => duplicateMgNrs.Contains(a.MgNr)));
ctx.RemoveRange(ctx.BillingAddresses.Where(a => duplicateMgNrs.Contains(a.MgNr)));
ctx.RemoveRange(ctx.MemberTelephoneNrs.Where(n => duplicateMgNrs.Contains(n.MgNr)));
ctx.RemoveRange(ctx.MemberEmailAddrs.Where(a => duplicateMgNrs.Contains(a.MgNr)));
ctx.UpdateRange(members.Where(m => duplicateMgNrs.Contains(m.MgNr)));
ctx.AddRange(billingAddresses.Where(a => duplicateMgNrs.Contains(a.MgNr)));
ctx.AddRange(telephoneNumbers.Where(n => duplicateMgNrs.Contains(n.MgNr)));
@@ -329,7 +329,7 @@ namespace Elwig.Helpers.Export {
}
if (importDuplicateContracts) {
ctx.RemoveRange(ctx.AreaCommitments.IgnoreAutoIncludes().Where(c => duplicateFbNrs.Contains(c.FbNr)));
ctx.RemoveRange(ctx.AreaCommitments.Where(c => duplicateFbNrs.Contains(c.FbNr)));
ctx.UpdateRange(contracts.Where(c => duplicateFbNrs.Contains(c.FbNr)));
ctx.AddRange(areaCommitments.Where(c => duplicateFbNrs.Contains(c.FbNr)));
}
@@ -339,9 +339,8 @@ namespace Elwig.Helpers.Export {
}
if (contracts.Count > 0) {
ctx.AddRange(riede);
var n = importNewContracts ? contracts.Count - duplicateFbNrs.Count : 0;
var o = importDuplicateContracts ? duplicateFbNrs.Count : 0;
importedAreaComs.Add((meta.FileName, meta.ZwstId, meta.Device, n, o, contracts.Count - n - o, meta.AreaComFilters));
var imported = contracts.Where(c => (importNewContracts && !duplicateFbNrs.Contains(c.FbNr)) || (importDuplicateContracts && duplicateFbNrs.Contains(c.FbNr))).ToList();
importedAreaComs.Add((meta.FileName, meta.ZwstId, meta.Device, imported.Count, areaCommitments.Count - imported.Count, meta.AreaComFilters));
}
if (allowedDuplicateLsNrs.Count > 0) {
@@ -350,10 +349,9 @@ namespace Elwig.Helpers.Export {
.Select(d => (d.Year, d.DId))
.ToList();
ctx.RemoveRange(ctx.DeliveryParts
.IgnoreAutoIncludes()
.Where(p => allowedDuplicateLsNrs.Contains(p.Delivery.LsNr))
.SelectMany(p => p.PartModifiers));
ctx.RemoveRange(ctx.DeliveryParts.IgnoreAutoIncludes().Where(p => allowedDuplicateLsNrs.Contains(p.Delivery.LsNr)));
ctx.RemoveRange(ctx.DeliveryParts.Where(p => allowedDuplicateLsNrs.Contains(p.Delivery.LsNr)));
ctx.UpdateRange(deliveries.Where(d => dids.Contains((d.Year, d.DId))));
ctx.AddRange(deliveryParts.Where(p => dids.Contains((p.Year, p.DId))));
ctx.AddRange(modifiers.Where(m => dids.Contains((m.Year, m.DId))));
@@ -365,10 +363,9 @@ namespace Elwig.Helpers.Export {
.Select(d => (d.Year, d.DId))
.ToList();
ctx.RemoveRange(ctx.DeliveryParts
.IgnoreAutoIncludes()
.Where(p => l.Contains(p.Delivery.LsNr))
.SelectMany(p => p.PartModifiers));
ctx.RemoveRange(ctx.DeliveryParts.IgnoreAutoIncludes().Where(p => l.Contains(p.Delivery.LsNr)));
ctx.RemoveRange(ctx.DeliveryParts.Where(p => l.Contains(p.Delivery.LsNr)));
ctx.UpdateRange(deliveries.Where(d => dids.Contains((d.Year, d.DId))));
ctx.AddRange(deliveryParts.Where(p => dids.Contains((p.Year, p.DId))));
ctx.AddRange(modifiers.Where(m => dids.Contains((m.Year, m.DId))));
@@ -421,10 +418,10 @@ namespace Elwig.Helpers.Export {
$" ({d.New} neu, {d.Overwritten} überschrieben, {d.NotImported} nicht importiert)\n" +
$" Zweigstelle: {branches[d.ZwstId].Name} (Gerät {d.Device})\n" +
$" Filter: {d.Filters}"),
$"Flächenbindungen: {importedAreaComs.Sum(d => d.New + d.Overwritten)}",
$"Flächenbindungen: {importedAreaComs.Sum(d => d.Imported)}",
..importedAreaComs.Select(d =>
$" {d.FileName} ({d.New + d.Overwritten})\n" +
$" ({d.New} importiert, {d.Overwritten} überschreiben, {d.NotImported} nicht importiert)\n" +
$" {d.FileName} ({d.Imported})\n" +
$" ({d.Imported} importiert, {d.NotImported} nicht importiert)\n" +
$" Zweigstelle: {branches[d.ZwstId].Name} (Gerät {d.Device})\n" +
$" Filter: {d.Filters}"),
$"Lieferungen: {importedDeliveries.Sum(d => d.New + d.Overwritten)}",
-21
View File
@@ -153,27 +153,6 @@ BEGIN
UPDATE area_commitment_contract SET mtime = UNIXEPOCH() WHERE fbnr = OLD.fbnr;
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
UPDATE area_commitment AS b
SET fbnr = a.fbnr, revnr = b.fbnr, year_from = a.year_to + 1
-8
View File
@@ -1,8 +0,0 @@
-- 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);
+1 -1
View File
@@ -66,7 +66,7 @@ namespace Elwig.Services {
var filter = vm.TextFilter;
if (filter.Count > 0) {
var var = await ctx.FetchWineVarieties().ToDictionaryAsync(v => v.SortId, v => v);
var mgnr = await ctx.FetchMembers(includeNotActive: true).ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
var mgnr = await ctx.FetchMembers(true).ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
var zwst = await ctx.FetchBranches().ToDictionaryAsync(b => b.Name.ToLower().Split(' ')[0], b => b);
var attr = await ctx.FetchWineAttributes().ToDictionaryAsync(a => a.Name.ToLower().Split(' ')[0], a => a);
var cult = await ctx.FetchWineCultivations().ToDictionaryAsync(c => c.Name.ToLower().Split(' ')[0], c => c);
+3 -3
View File
@@ -27,7 +27,7 @@ namespace Elwig.Services {
public static async Task<Member?> GetMemberAsync(int mgnr) {
using var ctx = new AppDbContext();
return await ctx.FetchMembers(mgnr).SingleOrDefaultAsync();
return await ctx.Members.Where(m => m.MgNr == mgnr).FirstOrDefaultAsync();
}
public static Member? GetMember(int mgnr) {
@@ -128,7 +128,7 @@ namespace Elwig.Services {
if (filter.Count > 0) {
var var = await ctx.FetchWineVarieties().ToDictionaryAsync(v => v.SortId, v => v);
var qual = await ctx.FetchWineQualityLevels(false).ToDictionaryAsync(q => q.QualId, q => q);
var mgnr = await ctx.FetchMembers(includeNotActive: true).ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
var mgnr = await ctx.FetchMembers(true).ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
var zwst = await ctx.FetchBranches().ToDictionaryAsync(b => b.Name.ToLower().Split(' ')[0], b => b);
var attr = await ctx.FetchWineAttributes().ToDictionaryAsync(a => a.Name.ToLower().Split(' ')[0], a => a);
var cult = await ctx.FetchWineCultivations().ToDictionaryAsync(c => c.Name.ToLower().Split(' ')[0], c => c);
@@ -553,7 +553,7 @@ namespace Elwig.Services {
if (originalMgNr != null && originalMgNr.Value != d.MgNr) {
// update origin (KgNr), if default is selected
var newKgNr = (await ctx.FetchMembers(d.MgNr).SingleOrDefaultAsync())?.DefaultKgNr;
var newKgNr = (await ctx.Members.FindAsync(d.MgNr))?.DefaultKgNr;
await ctx.DeliveryParts
.Where(p => p.Year == d.Year && p.DId == d.DId && p.DPNr != dpnr && p.KgNr == originalMemberKgNr)
.ExecuteUpdateAsync(u => u.SetProperty(p => p.KgNr, newKgNr));
+4 -4
View File
@@ -226,7 +226,7 @@ namespace Elwig.Services {
var filter = vm.TextFilter;
if (filter.Count > 0) {
var branches = await ctx.FetchBranches().ToListAsync();
var mgnr = await ctx.FetchMembers(includeNotActive: true).ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
var mgnr = await ctx.FetchMembers(true).ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
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);
@@ -413,7 +413,7 @@ namespace Elwig.Services {
await b.CalculateBuckets();
App.HintContextChange();
using var doc = new DeliveryConfirmation(year, m, null);
using var doc = new DeliveryConfirmation(year, m);
await Utils.ExportDocument(doc, mode, emailData: (m, $"{DeliveryConfirmation.Name} {year}", $"Im Anhang finden Sie die Anlieferungsbestätigung {year}"));
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
@@ -426,7 +426,7 @@ namespace Elwig.Services {
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
using var doc = await CreditNote.Initialize(year, avnr, m.MgNr, null);
using var doc = await CreditNote.Initialize(year, avnr, m.MgNr);
await Utils.ExportDocument(doc, mode, emailData: (m, $"{CreditNote.Name} {doc.Payment.Variant.Name}", $"Im Anhang finden Sie die Traubengutschrift {doc.Payment.Variant.Name}"));
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
@@ -708,7 +708,7 @@ namespace Elwig.Services {
await Task.Run(async () => {
using var ctx = new AppDbContext();
using var tx = await ctx.Database.BeginTransactionAsync();
var l = await ctx.FetchMembers(mgnr).SingleAsync();
var l = (await ctx.Members.FindAsync(mgnr))!;
if (deletePaymentData) {
await ctx.Credits.Where(c => c.MgNr == mgnr).ExecuteDeleteAsync();
}
+1 -1
View File
@@ -258,7 +258,7 @@ namespace Elwig.Services {
public static async Task<bool> ChangesAvailable(AppDbContext ctx, string url, string username, string password) {
try {
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);
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);
} catch {
return false;
}
-1
View File
@@ -104,7 +104,6 @@ namespace Elwig.Windows {
cb.SelectionChanged += ComboBox_SelectionChanged;
foreach (var lb in ListBoxInputs)
lb.SelectionChanged += ComboBox_SelectionChanged;
LockInputs();
}
private void OnClosing(object? sender, CancelEventArgs evt) {
+7 -5
View File
@@ -39,6 +39,10 @@ namespace Elwig.Windows {
ViewModel.FilterSeason = Utils.CurrentYear;
}
protected override async Task OnInit(AppDbContext ctx) {
LockInputs();
}
private void FocusSearchInput(object sender, RoutedEventArgs evt) {
if (!IsEditing && !IsCreating) {
SearchInput.Focus();
@@ -159,7 +163,7 @@ namespace Elwig.Windows {
protected override async Task OnRenewContext(AppDbContext ctx) {
await base.OnRenewContext(ctx);
if (await ctx.FetchMembers(ViewModel.FilterMember.MgNr).SingleOrDefaultAsync() is not Member m) {
if (await ctx.Members.FindAsync(ViewModel.FilterMember.MgNr) is not Member m) {
Close();
return;
}
@@ -176,7 +180,7 @@ namespace Elwig.Windows {
.Include(c => c.WineAttr)
.OrderBy(v => v.VtrgId)
.ToListAsync());
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: true).ToListAsync());
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(true).ToListAsync());
var cultList = await ctx.FetchWineCultivations().Cast<object>().ToListAsync();
cultList.Insert(0, new NullItem());
ControlUtils.RenewItemsSource(WineCultivationInput, cultList, null, ControlUtils.RenewSourceDefault.First);
@@ -447,19 +451,17 @@ namespace Elwig.Windows {
}
private async void ActiveAreaCommitmentInput_Changed(object sender, RoutedEventArgs evt) {
if (!HasContextLoaded) return;
await RefreshList();
}
private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) {
if (!HasContextLoaded) return;
var binding = ((TextBox)sender).GetBindingExpression(TextBox.TextProperty);
binding?.UpdateSource();
await RefreshList(true);
}
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
if (!HasContextLoaded || ViewModel.FilterSeason == null) return;
if (ViewModel.FilterSeason == null) return;
await RefreshList();
}
+12 -7
View File
@@ -19,7 +19,10 @@ namespace Elwig.Windows {
private bool _branchUpdate = false;
private async Task BranchesInitEditing(AppDbContext ctx) {
_branchList = new(await ctx.FetchBranches().ToListAsync());
_branchList = new(await ctx.Branches
.OrderBy(b => b.Name)
.Include(b => b.PostalDest)
.ToListAsync());
_branches = _branchList.ToDictionary(b => b.ZwstId, b => (string?)b.ZwstId);
_branchIds = _branchList.ToDictionary(b => b, b => b.ZwstId);
ControlUtils.RenewItemsSource(BranchList, _branchList);
@@ -27,7 +30,10 @@ namespace Elwig.Windows {
}
private async Task BranchesFinishEditing(AppDbContext ctx) {
ControlUtils.RenewItemsSource(BranchList, await ctx.FetchBranches().ToListAsync());
ControlUtils.RenewItemsSource(BranchList, await ctx.Branches
.OrderBy(b => b.Name)
.Include(b => b.PostalDest)
.ToListAsync());
_branchList = null;
_branches = null;
_branchIds = null;
@@ -41,10 +47,9 @@ namespace Elwig.Windows {
if (!_branchChanged || _branchList == null || _branches == null || _branchIds == null)
return;
var tx = await ctx.Database.BeginTransactionAsync();
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 (zwstid, _) in _branches.Where(b => b.Value == null)) {
ctx.Remove(ctx.Branches.Find(zwstid)!);
}
foreach (var (branch, old) in _branchIds) {
branch.ZwstId = old;
}
@@ -56,13 +61,13 @@ namespace Elwig.Windows {
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.SaveChangesAsync();
foreach (var branch in _branchList.Where(b => !_branchIds.ContainsKey(b))) {
if (branch.ZwstId == null) continue;
ctx.Add(branch);
}
await ctx.SaveChangesAsync();
await tx.CommitAsync();
}
private void BranchList_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) {
+2 -2
View File
@@ -22,7 +22,7 @@ namespace Elwig.Windows {
private async Task ModifiersInitEditing(AppDbContext ctx) {
SeasonList.IsEnabled = false;
var year = (SeasonList.SelectedItem as Season)?.Year;
_modList = new(await ctx.FetchModifiers(year ?? 0).ToListAsync());
_modList = new(await ctx.FetchModifiers(year).ToListAsync());
_mods = _modList.ToDictionary(m => m.ModId, m => (string?)m.ModId);
_modIds = _modList.ToDictionary(m => m, m => m.ModId);
ControlUtils.RenewItemsSource(SeasonModifierList, _modList);
@@ -31,7 +31,7 @@ namespace Elwig.Windows {
private async Task ModifiersFinishEditing(AppDbContext ctx) {
var year = (SeasonList.SelectedItem as Season)?.Year;
ControlUtils.RenewItemsSource(SeasonModifierList, await ctx.FetchModifiers(year ?? 0).ToListAsync());
ControlUtils.RenewItemsSource(SeasonModifierList, await ctx.FetchModifiers(year).ToListAsync());
_modList = null;
_mods = null;
_modIds = null;
+2 -2
View File
@@ -19,14 +19,14 @@ namespace Elwig.Windows {
private async Task SeasonsInitEditing(AppDbContext ctx) {
SeasonAddButton.IsEnabled = false;
SeasonRemoveButton.IsEnabled = false;
ControlUtils.RenewItemsSource(SeasonList, await ctx.FetchSeasons(includeModifiers: true).ToListAsync());
ControlUtils.RenewItemsSource(SeasonList, await ctx.FetchSeasons().ToListAsync());
SeasonList_SelectionChanged(null, null);
}
private async Task SeasonsFinishEditing(AppDbContext ctx) {
SeasonAddButton.IsEnabled = true;
SeasonRemoveButton.IsEnabled = true;
ControlUtils.RenewItemsSource(SeasonList, await ctx.FetchSeasons(includeModifiers: true).ToListAsync());
ControlUtils.RenewItemsSource(SeasonList, await ctx.FetchSeasons().ToListAsync());
_seasonChanged = false;
}
+9 -2
View File
@@ -153,12 +153,19 @@ namespace Elwig.Windows {
ParameterExportEbicsAddress.IsEnabled = true;
}
protected override async Task OnInit(AppDbContext ctx) {
LockInputs();
}
protected override async Task OnRenewContext(AppDbContext ctx) {
await base.OnRenewContext(ctx);
FillInputs(App.Client, await ctx.FetchSeasons(Utils.CurrentLastSeason).SingleOrDefaultAsync());
ControlUtils.RenewItemsSource(SeasonList, await ctx.FetchSeasons(includeModifiers: true).ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
ControlUtils.RenewItemsSource(SeasonList, await ctx.FetchSeasons().ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
var year = (SeasonList.SelectedItem as Season)?.Year;
ControlUtils.RenewItemsSource(BranchList, await ctx.FetchBranches().ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
ControlUtils.RenewItemsSource(BranchList, await ctx.Branches
.OrderBy(b => b.Name)
.Include(b => b.PostalDest)
.ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
ControlUtils.RenewItemsSource(WineAttributeList, await ctx.FetchWineAttributes().ToListAsync(), null, ControlUtils.RenewSourceDefault.First);
ControlUtils.RenewItemsSource(AreaCommitmentTypeWineVariantInput, await ctx.FetchWineVarieties().ToListAsync());
var attrList = await ctx.FetchWineAttributes().Cast<object>().ToListAsync();
-3
View File
@@ -18,8 +18,6 @@ namespace Elwig.Windows {
}
}
protected bool HasContextLoaded { get; private set; }
private bool _renewPending = false;
private readonly RoutedCommand CtrlR = new("CtrlR", typeof(ContextWindow), [new KeyGesture(Key.R, ModifierKeys.Control)]);
@@ -53,7 +51,6 @@ namespace Elwig.Windows {
Mouse.OverrideCursor = Cursors.AppStarting;
using var ctx = new AppDbContext();
await OnRenewContext(ctx);
HasContextLoaded = true;
await OnInit(ctx);
Mouse.OverrideCursor = null;
}
+2 -2
View File
@@ -529,12 +529,12 @@
</Grid.ColumnDefinitions>
<Label Content="Gradation:" Margin="10,10,10,10"/>
<ctrl:UnitTextBox x:Name="GradationOeInput" Unit="°Oe" Text="{Binding GradationOeString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextChanged="GradationOeInput_TextChanged" LostFocus="GradationOeInput_LostFocus" KeyUp="Input_KeyUp"
TextChanged="GradationOeInput_TextChanged" KeyUp="Input_KeyUp"
Grid.Column="1" Width="54" Margin="0,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Label Content="=" Margin="60,10,10,10" Grid.Column="1"/>
<ctrl:UnitTextBox x:Name="GradationKmwInput" Unit="°KMW" Text="{Binding GradationKmwString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextChanged="GradationKmwInput_TextChanged" LostFocus="GradationKmwInput_LostFocus" KeyUp="Input_KeyUp"
TextChanged="GradationKmwInput_TextChanged" KeyUp="Input_KeyUp"
Grid.Column="1" Width="68" Margin="78,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Label Content="Qualitätsstufe:" Margin="10,40,10,10"/>
+17 -19
View File
@@ -37,7 +37,6 @@ namespace Elwig.Windows {
private readonly Button[] WeighingButtons;
private List<WineQualLevel> WineQualityLevels = [];
private Dictionary<int, List<Modifier>> Modifiers = [];
public DeliveryAdminWindow(bool receipt = false) {
InitializeComponent();
@@ -123,8 +122,7 @@ namespace Elwig.Windows {
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.Title = $"Lieferungen - {ViewModel.FilterMember.AdministrativeName} - Elwig";
ViewModel.EnableAllSeasons = true;
@@ -134,6 +132,7 @@ namespace Elwig.Windows {
await base.OnInit(ctx);
OnSecondPassed(null, null);
SecondsTimer.Start();
LockInputs();
if (ViewModel.IsReceipt) {
NewDeliveryButton_Click(null, null);
if (await ctx.FetchSeasons(Utils.CurrentYear).SingleOrDefaultAsync() == null) {
@@ -431,8 +430,7 @@ namespace Elwig.Windows {
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)
.Include(d => d.Member.EmailAddresses)
.IgnoreAutoIncludes()
.AsSplitQuery()
.ToListAsync();
@@ -509,7 +507,7 @@ namespace Elwig.Windows {
}
var attributes = await ctx.FetchWineAttributes(!IsCreating).ToListAsync();
Modifiers = await ctx.FetchModifiers(null).GroupBy(m => m.Year).ToDictionaryAsync(g => g.Key, g => g.ToList());
var modifiers = await ctx.FetchModifiers(year, !IsCreating).ToListAsync();
var font = new FontFamily("Segoe MDL2 Assets");
Menu_BulkAction_SetAttribute.Items.Clear();
@@ -529,7 +527,7 @@ namespace Elwig.Windows {
Menu_BulkAction_AddModifier.Items.Clear();
Menu_BulkAction_RemoveModifier.Items.Clear();
foreach (var mod in Modifiers.GetValueOrDefault(ViewModel.SelectedDelivery?.Year ?? year, [])) {
foreach (var mod in modifiers) {
var i1 = new MenuItem {
Header = mod.Name,
};
@@ -544,7 +542,9 @@ namespace Elwig.Windows {
await RefreshList();
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: !IsCreating, includeContactInfo: true).ToListAsync());
var d = DeliveryList.SelectedItem as Delivery;
var y = d?.Year ?? ViewModel.FilterSeason ?? Utils.CurrentYear;
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(!IsCreating).ToListAsync());
ControlUtils.RenewItemsSource(BranchInput, await ctx.FetchBranches().ToListAsync());
ControlUtils.RenewItemsSource(WineVarietyInput, await ctx.FetchWineVarieties().ToListAsync());
var attrList = attributes.Cast<object>().ToList();
@@ -555,7 +555,7 @@ namespace Elwig.Windows {
ControlUtils.RenewItemsSource(CultivationInput, cultList, null, ControlUtils.RenewSourceDefault.First);
WineQualityLevels = await ctx.FetchWineQualityLevels().ToListAsync();
ControlUtils.RenewItemsSource(WineQualityLevelInput, WineQualityLevels);
ControlUtils.RenewItemsSource(ModifiersInput, Modifiers.GetValueOrDefault(year, []).Where(m => m.IsActive || !IsCreating).ToList());
ControlUtils.RenewItemsSource(ModifiersInput, modifiers);
var origins = await ctx.WineOrigins.ToListAsync();
origins.ForEach(o => { origins.FirstOrDefault(p => p.HkId == o.ParentHkId)?.Children.Add(o); });
origins = [.. origins.OrderByDescending(o => o.SortKey).ThenBy(o => o.HkId)];
@@ -582,11 +582,12 @@ namespace Elwig.Windows {
}
private async Task RefreshDeliveryParts() {
using var ctx = new AppDbContext();
if (DeliveryList.SelectedItem is Delivery d) {
ControlUtils.RenewItemsSource(ModifiersInput, Modifiers.GetValueOrDefault(d.Year, []).Where(m => m.IsActive || !IsCreating).ToList());
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.FetchModifiers(d.Year, !IsCreating).ToListAsync());
ControlUtils.RenewItemsSource(DeliveryPartList, d.Parts, DeliveryPartList_SelectionChanged, ControlUtils.RenewSourceDefault.First);
} else {
ControlUtils.RenewItemsSource(ModifiersInput, Modifiers.GetValueOrDefault(ViewModel.FilterSeason ?? 0, []).Where(m => m.IsActive || !IsCreating).ToList());
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.FetchModifiers(ViewModel.FilterSeason, !IsCreating).ToListAsync());
DeliveryPartList.ItemsSource = null;
}
}
@@ -678,19 +679,17 @@ namespace Elwig.Windows {
}
private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) {
if (!HasContextLoaded) return;
await RefreshList(true);
}
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
if (!HasContextLoaded || ViewModel.FilterSeason == null || TodayOnlyInput == null || AllSeasonsInput == null) return;
if (ViewModel.FilterSeason == null || TodayOnlyInput == null || AllSeasonsInput == null) return;
TodayOnlyInput.IsChecked = false;
AllSeasonsInput.IsChecked = false;
await RefreshList();
}
private async void TodayOnlyInput_Changed(object sender, RoutedEventArgs evt) {
if (!HasContextLoaded) return;
if (TodayOnlyInput.IsChecked == true && AllSeasonsInput.IsChecked == false) {
ViewModel.FilterSeason = Utils.Today.Year;
ViewModel.FilterTodayOnly = true;
@@ -699,7 +698,6 @@ namespace Elwig.Windows {
}
private async void AllSeasonsInput_Changed(object sender, RoutedEventArgs evt) {
if (!HasContextLoaded) return;
if (AllSeasonsInput.IsChecked == true) {
SeasonInput.IsEnabled = false;
ViewModel.FilterSeason = null;
@@ -719,7 +717,7 @@ namespace Elwig.Windows {
Menu_DeliveryNote_Show.IsEnabled = !IsEditing && !IsCreating;
Menu_DeliveryNote_SavePdf.IsEnabled = !IsEditing && !IsCreating;
Menu_DeliveryNote_Print.IsEnabled = !IsEditing && !IsCreating;
Menu_DeliveryNote_Email.IsEnabled = !IsEditing && !IsCreating && App.Config.Smtp != null && ViewModel.Member?.EmailAddresses.Count > 0;
Menu_DeliveryNote_Email.IsEnabled = !IsEditing && !IsCreating && App.Config.Smtp != null && d.Member.EmailAddresses.Count > 0;
Menu_Export_ExportSelected.IsEnabled = !IsEditing && !IsCreating;
Menu_Export_UploadSelected.IsEnabled = !IsEditing && !IsCreating && App.Config.SyncUrl != null;
} else {
@@ -880,7 +878,7 @@ namespace Elwig.Windows {
var attrList = await ctx.FetchWineAttributes().Cast<object>().ToListAsync();
attrList.Insert(0, new NullItem(""));
ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First);
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: !ViewModel.IsReceipt, includeContactInfo: true).ToListAsync());
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(!ViewModel.IsReceipt).ToListAsync());
if (DeliveryList.SelectedItem is not Delivery d) {
// switch away from creating mode
IsCreating = false;
@@ -915,8 +913,8 @@ namespace Elwig.Windows {
var attrList = await ctx.FetchWineAttributes(false).Cast<object>().ToListAsync();
attrList.Insert(0, new NullItem(""));
ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First);
ControlUtils.RenewItemsSource(ModifiersInput, Modifiers.GetValueOrDefault(ViewModel.FilterSeason ?? 0, []).Where(m => m.IsActive).ToList());
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: !ViewModel.IsReceipt, includeContactInfo: true).ToListAsync());
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.FetchModifiers(ViewModel.FilterSeason, false).ToListAsync());
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(!ViewModel.IsReceipt).ToListAsync());
IsCreating = true;
DeliveryList.IsEnabled = false;
DeliveryPartList.IsEnabled = false;
@@ -39,6 +39,10 @@ namespace Elwig.Windows {
ViewModel.FilterOnlyUpcoming = true;
}
protected override async Task OnInit(AppDbContext ctx) {
LockInputs();
}
private void Input_KeyUp(object sender, KeyEventArgs evt) {
if (sender is not Control ctrl) return;
if (evt.Key != Key.Enter) return;
@@ -177,7 +181,7 @@ namespace Elwig.Windows {
protected override async Task OnRenewContext(AppDbContext ctx) {
await base.OnRenewContext(ctx);
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: !IsCreating).ToListAsync());
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(!IsCreating).ToListAsync());
ControlUtils.RenewItemsSource(WineVarietyInput, await ctx.FetchWineVarieties().ToListAsync());
await RefreshDeliveryScheduleList();
@@ -189,7 +193,6 @@ namespace Elwig.Windows {
}
private async void DeliveryScheduleList_SelectionChanged(object sender, RoutedEventArgs evt) {
if (!HasContextLoaded) return;
await RefreshList();
if (DeliveryScheduleList.SelectedItem is DeliverySchedule s) {
Menu_DeliveryAncmtList_SaveSelected.IsEnabled = !IsEditing && !IsCreating;
@@ -211,13 +214,11 @@ namespace Elwig.Windows {
}
private async void OnlyUpcomingInput_Changed(object sender, RoutedEventArgs evt) {
if (!HasContextLoaded) return;
await RefreshDeliveryScheduleList();
await RefreshList(true);
}
private async void FromAllSchedulesInput_Changed(object sender, RoutedEventArgs evt) {
if (!HasContextLoaded) return;
if (ViewModel.FilterFromAllSchedules) {
DeliveryScheduleList.SelectedItem = null;
} else if (DeliveryScheduleList.SelectedItem == null) {
@@ -227,12 +228,11 @@ namespace Elwig.Windows {
}
private async void SearchInput_TextChanged(object sender, TextChangedEventArgs evt) {
if (!HasContextLoaded) return;
await RefreshList(true);
}
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
if (!HasContextLoaded || ViewModel.FilterSeason == null) return;
if (ViewModel.FilterSeason == null) return;
ViewModel.FilterOnlyUpcoming = false;
await RefreshDeliveryScheduleList();
await RefreshList();
@@ -271,7 +271,7 @@ namespace Elwig.Windows {
ViewModel.SelectedDeliveryAncmt = null;
using var ctx = new AppDbContext();
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: !IsCreating).ToListAsync());
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(!IsCreating).ToListAsync());
HideNewEditDeleteButtons();
ShowSaveResetCancelButtons();
@@ -393,7 +393,7 @@ namespace Elwig.Windows {
DeliveryAncmtList.IsEnabled = true;
using var ctx = new AppDbContext();
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: !IsCreating).ToListAsync());
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(!IsCreating).ToListAsync());
HideSaveResetCancelButtons();
ShowNewEditDeleteButtons();
@@ -33,6 +33,10 @@ namespace Elwig.Windows {
ViewModel.FilterOnlyUpcoming = true;
}
protected override async Task OnInit(AppDbContext ctx) {
LockInputs();
}
private async Task RefreshList(bool updateSort = false) {
var vm = ViewModel;
var cursor = Mouse.OverrideCursor != null;
@@ -120,17 +124,15 @@ namespace Elwig.Windows {
}
private async void OnlyUpcomingInput_Changed(object sender, RoutedEventArgs evt) {
if (!HasContextLoaded) return;
await RefreshList();
}
private async void SearchInput_TextChanged(object sender, TextChangedEventArgs evt) {
if (!HasContextLoaded) return;
await RefreshList(true);
}
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
if (!HasContextLoaded || ViewModel.FilterSeason == null) return;
if (ViewModel.FilterSeason == null) return;
ViewModel.FilterOnlyUpcoming = false;
await RefreshList();
}
+5 -8
View File
@@ -155,7 +155,7 @@ namespace Elwig.Windows {
}
protected override async Task OnRenewContext(AppDbContext ctx) {
var season = await ctx.Seasons.Include(s => s.PaymentVariants).Where(s => s.Year == Year).SingleOrDefaultAsync();
var season = await ctx.Seasons.Include(s => s.PaymentVariants).Where(s => s.Year == Year).SingleAsync();
var l = new List<string> {
MemberDataSheet.Name
};
@@ -165,7 +165,7 @@ namespace Elwig.Windows {
}
AvaiableDocumentsList.ItemsSource = l;
ControlUtils.RenewItemsSource(MemberBranchInput, await ctx.FetchBranches(includeWithoutMembers: false).ToListAsync(), MemberInput_SelectionChanged);
ControlUtils.RenewItemsSource(MemberBranchInput, await ctx.FetchBranches(true).ToListAsync(), MemberInput_SelectionChanged);
if (MemberBranchInput.SelectedItems.Count == 0) {
MemberBranchInput.SelectionChanged -= MemberInput_SelectionChanged;
MemberBranchInput.SelectAll();
@@ -690,7 +690,7 @@ namespace Elwig.Windows {
PrintButton.IsEnabled = PrintDocument != null && !hasPreviewDocs;
EmailButton.IsEnabled = EmailDocuments != null && !hasPreviewDocs && App.Config.Smtp != null;
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
MessageBox.Show(exc.ToString(), "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
} finally {
UnlockInputs();
GenerateButton.IsEnabled = true;
@@ -742,9 +742,6 @@ namespace Elwig.Windows {
Member = m,
Docs = docs.SelectMany<SelectedDoc, GeneratedDoc>(doc => {
try {
App.MainDispatcher.Invoke(() => {
ProgressBar.Value = offset + 100.0 * i / 2 / totalNum;
});
if (doc.Type == DocType.Custom) {
return [new GeneratedDoc((string)doc.Details!)];
} else if (doc.Type == DocType.MemberDataSheet) {
@@ -759,14 +756,14 @@ namespace Elwig.Windows {
} else {
return [];
}
return [new GeneratedDoc(new DeliveryConfirmation(year, m, postalDate, data) { Date = postalDate })];
return [new GeneratedDoc(new DeliveryConfirmation(year, m, data) { Date = postalDate })];
} else if (doc.Type == DocType.CreditNote) {
var details = ((int, int))doc.Details!;
var year = details.Item1;
var avnr = details.Item2;
var data = cnData[(year, avnr)];
try {
return [new GeneratedDoc(new CreditNote(data.Item2[m.MgNr], postalDate, data.Item3, data.Item1[m.MgNr]) { Date = postalDate })];
return [new GeneratedDoc(new CreditNote(data.Item2[m.MgNr], data.Item3, data.Item1[m.MgNr]) { Date = postalDate })];
} catch (Exception) {
return [];
}
-1
View File
@@ -41,7 +41,6 @@ namespace Elwig.Windows {
}
protected override async Task OnInit(AppDbContext ctx) {
await base.OnInit(ctx);
if (Utils.HasInternetConnectivity()) {
CheckSync(200);
}
+9 -6
View File
@@ -83,8 +83,11 @@ namespace Elwig.Windows {
Menu_Export_UploadFilters.IsEnabled = App.Config.SyncUrl != null;
Menu_Export_UploadAll.IsEnabled = App.Config.SyncUrl != null;
ViewModel.ShowOnlyActiveMembers = true;
}
protected override async Task OnInit(AppDbContext ctx) {
UpdateContactInfoVisibility();
LockInputs();
}
public void FocusMember(int mgnr) {
@@ -331,7 +334,7 @@ namespace Elwig.Windows {
}
private async void ActiveMemberInput_Changed(object sender, RoutedEventArgs evt) {
if (!HasContextLoaded) return;
if (!IsInitialized) return;
await RefreshList();
}
@@ -388,9 +391,10 @@ namespace Elwig.Windows {
int areaComs = 0, deliveries = 0, credits = 0;
using (var ctx = new AppDbContext()) {
areaComs = await ctx.AreaCommitments.Where(c => c.MgNr == m.MgNr).CountAsync();
deliveries = await ctx.Deliveries.Where(d => d.MgNr == m.MgNr).CountAsync();
credits = await ctx.Credits.Where(c => c.MgNr == m.MgNr).CountAsync();
var l = (await ctx.Members.FindAsync(m.MgNr))!;
areaComs = l.AreaCommitments.Count;
deliveries = l.Deliveries.Count;
credits = l.Credits.Count;
}
var d = new DeleteMemberDialog(m.MgNr, m.AdministrativeName, areaComs, deliveries, credits);
if (d.ShowDialog() == true) {
@@ -487,7 +491,6 @@ namespace Elwig.Windows {
}
private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) {
if (!HasContextLoaded) return;
await RefreshList(true);
}
@@ -793,7 +796,7 @@ namespace Elwig.Windows {
if (areaComs.Count == 0)
return;
var oldMember = await ctx.FetchMembers(mgnr).SingleAsync();
var oldMember = (await ctx.Members.FindAsync(mgnr))!;
var newName = $"{ViewModel.Name?.Replace('ß', 'ẞ').ToUpper()} " +
$"{ViewModel.Prefix}{(!string.IsNullOrEmpty(ViewModel.Prefix) ? " " : "")}" +
$"{ViewModel.GivenName}{(!string.IsNullOrEmpty(ViewModel.GivenName) ? " " : "")}" +
@@ -40,7 +40,7 @@ namespace Elwig.Windows {
}
protected override async Task OnRenewContext(AppDbContext ctx) {
var members = await ctx.FetchMembers(includeNotActive: true)
var members = await ctx.Members
.Select(m => new {
m.MgNr,
m.Name,
@@ -48,6 +48,9 @@ namespace Elwig.Windows {
m.BusinessShares,
m.IsActive,
})
.OrderBy(m => m.Name)
.ThenBy(m => m.GivenName)
.ThenBy(m => m.MgNr)
.ToListAsync();
var season = await ctx.FetchSeasons(Year).SingleAsync();
var contracts = await ctx.AreaCommitmentTypes.ToDictionaryAsync(t => t.VtrgId, t => t);
@@ -142,7 +145,7 @@ namespace Elwig.Windows {
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}";
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(includeNotActive: true).ToListAsync());
ControlUtils.RenewItemsSource(MemberInput, await ctx.FetchMembers(true).ToListAsync());
CustomAmountInput.Unit = sym;
}
+1 -2
View File
@@ -1,4 +1,4 @@
<Project Sdk="WixToolset.Sdk/7">
<Project Sdk="WixToolset.Sdk/6">
<PropertyGroup>
<HarvestFileSuppressUniqueIds>false</HarvestFileSuppressUniqueIds>
<HarvestFileGenerateGuidsNow>true</HarvestFileGenerateGuidsNow>
@@ -11,7 +11,6 @@
<BuildProjectReferences>False</BuildProjectReferences>
<OutputName>Elwig</OutputName>
<Cultures>de-AT</Cultures>
<AcceptEula>wix7</AcceptEula>
</PropertyGroup>
<UsingTask TaskName="GetFileVersion" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
+2 -2
View File
@@ -13,7 +13,7 @@ About
**Product:** Elwig
**Description:** Electronic Management for Vintners' Cooperatives
**Type:** ERP system
**Version:** 1.0.5.2 ([Changelog](./CHANGELOG.md))
**Version:** 1.0.4.1 ([Changelog](./CHANGELOG.md))
**License:** [GNU General Public License 3.0 (GPLv3)](./LICENSE)
**Website:** https://elwig.at/
**Source code:** https://git.necronda.net/winzer/elwig
@@ -33,7 +33,7 @@ Packaging: [WiX Toolset](https://www.firegiant.com/wixtoolset/)
**Produkt:** Elwig
**Beschreibung:** Elektronische Winzergenossenschaftsverwaltung
**Typ:** Warenwirtschaftssystem (ERP-System)
**Version:** 1.0.5.2 ([Änderungsprotokoll](./CHANGELOG.md))
**Version:** 1.0.4.1 ([Änderungsprotokoll](./CHANGELOG.md))
**Lizenz:** [GNU General Public License 3.0 (GPLv3)](./LICENSE)
**Website:** https://elwig.at/
**Quellcode:** https://git.necronda.net/winzer/elwig
+3 -4
View File
@@ -1,9 +1,8 @@
<Project Sdk="WixToolset.Sdk/7">
<Project Sdk="WixToolset.Sdk/6">
<PropertyGroup>
<OutputType>Bundle</OutputType>
<OutputName>Elwig</OutputName>
<Cultures>de-AT</Cultures>
<AcceptEula>wix7</AcceptEula>
</PropertyGroup>
<Target Name="CustomBeforeBuild" BeforeTargets="BeforeBuild">
<Exec Command="curl --fail -s -L &quot;https://go.microsoft.com/fwlink/p/?LinkId=2124703&quot; -z &quot;$(ProjectDir)\Files\MicrosoftEdgeWebview2Setup.exe&quot; -o &quot;$(ProjectDir)\Files\MicrosoftEdgeWebview2Setup.exe&quot;" />
@@ -14,7 +13,7 @@
</Target>
<ItemGroup>
<ProjectReference Include="..\Installer\Installer.wixproj" />
<PackageReference Include="WixToolset.Bal.wixext" Version="7.0.0" />
<PackageReference Include="WixToolset.Util.wixext" Version="7.0.0" />
<PackageReference Include="WixToolset.Bal.wixext" Version="6.0.2" />
<PackageReference Include="WixToolset.Util.wixext" Version="6.0.2" />
</ItemGroup>
</Project>
-1
View File
@@ -80,7 +80,6 @@ namespace Tests.E2ETests {
Window.FindElement(By.WpfId("SaveButton")).Click();
Thread.Sleep(500);
Window.FindElement(By.WpfId("SearchInput")).SendKeys("9999");
Thread.Sleep(500);
var memberListRow = Window.FindElement(By.WpfId("MemberList")).FindElement(By.ClassName("DataGridRow"));
+2 -2
View File
@@ -19,7 +19,7 @@
</Target>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.4.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
<PackageReference Include="Appium.WebDriver" Version="4.4.5" />
<PackageReference Include="NReco.PdfRenderer" Version="1.6.0" />
<PackageReference Include="NUnit" Version="4.5.1" />
@@ -28,7 +28,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="10.0.0">
<PackageReference Include="coverlet.collector" Version="8.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
@@ -6,7 +6,7 @@ namespace Tests.UnitTests.DocumentTests {
[Test]
public async Task Test_01_VirtualCreditNote() {
using var doc = await CreditNote.Initialize(2020, 1, 101, null);
using var doc = await CreditNote.Initialize(2020, 1, 101);
var text = await Utils.GeneratePdfText(doc);
Assert.Multiple(() => {
Assert.That(text, Contains.Substring("""
@@ -9,9 +9,9 @@ namespace Tests.UnitTests.DocumentTests {
[Test]
public async Task Test_01_SimpleDeliveryConfirmation() {
using var ctx = new AppDbContext();
var m = await ctx.FetchMembers(101).SingleAsync();
var m = await ctx.Members.FindAsync(101);
var data = await DeliveryConfirmationDeliveryData.ForMember(ctx.DeliveryParts, 2020, m!);
using var doc = new DeliveryConfirmation(2020, m!, null, data);
using var doc = new DeliveryConfirmation(2020, m!, data);
var text = await Utils.GeneratePdfText(doc);
Assert.Multiple(() => {
Assert.That(text, Contains.Substring("""
@@ -8,7 +8,7 @@ namespace Tests.UnitTests.DocumentTests {
[Test]
public async Task Test_01_SimpleLetterhead() {
using var ctx = new AppDbContext();
var m = await ctx.FetchMembers(104).SingleAsync();
var m = await ctx.Members.FindAsync(104);
using var doc = new Letterhead(m!);
var text = await Utils.GeneratePdfText(doc);
Assert.Multiple(() => {
+1 -1
View File
@@ -33,7 +33,7 @@ namespace Tests.UnitTests.HelperTests {
DateString = "2021-01-31",
};
using var ctx = new AppDbContext();
var members = await ctx.FetchMembers().ToListAsync();
var members = ctx.Members.ToList();
Assert.That(members, Has.Count.GreaterThan(0));
using var exporter = new Ebics(v, FileName, version, mode);
await exporter.ExportAsync(members.Select(m => new Transaction(m, 1234.56m, "EUR", m.MgNr % 100)));
@@ -10,7 +10,7 @@ namespace Tests.UnitTests.ServiceTests {
private static async Task InitViewModel(DeliveryAdminViewModel vm) {
using var ctx = new AppDbContext();
vm.MemberSource = await ctx.FetchMembers(includeNotActive: true).ToListAsync();
vm.MemberSource = await ctx.FetchMembers(true).ToListAsync();
vm.BranchSource = await ctx.FetchBranches().ToListAsync();
vm.WineVarSource = await ctx.FetchWineVarieties().ToListAsync();
List<object> attrs = await ctx.FetchWineAttributes().Cast<object>().ToListAsync();
@@ -31,14 +31,18 @@ namespace Tests.UnitTests.ServiceTests {
Assert.That(vm.MgNr, Is.EqualTo(205));
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.FetchMembers(205, includeNotActive: true).SingleOrDefaultAsync(), Is.Null);
Assert.That(await ctx.Members.FindAsync(205), Is.Null);
}
Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(null));
Member m;
using (var ctx = new AppDbContext()) {
m = await ctx.FetchMembers(vm.MgNr, includeNotActive: true, includeContactInfo: true).SingleAsync();
m = await ctx.Members
.Where(m => m.MgNr == vm.MgNr)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.SingleAsync();
}
Assert.That(m, Is.Not.Null);
@@ -111,14 +115,18 @@ namespace Tests.UnitTests.ServiceTests {
vm.IsFunktionär = true;
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.FetchMembers(999, includeNotActive: true).SingleOrDefaultAsync(), Is.Null);
Assert.That(await ctx.Members.FindAsync(999), Is.Null);
}
Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(null));
Member m;
using (var ctx = new AppDbContext()) {
m = await ctx.FetchMembers(vm.MgNr, includeNotActive: true, includeContactInfo: true).SingleAsync();
m = await ctx.Members
.Where(m => m.MgNr == vm.MgNr)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.SingleAsync();
}
Assert.That(m, Is.Not.Null);
@@ -218,7 +226,11 @@ namespace Tests.UnitTests.ServiceTests {
var vm = new MemberAdminViewModel();
await InitViewModel(vm);
using (var ctx = new AppDbContext()) {
vm.FillInputs(await ctx.FetchMembers(202, includeNotActive: true, includeContactInfo: true).SingleAsync());
vm.FillInputs(await ctx.Members
.Where(m => m.MgNr == 202)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.SingleAsync());
}
Assert.That(vm.IsActive, Is.True);
@@ -231,7 +243,11 @@ namespace Tests.UnitTests.ServiceTests {
Member m;
using (var ctx = new AppDbContext()) {
m = await ctx.FetchMembers(202, includeNotActive: true, includeContactInfo: true).SingleAsync();
m = await ctx.Members
.Where(m => m.MgNr == 202)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.SingleAsync();
}
Assert.That(m, Is.Not.Null);
@@ -254,7 +270,11 @@ namespace Tests.UnitTests.ServiceTests {
var vm = new MemberAdminViewModel();
await InitViewModel(vm);
using (var ctx = new AppDbContext()) {
vm.FillInputs(await ctx.FetchMembers(203, includeNotActive: true, includeContactInfo: true).SingleAsync());
vm.FillInputs(await ctx.Members
.Where(m => m.MgNr == 203)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.SingleAsync());
}
Assert.Multiple(() => {
@@ -268,7 +288,11 @@ namespace Tests.UnitTests.ServiceTests {
Member m;
using (var ctx = new AppDbContext()) {
m = await ctx.FetchMembers(210, includeNotActive: true, includeContactInfo: true).SingleAsync();
m = await ctx.Members
.Where(m => m.MgNr == 210)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.SingleAsync();
}
Assert.That(m, Is.Not.Null);
@@ -286,27 +310,27 @@ namespace Tests.UnitTests.ServiceTests {
[Test]
public async Task TestDelete_01_NoReferences() {
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.FetchMembers(201, includeNotActive: true).SingleOrDefaultAsync(), Is.Not.Null);
Assert.That(await ctx.Members.FindAsync(201), Is.Not.Null);
}
Assert.DoesNotThrowAsync(async () => await MemberService.DeleteMember(201, false, false, false));
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.FetchMembers(201, includeNotActive: true).SingleOrDefaultAsync(), Is.Null);
Assert.That(await ctx.Members.FindAsync(201), Is.Null);
}
}
[Test]
public async Task TestDelete_02_AllReferences() {
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.FetchMembers(204, includeNotActive: true).SingleOrDefaultAsync(), Is.Not.Null);
Assert.That(await ctx.Members.FindAsync(204), Is.Not.Null);
}
for (int i = 0; i < 7; i++) {
Assert.ThrowsAsync<DbUpdateException>(async () => await MemberService.DeleteMember(204, (i & 1) != 0, (i & 2) != 0, (i & 4) != 0));
using var ctx = new AppDbContext();
Assert.That(await ctx.FetchMembers(204, includeNotActive: true).SingleOrDefaultAsync(), Is.Not.Null);
Assert.That(await ctx.Members.FindAsync(204), Is.Not.Null);
}
Assert.DoesNotThrowAsync(async () => await MemberService.DeleteMember(204, true, true, true));
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.FetchMembers(204, includeNotActive: true).SingleOrDefaultAsync(), Is.Null);
Assert.That(await ctx.Members.FindAsync(204), Is.Null);
}
}
}
+1 -1
View File
@@ -1 +1 @@
curl --fail -s -L "https://elwig.at/files/create.sql?v=39" -u "elwig:ganzGeheim123!" -o "Resources\Sql\Create.sql"
curl --fail -s -L "https://elwig.at/files/create.sql?v=38" -u "elwig:ganzGeheim123!" -o "Resources\Sql\Create.sql"