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; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace Elwig.Windows { public partial class PaymentVariantsWindow : ContextWindow { public PaymentVariantsViewModel ViewModel => (PaymentVariantsViewModel)DataContext; 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)]); private readonly RoutedCommand CtrlÜ = new("CtrlÜ", typeof(MemberAdminWindow), [new KeyGesture(Key.Oem1, ModifierKeys.Control)]); private readonly RoutedCommand CtrlShiftP = new("CtrlShiftP", typeof(MemberAdminWindow), [new KeyGesture(Key.P, ModifierKeys.Control | ModifierKeys.Shift)]); public PaymentVariantsWindow(int year) { InitializeComponent(); CommandBindings.Add(new CommandBinding(CtrlL, Menu_ExportSave_Click)); CommandBindings.Add(new CommandBinding(CtrlP, Menu_SummaryShow_Click)); CommandBindings.Add(new CommandBinding(CtrlÜ, Menu_EbicsSave_Click)); CommandBindings.Add(new CommandBinding(CtrlShiftP, Menu_SummaryPrint_Click)); Year = year; using (var ctx = new AppDbContext()) { ViewModel.SeasonLocked = ctx.Seasons.Find(Year + 1) != null; } Title = $"Auszahlungsvarianten - Lese {Year} - Elwig"; if (!App.Config.Debug) { DataInput.Visibility = Visibility.Hidden; } if (App.Client.IsMatzen) { ConsiderCustomInput.Content = ConsiderCustomInput.Content.ToString()?.Replace("Benutzerdefinierte", "Bentz.def.").Replace("Mitglied", "Mg.") + " (inkl. Treuebonus)"; } else { MatzenNote.Visibility = Visibility.Hidden; } } protected override async Task OnRenewContext(AppDbContext ctx) { ControlUtils.RenewItemsSource(PaymentVariantList, await ctx.PaymentVariants .Where(v => v.Year == Year) .OrderBy(v => v.AvNr) .Include(v => v.Season.Currency) .ToListAsync()); Update(); } private void Update() { if (PaymentVariantList.SelectedItem is PaymentVar v) { ViewModel.FillInputs(v); } else { ViewModel.ClearInputs(); } UpdateButtons(); } private void UpdateButtons() { ViewModel.SaveIsEnabled = PaymentVariantList.SelectedItem != null && ((DataChanged && DataValid) || NameChanged || CommentChanged || (DateChanged && DateValid) || (TransferDateChanged && TransferDateValid) || (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) { Update(); } private async void AddButton_Click(object sender, RoutedEventArgs evt) { try { 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; if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message; MessageBox.Show(str, "Auszahlungsvariante erstellen", MessageBoxButton.OK, MessageBoxImage.Error); } } private async void CopyButton_Click(object sender, RoutedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar orig) return; try { 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; if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message; MessageBox.Show(str, "Auszahlungsvariante kopieren", MessageBoxButton.OK, MessageBoxImage.Error); } } private async void DeleteButton_Click(object sender, RoutedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v || !v.TestVariant) return; try { 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; MessageBox.Show(str, "Auszahlungsvariante löschen", MessageBoxButton.OK, MessageBoxImage.Error); } } private async void CalculateButton_Click(object sender, RoutedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) return; ViewModel.CalculateIsEnabled = false; Mouse.OverrideCursor = Cursors.AppStarting; try { await PaymentVariantService.Calculate(v.Year, v.AvNr); } catch (Exception exc) { MessageBox.Show(exc.Message, "Berechnungsfehler", MessageBoxButton.OK, MessageBoxImage.Error); } App.HintContextChange(); Mouse.OverrideCursor = null; ViewModel.CalculateIsEnabled = true; } private void EditButton_Click(object sender, RoutedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) return; App.FocusChartWindow(v.Year, v.AvNr); } private void PaymentAdjustmentButton_Click(object sender, RoutedEventArgs evt) { App.FocusPaymentAdjustment(Year); } private async void MailButton_Click(object sender, RoutedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar pv) return; using var ctx = new AppDbContext(); var vars = await ctx.PaymentVariants .Where(v => pv.Year == v.Year) .OrderBy(v => v.AvNr) .Select(v => v.AvNr) .ToArrayAsync(); var w = App.FocusMailWindow(pv.Year); w.AddCreditNote(Array.IndexOf(vars, pv.AvNr)); } private async void Menu_SummaryExport_Click(object sender, RoutedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) return; var d = new SaveFileDialog() { FileName = $"Variantendaten-{v.Name.Trim().Replace(' ', '-')}.ods", DefaultExt = "ods", Filter = "OpenDocument Format Spreadsheet (*.ods)|*.ods", Title = $"Variantendaten {v.Name} speichern unter - Elwig" }; if (d.ShowDialog() == false) return; Mouse.OverrideCursor = Cursors.AppStarting; try { using var ctx = new AppDbContext(); var data = await PaymentVariantSummaryData.ForPaymentVariant(v, ctx.PaymentVariantSummaryRows); using var ods = new OdsFile(d.FileName); await ods.AddTable(data); } catch (Exception exc) { MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); } Mouse.OverrideCursor = null; } private async void Menu_SummaryShow_Click(object sender, RoutedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) return; 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 PaymentVariantService.GenerateSummary(v, ExportMode.SavePdf); } private async void Menu_SummaryPrint_Click(object sender, RoutedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) return; await PaymentVariantService.GenerateSummary(v, ExportMode.Print); } private async void CommitButton_Click(object sender, RoutedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) return; ViewModel.CommitIsEnabled = false; Mouse.OverrideCursor = Cursors.AppStarting; try { var b = new BillingVariant(v.Year, v.AvNr); await b.Commit(); } catch (Exception exc) { MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); } Mouse.OverrideCursor = null; ViewModel.RevertIsEnabled = true; App.HintContextChange(); } private async void RevertButton_Click(object sender, RoutedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) return; var res = MessageBox.Show( "Sollen wirklich alle festgesetzten Traubengutschriften der ausgewählten Auszahlungsvariante unwiderruflich gelöscht werden?\n\n" + "Dies ist im Allgemeinen nie empfohlen. Handelt es sich um die aktuellste Auszahlungsvariante könnte das eine Ausnahme sein.", "Traubengutschriften löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No); if (res != MessageBoxResult.Yes) return; ViewModel.RevertIsEnabled = false; Mouse.OverrideCursor = Cursors.AppStarting; var b = new BillingVariant(v.Year, v.AvNr); await b.Revert(); App.HintContextChange(); Mouse.OverrideCursor = null; ViewModel.CommitIsEnabled = true; } private async void Menu_EbicsSave_Click(object sender, RoutedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) { return; } else if (v.TransferDate == null) { MessageBox.Show("Überweisungsdatum muss gesetzt sein!", "Exportieren nicht möglich", MessageBoxButton.OK, MessageBoxImage.Error); return; } await PaymentVariantService.GenerateEbics(v.Year, v.AvNr); } private async void Menu_ExportSave_Click(object sender, RoutedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) return; 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 || ViewModel.BillingData == null) return; try { 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) { App.FocusBaseDataSeason(Year); } private void NameInput_TextChanged(object sender, TextChangedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) { ControlUtils.ClearInputState(NameInput); return; } if (NameInput.Text != v.Name) { ControlUtils.SetInputChanged(NameInput); NameChanged = true; } else { ControlUtils.ClearInputState(NameInput); NameChanged = false; } UpdateButtons(); } private void CommentInput_TextChanged(object? sender, TextChangedEventArgs? evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) { ControlUtils.ClearInputState(CommentInput); return; } if (CommentInput.Text != (v.Comment ?? "")) { ControlUtils.SetInputChanged(CommentInput); CommentChanged = true; } else { ControlUtils.ClearInputState(CommentInput); CommentChanged = false; } UpdateButtons(); } private void DateInput_TextChanged(object? sender, TextChangedEventArgs? evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) { ControlUtils.ClearInputState(DateInput); return; } var res = Validator.CheckDate(DateInput, true); if (!res.IsValid) { ControlUtils.SetInputInvalid(DateInput); DateValid = false; } else if (DateInput.Text != $"{v.Date:dd.MM.yyyy}") { ControlUtils.SetInputChanged(DateInput); DateValid = true; DateChanged = true; } else { ControlUtils.ClearInputState(DateInput); DateValid = true; DateChanged = false; } UpdateButtons(); } private void TransferDateInput_TextChanged(object? sender, TextChangedEventArgs? evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) { ControlUtils.ClearInputState(TransferDateInput); return; } var res = Validator.CheckDate(TransferDateInput, false); if (!res.IsValid) { ControlUtils.SetInputInvalid(TransferDateInput); TransferDateValid = false; } else if (TransferDateInput.Text != $"{v.TransferDate:dd.MM.yyyy}") { ControlUtils.SetInputChanged(TransferDateInput); TransferDateValid = true; TransferDateChanged = true; } else { ControlUtils.ClearInputState(TransferDateInput); TransferDateValid = true; TransferDateChanged = false; } UpdateButtons(); } private void DataInput_TextChanged(object sender, TextChangedEventArgs evt) { if (PaymentVariantList.SelectedItem is not PaymentVar v) { ControlUtils.ClearInputState(DataInput); return; } try { var data = BillingData.FromJson(DataInput.Text); var origJson = v.Data; try { origJson = JsonSerializer.Serialize(BillingData.FromJson(v.Data).Data); } catch { } DataValid = true; if (JsonSerializer.Serialize(data.Data) != origJson) { ControlUtils.SetInputChanged(DataInput); DataChanged = true; } else { ControlUtils.ClearInputState(DataInput); DataChanged = false; } } catch { ControlUtils.SetInputInvalid(DataInput); DataValid = false; } UpdateButtons(); } private void ConsiderModifiersInput_Changed(object? sender, RoutedEventArgs? evt) { if (ViewModel.BillingData == null) { ControlUtils.ClearInputState(ConsiderModifiersInput); return; } if (ViewModel.BillingData.ConsiderDelieryModifiers != ConsiderModifiersInput.IsChecked) { ControlUtils.SetInputChanged(ConsiderModifiersInput); } else { ControlUtils.ClearInputState(ConsiderModifiersInput); } UpdateButtons(); } private void ConsiderPenaltiesInput_Changed(object? sender, RoutedEventArgs? evt) { if (ViewModel.BillingData == null) { ControlUtils.ClearInputState(ConsiderPenaltiesInput); return; } if (ViewModel.BillingData.ConsiderContractPenalties != ConsiderPenaltiesInput.IsChecked) { ControlUtils.SetInputChanged(ConsiderPenaltiesInput); } else { ControlUtils.ClearInputState(ConsiderPenaltiesInput); } UpdateButtons(); } private void ConsiderPenaltyInput_Changed(object? sender, RoutedEventArgs? evt) { if (ViewModel.BillingData == null) { ControlUtils.ClearInputState(ConsiderPenaltyInput); return; } if (ViewModel.BillingData.ConsiderTotalPenalty != ConsiderPenaltyInput.IsChecked) { ControlUtils.SetInputChanged(ConsiderPenaltyInput); } else { ControlUtils.ClearInputState(ConsiderPenaltyInput); } UpdateButtons(); } private void ConsiderAutoInput_Changed(object? sender, RoutedEventArgs? evt) { if (ViewModel.BillingData == null) { ControlUtils.ClearInputState(ConsiderAutoInput); return; } if (ViewModel.BillingData.ConsiderAutoBusinessShares != ConsiderAutoInput.IsChecked) { ControlUtils.SetInputChanged(ConsiderAutoInput); } else { ControlUtils.ClearInputState(ConsiderAutoInput); } UpdateButtons(); } private void ConsiderCustomInput_Changed(object? sender, RoutedEventArgs? evt) { if (ViewModel.BillingData == null) { ControlUtils.ClearInputState(ConsiderCustomInput); return; } if (ViewModel.BillingData.ConsiderCustomModifiers != ConsiderCustomInput.IsChecked) { ControlUtils.SetInputChanged(ConsiderCustomInput); } else { ControlUtils.ClearInputState(ConsiderCustomInput); } UpdateButtons(); } private void WeightModifierInput_TextChanged(object? sender, TextChangedEventArgs? evt) { var res = Validator.CheckDecimal(WeightModifierInput, false, 3, 2, true); if (ViewModel.BillingData == null) { ControlUtils.ClearInputState(WeightModifierInput); return; } var val = WeightModifierInput.Text.Length > 0 && res.IsValid ? double.Parse(WeightModifierInput.Text) : 0; 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); } UpdateButtons(); } private void WeightModifierInput_LostFocus(object sender, RoutedEventArgs evt) { if (WeightModifierInput.Text.EndsWith(',')) WeightModifierInput.Text = WeightModifierInput.Text[..^1]; } } }