using Elwig.Helpers; using Elwig.Models.Entities; using Elwig.ViewModels; using System.Linq; using System; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using Elwig.Services; using Microsoft.EntityFrameworkCore; namespace Elwig.Windows { public partial class DeliveryAncmtAdminWindow : AdministrationWindow { public DeliveryAncmtAdminViewModel ViewModel => (DeliveryAncmtAdminViewModel)DataContext; private readonly RoutedCommand CtrlF = new("CtrlF", typeof(DeliveryAncmtAdminWindow), [new KeyGesture(Key.F, ModifierKeys.Control)]); private readonly RoutedCommand CtrlP = new("CtrlP", typeof(DeliveryAncmtAdminWindow), [new KeyGesture(Key.P, ModifierKeys.Control)]); private readonly RoutedCommand CtrlShiftP = new("CtrlShiftP", typeof(DeliveryAncmtAdminWindow), [new KeyGesture(Key.P, ModifierKeys.Control | ModifierKeys.Shift)]); public DeliveryAncmtAdminWindow() { InitializeComponent(); CommandBindings.Add(new CommandBinding(CtrlF, FocusSearchInput)); CommandBindings.Add(new CommandBinding(CtrlP, Menu_DeliveryAncmtList_ShowSelected_Click)); CommandBindings.Add(new CommandBinding(CtrlShiftP, Menu_DeliveryAncmtList_PrintSelected_Click)); ExemptInputs = [ SearchInput, SeasonInput, OnlyUpcomingInput, FromAllSchedulesInput, DeliveryScheduleList, DeliveryAncmtList, ]; RequiredInputs = [ MgNrInput, MemberInput, DeliveryScheduleInput, SortIdInput, WineVarietyInput, WeightInput, ]; DoShowWarningWindows = false; InitializeDelayTimer(SearchInput, SearchInput_TextChanged); SearchInput.TextChanged -= SearchInput_TextChanged; ViewModel.FilterSeason = Utils.CurrentLastSeason; } private void Window_Loaded(object sender, RoutedEventArgs evt) { ViewModel.FilterOnlyUpcoming = true; LockInputs(); } private void Input_KeyUp(object sender, KeyEventArgs evt) { if (sender is not Control ctrl) return; if (evt.Key != Key.Enter) return; if (ctrl == MgNrInput || ctrl == MemberInput) { SortIdInput.Focus(); SortIdInput.SelectAll(); } else if (ctrl == SortIdInput || ctrl == WineVarietyInput) { WeightInput.Focus(); WeightInput.SelectAll(); } else if (ctrl == WeightInput) { ShortcutSave(); } } private async void Menu_DeliveryAncmtList_SaveSelected_Click(object sender, RoutedEventArgs evt) { if (DeliveryScheduleList.SelectedItem is not DeliverySchedule s) return; await ViewModel.GenerateDeliveryAncmtList(DeliveryAncmtService.ExportSubject.FromSelectedSchedule, ExportMode.SaveList); } private async void Menu_DeliveryAncmtList_ShowSelected_Click(object sender, RoutedEventArgs evt) { if (DeliveryScheduleList.SelectedItem is not DeliverySchedule s) return; await ViewModel.GenerateDeliveryAncmtList(DeliveryAncmtService.ExportSubject.FromSelectedSchedule, ExportMode.Show); } private async void Menu_DeliveryAncmtList_SavePdfSelected_Click(object sender, RoutedEventArgs evt) { if (DeliveryScheduleList.SelectedItem is not DeliverySchedule s) return; await ViewModel.GenerateDeliveryAncmtList(DeliveryAncmtService.ExportSubject.FromSelectedSchedule, ExportMode.SavePdf); } private async void Menu_DeliveryAncmtList_PrintSelected_Click(object sender, RoutedEventArgs evt) { if (DeliveryScheduleList.SelectedItem is not DeliverySchedule s) return; await ViewModel.GenerateDeliveryAncmtList(DeliveryAncmtService.ExportSubject.FromSelectedSchedule, ExportMode.Print); } private async Task RefreshDeliveryScheduleList() { using var ctx = new AppDbContext(); var deliverySchedules = await ctx.DeliverySchedules .Where(s => s.Year == ViewModel.FilterSeason) .Include(s => s.Branch) .Include(s => s.Announcements) .OrderBy(s => s.DateString) .ThenBy(s => s.Branch.Name) .ThenBy(s => s.Description) .ToListAsync(); ControlUtils.RenewItemsSource(DeliveryScheduleList, deliverySchedules .Where(s => !ViewModel.FilterOnlyUpcoming || s.DateString.CompareTo(Utils.Today.ToString("yyyy-MM-dd")) >= 0) .ToList(), DeliveryScheduleList_SelectionChanged, ViewModel.FilterFromAllSchedules ? ControlUtils.RenewSourceDefault.None : ControlUtils.RenewSourceDefault.First); ControlUtils.RenewItemsSource(DeliveryScheduleInput, deliverySchedules, DeliveryScheduleInput_SelectionChanged); } private async Task RefreshList(bool updateSort = false) { using var ctx = new AppDbContext(); var (_, deliveryAncmtQuery, filter) = await ViewModel.GetFilters(ctx); var deliveryAncmts = await deliveryAncmtQuery .Include(a => a.Member.BillingAddress) .Include(a => a.Schedule) .AsSplitQuery() .ToListAsync(); if (filter.Count > 0 && deliveryAncmts.Count > 0) { var dict = deliveryAncmts.AsParallel() .ToDictionary(a => a, a => a.SearchScore(filter)) .OrderByDescending(a => a.Value) .ThenBy(a => a.Key.Schedule.DateString) .ThenBy(a => a.Key.Member.Name) .ThenBy(a => a.Key.Member.GivenName) .ThenBy(a => a.Key.Member.MgNr); var threshold = dict.Select(a => a.Value).Max() * 3 / 4; deliveryAncmts = dict .Where(a => a.Value > threshold) .Select(a => a.Key) .ToList(); } else { deliveryAncmts = deliveryAncmts .OrderBy(a => a.Schedule.DateString) .ThenBy(a => a.Member.Name) .ThenBy(a => a.Member.GivenName) .ThenBy(a => a.Member.MgNr) .ToList(); } ControlUtils.RenewItemsSource(DeliveryAncmtList, deliveryAncmts, DeliveryAncmtList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort); if (updateSort && DeliveryAncmtList.SelectedItem != null) DeliveryAncmtList.ScrollIntoView(DeliveryAncmtList.SelectedItem); ViewModel.StatusAncmts = $"{deliveryAncmts.Count:N0}"; ViewModel.StatusWeight = $"{deliveryAncmts.Sum(a => a.Weight):N0} kg"; } private async Task RefreshInputs(bool validate = false) { ClearInputStates(); if (ViewModel.SelectedDeliveryAncmt is DeliveryAncmt a) { EditDeliveryAncmtButton.IsEnabled = true; DeleteDeliveryAncmtButton.IsEnabled = true; await FillInputs(a); } else { EditDeliveryAncmtButton.IsEnabled = false; DeleteDeliveryAncmtButton.IsEnabled = false; ClearOriginalValues(); ClearDefaultValues(); ClearInputs(validate); ClearInputStates(); } GC.Collect(); } private void InitInputs() { ClearOriginalValues(); ClearDefaultValues(); ViewModel.InitInputs(); ValidateRequiredInputs(); } protected override async Task OnRenewContext(AppDbContext ctx) { await base.OnRenewContext(ctx); ControlUtils.RenewItemsSource(MemberInput, await ctx.Members .Where(m => m.IsActive || !IsCreating) .Include(m => m.PostalDest.AtPlz!.Ort) .Include(m => m.DefaultWbKg!.AtKg) .OrderBy(m => m.Name) .ThenBy(m => m.GivenName) .ThenBy(m => m.MgNr) .ToListAsync()); ControlUtils.RenewItemsSource(WineVarietyInput, await ctx.WineVarieties.OrderBy(v => v.Name).ToListAsync()); await RefreshDeliveryScheduleList(); await RefreshList(); } private async void DeliveryAncmtList_SelectionChanged(object sender, RoutedEventArgs evt) { await RefreshInputs(); } private async void DeliveryScheduleList_SelectionChanged(object sender, RoutedEventArgs evt) { await RefreshList(); if (DeliveryScheduleList.SelectedItem is DeliverySchedule s) { Menu_DeliveryAncmtList_SaveSelected.IsEnabled = !IsEditing && !IsCreating; Menu_DeliveryAncmtList_ShowSelected.IsEnabled = !IsEditing && !IsCreating; Menu_DeliveryAncmtList_SavePdfSelected.IsEnabled = !IsEditing && !IsCreating; Menu_DeliveryAncmtList_PrintSelected.IsEnabled = !IsEditing && !IsCreating; ViewModel.FilterFromAllSchedules = false; } else { Menu_DeliveryAncmtList_SaveSelected.IsEnabled = false; Menu_DeliveryAncmtList_ShowSelected.IsEnabled = false; Menu_DeliveryAncmtList_SavePdfSelected.IsEnabled = false; Menu_DeliveryAncmtList_PrintSelected.IsEnabled = false; ViewModel.FilterFromAllSchedules = true; } } private void DeliveryScheduleInput_SelectionChanged(object sender, RoutedEventArgs evt) { } private async void OnlyUpcomingInput_Changed(object sender, RoutedEventArgs evt) { await RefreshDeliveryScheduleList(); await RefreshList(true); } private async void FromAllSchedulesInput_Changed(object sender, RoutedEventArgs evt) { if (ViewModel.FilterFromAllSchedules) { DeliveryScheduleList.SelectedItem = null; } else if (DeliveryScheduleList.SelectedItem == null) { ViewModel.FilterFromAllSchedules = true; } await RefreshList(true); } private async void SearchInput_TextChanged(object sender, TextChangedEventArgs evt) { await RefreshList(true); } private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) { if (ViewModel.FilterSeason == null) return; ViewModel.FilterOnlyUpcoming = false; await RefreshDeliveryScheduleList(); await RefreshList(); } private void MgNrInput_TextChanged(object sender, TextChangedEventArgs evt) { var valid = InputTextChanged((TextBox)sender, Validator.CheckMgNr); var text = MgNrInput.Text; var caret = MgNrInput.CaretIndex; ControlUtils.SelectItemWithPk(MemberInput, valid ? ViewModel.MgNr : null); MgNrInput.Text = text; MgNrInput.CaretIndex = caret; } private void MgNrInput_LostFocus(object sender, RoutedEventArgs evt) { var valid = InputLostFocus((TextBox)sender, Validator.CheckMgNr); ControlUtils.SelectItemWithPk(MemberInput, valid ? ViewModel.MgNr : null); } private void MemberInput_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) { var m = MemberInput.SelectedItem as Member; ViewModel.MgNr = m?.MgNr; ViewModel.MemberAddress = m?.FullAddress; } protected override void ShortcutNew() { if (!NewDeliveryAncmtButton.IsEnabled || NewDeliveryAncmtButton.Visibility != Visibility.Visible) return; NewDeliveryAncmtButton_Click(null, null); } private async void NewDeliveryAncmtButton_Click(object? sender, RoutedEventArgs? evt) { IsCreating = true; DeliveryAncmtList.IsEnabled = false; var mgnr = ViewModel.MgNr; ViewModel.SelectedDeliveryAncmt = null; using var ctx = new AppDbContext(); ControlUtils.RenewItemsSource(MemberInput, await ctx.Members .Where(m => m.IsActive || !IsCreating) .Include(m => m.PostalDest.AtPlz!.Ort) .Include(m => m.DefaultWbKg!.AtKg) .OrderBy(m => m.Name) .ThenBy(m => m.GivenName) .ThenBy(m => m.MgNr) .ToListAsync()); HideNewEditDeleteButtons(); ShowSaveResetCancelButtons(); UnlockInputs(); InitInputs(); ViewModel.MgNr = mgnr; ViewModel.EnableSearchInputs = false; } protected override void ShortcutEdit() { if (!EditDeliveryAncmtButton.IsEnabled || EditDeliveryAncmtButton.Visibility != Visibility.Visible) return; EditDeliveryAncmtButton_Click(null, null); } private void EditDeliveryAncmtButton_Click(object? sender, RoutedEventArgs? evt) { if (ViewModel.SelectedDeliveryAncmt == null) return; IsEditing = true; DeliveryAncmtList.IsEnabled = false; HideNewEditDeleteButtons(); ShowSaveResetCancelButtons(); UnlockInputs(); ViewModel.EnableSearchInputs = false; } protected override void ShortcutDelete() { if (!DeleteDeliveryAncmtButton.IsEnabled || DeleteDeliveryAncmtButton.Visibility != Visibility.Visible) return; DeleteDeliveryAncmtButton_Click(null, null); } private async void DeleteDeliveryAncmtButton_Click(object? sender, RoutedEventArgs? evt) { if (ViewModel.SelectedDeliveryAncmt is not DeliveryAncmt a) return; var r = MessageBox.Show( $"Soll die Traubenanmeldung wirklich unwiderruflich gelöscht werden?", "Traubenanmeldung löschen", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel); if (r == MessageBoxResult.OK) { Mouse.OverrideCursor = Cursors.AppStarting; try { using (var ctx = new AppDbContext()) { ctx.Remove(a); await ctx.SaveChangesAsync(); } await App.HintContextChange(); } 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, "Traubenanmeldung löschen", MessageBoxButton.OK, MessageBoxImage.Error); } Mouse.OverrideCursor = null; } } protected override void ShortcutSave() { if (!SaveButton.IsEnabled || SaveButton.Visibility != Visibility.Visible) return; SaveButton_Click(null, null); } private async void SaveButton_Click(object? sender, RoutedEventArgs? evt) { Mouse.OverrideCursor = Cursors.AppStarting; int year = -1, dsnr = -1, mgnr = -1; string? sortid = null; try { var s = ViewModel.SelectedDeliveryAncmt; (year, dsnr, mgnr, sortid) = await ViewModel.UpdateDeliveryAncmt(s?.Year, s?.DsNr, s?.MgNr, s?.SortId, s?.Type); } 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, "Traubenanmeldung aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error); } Mouse.OverrideCursor = null; IsEditing = false; IsCreating = false; DeliveryAncmtList.IsEnabled = true; HideSaveResetCancelButtons(); ShowNewEditDeleteButtons(); LockInputs(); ViewModel.EnableSearchInputs = true; FinishInputFilling(); await RefreshList(); await RefreshInputs(); ViewModel.SearchQuery = ""; ControlUtils.SelectItemWithPk(DeliveryScheduleList, year, dsnr); if (sortid != null) ControlUtils.SelectItemWithPk(DeliveryAncmtList, year, dsnr, mgnr, sortid); } protected override void ShortcutReset() { if (!ResetButton.IsEnabled || ResetButton.Visibility != Visibility.Visible) return; ResetButton_Click(null, null); } private async void ResetButton_Click(object? sender, RoutedEventArgs? evt) { if (IsEditing) { await RefreshInputs(); } else if (IsCreating) { ClearInputs(); InitInputs(); } UpdateButtons(); } private async void CancelButton_Click(object? sender, RoutedEventArgs? evt) { IsEditing = false; IsCreating = false; DeliveryAncmtList.IsEnabled = true; using var ctx = new AppDbContext(); ControlUtils.RenewItemsSource(MemberInput, await ctx.Members .Where(m => m.IsActive || !IsCreating) .Include(m => m.PostalDest.AtPlz!.Ort) .Include(m => m.DefaultWbKg!.AtKg) .OrderBy(m => m.Name) .ThenBy(m => m.GivenName) .ThenBy(m => m.MgNr) .ToListAsync()); HideSaveResetCancelButtons(); ShowNewEditDeleteButtons(); await RefreshInputs(); LockInputs(); ViewModel.EnableSearchInputs = true; } private async Task FillInputs(DeliveryAncmt a) { ClearOriginalValues(); ClearDefaultValues(); await ViewModel.FillInputs(a); FinishInputFilling(); } private void UpdateWineVariety(bool valid) { if (valid) { ViewModel.SortId = ViewModel.SortId![0..2]; ControlUtils.SelectItemWithPk(WineVarietyInput, ViewModel.SortId); } else { WineVarietyInput.SelectedItem = null; } } private void SortIdInput_TextChanged(object sender, TextChangedEventArgs evt) { UpdateWineVariety(InputTextChanged((TextBox)sender, Validator.CheckSortId)); } private void SortIdInput_LostFocus(object sender, RoutedEventArgs evt) { UpdateWineVariety(InputLostFocus((TextBox)sender, Validator.CheckSortId)); } private void WineVarietyInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) { if (WineVarietyInput.SelectedItem is WineVar s) ViewModel.SortId = s.SortId; } new protected void ClearInputs(bool validate = false) { ViewModel.ClearInputs(); base.ClearInputs(validate); } protected override void UpdateButtons() { if (!IsEditing && !IsCreating) return; bool ch = HasChanged, v = IsValid; ResetButton.IsEnabled = ch; SaveButton.IsEnabled = v && ch; } private void FocusSearchInput(object sender, RoutedEventArgs evt) { if (!IsEditing && !IsCreating) { SearchInput.Focus(); SearchInput.SelectAll(); } } private void ShowSaveResetCancelButtons() { SaveButton.IsEnabled = false; ResetButton.IsEnabled = false; CancelButton.IsEnabled = true; ViewModel.EditingButtonsVisibility = Visibility.Visible; } private void HideSaveResetCancelButtons() { SaveButton.IsEnabled = false; ResetButton.IsEnabled = false; CancelButton.IsEnabled = false; ViewModel.EditingButtonsVisibility = Visibility.Hidden; } private void ShowNewEditDeleteButtons() { NewDeliveryAncmtButton.IsEnabled = true; EditDeliveryAncmtButton.IsEnabled = ViewModel.SelectedDeliveryAncmt != null; DeleteDeliveryAncmtButton.IsEnabled = ViewModel.SelectedDeliveryAncmt != null; ViewModel.ControlButtonsVisibility = Visibility.Visible; } private void HideNewEditDeleteButtons() { NewDeliveryAncmtButton.IsEnabled = false; EditDeliveryAncmtButton.IsEnabled = false; DeleteDeliveryAncmtButton.IsEnabled = false; ViewModel.ControlButtonsVisibility = Visibility.Hidden; } private void WeightInput_TextChanged(object sender, TextChangedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckInteger((TextBox)sender, false, 5)); } private void MemberReferenceButton_Click(object sender, RoutedEventArgs evt) { if (MemberInput.SelectedItem is not Member m) return; App.FocusMember(m.MgNr); } private void DeliveryScheduleButton_Click(object sender, RoutedEventArgs evt) { App.FocusDeliverySchedule(); } } }