Compare commits

...

6 Commits

Author SHA1 Message Date
7c9844e277 [#57] MainWindow: Use Task.Run()
All checks were successful
Test / Run tests (push) Successful in 1m40s
2025-07-07 22:45:28 +02:00
19d2208fc3 [#57] AreaComAdminWindow: Use Task.Run() 2025-07-07 22:45:28 +02:00
38d0ff969d BaseDataWindow: Use Cursors.Wait instead of Cursors.AppStarting 2025-07-07 22:45:28 +02:00
fb2b998d1b [#57] DeliveryAdminWindow: Use Task.Run() 2025-07-07 22:45:28 +02:00
10d5f49f63 [#57] MemberAdminWinodw: Use Task.Run() 2025-07-07 22:45:28 +02:00
41811925be PaymentVariantsWindow: Add ViewModel and Service
All checks were successful
Test / Run tests (push) Successful in 1m58s
2025-07-07 22:44:30 +02:00
20 changed files with 1101 additions and 872 deletions

View File

@@ -200,10 +200,12 @@ namespace Elwig {
var ch = CurrentLastWrite;
if (ch > CurrentApp.LastChanged)
CurrentApp.LastChanged = ch;
MainDispatcher.Invoke(() => {
foreach (Window w in CurrentApp.Windows) {
if (w is not ContextWindow c) continue;
MainDispatcher.BeginInvoke(c.HintContextChange);
}
});
}
private void OnAutoUpdateTimer(object? sender, EventArgs? evt) {

View File

@@ -499,9 +499,11 @@ namespace Elwig.Helpers {
if (App.Config.Smtp == null)
return false;
Mouse.OverrideCursor = Cursors.Wait;
var success = await Task.Run(async () => {
SmtpClient? client = null;
try {
Mouse.OverrideCursor = Cursors.AppStarting;
client = await GetSmtpClient();
using var msg = new MimeMessage();
@@ -524,9 +526,12 @@ namespace Elwig.Helpers {
if (client != null)
await client.DisconnectAsync(true);
client?.Dispose();
Mouse.OverrideCursor = null;
}
return true;
});
Mouse.OverrideCursor = null;
return success;
}
public static async Task ExportDocument(Document doc, ExportMode mode, string? filename = null, (Member, string, string)? emailData = null) {

View File

@@ -108,7 +108,8 @@ namespace Elwig.Services {
public static async Task<int> UpdateAreaCommitment(this AreaComAdminViewModel vm, int? oldFbNr) {
int newFbNr = (int)vm.FbNr!;
using (var ctx = new AppDbContext()) {
await Task.Run(async () => {
using var ctx = new AppDbContext();
var a = new AreaCom {
FbNr = oldFbNr ?? newFbNr,
MgNr = (int)vm.MgNr!,
@@ -140,7 +141,7 @@ namespace Elwig.Services {
if (newFbNr != a.FbNr) {
await ctx.Database.ExecuteSqlAsync($"UPDATE area_commitment SET fbnr = {newFbNr} WHERE fbnr = {oldFbNr}");
}
}
});
App.HintContextChange();
@@ -253,5 +254,16 @@ namespace Elwig.Services {
}
return grid;
}
public static async Task DeleteAreaCom(int fbnr) {
await Task.Run(async () => {
using var ctx = new AppDbContext();
var l = (await ctx.AreaCommitments.FindAsync(fbnr))!;
ctx.Remove(l);
await ctx.SaveChangesAsync();
});
App.HintContextChange();
}
}
}

View File

@@ -430,9 +430,10 @@ namespace Elwig.Services {
}
public static async Task<DeliveryPart> UpdateDeliveryPart(this DeliveryAdminViewModel vm, int? oldYear, int? oldDid, int? oldDpnr, bool dateHasChanged, bool timeHasChanged, bool timeIsDefault) {
var p = await Task.Run(async () => {
DeliveryPart p;
using (var ctx = new AppDbContext()) {
using var ctx = new AppDbContext();
int year = oldYear ?? Utils.CurrentYear;
int did = oldDid ?? await ctx.NextDId(year);
int dpnr = oldDpnr ?? await ctx.NextDPNr(year, did);
@@ -524,7 +525,9 @@ namespace Elwig.Services {
}
await ctx.SaveChangesAsync();
}
return p;
});
App.HintContextChange();
@@ -532,9 +535,10 @@ namespace Elwig.Services {
}
public static async Task<Delivery> SplitDeliveryToMember(int year, int did, int[] weights, int mgnr) {
var n = await Task.Run(async () => {
Delivery n;
using (var ctx = new AppDbContext()) {
using var ctx = new AppDbContext();
bool anyLeft = false;
var d = (await ctx.Deliveries.FindAsync(year, did))!;
var lnr = await ctx.NextLNr(d.Date, d.ZwstId);
@@ -577,7 +581,9 @@ namespace Elwig.Services {
await ctx.SaveChangesAsync();
if (!anyLeft)
await ctx.Database.ExecuteSqlAsync($"DELETE FROM delivery WHERE (year, did) = ({d.Year}, {d.DId})");
}
return n;
});
App.HintContextChange();
@@ -585,9 +591,9 @@ namespace Elwig.Services {
}
public static async Task<Delivery> SplitDeliveryToLsNr(int year, int did, int[] weights, string lsnr) {
var n = await Task.Run(async () => {
Delivery n;
using (var ctx = new AppDbContext()) {
using var ctx = new AppDbContext();
var anyLeft = false;
n = (await ctx.Deliveries.FirstAsync(d => d.LsNr == lsnr))!;
var d = (await ctx.Deliveries.FindAsync(year, did))!;
@@ -616,7 +622,9 @@ namespace Elwig.Services {
await ctx.SaveChangesAsync();
if (!anyLeft && n.LsNr != d.LsNr)
await ctx.Database.ExecuteSqlAsync($"DELETE FROM delivery WHERE (year, did) = ({d.Year}, {d.DId})");
}
return n;
});
App.HintContextChange();
@@ -624,7 +632,8 @@ namespace Elwig.Services {
}
public static async Task DepreciateDelivery(int year, int did, int[] weights) {
using (var ctx = new AppDbContext()) {
await Task.Run(async () => {
using var ctx = new AppDbContext();
var d = (await ctx.Deliveries.FindAsync(year, did))!;
var dpnr = await ctx.NextDPNr(year, did);
foreach (var (p, w) in d.Parts.ToList().Zip(weights)) {
@@ -648,13 +657,14 @@ namespace Elwig.Services {
}
}
await ctx.SaveChangesAsync();
}
});
App.HintContextChange();
}
public static async Task GenerateDeliveryNote(int year, int did, ExportMode mode) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
using var ctx = new AppDbContext();
var d = (await ctx.Deliveries.FindAsync(year, did))!;
@@ -663,6 +673,7 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
@@ -707,7 +718,8 @@ namespace Elwig.Services {
Title = $"{DeliveryJournal.Name} speichern unter - Elwig"
};
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var data = await DeliveryJournalData.FromQuery(query, filterNames);
using var ods = new OdsFile(d.FileName);
@@ -715,6 +727,7 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
} else if (mode == ExportMode.Export) {
@@ -725,7 +738,8 @@ namespace Elwig.Services {
Title = $"{DeliveryJournal.Name} speichern unter - Elwig"
};
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
await ElwigData.Export(d.FileName, await query
.Select(p => p.Delivery)
@@ -737,10 +751,12 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
} else if (mode == ExportMode.Upload && App.Config.SyncUrl != null) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var filename = $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{App.ZwstId}.elwig.zip";
var path = Path.Combine(App.TempPath, filename);
@@ -767,9 +783,11 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
} else {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var data = await DeliveryJournalData.FromQuery(query, filterNames);
using var doc = new DeliveryJournal(string.Join(" / ", filterNames), data);
@@ -777,6 +795,7 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
}
@@ -798,7 +817,8 @@ namespace Elwig.Services {
throw new ArgumentException("Invalid value for ExportSubject");
}
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var data = await WineQualityStatisticsData.FromQuery(query, App.Client.OrderingMemberList);
using var doc = new WineQualityStatistics(string.Join(" / ", filterNames), data);
@@ -806,6 +826,7 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
@@ -829,7 +850,8 @@ namespace Elwig.Services {
Title = $"Lieferstatistik pro Ort speichern unter - Elwig"
};
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
using var ods = new OdsFile(d.FileName);
var tbl = await WineLocalityStatisticsData.FromQuery(query, filterNames);
@@ -837,6 +859,7 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
}
@@ -875,7 +898,8 @@ namespace Elwig.Services {
Title = $"{DeliveryDepreciationList.Name} speichern unter - Elwig"
};
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
using var ods = new OdsFile(d.FileName);
var tblTotal = await DeliveryJournalData.FromQuery(query, filterNames);
@@ -891,10 +915,12 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
} else {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var data = await DeliveryJournalData.FromQuery(query, filterNames);
using var doc = new DeliveryDepreciationList(string.Join(" / ", filterNames), data);
@@ -902,6 +928,7 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
}
@@ -1070,10 +1097,12 @@ namespace Elwig.Services {
}
public static async Task DeleteDelivery(string lsnr) {
using (var ctx = new AppDbContext()) {
await Task.Run(async () => {
using var ctx = new AppDbContext();
await ctx.Deliveries.Where(d => d.LsNr == lsnr).ExecuteDeleteAsync();
await ctx.SaveChangesAsync();
}
});
App.HintContextChange();
}
}

View File

@@ -378,7 +378,8 @@ namespace Elwig.Services {
}
public static async Task GenerateMemberDataSheet(Member m, ExportMode mode) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
using var ctx = new AppDbContext();
using var doc = new MemberDataSheet(m, ctx);
@@ -386,11 +387,13 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
public static async Task GenerateDeliveryConfirmation(Member m, int year, ExportMode mode) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var b = new Billing(year);
await b.FinishSeason();
@@ -404,11 +407,13 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
public static async Task GenerateCreditNote(Member m, int year, int avnr, ExportMode mode) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
using var ctx = new AppDbContext();
var v = (await ctx.PaymentVariants.FindAsync(year, avnr))!;
@@ -423,6 +428,7 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
@@ -475,7 +481,8 @@ namespace Elwig.Services {
Title = $"{MemberList.Name} speichern unter - Elwig"
};
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var data = await MemberListData.FromQuery(query, filterNames, filterNames.Where(f => f.StartsWith("Flächenbindung")).Select(f => f.Split(' ')[^1]));
using var ods = new OdsFile(d.FileName);
@@ -483,6 +490,7 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
} else if (mode == ExportMode.Export) {
@@ -493,7 +501,8 @@ namespace Elwig.Services {
Title = $"{MemberList.Name} speichern unter - Elwig"
};
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var members = await query
.OrderBy(m => m.MgNr)
@@ -510,10 +519,12 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
} else if (mode == ExportMode.Upload && App.Config.SyncUrl != null) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var filename = $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{App.ZwstId}.elwig.zip";
var path = Path.Combine(App.TempPath, filename);
@@ -544,9 +555,11 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
} else {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var data = await MemberListData.FromQuery(query, filterNames, filterNames.Where(f => f.StartsWith("Flächenbindung")).Select(f => f.Split(' ')[^1]));
using var doc = new MemberList(string.Join(" / ", filterNames), data);
@@ -554,14 +567,13 @@ namespace Elwig.Services {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
}
public static async Task<int> UpdateMember(this MemberAdminViewModel vm, int? oldMgNr) {
var newMgNr = (int)vm.MgNr!;
using (var ctx = new AppDbContext()) {
var m = new Member {
MgNr = oldMgNr ?? newMgNr,
PredecessorMgNr = vm.PredecessorMgNr,
@@ -599,6 +611,8 @@ namespace Elwig.Services {
ContactViaEmail = vm.ContactViaEmail,
};
await Task.Run(async () => {
using var ctx = new AppDbContext();
if (oldMgNr != null) {
ctx.Update(m);
} else {
@@ -681,7 +695,7 @@ namespace Elwig.Services {
if (newMgNr != m.MgNr) {
await ctx.Database.ExecuteSqlAsync($"UPDATE member SET mgnr = {newMgNr} WHERE mgnr = {oldMgNr}");
}
}
});
App.HintContextChange();
@@ -689,7 +703,8 @@ namespace Elwig.Services {
}
public static async Task DeleteMember(int mgnr, bool deletePaymentData, bool deleteDeliveries, bool deleteAreaComs) {
using (var ctx = new AppDbContext()) {
await Task.Run(async () => {
using var ctx = new AppDbContext();
var l = (await ctx.Members.FindAsync(mgnr))!;
if (deletePaymentData) {
ctx.RemoveRange(l.Credits);
@@ -702,7 +717,8 @@ namespace Elwig.Services {
}
ctx.Remove(l);
await ctx.SaveChangesAsync();
}
});
App.HintContextChange();
}
}

View File

@@ -0,0 +1,346 @@
using Elwig.Documents;
using Elwig.Helpers;
using Elwig.Helpers.Billing;
using Elwig.Helpers.Export;
using Elwig.Models.Dtos;
using Elwig.Models.Entities;
using Elwig.ViewModels;
using Microsoft.EntityFrameworkCore;
using Microsoft.Win32;
using System;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
namespace Elwig.Services {
public static class PaymentVariantService {
private static readonly JsonSerializerOptions JsonOpt = new() { WriteIndented = true };
public static void ClearInputs(this PaymentVariantsViewModel vm) {
vm.IsPaymentVariantSelected = false;
vm.EditText = "Bearbeiten";
vm.SaveIsEnabled = false;
vm.DeleteIsEnabled = false;
vm.CalculateIsEnabled = false;
vm.CommitIsEnabled = false;
vm.CommitVisibility = Visibility.Visible;
vm.RevertIsEnabled = false;
vm.RevertVisibility = Visibility.Hidden;
vm.Arrow = "\xF0AF";
vm.ExportIsEnabled = false;
vm.IsReadOnly = true;
vm.DataIsReadOnly = true;
vm.BillingData = null;
vm.Name = "";
vm.Comment = "";
vm.Date = null;
vm.TransferDate = null;
vm.WeightModifier = null;
vm.ConsiderModifiers = false;
vm.ConsiderPenalties = false;
vm.ConsiderPenalty = false;
vm.ConsiderAuto = false;
vm.ConsiderCustom = false;
vm.IsEnabled = false;
vm.Data = "";
vm.StatusModifierSum = "-";
vm.StatusTotalSum = "-";
vm.StatusVatSum = "-";
vm.StatusDeductionSum = "-";
vm.StatusPaymentSum = "-";
}
public static void FillInputs(this PaymentVariantsViewModel vm, PaymentVar v) {
var locked = !v.TestVariant;
vm.IsPaymentVariantSelected = true;
vm.SaveIsEnabled = !locked;
vm.DeleteIsEnabled = !locked;
vm.CalculateIsEnabled = !locked;
vm.CommitIsEnabled = !locked && !vm.SeasonLocked;
vm.CommitVisibility = !locked ? Visibility.Visible : Visibility.Hidden;
vm.RevertIsEnabled = locked && !vm.SeasonLocked;
vm.RevertVisibility = locked ? Visibility.Visible : Visibility.Hidden;
vm.Arrow = locked ? "\xF0B0" : "\xF0AF";
vm.EditText = locked ? "Ansehen" : "Bearbeiten";
vm.ExportIsEnabled = locked;
vm.IsReadOnly = false;
vm.DataIsReadOnly = locked;
vm.Name = v.Name;
vm.Comment = v.Comment ?? "";
vm.Date = v.Date;
vm.TransferDate = v.TransferDate;
try {
vm.BillingData = BillingData.FromJson(v.Data);
vm.ConsiderModifiers = vm.BillingData.ConsiderDelieryModifiers;
vm.ConsiderPenalties = vm.BillingData.ConsiderContractPenalties;
vm.ConsiderPenalty = vm.BillingData.ConsiderTotalPenalty;
vm.ConsiderAuto = vm.BillingData.ConsiderAutoBusinessShares;
vm.ConsiderCustom = vm.BillingData.ConsiderCustomModifiers;
if (vm.BillingData.NetWeightModifier != 0) {
vm.WeightModifier = Math.Round(vm.BillingData.NetWeightModifier * 100.0, 8);
} else if (vm.BillingData.GrossWeightModifier != 0) {
vm.WeightModifier = Math.Round(vm.BillingData.GrossWeightModifier * 100.0, 8);
} else {
vm.WeightModifier = null;
}
vm.Data = JsonSerializer.Serialize(vm.BillingData.Data, JsonOpt);
} catch {
vm.BillingData = null;
vm.ConsiderModifiers = false;
vm.ConsiderPenalties = false;
vm.ConsiderPenalty = false;
vm.ConsiderAuto = false;
vm.ConsiderCustom = false;
vm.WeightModifier = null;
vm.Data = v.Data;
}
vm.IsEnabled = !locked;
vm.StatusModifierSum = "...";
vm.StatusTotalSum = "...";
vm.StatusVatSum = "...";
vm.StatusDeductionSum = "...";
vm.StatusPaymentSum = "...";
Utils.RunBackground("Variantendaten laden", async () => {
await vm.UpdateSums(v);
});
}
private static async Task UpdateSums(this PaymentVariantsViewModel vm, PaymentVar v) {
if (App.MainDispatcher == null)
return;
var modText = "-";
var totalText = "-";
var vatText = "-";
var deductionText = "-";
var paymentText = "-";
using var ctx = new AppDbContext();
var sym = v.Season.Currency.Symbol ?? v.Season.Currency.Code;
var modSum = await ctx.PaymentDeliveryParts
.Where(p => p.Year == v.Year && p.AvNr == v.AvNr)
.SumAsync(p => p.AmountValue - p.NetAmountValue);
modText = $"{v.Season.DecFromDb(modSum):N2} {sym}";
var totalSum = await ctx.MemberPayments
.Where(p => p.Year == v.Year && p.AvNr == v.AvNr)
.SumAsync(p => p.AmountValue);
totalText = $"{v.Season.DecFromDb(totalSum):N2} {sym}";
await App.MainDispatcher.BeginInvoke(() => {
if (vm.SelectedPaymentVariant != v)
return;
vm.StatusModifierSum = modText;
vm.StatusTotalSum = totalText;
});
var credits = ctx.Credits.Where(c => c.Year == v.Year && c.AvNr == v.AvNr);
if (!credits.Any()) {
long lastTotalSum = 0;
decimal vatSum = 0;
var currentPayments = await ctx.MemberPayments
.Where(p => p.Year == v.Year && p.AvNr == v.AvNr)
.ToDictionaryAsync(p => p.MgNr);
var lastV = await ctx.PaymentVariants
.Where(l => l.Year == v.Year && !l.TestVariant)
.OrderByDescending(l => l.TransferDateString ?? l.DateString)
.ThenByDescending(l => l.AvNr)
.FirstOrDefaultAsync();
if (lastV != null) {
var lastPayments = await ctx.MemberPayments
.Where(p => p.Year == v.Year && p.AvNr == lastV.AvNr)
.ToDictionaryAsync(p => p.MgNr);
lastTotalSum = lastPayments.Sum(e => e.Value.AmountValue);
foreach (int mgnr in currentPayments.Keys) {
var c = currentPayments[mgnr];
var l = lastPayments[mgnr];
vatSum += (c.Amount - l.Amount) * (decimal)(c.Member.IsBuchführend ? v.Season.VatNormal : v.Season.VatFlatrate);
}
} else {
vatSum = currentPayments.Sum(e => e.Value.Amount * (decimal)(e.Value.Member.IsBuchführend ? v.Season.VatNormal : v.Season.VatFlatrate));
}
vatText = $"~{vatSum:N2} {sym}";
deductionText = $"- {sym}";
paymentText = $"~{v.Season.DecFromDb(totalSum - lastTotalSum) + vatSum:N2} {sym}";
} else {
// all values in the credit table are stored with precision 2!
totalText = $"{Utils.DecFromDb(await credits.SumAsync(c => c.NetAmountValue), 2):N2} {sym}";
vatText = $"{Utils.DecFromDb(await credits.SumAsync(c => c.VatAmountValue), 2):N2} {sym}";
deductionText = $"{-Utils.DecFromDb(await credits.SumAsync(c => c.ModifiersValue ?? 0), 2):N2} {sym}";
paymentText = $"{Utils.DecFromDb(await credits.SumAsync(c => c.AmountValue), 2):N2} {sym}";
}
await App.MainDispatcher.BeginInvoke(() => {
if (vm.SelectedPaymentVariant != v)
return;
vm.StatusModifierSum = modText;
vm.StatusTotalSum = totalText;
vm.StatusVatSum = vatText;
vm.StatusDeductionSum = deductionText;
vm.StatusPaymentSum = paymentText;
});
}
public static async Task GenerateSummary(PaymentVar v, ExportMode mode) {
Mouse.OverrideCursor = Cursors.AppStarting;
try {
using var ctx = new AppDbContext();
var data = await PaymentVariantSummaryData.ForPaymentVariant(v, ctx.PaymentVariantSummaryRows);
using var doc = new PaymentVariantSummary((await ctx.PaymentVariants.FindAsync(v.Year, v.AvNr))!, data);
await Utils.ExportDocument(doc, mode);
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
Mouse.OverrideCursor = null;
}
public static async Task GenerateEbics(int year, int avnr) {
using var ctx = new AppDbContext();
var v = (await ctx.PaymentVariants.FindAsync(year, avnr))!;
var withoutIban = v.Credits.Count(c => c.Member.Iban == null);
if (withoutIban > 0) {
var r = MessageBox.Show($"Achtung: Für {withoutIban:N0} Mitglieder ist kein IBAN hinterlegt.\n\nDiese werden NICHT exportiert.",
"Mitglieder ohne IBAN", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel);
if (r != MessageBoxResult.OK) return;
}
var withNegAmount = v.Credits.Count(c => c.Amount <= 0);
if (withNegAmount > 0) {
var r = MessageBox.Show($"Achtung: Es gibt {withNegAmount:N0} Traubengutschriften mit negativem Betrag.\n\nDiese werden NICHT exportiert.",
"Traubengutschriften mit negativem Betrag", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.OK);
if (r != MessageBoxResult.OK) return;
}
var d = new SaveFileDialog() {
FileName = $"{App.Client.NameToken}-Überweisungsdaten-{v.Year}-{v.Name.Trim().Replace(' ', '-')}.{Ebics.FileExtension}",
DefaultExt = Ebics.FileExtension,
Filter = "EBICS-Datei (*.xml)|*.xml",
Title = $"Überweisungsdaten speichern unter - Elwig",
};
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
try {
using var e = new Ebics(v, d.FileName, App.Client.ExportEbicsVersion, (Ebics.AddressMode)App.Client.ExportEbicsAddress);
await e.ExportAsync(Transaction.FromPaymentVariant(v));
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
Mouse.OverrideCursor = null;
}
}
public static async Task GenerateAccountingList(int year, int avnr, string name) {
var d = new SaveFileDialog() {
FileName = $"{App.Client.NameToken}-Buchungsliste-{year}-{name.Trim().Replace(' ', '-')}.ods",
DefaultExt = "ods",
Filter = "OpenDocument Format Spreadsheet (*.ods)|*.ods",
Title = $"Buchungsliste speichern unter - Elwig"
};
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
try {
using var ctx = new AppDbContext();
var tbl = await CreditNoteData.ForPaymentVariant(ctx, year, avnr);
using var ods = new OdsFile(d.FileName);
await ods.AddTable(tbl);
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
Mouse.OverrideCursor = null;
}
}
public static async Task<PaymentVar> CreatePaymentVariant(int year) {
PaymentVar? v;
using (var ctx = new AppDbContext()) {
v = new PaymentVar {
Year = year,
AvNr = await ctx.NextAvNr(year),
Name = "Neue Auszahlungsvariante",
TestVariant = true,
DateString = $"{DateTime.Today:yyyy-MM-dd}",
Data = "{\"mode\": \"elwig\", \"version\": 1, \"payment\": {}, \"curves\": []}",
};
ctx.Add(v);
await ctx.SaveChangesAsync();
}
App.HintContextChange();
return v;
}
public static async Task<PaymentVar> Duplicate(this PaymentVar orig) {
PaymentVar? n;
using (var ctx = new AppDbContext()) {
n = new PaymentVar {
Year = orig.Year,
AvNr = await ctx.NextAvNr(orig.Year),
Name = $"{orig.Name} (Kopie)",
TestVariant = true,
DateString = $"{DateTime.Today:yyyy-MM-dd}",
Data = orig.Data,
};
ctx.Add(n);
await ctx.SaveChangesAsync();
}
App.HintContextChange();
return n;
}
public static async Task<(int, int)> UpdatePaymentVariant(this PaymentVariantsViewModel vm, int? oldYear, int? oldAvNr) {
var year = oldYear ?? Utils.CurrentYear;
int avnr = 0;
var d = App.Config.Debug ? BillingData.FromJson(vm.Data ?? "{}") : vm.BillingData!;
d.ConsiderDelieryModifiers = vm.ConsiderModifiers;
d.ConsiderContractPenalties = vm.ConsiderPenalties;
d.ConsiderTotalPenalty = vm.ConsiderPenalty;
d.ConsiderAutoBusinessShares = vm.ConsiderAuto;
d.ConsiderCustomModifiers = vm.ConsiderCustom;
var modVal = vm.WeightModifier ?? 0;
d.NetWeightModifier = modVal > 0 ? modVal / 100.0 : 0;
d.GrossWeightModifier = modVal < 0 ? modVal / 100.0 : 0;
using (var ctx = new AppDbContext()) {
var v = new PaymentVar {
Year = year,
AvNr = oldAvNr ?? await ctx.NextAvNr(year),
Name = vm.Name!,
DateString = $"{vm.Date!.Value:yyyy-MM-dd}",
TransferDate = vm.TransferDate,
TestVariant = vm.SelectedPaymentVariant?.TestVariant ?? true,
CalcTimeUnix = vm.SelectedPaymentVariant?.CalcTimeUnix,
Comment = string.IsNullOrEmpty(vm.Comment) ? null : vm.Comment,
Data = JsonSerializer.Serialize(d.Data),
};
avnr = v.AvNr;
ctx.Update(v);
await ctx.SaveChangesAsync();
}
vm.WeightModifierChanged = false;
App.HintContextChange();
return (year, avnr);
}
public static async Task DeletePaymentVariant(int year, int avnr) {
using (var ctx = new AppDbContext()) {
var v = (await ctx.PaymentVariants.FindAsync(year, avnr))!;
ctx.Remove(v);
await ctx.SaveChangesAsync();
}
App.HintContextChange();
}
public static async Task Calculate(int year, int avnr) {
var b = new BillingVariant(year, avnr);
await b.Calculate();
}
}
}

View File

@@ -15,7 +15,7 @@ namespace Elwig.ViewModels {
[ObservableProperty]
private string? _searchQuery = "";
public List<string> TextFilter {
get => [.. SearchQuery?.ToLower().Split(' ').ToList().FindAll(e => e.Length > 0)];
get => [.. SearchQuery?.ToLower().Split(' ').ToList().FindAll(e => e.Length > 0) ?? []];
set => SearchQuery = string.Join(' ', value.Where(e => e.Length > 0));
}

View File

@@ -18,7 +18,7 @@ namespace Elwig.ViewModels {
[ObservableProperty]
private string? _searchQuery = "";
public List<string> TextFilter => [.. SearchQuery?.ToLower().Split(' ').ToList().FindAll(e => e.Length > 0)];
public List<string> TextFilter => [.. SearchQuery?.ToLower().Split(' ').ToList().FindAll(e => e.Length > 0) ?? []];
[ObservableProperty]
private string? _lastScaleError;

View File

@@ -10,7 +10,7 @@ namespace Elwig.ViewModels {
[ObservableProperty]
private string? _searchQuery = "";
public List<string> TextFilter => [.. SearchQuery?.ToLower().Split(' ').ToList().FindAll(e => e.Length > 0)];
public List<string> TextFilter => [.. SearchQuery?.ToLower().Split(' ').ToList().FindAll(e => e.Length > 0) ?? []];
[ObservableProperty]
private bool _filterOnlyUpcoming;

View File

@@ -11,7 +11,7 @@ namespace Elwig.ViewModels {
[ObservableProperty]
private string? _searchQuery = "";
public List<string> TextFilter => [.. SearchQuery?.ToLower().Split(' ').ToList().FindAll(e => e.Length > 0)];
public List<string> TextFilter => [.. SearchQuery?.ToLower().Split(' ').ToList().FindAll(e => e.Length > 0) ?? []];
[ObservableProperty]
private bool _filterOnlyUpcoming;

View File

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

View File

@@ -0,0 +1,95 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Elwig.Helpers.Billing;
using Elwig.Models.Entities;
using System;
using System.Collections.Generic;
using System.Windows;
namespace Elwig.ViewModels {
public partial class PaymentVariantsViewModel : ObservableObject {
[ObservableProperty]
private PaymentVar? _selectedPaymentVariant;
[ObservableProperty]
private IEnumerable<PaymentVar> _paymentVariants = [];
public BillingData? BillingData;
public bool SeasonLocked;
public bool WeightModifierChanged;
[ObservableProperty]
private string _name = "";
[ObservableProperty]
private string _comment = "";
[ObservableProperty]
private string _dateString = "";
public DateOnly? Date {
get => DateOnly.TryParseExact(DateString, "dd.MM.yyyy", out var d) ? d : null;
set => DateString = $"{value:dd.MM.yyyy}";
}
[ObservableProperty]
private string _transferDateString = "";
public DateOnly? TransferDate {
get => DateOnly.TryParseExact(TransferDateString, "dd.MM.yyyy", out var d) ? d : null;
set => TransferDateString = $"{value:dd.MM.yyyy}";
}
[ObservableProperty]
private string _weightModifierString = "";
public double? WeightModifier {
get => double.TryParse(WeightModifierString, out var d) ? d : null;
set => WeightModifierString = $"{value}";
}
[ObservableProperty]
private string _data = "";
[ObservableProperty]
private bool _considerModifiers;
[ObservableProperty]
private bool _considerPenalties;
[ObservableProperty]
private bool _considerPenalty;
[ObservableProperty]
private bool _considerAuto;
[ObservableProperty]
private bool _considerCustom;
[ObservableProperty]
private bool _isPaymentVariantSelected;
[ObservableProperty]
private bool _isReadOnly = true;
[ObservableProperty]
private bool _dataIsReadOnly = true;
[ObservableProperty]
private bool _isEnabled = false;
[ObservableProperty]
private bool _saveIsEnabled = false;
[ObservableProperty]
private bool _deleteIsEnabled = false;
[ObservableProperty]
private bool _calculateIsEnabled = false;
[ObservableProperty]
private bool _exportIsEnabled = false;
[ObservableProperty]
private bool _commitIsEnabled = false;
[ObservableProperty]
private Visibility _commitVisibility = Visibility.Visible;
[ObservableProperty]
private bool _revertIsEnabled = false;
[ObservableProperty]
private Visibility _revertVisibility = Visibility.Hidden;
[ObservableProperty]
private string _arrow = "\xF0AF";
[ObservableProperty]
private string _editText = "Bearbeiten";
[ObservableProperty]
private string _statusModifierSum = "-";
[ObservableProperty]
private string _statusTotalSum = "-";
[ObservableProperty]
private string _statusVatSum = "-";
[ObservableProperty]
private string _statusDeductionSum = "-";
[ObservableProperty]
private string _statusPaymentSum = "-";
}
}

View File

@@ -203,13 +203,9 @@ namespace Elwig.Windows {
$"Soll die Flächenbindung {a.GstNr} ({a.Area} m²) wirklich unwiderruflich gelöscht werden?",
"Flächenbindung löschen", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel);
if (r == MessageBoxResult.OK) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
try {
using (var ctx = new AppDbContext()) {
ctx.Remove(a);
await ctx.SaveChangesAsync();
}
App.HintContextChange();
await AreaComService.DeleteAreaCom(a.FbNr);
} catch (Exception exc) {
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;
@@ -227,7 +223,7 @@ namespace Elwig.Windows {
private async void AreaCommitmentSaveButton_Click(object? sender, RoutedEventArgs? evt) {
AreaCommitmentSaveButton.IsEnabled = false;
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
int fbnr;
try {
@@ -237,9 +233,8 @@ namespace Elwig.Windows {
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
MessageBox.Show(str, "Flächenbindung aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
AreaCommitmentSaveButton.IsEnabled = true;
return;
} finally {
Mouse.OverrideCursor = null;
return;
}
IsEditing = false;
@@ -252,6 +247,7 @@ namespace Elwig.Windows {
FinishInputFilling();
await RefreshList();
RefreshInputs();
Mouse.OverrideCursor = null;
ViewModel.SearchQuery = "";
ControlUtils.SelectItem(AreaCommitmentList, AreaCommitmentList.ItemsSource.Cast<AreaCom>().Where(a => a.FbNr == fbnr).FirstOrDefault());
}

View File

@@ -157,7 +157,7 @@ namespace Elwig.Windows {
}
var d = new NewSeasonDialog(s, currencies);
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
try {
using var ctx = new AppDbContext();
ctx.Add(new Season {
@@ -209,7 +209,7 @@ namespace Elwig.Windows {
$"Soll die Saison {s.Year} wirklich unwiderruflich gelöscht werden?",
"Saison löschen", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel);
if (r == MessageBoxResult.OK) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
try {
using var ctx = new AppDbContext();
ctx.Remove(s);

View File

@@ -318,8 +318,7 @@ namespace Elwig.Windows {
private async void SaveButton_Click(object? sender, RoutedEventArgs? evt) {
SaveButton.IsEnabled = false;
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
try {
await Save();
} catch (Exception exc) {
@@ -327,9 +326,8 @@ namespace Elwig.Windows {
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
MessageBox.Show(str, "Stammdaten aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
SaveButton.IsEnabled = true;
return;
} finally {
Mouse.OverrideCursor = null;
return;
}
IsEditing = false;
@@ -349,6 +347,7 @@ namespace Elwig.Windows {
}
App.HintContextChange();
Mouse.OverrideCursor = null;
}
private void FillInputs(ClientParameters p, Season? s) {

View File

@@ -719,7 +719,7 @@ namespace Elwig.Windows {
private async void NewDeliveryPartButton_Click(object sender, RoutedEventArgs evt) {
FinishButton.IsEnabled = false;
NewDeliveryPartButton.IsEnabled = false;
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
DeliveryPartList.IsEnabled = false;
DeliveryPart? p;
@@ -757,7 +757,7 @@ namespace Elwig.Windows {
private async void FinishButton_Click(object sender, RoutedEventArgs evt) {
FinishButton.IsEnabled = false;
NewDeliveryPartButton.IsEnabled = false;
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
DeliveryPartList.IsEnabled = false;
DeliveryPart? p;
@@ -888,7 +888,7 @@ namespace Elwig.Windows {
if (res == null)
return;
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
try {
var id = res.Value.Item1;
var weights = res.Value.Item2;
@@ -959,7 +959,7 @@ namespace Elwig.Windows {
$"Soll die Lieferung {d.LsNr} ({d.Member.AdministrativeName}, MgNr. {d.Member.MgNr}) wirklich unwiderruflich gelöscht werden?",
"Lieferung löschen", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel);
if (r == MessageBoxResult.OK) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
try {
await DeliveryService.DeleteDelivery(d.LsNr);
} catch (Exception exc) {
@@ -979,7 +979,7 @@ namespace Elwig.Windows {
private async void SaveButton_Click(object? sender, RoutedEventArgs? evt) {
SaveButton.IsEnabled = false;
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
DeliveryPart? p;
try {
@@ -996,9 +996,8 @@ namespace Elwig.Windows {
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
MessageBox.Show(str, "Lieferung aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
SaveButton.IsEnabled = true;
return;
} finally {
Mouse.OverrideCursor = null;
return;
}
IsEditing = false;
@@ -1015,6 +1014,7 @@ namespace Elwig.Windows {
await RefreshDeliveryParts();
RefreshInputs();
Mouse.OverrideCursor = null;
DepreciateButton.IsEnabled = true;
}

View File

@@ -62,7 +62,7 @@ namespace Elwig.Windows {
}
private async void Menu_Help_Smtp_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
try {
using var client = await Utils.GetSmtpClient();
await client!.DisconnectAsync(true);
@@ -133,8 +133,10 @@ namespace Elwig.Windows {
Multiselect = true,
};
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
await ElwigData.Import(d.FileNames, ElwigData.ImportMode.Interactively);
});
}
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
@@ -145,7 +147,8 @@ namespace Elwig.Windows {
private async void DownloadButton_Click(object sender, RoutedEventArgs evt) {
if (App.Config.SyncUrl == null)
return;
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var data = await Utils.GetExportMetaData(App.Config.SyncUrl, App.Config.SyncUsername, App.Config.SyncPassword);
var files = data
@@ -181,13 +184,15 @@ namespace Elwig.Windows {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
private async void UploadButton_Click(object sender, RoutedEventArgs evt) {
if (App.Config.SyncUrl == null)
return;
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var path = Path.Combine(App.TempPath, $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{App.ZwstId}.elwig.zip");
using var ctx = new AppDbContext();
@@ -216,6 +221,7 @@ namespace Elwig.Windows {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Lieferungen hochladen", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
@@ -270,24 +276,31 @@ namespace Elwig.Windows {
AreaCommitmentsButton.IsEnabled = valid;
BreakdownMemberVarietyButton.IsEnabled = valid;
if (valid) {
var areaComs = Utils.ActiveAreaCommitments(ctx.AreaCommitments, year!.Value);
var weightTotal = await ctx.DeliveryParts.Where(p => p.Year == year).SumAsync(p => p.Weight);
var gebWeight = await ctx.DeliveryPartBuckets.Where(b => b.Year == year && b.Discr != "_").SumAsync(b => b.Value);
SeasonStatMembersTotal.Text = $"{await ctx.Deliveries.Where(d => d.Year == year).Select(d => d.Member).Distinct().CountAsync():N0}";
SeasonStatMembersGeb.Text = $"{await areaComs.Select(c => c.Member).Distinct().CountAsync():N0}";
SeasonStatWeightTotal.Text = $"{weightTotal:N0} kg";
SeasonStatWeightGeb.Text = $"{gebWeight:N0} kg";
SeasonStatWeightUngeb.Text = $"{weightTotal - gebWeight:N0} kg";
SeasonStatArea.Text = $"{await areaComs.SumAsync(c => c.Area):N0} m²";
} else {
SeasonStatMembersTotal.Text = "-";
SeasonStatMembersGeb.Text = "-";
SeasonStatWeightTotal.Text = "-";
SeasonStatWeightGeb.Text = "-";
SeasonStatWeightUngeb.Text = "-";
SeasonStatArea.Text = "-";
}
if (valid) {
await Task.Run(async () => {
var membersTotal = await ctx.Deliveries.Where(d => d.Year == year).Select(d => d.Member).Distinct().CountAsync();
var areaComs = Utils.ActiveAreaCommitments(ctx.AreaCommitments, year!.Value);
var membersGeb = await areaComs.Select(c => c.Member).Distinct().CountAsync();
var weightTotal = await ctx.DeliveryParts.Where(p => p.Year == year).SumAsync(p => p.Weight);
var gebWeight = await ctx.DeliveryPartBuckets.Where(b => b.Year == year && b.Discr != "_").SumAsync(b => b.Value);
var area = await areaComs.SumAsync(c => c.Area);
await App.MainDispatcher.BeginInvoke(() => {
if (year != SeasonInput.Value) return;
SeasonStatMembersTotal.Text = $"{membersTotal:N0}";
SeasonStatMembersGeb.Text = $"{membersGeb:N0}";
SeasonStatWeightTotal.Text = $"{weightTotal:N0} kg";
SeasonStatWeightGeb.Text = $"{gebWeight:N0} kg";
SeasonStatWeightUngeb.Text = $"{weightTotal - gebWeight:N0} kg";
SeasonStatArea.Text = $"{area:N0} m²";
});
});
};
}
private void DeliveryConfirmationButton_Click(object sender, RoutedEventArgs evt) {
@@ -315,7 +328,8 @@ namespace Elwig.Windows {
if (d.ShowDialog() == false)
return;
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var b = new Billing(year);
await b.FinishSeason();
@@ -331,6 +345,7 @@ namespace Elwig.Windows {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
@@ -346,7 +361,8 @@ namespace Elwig.Windows {
if (d.ShowDialog() == false)
return;
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var b = new Billing(year);
await b.FinishSeason();
@@ -364,6 +380,7 @@ namespace Elwig.Windows {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
@@ -379,7 +396,8 @@ namespace Elwig.Windows {
if (d.ShowDialog() == false)
return;
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var b = new Billing(year);
await b.FinishSeason();
@@ -393,6 +411,7 @@ namespace Elwig.Windows {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
@@ -408,7 +427,8 @@ namespace Elwig.Windows {
if (d.ShowDialog() == false)
return;
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
try {
var b = new Billing(year);
await b.FinishSeason();
@@ -422,6 +442,7 @@ namespace Elwig.Windows {
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
Mouse.OverrideCursor = null;
}
}

View File

@@ -389,7 +389,7 @@ namespace Elwig.Windows {
}
var d = new DeleteMemberDialog(m.MgNr, m.AdministrativeName, areaComs, deliveries, credits);
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
try {
await MemberService.DeleteMember(m.MgNr, d.DeletePaymentData, d.DeleteDeliveries, d.DeleteAreaComs);
} catch (Exception exc) {
@@ -408,7 +408,7 @@ namespace Elwig.Windows {
}
private async void SaveButton_Click(object? sender, RoutedEventArgs? evt) {
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
SaveButton.IsEnabled = false;
int mgnr;
@@ -419,9 +419,8 @@ namespace Elwig.Windows {
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
MessageBox.Show(str, "Mitglied aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
SaveButton.IsEnabled = true;
return;
} finally {
Mouse.OverrideCursor = null;
return;
}
IsEditing = false;
@@ -436,6 +435,7 @@ namespace Elwig.Windows {
await RefreshList();
RefreshInputs();
ViewModel.SearchQuery = "";
Mouse.OverrideCursor = null;
if (mgnr is int m)
FocusMember(m);
}
@@ -491,8 +491,9 @@ namespace Elwig.Windows {
private async void Menu_Contact_Letterhead_Click(object sender, RoutedEventArgs evt) {
if (ViewModel.SelectedMember is not Member m) return;
Mouse.OverrideCursor = Cursors.AppStarting;
Mouse.OverrideCursor = Cursors.Wait;
try {
await Task.Run(async () => {
using var doc = new Letterhead(m);
await doc.Generate();
if (!App.Config.Debug) {
@@ -500,6 +501,7 @@ namespace Elwig.Windows {
} else {
doc.Show();
}
});
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}

View File

@@ -5,8 +5,12 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Elwig.Windows"
xmlns:vm="clr-namespace:Elwig.ViewModels"
xmlns:ctrl="clr-namespace:Elwig.Controls"
Title="Auszahlungsvarianten - Elwig" Height="480" Width="850" MinHeight="400" MinWidth="850">
<Window.DataContext>
<vm:PaymentVariantsViewModel/>
</Window.DataContext>
<Window.Resources>
<Style TargetType="Label">
<Setter Property="HorizontalAlignment" Value="Left"/>
@@ -55,25 +59,25 @@
<Menu Grid.ColumnSpan="2" BorderThickness="0,0,0,1" BorderBrush="LightGray" Background="White">
<MenuItem Header="Variantendaten">
<MenuItem x:Name="Menu_SummaryShow" Header="...anzeigen (PDF)" IsEnabled="False"
<MenuItem x:Name="Menu_SummaryShow" Header="...anzeigen (PDF)" IsEnabled="{Binding IsPaymentVariantSelected}"
Click="Menu_SummaryShow_Click" InputGestureText="Strg+P">
<MenuItem.Icon>
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text="&#xE8FF;"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="Menu_SummarySave" Header="...speichern... (PDF)" IsEnabled="False"
<MenuItem x:Name="Menu_SummarySave" Header="...speichern... (PDF)" IsEnabled="{Binding IsPaymentVariantSelected}"
Click="Menu_SummarySave_Click">
<MenuItem.Icon>
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text="&#xEA90;"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="Menu_SummaryExport" Header="...speichern... (Excel)" IsEnabled="False"
<MenuItem x:Name="Menu_SummaryExport" Header="...speichern... (Excel)" IsEnabled="{Binding IsPaymentVariantSelected}"
Click="Menu_SummaryExport_Click">
<MenuItem.Icon>
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text="&#xE9F9;"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="Menu_SummaryPrint" Header="...drucken" IsEnabled="False"
<MenuItem x:Name="Menu_SummaryPrint" Header="...drucken" IsEnabled="{Binding IsPaymentVariantSelected}"
Click="Menu_SummaryPrint_Click" InputGestureText="Strg+Shift+P">
<MenuItem.Icon>
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text="&#xE749;"/>
@@ -81,7 +85,7 @@
</MenuItem>
</MenuItem>
<MenuItem Header="Buchungsliste">
<MenuItem x:Name="Menu_ExportSave" Header="...speichern... (Excel)" IsEnabled="False"
<MenuItem x:Name="Menu_ExportSave" Header="...speichern... (Excel)" IsEnabled="{Binding ExportIsEnabled}"
Click="Menu_ExportSave_Click" InputGestureText="Strg+L">
<MenuItem.Icon>
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text="&#xE9F9;"/>
@@ -89,7 +93,7 @@
</MenuItem>
</MenuItem>
<MenuItem Header="Überweisungsdaten">
<MenuItem x:Name="Menu_EbicsSave" Header="...exportieren... (EBICS)" IsEnabled="False"
<MenuItem x:Name="Menu_EbicsSave" Header="...exportieren... (EBICS)" IsEnabled="{Binding ExportIsEnabled}"
Click="Menu_EbicsSave_Click" InputGestureText="Strg+Ü">
<MenuItem.Icon>
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text="&#xE792;"/>
@@ -99,7 +103,9 @@
</Menu>
<Grid Grid.Row="1">
<ListBox x:Name="PaymentVariantList" Margin="10,10,35,10" Grid.RowSpan="2" SelectionChanged="PaymentVariantList_SelectionChanged">
<ListBox x:Name="PaymentVariantList" Margin="10,10,35,10" Grid.RowSpan="2"
SelectionChanged="PaymentVariantList_SelectionChanged"
ItemsSource="{Binding PaymentVariants, Mode=TwoWay}" SelectedItem="{Binding SelectedPaymentVariant, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
@@ -109,17 +115,20 @@
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="AddButton" Content="&#xF8AA;" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" ToolTip="Neue Auszahlungsvariante hinzufügen"
<Button x:Name="AddButton"
Content="&#xF8AA;" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" ToolTip="Neue Auszahlungsvariante hinzufügen"
VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="5,0,5,60" Grid.RowSpan="2"
Click="AddButton_Click"/>
<Button x:Name="CopyButton" Content="&#xE8C8;" FontFamily="Segoe MDL2 Assets" FontSize="12" Padding="0,0,0,0" IsEnabled="False" ToolTip="Ausgewählte Auszahlungsvariante duplizieren"
<Button x:Name="CopyButton" IsEnabled="{Binding IsPaymentVariantSelected}"
Content="&#xE8C8;" FontFamily="Segoe MDL2 Assets" FontSize="12" Padding="0,0,0,0" ToolTip="Ausgewählte Auszahlungsvariante duplizieren"
VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="5,0,5,0" Grid.RowSpan="2"
Click="CopyButton_Click"/>
<Button x:Name="DeleteButton" Content="&#xF8AB;" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" IsEnabled="False" ToolTip="Ausgewählte Auszahlungsvariante löschen"
<Button x:Name="DeleteButton" IsEnabled="{Binding DeleteIsEnabled}"
Content="&#xF8AB;" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" ToolTip="Ausgewählte Auszahlungsvariante löschen"
VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="5,60,5,0" Grid.RowSpan="2"
Click="DeleteButton_Click"/>
<TextBox x:Name="DataInput" Margin="10,200,35,10"
<TextBox x:Name="DataInput" Margin="10,200,35,10" IsReadOnly="{Binding DataIsReadOnly}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="auto"
AcceptsReturn="True" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Auto"
FontFamily="Cascadia Code Light" FontSize="13"
@@ -133,23 +142,28 @@
</Grid.ColumnDefinitions>
<Label Content="Name:" Margin="10,10,0,0" Grid.Column="0"/>
<TextBox x:Name="NameInput" Width="200" Grid.Column="1" HorizontalAlignment="Left" Margin="0,10,0,0"
<TextBox x:Name="NameInput" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="{Binding IsReadOnly}"
Width="200" Grid.Column="1" HorizontalAlignment="Left" Margin="0,10,0,0"
TextChanged="NameInput_TextChanged"/>
<Label Content="Beschreibung:" Margin="10,40,0,0" Grid.Column="0"/>
<TextBox x:Name="CommentInput" Grid.Column="1" HorizontalAlignment="Stretch" Margin="0,40,10,0"
<TextBox x:Name="CommentInput" Text="{Binding Comment, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="{Binding IsReadOnly}"
Grid.Column="1" HorizontalAlignment="Stretch" Margin="0,40,10,0"
TextChanged="CommentInput_TextChanged"/>
<Label Content="Datum:" Margin="10,70,0,0" Grid.Column="0"/>
<TextBox x:Name="DateInput" Grid.Column="1" Width="77" HorizontalAlignment="Left" Margin="0,70,10,0"
<TextBox x:Name="DateInput" Text="{Binding DateString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="{Binding IsReadOnly}"
Grid.Column="1" Width="77" HorizontalAlignment="Left" Margin="0,70,10,0"
TextChanged="DateInput_TextChanged"/>
<Label Content="Überwiesen am:" Margin="10,100,0,0" Grid.Column="0"/>
<TextBox x:Name="TransferDateInput" Grid.Column="1" Width="77" HorizontalAlignment="Left" Margin="0,100,10,0"
<TextBox x:Name="TransferDateInput" Text="{Binding TransferDateString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="{Binding IsReadOnly}"
Grid.Column="1" Width="77" HorizontalAlignment="Left" Margin="0,100,10,0"
TextChanged="TransferDateInput_TextChanged"/>
<Label Content="Rebelzuschlag:" Margin="10,130,0,0" Grid.Column="0"/>
<ctrl:UnitTextBox x:Name="WeightModifierInput" Grid.Column="1" Width="60" Margin="0,130,10,0" Unit="%"
<ctrl:UnitTextBox x:Name="WeightModifierInput" Text="{Binding WeightModifierString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="{Binding IsReadOnly}"
Grid.Column="1" Width="60" Margin="0,130,10,0" Unit="%"
HorizontalAlignment="Left" VerticalAlignment="Top"
TextChanged="WeightModifierInput_TextChanged" LostFocus="WeightModifierInput_LostFocus"/>
@@ -160,19 +174,24 @@
</TextBlock>
<Label Content="Berücksichtigen:" Margin="90,70,10,10" Grid.Column="1"/>
<CheckBox x:Name="ConsiderModifiersInput" Content="Zu-/Abschläge bei Lieferungen (inkl. Rebelzuschl.)"
<CheckBox x:Name="ConsiderModifiersInput" IsChecked="{Binding ConsiderModifiers, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding IsEnabled}"
Content="Zu-/Abschläge bei Lieferungen (inkl. Rebelzuschl.)"
Margin="110,95,10,10" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top"
Checked="ConsiderModifiersInput_Changed" Unchecked="ConsiderModifiersInput_Changed"/>
<CheckBox x:Name="ConsiderPenaltiesInput" Content="Pönalen bei Unterlieferungen (FB)"
<CheckBox x:Name="ConsiderPenaltiesInput" IsChecked="{Binding ConsiderPenalties, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding IsEnabled}"
Content="Pönalen bei Unterlieferungen (FB)"
Margin="110,115,10,10" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top"
Checked="ConsiderPenaltiesInput_Changed" Unchecked="ConsiderPenaltiesInput_Changed"/>
<CheckBox x:Name="ConsiderPenaltyInput" Content="Strafen bei Unterlieferungen (GA)"
<CheckBox x:Name="ConsiderPenaltyInput" IsChecked="{Binding ConsiderPenalty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding IsEnabled}"
Content="Strafen bei Unterlieferungen (GA)"
Margin="110,135,10,10" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top"
Checked="ConsiderPenaltyInput_Changed" Unchecked="ConsiderPenaltyInput_Changed"/>
<CheckBox x:Name="ConsiderAutoInput" Content="Automatische Nachzeichnungen der GA"
<CheckBox x:Name="ConsiderAutoInput" IsChecked="{Binding ConsiderAuto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding IsEnabled}"
Content="Automatische Nachzeichnungen der GA"
Margin="110,155,10,10" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top"
Checked="ConsiderAutoInput_Changed" Unchecked="ConsiderAutoInput_Changed"/>
<CheckBox x:Name="ConsiderCustomInput" Content="Benutzerdefinierte Zu-/Abschläge pro Mitglied"
<CheckBox x:Name="ConsiderCustomInput" IsChecked="{Binding ConsiderCustom, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding IsEnabled}"
Content="Benutzerdefinierte Zu-/Abschläge pro Mitglied"
Margin="110,175,10,10" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top"
Checked="ConsiderCustomInput_Changed" Unchecked="ConsiderCustomInput_Changed"/>
<Label Content="&#xF0AE;" FontFamily="Segoe MDL2 Assets" FontSize="16" Grid.Row="0" Grid.Column="1" Margin="108,195,10,10"/>
@@ -206,7 +225,8 @@
</Style>
</Grid.Resources>
<Button x:Name="EditButton" Content="Bearbeiten" Grid.Column="0" Grid.Row="2"
<Button x:Name="EditButton" IsEnabled="{Binding IsPaymentVariantSelected}"
Content="{Binding EditText}" Grid.Column="0" Grid.Row="2"
Click="EditButton_Click"/>
<Label Content="&#xF0AF;" FontFamily="Segoe MDL2 Assets" FontSize="16" Grid.Row="2" Grid.Column="1"/>
<Button x:Name="ModifierButton" Content="Zu-/Abschläge" Grid.Column="0" Grid.Row="4"
@@ -219,12 +239,13 @@
</TransformGroup>
</Label.RenderTransform>
</Label>
<Button x:Name="CalculateButton" Content="Berechnen" Grid.Column="2" Grid.Row="2"
<Button x:Name="CalculateButton" IsEnabled="{Binding CalculateIsEnabled}"
Content="Berechnen" Grid.Column="2" Grid.Row="2"
Click="CalculateButton_Click"/>
<Label Content="&#xF0AF;" FontFamily="Segoe MDL2 Assets" FontSize="16" Grid.Row="2" Grid.Column="3" x:Name="Arrow3"/>
<Label Content="{Binding Arrow}" FontFamily="Segoe MDL2 Assets" FontSize="16" Grid.Row="2" Grid.Column="3"/>
<Button x:Name="PaymentAdjustmentButton" Content="Anpassen" Grid.Column="2" Grid.Row="4"
Click="PaymentAdjustmentButton_Click"/>
<Label Content="&#xF0AF;" FontFamily="Segoe MDL2 Assets" FontSize="16" Grid.Row="4" Grid.Column="3" x:Name="Arrow4" RenderTransformOrigin="0.5,0.5" >
<Label Content="{Binding Arrow}" FontFamily="Segoe MDL2 Assets" FontSize="16" Grid.Row="4" Grid.Column="3" RenderTransformOrigin="0.5,0.5" >
<Label.RenderTransform>
<TransformGroup>
<RotateTransform Angle="-45"/>
@@ -232,16 +253,19 @@
</TransformGroup>
</Label.RenderTransform>
</Label>
<Button x:Name="CommitButton" Content="Festsetzen" Grid.Column="4" Grid.Row="2"
<Button x:Name="CommitButton" IsEnabled="{Binding CommitIsEnabled}" Visibility="{Binding CommitVisibility}"
Content="Festsetzen" Grid.Column="4" Grid.Row="2"
Click="CommitButton_Click"/>
<Button x:Name="RevertButton" Content="Freigeben" Grid.Column="4" Grid.Row="2"
<Button x:Name="RevertButton" IsEnabled="{Binding RevertIsEnabled}" Visibility="{Binding RevertVisibility}"
Content="Freigeben" Grid.Column="4" Grid.Row="2"
Click="RevertButton_Click"/>
<Button x:Name="SaveButton" Content="Speichern" Grid.Column="4" Grid.Row="0"
<Button x:Name="SaveButton" IsEnabled="{Binding SaveIsEnabled}"
Content="Speichern" Grid.Column="4" Grid.Row="0"
Click="SaveButton_Click"/>
</Grid>
<Button x:Name="MailButton"
FontSize="14" Width="180" Margin="10,10,10,10" Height="30" IsEnabled="False"
<Button x:Name="MailButton" IsEnabled="{Binding IsPaymentVariantSelected}"
FontSize="14" Width="180" Margin="10,10,10,10" Height="30"
Click="MailButton_Click"
VerticalAlignment="Bottom" HorizontalAlignment="Right" HorizontalContentAlignment="Stretch" Grid.Column="1">
<Grid>
@@ -273,35 +297,35 @@
<StatusBarItem Grid.Column="0" HorizontalContentAlignment="Stretch">
<DockPanel>
<TextBlock Text="Zu-/Abschl.:"/>
<TextBlock x:Name="ModifierSum" Text="-" TextAlignment="Right"/>
<TextBlock Text="{Binding StatusModifierSum}" TextAlignment="Right"/>
</DockPanel>
</StatusBarItem>
<Separator Grid.Column="1"/>
<StatusBarItem Grid.Column="2" HorizontalContentAlignment="Stretch">
<DockPanel>
<TextBlock Text="Gesamt:"/>
<TextBlock x:Name="TotalSum" Text="-" TextAlignment="Right"/>
<TextBlock Text="{Binding StatusTotalSum}" TextAlignment="Right"/>
</DockPanel>
</StatusBarItem>
<Separator Grid.Column="3"/>
<StatusBarItem Grid.Column="4" HorizontalContentAlignment="Stretch">
<DockPanel>
<TextBlock Text="MwSt.:"/>
<TextBlock x:Name="VatSum" Text="-" TextAlignment="Right"/>
<TextBlock Text="{Binding StatusVatSum}" TextAlignment="Right"/>
</DockPanel>
</StatusBarItem>
<Separator Grid.Column="5"/>
<StatusBarItem Grid.Column="6" HorizontalContentAlignment="Stretch">
<DockPanel>
<TextBlock Text="Abzüge:"/>
<TextBlock x:Name="DeductionSum" Text="-" TextAlignment="Right"/>
<TextBlock Text="{Binding StatusDeductionSum}" TextAlignment="Right"/>
</DockPanel>
</StatusBarItem>
<Separator Grid.Column="7"/>
<StatusBarItem Grid.Column="8" HorizontalContentAlignment="Stretch">
<DockPanel>
<TextBlock Text="Auszahl.:"/>
<TextBlock x:Name="PaymentSum" Text="-" TextAlignment="Right"/>
<TextBlock Text="{Binding StatusPaymentSum}" TextAlignment="Right"/>
</DockPanel>
</StatusBarItem>
</StatusBar>

View File

@@ -1,9 +1,10 @@
using Elwig.Documents;
using Elwig.Helpers;
using Elwig.Helpers.Billing;
using Elwig.Helpers.Export;
using Elwig.Models.Dtos;
using Elwig.Models.Entities;
using Elwig.Services;
using Elwig.ViewModels;
using Microsoft.EntityFrameworkCore;
using Microsoft.Win32;
using System;
@@ -17,13 +18,10 @@ using System.Windows.Input;
namespace Elwig.Windows {
public partial class PaymentVariantsWindow : ContextWindow {
public readonly int Year;
public readonly bool SeasonLocked;
private bool DataValid, DataChanged, NameChanged, CommentChanged, DateValid, DateChanged, TransferDateValid, TransferDateChanged;
private BillingData? BillingData;
private bool WeightModifierChanged = false;
public PaymentVariantsViewModel ViewModel => (PaymentVariantsViewModel)DataContext;
private static readonly JsonSerializerOptions JsonOpt = new() { WriteIndented = true };
public readonly int Year;
private bool DataValid, DataChanged, NameChanged, CommentChanged, DateValid, DateChanged, TransferDateValid, TransferDateChanged;
private readonly RoutedCommand CtrlL = new("CtrlL", typeof(MemberAdminWindow), [new KeyGesture(Key.L, ModifierKeys.Control)]);
private readonly RoutedCommand CtrlP = new("CtrlP", typeof(MemberAdminWindow), [new KeyGesture(Key.P, ModifierKeys.Control)]);
@@ -38,7 +36,7 @@ namespace Elwig.Windows {
CommandBindings.Add(new CommandBinding(CtrlShiftP, Menu_SummaryPrint_Click));
Year = year;
using (var ctx = new AppDbContext()) {
SeasonLocked = ctx.Seasons.Find(Year + 1) != null;
ViewModel.SeasonLocked = ctx.Seasons.Find(Year + 1) != null;
}
Title = $"Auszahlungsvarianten - Lese {Year} - Elwig";
if (!App.Config.Debug) {
@@ -62,220 +60,26 @@ namespace Elwig.Windows {
private void Update() {
if (PaymentVariantList.SelectedItem is PaymentVar v) {
var locked = !v.TestVariant;
DeleteButton.IsEnabled = !locked;
CalculateButton.IsEnabled = !locked;
CommitButton.IsEnabled = !locked && !SeasonLocked;
CommitButton.Visibility = !locked ? Visibility.Visible : Visibility.Hidden;
RevertButton.IsEnabled = locked && !SeasonLocked;
RevertButton.Visibility = locked ? Visibility.Visible : Visibility.Hidden;
Arrow3.Content = locked ? "\xF0B0" : "\xF0AF";
Arrow4.Content = locked ? "\xF0B0" : "\xF0AF";
CopyButton.IsEnabled = true;
EditButton.Content = locked ? "Ansehen" : "Bearbeiten";
EditButton.IsEnabled = true;
SaveButton.IsEnabled = !locked;
MailButton.IsEnabled = true;
Menu_ExportSave.IsEnabled = locked;
Menu_EbicsSave.IsEnabled = locked;
Menu_SummaryExport.IsEnabled = true;
Menu_SummaryShow.IsEnabled = true;
Menu_SummarySave.IsEnabled = true;
Menu_SummaryPrint.IsEnabled = true;
NameInput.Text = v.Name;
NameInput.IsReadOnly = false;
CommentInput.Text = v.Comment;
CommentInput.IsReadOnly = false;
DateInput.Text = $"{v.Date:dd.MM.yyyy}";
DateInput.IsReadOnly = false;
TransferDateInput.Text = $"{v.TransferDate:dd.MM.yyyy}";
TransferDateInput.IsReadOnly = false;
try {
BillingData = BillingData.FromJson(v.Data);
ConsiderModifiersInput.IsChecked = BillingData.ConsiderDelieryModifiers;
ConsiderPenaltiesInput.IsChecked = BillingData.ConsiderContractPenalties;
ConsiderPenaltyInput.IsChecked = BillingData.ConsiderTotalPenalty;
ConsiderAutoInput.IsChecked = BillingData.ConsiderAutoBusinessShares;
ConsiderCustomInput.IsChecked = BillingData.ConsiderCustomModifiers;
if (BillingData.NetWeightModifier != 0) {
WeightModifierInput.Text = $"{Math.Round(BillingData.NetWeightModifier * 100.0, 8)}";
} else if (BillingData.GrossWeightModifier != 0) {
WeightModifierInput.Text = $"{Math.Round(BillingData.GrossWeightModifier * 100.0, 8)}";
ViewModel.FillInputs(v);
} else {
WeightModifierInput.Text = "";
ViewModel.ClearInputs();
}
DataInput.Text = JsonSerializer.Serialize(BillingData.Data, JsonOpt);
} catch {
BillingData = null;
ConsiderModifiersInput.IsChecked = false;
ConsiderPenaltiesInput.IsChecked = false;
ConsiderPenaltyInput.IsChecked = false;
ConsiderAutoInput.IsChecked = false;
ConsiderCustomInput.IsChecked = false;
WeightModifierInput.Text = "";
DataInput.Text = v.Data;
}
WeightModifierInput.IsReadOnly = false;
ConsiderModifiersInput.IsEnabled = !locked;
ConsiderPenaltiesInput.IsEnabled = !locked;
ConsiderPenaltyInput.IsEnabled = !locked;
ConsiderAutoInput.IsEnabled = !locked;
ConsiderCustomInput.IsEnabled = !locked;
DataInput.IsReadOnly = locked;
ModifierSum.Text = "...";
TotalSum.Text = "...";
VatSum.Text = "...";
DeductionSum.Text = "...";
PaymentSum.Text = "...";
Utils.RunBackground("Variantendaten laden", async () => {
await UpdateSums(v);
});
} else {
EditButton.Content = "Bearbeiten";
EditButton.IsEnabled = false;
SaveButton.IsEnabled = false;
CopyButton.IsEnabled = false;
CalculateButton.IsEnabled = false;
CommitButton.IsEnabled = false;
CommitButton.Visibility = Visibility.Visible;
RevertButton.IsEnabled = false;
RevertButton.Visibility = Visibility.Hidden;
Arrow3.Content = "\xF0AF";
Arrow4.Content = "\xF0AF";
DeleteButton.IsEnabled = false;
MailButton.IsEnabled = false;
Menu_ExportSave.IsEnabled = false;
Menu_EbicsSave.IsEnabled = false;
Menu_SummaryExport.IsEnabled = false;
Menu_SummaryShow.IsEnabled = false;
Menu_SummarySave.IsEnabled = false;
Menu_SummaryPrint.IsEnabled = false;
BillingData = null;
NameInput.Text = "";
NameInput.IsReadOnly = true;
CommentInput.Text = "";
CommentInput.IsReadOnly = true;
DateInput.Text = "";
DateInput.IsReadOnly = true;
TransferDateInput.Text = "";
TransferDateInput.IsReadOnly = true;
WeightModifierInput.Text = "";
WeightModifierInput.IsReadOnly = true;
ConsiderModifiersInput.IsChecked = false;
ConsiderModifiersInput.IsEnabled = false;
ConsiderPenaltiesInput.IsChecked = false;
ConsiderPenaltiesInput.IsEnabled = false;
ConsiderPenaltyInput.IsChecked = false;
ConsiderPenaltyInput.IsEnabled = false;
ConsiderAutoInput.IsChecked = false;
ConsiderAutoInput.IsEnabled = false;
ConsiderCustomInput.IsChecked = false;
ConsiderCustomInput.IsEnabled = false;
DataInput.Text = "";
DataInput.IsReadOnly = true;
ModifierSum.Text = "-";
TotalSum.Text = "-";
VatSum.Text = "-";
DeductionSum.Text = "-";
PaymentSum.Text = "-";
UpdateButtons();
}
UpdateSaveButton();
}
private void UpdateSaveButton() {
SaveButton.IsEnabled = PaymentVariantList.SelectedItem != null &&
private void UpdateButtons() {
ViewModel.SaveIsEnabled = PaymentVariantList.SelectedItem != null &&
((DataChanged && DataValid) || NameChanged || CommentChanged ||
(DateChanged && DateValid) ||
(TransferDateChanged && TransferDateValid) ||
(ConsiderModifiersInput.IsChecked != BillingData?.ConsiderDelieryModifiers) ||
(ConsiderPenaltiesInput.IsChecked != BillingData?.ConsiderContractPenalties) ||
(ConsiderPenaltyInput.IsChecked != BillingData?.ConsiderTotalPenalty) ||
(ConsiderAutoInput.IsChecked != BillingData?.ConsiderAutoBusinessShares) ||
(ConsiderCustomInput.IsChecked != BillingData?.ConsiderCustomModifiers) ||
WeightModifierChanged);
CalculateButton.IsEnabled = !SaveButton.IsEnabled && PaymentVariantList.SelectedItem is PaymentVar { TestVariant: true };
CommitButton.IsEnabled = CalculateButton.IsEnabled;
}
private async Task UpdateSums(PaymentVar v) {
if (App.MainDispatcher == null)
return;
var modText = "-";
var totalText = "-";
var vatText = "-";
var deductionText = "-";
var paymentText = "-";
using var ctx = new AppDbContext();
var sym = v.Season.Currency.Symbol ?? v.Season.Currency.Code;
var modSum = await ctx.PaymentDeliveryParts
.Where(p => p.Year == v.Year && p.AvNr == v.AvNr)
.SumAsync(p => p.AmountValue - p.NetAmountValue);
modText = $"{v.Season.DecFromDb(modSum):N2} {sym}";
var totalSum = await ctx.MemberPayments
.Where(p => p.Year == v.Year && p.AvNr == v.AvNr)
.SumAsync(p => p.AmountValue);
totalText = $"{v.Season.DecFromDb(totalSum):N2} {sym}";
await App.MainDispatcher.BeginInvoke(() => {
if (PaymentVariantList.SelectedItem != v)
return;
ModifierSum.Text = modText;
TotalSum.Text = totalText;
});
var credits = ctx.Credits.Where(c => c.Year == v.Year && c.AvNr == v.AvNr);
if (!credits.Any()) {
long lastTotalSum = 0;
decimal vatSum = 0;
var currentPayments = await ctx.MemberPayments
.Where(p => p.Year == v.Year && p.AvNr == v.AvNr)
.ToDictionaryAsync(p => p.MgNr);
var lastV = await ctx.PaymentVariants
.Where(l => l.Year == v.Year && !l.TestVariant)
.OrderByDescending(l => l.TransferDateString ?? l.DateString)
.ThenByDescending(l => l.AvNr)
.FirstOrDefaultAsync();
if (lastV != null) {
var lastPayments = await ctx.MemberPayments
.Where(p => p.Year == v.Year && p.AvNr == lastV.AvNr)
.ToDictionaryAsync(p => p.MgNr);
lastTotalSum = lastPayments.Sum(e => e.Value.AmountValue);
foreach (int mgnr in currentPayments.Keys) {
var c = currentPayments[mgnr];
var l = lastPayments[mgnr];
vatSum += (c.Amount - l.Amount) * (decimal)(c.Member.IsBuchführend ? v.Season.VatNormal : v.Season.VatFlatrate);
}
} else {
vatSum = currentPayments.Sum(e => e.Value.Amount * (decimal)(e.Value.Member.IsBuchführend ? v.Season.VatNormal : v.Season.VatFlatrate));
}
vatText = $"~{vatSum:N2} {sym}";
deductionText = $"- {sym}";
paymentText = $"~{v.Season.DecFromDb(totalSum - lastTotalSum) + vatSum:N2} {sym}";
} else {
// all values in the credit table are stored with precision 2!
totalText = $"{Utils.DecFromDb(await credits.SumAsync(c => c.NetAmountValue), 2):N2} {sym}";
vatText = $"{Utils.DecFromDb(await credits.SumAsync(c => c.VatAmountValue), 2):N2} {sym}";
deductionText = $"{-Utils.DecFromDb(await credits.SumAsync(c => c.ModifiersValue ?? 0), 2):N2} {sym}";
paymentText = $"{Utils.DecFromDb(await credits.SumAsync(c => c.AmountValue), 2):N2} {sym}";
}
await App.MainDispatcher.BeginInvoke(() => {
if (PaymentVariantList.SelectedItem != v)
return;
ModifierSum.Text = modText;
TotalSum.Text = totalText;
VatSum.Text = vatText;
DeductionSum.Text = deductionText;
PaymentSum.Text = paymentText;
});
(ViewModel.ConsiderModifiers != ViewModel.BillingData?.ConsiderDelieryModifiers) ||
(ViewModel.ConsiderPenalties != ViewModel.BillingData?.ConsiderContractPenalties) ||
(ViewModel.ConsiderPenalty != ViewModel.BillingData?.ConsiderTotalPenalty) ||
(ViewModel.ConsiderAuto != ViewModel.BillingData?.ConsiderAutoBusinessShares) ||
(ViewModel.ConsiderCustom != ViewModel.BillingData?.ConsiderCustomModifiers) ||
ViewModel.WeightModifierChanged);
ViewModel.CalculateIsEnabled = !ViewModel.SaveIsEnabled && PaymentVariantList.SelectedItem is PaymentVar { TestVariant: true };
ViewModel.CommitIsEnabled = ViewModel.CalculateIsEnabled;
}
private void PaymentVariantList_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
@@ -284,23 +88,7 @@ namespace Elwig.Windows {
private async void AddButton_Click(object sender, RoutedEventArgs evt) {
try {
PaymentVar? v;
using (var ctx = new AppDbContext()) {
v = new PaymentVar {
Year = Year,
AvNr = await ctx.NextAvNr(Year),
Name = "Neue Auszahlungsvariante",
TestVariant = true,
DateString = $"{DateTime.Today:yyyy-MM-dd}",
Data = "{\"mode\": \"elwig\", \"version\": 1, \"payment\": {}, \"curves\": []}",
};
ctx.Add(v);
await ctx.SaveChangesAsync();
}
App.HintContextChange();
var v = await PaymentVariantService.CreatePaymentVariant(Year);
ControlUtils.SelectItem(PaymentVariantList, v);
} catch (Exception exc) {
var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message;
@@ -312,23 +100,7 @@ namespace Elwig.Windows {
private async void CopyButton_Click(object sender, RoutedEventArgs evt) {
if (PaymentVariantList.SelectedItem is not PaymentVar orig) return;
try {
PaymentVar? n;
using (var ctx = new AppDbContext()) {
n = new PaymentVar {
Year = orig.Year,
AvNr = await ctx.NextAvNr(Year),
Name = $"{orig.Name} (Kopie)",
TestVariant = true,
DateString = $"{DateTime.Today:yyyy-MM-dd}",
Data = orig.Data,
};
ctx.Add(n);
await ctx.SaveChangesAsync();
}
App.HintContextChange();
PaymentVar n = await orig.Duplicate();
ControlUtils.SelectItem(PaymentVariantList, n);
} catch (Exception exc) {
var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message;
@@ -340,11 +112,7 @@ namespace Elwig.Windows {
private async void DeleteButton_Click(object sender, RoutedEventArgs evt) {
if (PaymentVariantList.SelectedItem is not PaymentVar v || !v.TestVariant) return;
try {
using (var ctx = new AppDbContext()) {
ctx.Remove(v);
await ctx.SaveChangesAsync();
}
App.HintContextChange();
await PaymentVariantService.DeletePaymentVariant(v.Year, v.AvNr);
} catch (Exception exc) {
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;
@@ -355,17 +123,16 @@ namespace Elwig.Windows {
private async void CalculateButton_Click(object sender, RoutedEventArgs evt) {
if (PaymentVariantList.SelectedItem is not PaymentVar v)
return;
CalculateButton.IsEnabled = false;
ViewModel.CalculateIsEnabled = false;
Mouse.OverrideCursor = Cursors.AppStarting;
try {
var b = new BillingVariant(v.Year, v.AvNr);
await b.Calculate();
await PaymentVariantService.Calculate(v.Year, v.AvNr);
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Berechnungsfehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
App.HintContextChange();
Mouse.OverrideCursor = null;
CalculateButton.IsEnabled = true;
ViewModel.CalculateIsEnabled = true;
}
private void EditButton_Click(object sender, RoutedEventArgs evt) {
@@ -417,38 +184,25 @@ namespace Elwig.Windows {
private async void Menu_SummaryShow_Click(object sender, RoutedEventArgs evt) {
if (PaymentVariantList.SelectedItem is not PaymentVar v)
return;
await GenerateSummary(v, ExportMode.Show);
await PaymentVariantService.GenerateSummary(v, ExportMode.Show);
}
private async void Menu_SummarySave_Click(object sender, RoutedEventArgs evt) {
if (PaymentVariantList.SelectedItem is not PaymentVar v)
return;
await GenerateSummary(v, ExportMode.SavePdf);
await PaymentVariantService.GenerateSummary(v, ExportMode.SavePdf);
}
private async void Menu_SummaryPrint_Click(object sender, RoutedEventArgs evt) {
if (PaymentVariantList.SelectedItem is not PaymentVar v)
return;
await GenerateSummary(v, ExportMode.Print);
}
private static async Task GenerateSummary(PaymentVar v, ExportMode mode) {
Mouse.OverrideCursor = Cursors.AppStarting;
try {
using var ctx = new AppDbContext();
var data = await PaymentVariantSummaryData.ForPaymentVariant(v, ctx.PaymentVariantSummaryRows);
using var doc = new PaymentVariantSummary((await ctx.PaymentVariants.FindAsync(v.Year, v.AvNr))!, data);
await Utils.ExportDocument(doc, mode);
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
Mouse.OverrideCursor = null;
await PaymentVariantService.GenerateSummary(v, ExportMode.Print);
}
private async void CommitButton_Click(object sender, RoutedEventArgs evt) {
if (PaymentVariantList.SelectedItem is not PaymentVar v)
return;
CommitButton.IsEnabled = false;
ViewModel.CommitIsEnabled = false;
Mouse.OverrideCursor = Cursors.AppStarting;
try {
var b = new BillingVariant(v.Year, v.AvNr);
@@ -457,7 +211,7 @@ namespace Elwig.Windows {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
Mouse.OverrideCursor = null;
RevertButton.IsEnabled = true;
ViewModel.RevertIsEnabled = true;
App.HintContextChange();
}
@@ -470,13 +224,13 @@ namespace Elwig.Windows {
"Traubengutschriften löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (res != MessageBoxResult.Yes)
return;
RevertButton.IsEnabled = false;
ViewModel.RevertIsEnabled = false;
Mouse.OverrideCursor = Cursors.AppStarting;
var b = new BillingVariant(v.Year, v.AvNr);
await b.Revert();
App.HintContextChange();
Mouse.OverrideCursor = null;
CommitButton.IsEnabled = true;
ViewModel.CommitIsEnabled = true;
}
private async void Menu_EbicsSave_Click(object sender, RoutedEventArgs evt) {
@@ -486,107 +240,35 @@ namespace Elwig.Windows {
MessageBox.Show("Überweisungsdatum muss gesetzt sein!", "Exportieren nicht möglich", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
using var ctx = new AppDbContext();
v = (await ctx.PaymentVariants.FindAsync(v.Year, v.AvNr))!;
var withoutIban = v.Credits.Count(c => c.Member.Iban == null);
if (withoutIban > 0) {
var r = MessageBox.Show($"Achtung: Für {withoutIban:N0} Mitglieder ist kein IBAN hinterlegt.\n\nDiese werden NICHT exportiert.",
"Mitglieder ohne IBAN", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel);
if (r != MessageBoxResult.OK) return;
}
var withNegAmount = v.Credits.Count(c => c.Amount <= 0);
if (withNegAmount > 0) {
var r = MessageBox.Show($"Achtung: Es gibt {withNegAmount:N0} Traubengutschriften mit negativem Betrag.\n\nDiese werden NICHT exportiert.",
"Traubengutschriften mit negativem Betrag", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.OK);
if (r != MessageBoxResult.OK) return;
}
var d = new SaveFileDialog() {
FileName = $"{App.Client.NameToken}-Überweisungsdaten-{v.Year}-{v.Name.Trim().Replace(' ', '-')}.{Ebics.FileExtension}",
DefaultExt = Ebics.FileExtension,
Filter = "EBICS-Datei (*.xml)|*.xml",
Title = $"Überweisungsdaten speichern unter - Elwig",
};
if (d.ShowDialog() == true) {
Menu_EbicsSave.IsEnabled = false;
Mouse.OverrideCursor = Cursors.AppStarting;
try {
using var e = new Ebics(v, d.FileName, App.Client.ExportEbicsVersion, (Ebics.AddressMode)App.Client.ExportEbicsAddress);
await e.ExportAsync(Transaction.FromPaymentVariant(v));
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
Mouse.OverrideCursor = null;
Menu_EbicsSave.IsEnabled = true;
}
await PaymentVariantService.GenerateEbics(v.Year, v.AvNr);
}
private async void Menu_ExportSave_Click(object sender, RoutedEventArgs evt) {
if (PaymentVariantList.SelectedItem is not PaymentVar v) {
if (PaymentVariantList.SelectedItem is not PaymentVar v)
return;
}
var d = new SaveFileDialog() {
FileName = $"{App.Client.NameToken}-Buchungsliste-{v.Year}-{v.Name.Trim().Replace(' ', '-')}.ods",
DefaultExt = "ods",
Filter = "OpenDocument Format Spreadsheet (*.ods)|*.ods",
Title = $"Buchungsliste speichern unter - Elwig"
};
if (d.ShowDialog() == true) {
Menu_ExportSave.IsEnabled = false;
Mouse.OverrideCursor = Cursors.AppStarting;
try {
using var ctx = new AppDbContext();
var tbl = await CreditNoteData.ForPaymentVariant(ctx, v.Year, v.AvNr);
using var ods = new OdsFile(d.FileName);
await ods.AddTable(tbl);
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
Mouse.OverrideCursor = null;
Menu_ExportSave.IsEnabled = true;
}
await PaymentVariantService.GenerateAccountingList(v.Year, v.AvNr, v.Name);
}
private async void SaveButton_Click(object sender, RoutedEventArgs evt) {
if (PaymentVariantList.SelectedItem is not PaymentVar v || BillingData == null) return;
if (PaymentVariantList.SelectedItem is not PaymentVar v || ViewModel.BillingData == null) return;
try {
v.Name = NameInput.Text;
v.Comment = (CommentInput.Text != "") ? CommentInput.Text : null;
v.DateString = string.Join("-", DateInput.Text.Split(".").Reverse());
v.TransferDateString = (TransferDateInput.Text != "") ? string.Join("-", TransferDateInput.Text.Split(".").Reverse()) : null;
var d = App.Config.Debug ? BillingData.FromJson(DataInput.Text) : BillingData;
d.ConsiderDelieryModifiers = ConsiderModifiersInput.IsChecked ?? false;
d.ConsiderContractPenalties = ConsiderPenaltiesInput.IsChecked ?? false;
d.ConsiderTotalPenalty = ConsiderPenaltyInput.IsChecked ?? false;
d.ConsiderAutoBusinessShares = ConsiderAutoInput.IsChecked ?? false;
d.ConsiderCustomModifiers = ConsiderCustomInput.IsChecked ?? false;
var modVal = WeightModifierInput.Text.Length > 0 ? double.Parse(WeightModifierInput.Text) : 0;
d.NetWeightModifier = modVal > 0 ? modVal / 100.0 : 0;
d.GrossWeightModifier = modVal < 0 ? modVal / 100.0 : 0;
WeightModifierChanged = false;
v.Data = JsonSerializer.Serialize(d.Data);
using (var ctx = new AppDbContext()) {
ctx.Update(v);
await ctx.SaveChangesAsync();
}
App.HintContextChange();
CommentInput_TextChanged(null, null);
ConsiderModifiersInput_Changed(null, null);
ConsiderPenaltiesInput_Changed(null, null);
ConsiderPenaltyInput_Changed(null, null);
ConsiderAutoInput_Changed(null, null);
ConsiderCustomInput_Changed(null, null);
WeightModifierInput_TextChanged(null, null);
await ViewModel.UpdatePaymentVariant(v.Year, v.AvNr);
} catch (Exception exc) {
await HintContextChange();
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;
MessageBox.Show(str, "Auszahlungsvariante aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
}
await HintContextChange();
CommentInput_TextChanged(null, null);
DateInput_TextChanged(null, null);
TransferDateInput_TextChanged(null, null);
ConsiderModifiersInput_Changed(null, null);
ConsiderPenaltiesInput_Changed(null, null);
ConsiderPenaltyInput_Changed(null, null);
ConsiderAutoInput_Changed(null, null);
ConsiderCustomInput_Changed(null, null);
WeightModifierInput_TextChanged(null, null);
}
private void ModifierButton_Click(object sender, RoutedEventArgs evt) {
@@ -605,7 +287,7 @@ namespace Elwig.Windows {
ControlUtils.ClearInputState(NameInput);
NameChanged = false;
}
UpdateSaveButton();
UpdateButtons();
}
private void CommentInput_TextChanged(object? sender, TextChangedEventArgs? evt) {
@@ -620,10 +302,10 @@ namespace Elwig.Windows {
ControlUtils.ClearInputState(CommentInput);
CommentChanged = false;
}
UpdateSaveButton();
UpdateButtons();
}
private void DateInput_TextChanged(object sender, TextChangedEventArgs evt) {
private void DateInput_TextChanged(object? sender, TextChangedEventArgs? evt) {
if (PaymentVariantList.SelectedItem is not PaymentVar v) {
ControlUtils.ClearInputState(DateInput);
return;
@@ -641,10 +323,10 @@ namespace Elwig.Windows {
DateValid = true;
DateChanged = false;
}
UpdateSaveButton();
UpdateButtons();
}
private void TransferDateInput_TextChanged(object sender, TextChangedEventArgs evt) {
private void TransferDateInput_TextChanged(object? sender, TextChangedEventArgs? evt) {
if (PaymentVariantList.SelectedItem is not PaymentVar v) {
ControlUtils.ClearInputState(TransferDateInput);
return;
@@ -662,7 +344,7 @@ namespace Elwig.Windows {
TransferDateValid = true;
TransferDateChanged = false;
}
UpdateSaveButton();
UpdateButtons();
}
private void DataInput_TextChanged(object sender, TextChangedEventArgs evt) {
@@ -688,89 +370,89 @@ namespace Elwig.Windows {
ControlUtils.SetInputInvalid(DataInput);
DataValid = false;
}
UpdateSaveButton();
UpdateButtons();
}
private void ConsiderModifiersInput_Changed(object? sender, RoutedEventArgs? evt) {
if (BillingData == null) {
if (ViewModel.BillingData == null) {
ControlUtils.ClearInputState(ConsiderModifiersInput);
return;
}
if (BillingData.ConsiderDelieryModifiers != ConsiderModifiersInput.IsChecked) {
if (ViewModel.BillingData.ConsiderDelieryModifiers != ConsiderModifiersInput.IsChecked) {
ControlUtils.SetInputChanged(ConsiderModifiersInput);
} else {
ControlUtils.ClearInputState(ConsiderModifiersInput);
}
UpdateSaveButton();
UpdateButtons();
}
private void ConsiderPenaltiesInput_Changed(object? sender, RoutedEventArgs? evt) {
if (BillingData == null) {
if (ViewModel.BillingData == null) {
ControlUtils.ClearInputState(ConsiderPenaltiesInput);
return;
}
if (BillingData.ConsiderContractPenalties != ConsiderPenaltiesInput.IsChecked) {
if (ViewModel.BillingData.ConsiderContractPenalties != ConsiderPenaltiesInput.IsChecked) {
ControlUtils.SetInputChanged(ConsiderPenaltiesInput);
} else {
ControlUtils.ClearInputState(ConsiderPenaltiesInput);
}
UpdateSaveButton();
UpdateButtons();
}
private void ConsiderPenaltyInput_Changed(object? sender, RoutedEventArgs? evt) {
if (BillingData == null) {
if (ViewModel.BillingData == null) {
ControlUtils.ClearInputState(ConsiderPenaltyInput);
return;
}
if (BillingData.ConsiderTotalPenalty != ConsiderPenaltyInput.IsChecked) {
if (ViewModel.BillingData.ConsiderTotalPenalty != ConsiderPenaltyInput.IsChecked) {
ControlUtils.SetInputChanged(ConsiderPenaltyInput);
} else {
ControlUtils.ClearInputState(ConsiderPenaltyInput);
}
UpdateSaveButton();
UpdateButtons();
}
private void ConsiderAutoInput_Changed(object? sender, RoutedEventArgs? evt) {
if (BillingData == null) {
if (ViewModel.BillingData == null) {
ControlUtils.ClearInputState(ConsiderAutoInput);
return;
}
if (BillingData.ConsiderAutoBusinessShares != ConsiderAutoInput.IsChecked) {
if (ViewModel.BillingData.ConsiderAutoBusinessShares != ConsiderAutoInput.IsChecked) {
ControlUtils.SetInputChanged(ConsiderAutoInput);
} else {
ControlUtils.ClearInputState(ConsiderAutoInput);
}
UpdateSaveButton();
UpdateButtons();
}
private void ConsiderCustomInput_Changed(object? sender, RoutedEventArgs? evt) {
if (BillingData == null) {
if (ViewModel.BillingData == null) {
ControlUtils.ClearInputState(ConsiderCustomInput);
return;
}
if (BillingData.ConsiderCustomModifiers != ConsiderCustomInput.IsChecked) {
if (ViewModel.BillingData.ConsiderCustomModifiers != ConsiderCustomInput.IsChecked) {
ControlUtils.SetInputChanged(ConsiderCustomInput);
} else {
ControlUtils.ClearInputState(ConsiderCustomInput);
}
UpdateSaveButton();
UpdateButtons();
}
private void WeightModifierInput_TextChanged(object? sender, TextChangedEventArgs? evt) {
var res = Validator.CheckDecimal(WeightModifierInput, false, 3, 2, true);
if (BillingData == null) {
if (ViewModel.BillingData == null) {
ControlUtils.ClearInputState(WeightModifierInput);
return;
}
var val = WeightModifierInput.Text.Length > 0 && res.IsValid ? double.Parse(WeightModifierInput.Text) : 0;
WeightModifierChanged = (val != Math.Round(BillingData.NetWeightModifier * 100.0, 8) && val != Math.Round(BillingData.GrossWeightModifier * 100.0, 8)) ||
(val == 0 && (BillingData.NetWeightModifier != 0 || BillingData.GrossWeightModifier != 0));
if (WeightModifierChanged) {
ViewModel.WeightModifierChanged = (val != Math.Round(ViewModel.BillingData.NetWeightModifier * 100.0, 8) && val != Math.Round(ViewModel.BillingData.GrossWeightModifier * 100.0, 8)) ||
(val == 0 && (ViewModel.BillingData.NetWeightModifier != 0 || ViewModel.BillingData.GrossWeightModifier != 0));
if (ViewModel.WeightModifierChanged) {
ControlUtils.SetInputChanged(WeightModifierInput);
} else {
ControlUtils.ClearInputState(WeightModifierInput);
}
UpdateSaveButton();
UpdateButtons();
}
private void WeightModifierInput_LostFocus(object sender, RoutedEventArgs evt) {