using Elwig.Helpers; using Elwig.Models; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Threading; using Xceed.Wpf.Toolkit.Primitives; namespace Elwig.Windows { public partial class DeliveryAdminWindow : AdministrationWindow { private bool IsUpdatingGradation = false; private readonly bool IsReceipt = false; private Member? Member = null; private readonly DispatcherTimer Timer; private List TextFilter = new(); private readonly RoutedCommand CtrlF = new(); public DeliveryAdminWindow(bool receipt = false) { InitializeComponent(); CtrlF.InputGestures.Add(new KeyGesture(Key.F, ModifierKeys.Control)); CommandBindings.Add(new CommandBinding(CtrlF, FocusSearchInput)); RequiredInputs = new Control[] { MgNrInput, MemberInput, LsNrInput, DateInput, BranchInput, SortIdInput, WineVarietyInput, GradationOeInput, GradationKmwInput, WineQualityLevelInput, WineOriginInput, WineKgInput, WeightInput }; ExemptInputs = new Control[] { SearchInput, TodayOnlyInput, SeasonOnlyInput, DeliveryList, DeliveryPartList, MemberAddressField, }; IsReceipt = receipt; Timer = new DispatcherTimer(); Timer.Tick += new EventHandler(OnSecondPassed); Timer.Interval = new TimeSpan(0, 0, 1); InitializeDelayTimer(SearchInput, SearchInput_TextChanged); SearchInput.TextChanged -= SearchInput_TextChanged; if (IsReceipt) { Title = "Übernahme - Elwig"; TodayOnlyInput.IsChecked = true; var n = App.Scales.Count(); if (n < 1) WeighingAButton.Visibility = Visibility.Hidden; if (n < 2) WeighingBButton.Visibility = Visibility.Hidden; if (n < 3) WeighingCButton.Visibility = Visibility.Hidden; if (n < 4) WeighingDButton.Visibility = Visibility.Hidden; if (n == 1) WeighingAButton.Content = "Wiegen"; } else { WeighingManualButton.Visibility = Visibility.Hidden; WeighingAButton.Visibility = Visibility.Hidden; WeighingBButton.Visibility = Visibility.Hidden; WeighingCButton.Visibility = Visibility.Hidden; WeighingDButton.Visibility = Visibility.Hidden; } } public DeliveryAdminWindow(int mgnr) : this() { Member = Context.Members.Find(mgnr) ?? throw new ArgumentException("MgNr argument has invalid value"); Title = $"Lieferungen - {Member.AdministrativeName} - Elwig"; } private void Window_Loaded(object sender, RoutedEventArgs evt) { OnSecondPassed(null, null); Timer.Start(); LockInputs(); } private void OnSecondPassed(object? sender, EventArgs? evt) { if (IsReceipt && (IsEditing || IsCreating)) { var now = DateTime.Now; TimeInput.Text = now.ToString("HH:mm"); DateInput.Text = now.ToString("dd.MM.yyyy"); } } protected override void UpdateButtons() { if (!IsEditing && !IsCreating) return; bool ch = HasChanged, v = IsValid; ResetButton.IsEnabled = (ch); SaveButton.IsEnabled = (v && ch); } private async Task RefreshDeliveryList() { await RefreshDeliveryListQuery(); } private async Task RefreshDeliveryListQuery(bool updateSort = false) { IQueryable deliveryQuery = Context.Deliveries; if (Member != null) { deliveryQuery = deliveryQuery.Where(d => d.MgNr == Member.MgNr); } if (TodayOnlyInput.IsChecked == true) { deliveryQuery = deliveryQuery .Where(d => (d.DateString == Utils.Today.ToString("yyyy-MM-dd") && d.TimeString.CompareTo("03:00:00") > 0) || (d.DateString == Utils.Today.AddDays(1).ToString("yyyy-MM-dd") && d.TimeString.CompareTo("03:00:00") <= 0)); } else if (SeasonOnlyInput.IsChecked == true) { deliveryQuery = deliveryQuery.Where(d => d.Year == Utils.CurrentLastSeason); } List deliveries = await deliveryQuery.OrderByDescending(d => d.DateString).ThenByDescending(d => d.TimeString).ToListAsync(); if (TextFilter.Count > 0) { var dict = deliveries .ToDictionary(d => d, d => d.SearchScore(TextFilter)) .OrderByDescending(a => a.Value) .ThenBy(a => a.Key.DateTime); var threshold = dict.Select(a => a.Value).Max() * 3 / 4; deliveries = dict .Where(a => a.Value > threshold) .Select(a => a.Key) .ToList(); } ControlUtils.RenewItemsSource(DeliveryList, deliveries, d => ((d as Delivery)?.Year, (d as Delivery)?.DId), DeliveryList_SelectionChanged, ControlUtils.RenewSourceDefault.IfOnly, !updateSort); } protected override async Task RenewContext() { await base.RenewContext(); if (Member != null) { if (Context.Members.Find(Member.MgNr) is not Member m) { Close(); return; } Member = m; Title = $"Lieferungen - {Member.AdministrativeName} - Elwig"; } await RefreshDeliveryList(); var d = DeliveryList.SelectedItem as Delivery; var y = d?.Year ?? Utils.CurrentLastSeason; ControlUtils.RenewItemsSource(MemberInput, await Context.Members.OrderBy(m => m.FamilyName).ThenBy(m => m.GivenName).ToListAsync(), i => (i as Member)?.MgNr); ControlUtils.RenewItemsSource(BranchInput, await Context.Branches.OrderBy(b => b.Name).ToListAsync(), i => (i as Branch)?.ZwstId); ControlUtils.RenewItemsSource(WineVarietyInput, await Context.WineVarieties.OrderBy(v => v.Name).ToListAsync(), i => (i as WineVar)?.SortId); ControlUtils.RenewItemsSource(AttributesInput, await Context.WineAttributes.OrderBy(a => a.Name).ToListAsync(), i => (i as WineAttr)?.AttrId); ControlUtils.RenewItemsSource(WineQualityLevelInput, await Context.WineQualityLevels.ToListAsync(), i => (i as WineQualLevel)?.QualId); ControlUtils.RenewItemsSource(ModifiersInput, await Context.Modifiers.Where(m => m.Year == y).OrderBy(m => m.Name).ToListAsync(), i => (i as Modifier)?.ModId); ControlUtils.RenewItemsSource(WineOriginInput, (await Context.WineOrigins.ToListAsync()).OrderByDescending(o => o.SortKey).ThenBy(o => o.HkId), i => (i as WineOrigin)?.HkId); var kgList = await Context.WbKgs.Select(k => k.AtKg).OrderBy(k => k.Name).Cast().ToListAsync(); kgList.Insert(0, new NullItem()); ControlUtils.RenewItemsSource(WineKgInput, kgList, i => (i as AT_Kg)?.KgNr); UpdateRdInput(); if (IsCreating) await UpdateLsNr(); } private void FocusSearchInput(object sender, RoutedEventArgs evt) { if (!IsEditing && !IsCreating) { SearchInput.Focus(); SearchInput.SelectAll(); } } private void RefreshDeliveryParts() { if (DeliveryList.SelectedItem is Delivery d) { ControlUtils.RenewItemsSource(ModifiersInput, Context.Modifiers.Where(m => m.Year == d.Year).OrderBy(m => m.Name).ToList(), i => (i as Modifier)?.ModId); ControlUtils.RenewItemsSource(DeliveryPartList, d.Parts.OrderBy(p => p.DPNr).ToList(), i => ((i as DeliveryPart)?.Year, (i as DeliveryPart)?.DId, (i as DeliveryPart)?.DPNr), DeliveryPartList_SelectionChanged, ControlUtils.RenewSourceDefault.First); } else { ControlUtils.RenewItemsSource(ModifiersInput, Context.Modifiers.Where(m => m.Year == Utils.CurrentLastSeason).OrderBy(m => m.Name).ToList(), i => (i as Modifier)?.ModId); DeliveryPartList.ItemsSource = null; } } private void RefreshInputs(bool validate = false) { ClearInputStates(); if (DeliveryPartList.SelectedItem is DeliveryPart p) { FillInputs(p); } else { ClearOriginalValues(); ClearInputs(validate); ClearInputStates(); } GC.Collect(); } private void FillInputs(DeliveryPart p) { ClearOriginalValues(); var d = p.Delivery; MgNrInput.Text = d.MgNr.ToString(); ControlUtils.SelectComboBoxItem(BranchInput, i => (i as Branch)?.ZwstId, d.ZwstId); LsNrInput.Text = d.LsNr; DateInput.Text = d.Date.ToString("dd.MM.yyyy"); TimeInput.Text = d.Time?.ToString("HH:mm") ?? ""; CommentInput.Text = d.Comment ?? ""; SortIdInput.Text = p?.SortId ?? ""; ControlUtils.SelectCheckComboBoxItems(AttributesInput, p?.Attributes, i => (i as WineAttr)?.AttrId); GradationKmwInput.Text = (p != null) ? $"{p.Kmw:N1}" : ""; ControlUtils.SelectComboBoxItem(WineQualityLevelInput, q => (q as WineQualLevel)?.QualId, p?.QualId); ControlUtils.SelectComboBoxItem(WineKgInput, k => (k as AT_Kg)?.KgNr, p?.KgNr); ControlUtils.SelectComboBoxItem(WineRdInput, r => (r as WbRd)?.RdNr, p?.RdNr); ControlUtils.SelectComboBoxItem(WineOriginInput, r => (r as WineOrigin)?.HkId, p?.HkId); WeightInput.Text = p?.Weight.ToString() ?? ""; ManualWeighingInput.IsChecked = p?.ManualWeighing ?? false; GerebeltGewogenInput.IsChecked = p?.IsGerebelt ?? false; ControlUtils.SelectCheckComboBoxItems(ModifiersInput, p?.Modifiers, i => (i as Modifier)?.ModId); PartCommentInput.Text = p?.Comment ?? ""; TemperatureInput.Text = p?.Temperature?.ToString() ?? ""; AcidInput.Text = p?.Acid?.ToString() ?? ""; LesewagenInput.IsChecked = p?.IsLesewagen ?? false; HandPickedInput.IsChecked = p?.IsHandPicked; FillOriginalValues(); } private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) { TextFilter = SearchInput.Text.ToLower().Split(" ").ToList().FindAll(e => e.Length > 0); await RefreshDeliveryListQuery(true); } private async void TodayOnlyInput_Changed(object sender, RoutedEventArgs evt) { if (TodayOnlyInput.IsChecked == true && SeasonOnlyInput.IsChecked == true) SeasonOnlyInput.IsChecked = false; await RefreshDeliveryListQuery(); } private async void SeasonOnlyInput_Changed(object sender, RoutedEventArgs evt) { if (!IsInitialized) return; if (SeasonOnlyInput.IsChecked == true && TodayOnlyInput.IsChecked == true) TodayOnlyInput.IsChecked = false; await RefreshDeliveryListQuery(); } private void DeliveryList_SelectionChanged(object sender, SelectionChangedEventArgs evt) { RefreshDeliveryParts(); if (DeliveryList.SelectedItem != null) { DeleteDeliveryButton.IsEnabled = true; } else { DeleteDeliveryButton.IsEnabled = false; } } private void DeliveryPartList_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) { RefreshInputs(); if (DeliveryPartList.SelectedItem != null) { AbwertenButton.IsEnabled = true; EditDeliveryButton.IsEnabled = true; ExtractDeliveryPartButton.IsEnabled = true; DeleteDeliveryPartButton.IsEnabled = true; } else { AbwertenButton.IsEnabled = false; EditDeliveryButton.IsEnabled = false; ExtractDeliveryPartButton.IsEnabled = false; DeleteDeliveryPartButton.IsEnabled = false; } } private void MgNrInput_TextChanged(object sender, TextChangedEventArgs evt) { var valid = InputTextChanged((TextBox)sender, Validator.CheckMgNr); MemberInput.SelectedItem = valid ? Context.Members.Find(int.Parse(MgNrInput.Text)) : null; } private void MgNrInput_LostFocus(object sender, RoutedEventArgs evt) { var valid = InputLostFocus((TextBox)sender, Validator.CheckMgNr); MemberInput.SelectedItem = valid ? Context.Members.Find(int.Parse(MgNrInput.Text)) : null; } private void MemberInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) { var m = MemberInput.SelectedItem as Member; if (m != null) MgNrInput.Text = m.MgNr.ToString(); MemberAddressField.Text = m?.FullAddress; if (m == null) { UnsetOriginalValue(WineKgInput); WineKgInput.SelectedIndex = 0; } else { SetOriginalValue(WineKgInput, m.DefaultKg); WineKgInput.SelectedItem = m.DefaultKg; } } private void NewDeliveryButton_Click(object sender, RoutedEventArgs evt) { } private void AbwertenButton_Click(object sender, RoutedEventArgs evt) { } private void EditDeliveryButton_Click(object sender, RoutedEventArgs evt) { if (DeliveryPartList.SelectedItem == null) return; IsEditing = true; DeliveryList.IsEnabled = false; DeliveryPartList.IsEnabled = false; HideNewEditDeleteButtons(); ShowSaveResetCancelButtons(); UnlockInputs(); LockSearchInputs(); AbwertenButton.IsEnabled = false; ExtractDeliveryPartButton.IsEnabled = false; DeleteDeliveryPartButton.IsEnabled = false; } private void DeleteDeliveryButton_Click(object sender, RoutedEventArgs evt) { } private void SaveButton_Click(object sender, RoutedEventArgs evt) { } private void ResetButton_Click(object sender, RoutedEventArgs evt) { if (IsEditing) { RefreshInputs(); } else if (IsCreating) { ClearInputs(); //InitInputs(); TODO } UpdateButtons(); } private void CancelButton_Click(object sender, RoutedEventArgs evt) { IsEditing = false; IsCreating = false; DeliveryList.IsEnabled = true; DeliveryPartList.IsEnabled = true; HideSaveResetCancelButtons(); ShowNewEditDeleteButtons(); RefreshInputs(); ClearInputStates(); LockInputs(); UnlockSearchInputs(); AbwertenButton.IsEnabled = DeliveryPartList.SelectedItem != null; ExtractDeliveryPartButton.IsEnabled = DeliveryPartList.SelectedItem != null; DeleteDeliveryPartButton.IsEnabled = DeliveryPartList.SelectedItem != null; } private void ExtractDeliveryPartButton_Click(object sender, RoutedEventArgs evt) { } private void DeleteDeliveryPartButton_Click(object sender, RoutedEventArgs evt) { } private void ShowSaveResetCancelButtons() { SaveButton.IsEnabled = false; ResetButton.IsEnabled = false; CancelButton.IsEnabled = true; SaveButton.Visibility = Visibility.Visible; ResetButton.Visibility = Visibility.Visible; CancelButton.Visibility = Visibility.Visible; } private void HideSaveResetCancelButtons() { SaveButton.IsEnabled = false; ResetButton.IsEnabled = false; CancelButton.IsEnabled = false; SaveButton.Visibility = Visibility.Hidden; ResetButton.Visibility = Visibility.Hidden; CancelButton.Visibility = Visibility.Hidden; } private void ShowNewEditDeleteButtons() { NewDeliveryButton.IsEnabled = IsReceipt; AbwertenButton.IsEnabled = DeliveryPartList.SelectedItem != null; EditDeliveryButton.IsEnabled = DeliveryPartList.SelectedItem != null; DeleteDeliveryButton.IsEnabled = DeliveryList.SelectedItem != null; NewDeliveryButton.Visibility = IsReceipt ? Visibility.Visible : Visibility.Hidden; AbwertenButton.Visibility = !IsReceipt ? Visibility.Visible : Visibility.Hidden; EditDeliveryButton.Visibility = Visibility.Visible; DeleteDeliveryButton.Visibility = Visibility.Visible; } private void HideNewEditDeleteButtons() { NewDeliveryButton.IsEnabled = false; AbwertenButton.IsEnabled = false; EditDeliveryButton.IsEnabled = false; DeleteDeliveryButton.IsEnabled = false; NewDeliveryButton.Visibility = Visibility.Hidden; AbwertenButton.Visibility = Visibility.Hidden; EditDeliveryButton.Visibility = Visibility.Hidden; DeleteDeliveryButton.Visibility = Visibility.Hidden; } private void LockSearchInputs() { SearchInput.IsEnabled = false; TodayOnlyInput.IsEnabled = false; SeasonOnlyInput.IsEnabled = false; } private void UnlockSearchInputs() { SearchInput.IsEnabled = true; TodayOnlyInput.IsEnabled = true; SeasonOnlyInput.IsEnabled = true; } new protected void UnlockInputs() { base.UnlockInputs(); if (WineQualityLevelInput.SelectedItem != null && WineKgInput.SelectedItem != null) WineOriginInput.IsEnabled = false; if (WineKgInput.SelectedItem == null) WineRdInput.IsEnabled = false; WeightInput.IsReadOnly = true; AbgewertetInput.IsEnabled = false; ManualWeighingInput.IsEnabled = false; LsNrInput.IsReadOnly = true; DateInput.IsReadOnly = true; TimeInput.IsReadOnly = true; BranchInput.IsEnabled = false; } private async Task UpdateLsNr() { var branch = (Branch)BranchInput.SelectedItem; var date = DateOnly.ParseExact(DateInput.Text, "dd.MM.yyyy"); var lnr = await Context.NextLNr(date); LsNrInput.Text = $"{date:yyyyMMdd}{branch.ZwstId}{lnr:000}"; } private void DateInput_TextChanged(object sender, TextChangedEventArgs evt) { if (IsCreating) UpdateLsNr().GetAwaiter().GetResult(); } private void UpdateWineVariety(bool valid) { if (valid) { var text = SortIdInput.Text; WineVarietyInput.SelectedItem = Context.WineVarieties.Find(text[0..2]); if (text.Length >= 3) { AttributesInput.UnSelectAll(); AttributesInput.SelectedItems.Add(Context.WineAttributes.Find(text[2..])); SortIdInput.Text = text[0..2]; } } else { WineVarietyInput.SelectedItem = null; AttributesInput.UnSelectAll(); } } 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) SortIdInput.Text = s.SortId; } private void UpdateWineQualityLevels() { if (!GetInputValid(GradationKmwInput)) { UnsetOriginalValue(WineQualityLevelInput); WineQualityLevelInput.ItemsSource = null; return; } var kmw = double.Parse(GradationKmwInput.Text); WineQualityLevelInput.ItemsSource = Context.WineQualityLevels.Where(q => q.MinKmw == null || q.MinKmw <= kmw).ToList(); var qual = Context.GetWineQualityLevel(kmw).GetAwaiter().GetResult(); SetOriginalValue(WineQualityLevelInput, qual); if (WineQualityLevelInput.SelectedItem == null || (WineQualityLevelInput.SelectedItem is WineQualLevel selected && !selected.IsPredicate)) { WineQualityLevelInput.SelectedItem = qual; } } private void UpdateGradationKmw() { IsUpdatingGradation = true; var caret = GradationKmwInput.CaretIndex; GradationKmwInput.Text = $"{Utils.OeToKmw(double.Parse(GradationOeInput.Text)):#.0}"; GradationKmwInput.CaretIndex = caret; IsUpdatingGradation = false; } private void UpdateGradationOe() { IsUpdatingGradation = true; var caret = GradationOeInput.CaretIndex; GradationOeInput.Text = $"{Utils.KmwToOe(double.Parse(GradationKmwInput.Text)):#}"; GradationOeInput.CaretIndex = caret; IsUpdatingGradation = false; } private void GradationOeInput_TextChanged(object sender, TextChangedEventArgs evt) { var valid = InputTextChanged((TextBox)sender, Validator.CheckGradatoinOe); if (!IsUpdatingGradation) { if (valid) UpdateGradationKmw(); else if (GradationOeInput.Text.Length == 0) GradationKmwInput.Text = ""; if (valid || GradationOeInput.Text.Length == 0) UpdateWineQualityLevels(); } } private void GradationOeInput_LostFocus(object sender, RoutedEventArgs evt) { InputLostFocus((TextBox)sender, Validator.CheckGradatoinOe); } private void GradationKmwInput_TextChanged(object sender, TextChangedEventArgs evt) { var valid = InputTextChanged((TextBox)sender, Validator.CheckGradationKmw); if (!IsUpdatingGradation) { if (valid) UpdateGradationOe(); else if (GradationKmwInput.Text.Length == 0) GradationOeInput.Text = ""; if (valid || GradationKmwInput.Text.Length == 0) UpdateWineQualityLevels(); } } private void GradationKmwInput_LostFocus(object sender, RoutedEventArgs evt) { if (GradationKmwInput.Text.EndsWith(",")) GradationKmwInput.Text += "0"; InputLostFocus((TextBox)sender, Validator.CheckGradationKmw); if (GradationKmwInput.Text.Length != 0 && !GradationKmwInput.Text.Contains(',')) GradationKmwInput.Text += ",0"; } private void AttributesInput_SelectionChanged(object sender, ItemSelectionChangedEventArgs evt) { } private void ModifiersInput_SelectionChanged(object sender, ItemSelectionChangedEventArgs evt) { } private void UpdateWineOrigin() { var qual = WineQualityLevelInput.SelectedItem as WineQualLevel; var kg = (WineKgInput.SelectedItem as AT_Kg)?.WbKg; if (qual == null || kg == null) { WineOriginInput.IsEnabled = (IsEditing || IsCreating); return; } WineOriginInput.IsEnabled = false; var o = kg.Origin; while (o != null && o.Level > qual.OriginLevel) o = o.Parent; WineOriginInput.SelectedItem = o; } private void WineQualityLevelInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) { UpdateWineOrigin(); UpdateAbgewertet(); } private void UpdateRdInput() { if (WineKgInput.SelectedItem is AT_Kg kg) { var list = Context.WbRde.Where(r => r.KgNr == kg.KgNr).OrderBy(r => r.Name).Cast().ToList(); list.Insert(0, new NullItem()); ControlUtils.RenewItemsSource(WineRdInput, list, i => ((i as WbRd)?.KgNr, (i as WbRd)?.RdNr)); if (WineRdInput.SelectedItem == null) WineRdInput.SelectedIndex = 0; WineRdInput.IsEnabled = (IsEditing || IsCreating) && list.Count > 1; } else { WineRdInput.ItemsSource = null; WineRdInput.IsEnabled = false; } } private void WineKgInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) { UpdateWineOrigin(); UpdateRdInput(); } private void UpdateAbgewertet() { var qual = WineQualityLevelInput.SelectedItem as WineQualLevel; if (qual == null) { AbgewertetInput.IsChecked = false; return; } var defQual = Context.GetWineQualityLevel(double.Parse(GradationKmwInput.Text)).GetAwaiter().GetResult(); AbgewertetInput.IsChecked = !qual.IsPredicate && defQual != qual; } } }