using Microsoft.EntityFrameworkCore; using System.Linq; using System.Windows; using System.Windows.Controls; using Elwig.Helpers; using Elwig.Models.Entities; using System; using System.Threading.Tasks; using System.Collections.Generic; using Microsoft.EntityFrameworkCore.ChangeTracking; using Xceed.Wpf.Toolkit.Primitives; namespace Elwig.Windows { public partial class AreaComAdminWindow : AdministrationWindow { private readonly Member Member; private List TextFilter = new(); public AreaComAdminWindow(int mgnr) { InitializeComponent(); Member = Context.Members.Find(mgnr) ?? throw new ArgumentException("MgNr argument has invalid value"); Title = $"Flächenbindungen - {Member.AdministrativeName} - Elwig"; ExemptInputs = new Control[] { MgNrInput, AreaCommitmentList, NewAreaCommitmentButton, EditAreaCommitmentButton, DeleteAreaCommitmentButton, AreaCommitmentSaveButton, AreaCommitmentResetButton, AreaCommitmentCancelButton, SearchInput, ActiveAreaCommitmentInput }; RequiredInputs = new Control[] { FbNrInput, YearFromInput, KgInput, RdInput, GstNrInput, AreaInput.TextBox, AreaComTypeInput, WineCultivationInput }; } private void Window_Loaded(object sender, RoutedEventArgs e) { ActiveAreaCommitmentInput.IsChecked = true; LockInputs(); } private async Task RefreshAreaCommitmentList() { await Context.AreaCommitments.LoadAsync(); await RefreshAreaCommitmentListQuery(); } private async Task RefreshAreaCommitmentListQuery(bool updateSort = false) { var (_, areaComQuery, filter) = await GetFilters(); var areaComs = await areaComQuery.ToListAsync(); if (filter.Count > 0 && areaComs.Count > 0) { var dict = areaComs.AsParallel() .ToDictionary(d => d, d => d.SearchScore(TextFilter)) .OrderByDescending(c => c.Value); var threshold = dict.Select(a => a.Value).Max() * 3 / 4; areaComs = dict .Where(a => a.Value > threshold) .Select(a => a.Key) .ToList(); } ControlUtils.RenewItemsSource(AreaCommitmentList, areaComs, i => (i as AreaCom)?.FbNr, AreaCommitmentList_SelectionChanged, filter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort); RefreshInputs(); if(filter.Count == 0) { StatusAreaCommitments.Text = $"Flächenbindungen: {await areaComQuery.CountAsync()}"; StatusArea.Text = $"Fläche: {await areaComQuery.Select(a => a.Area).SumAsync():N0} m²"; } else { StatusAreaCommitments.Text = $"Flächenbindungen: {areaComs.Count}"; StatusArea.Text = $"Fläche: {areaComs.Select(a => a.Area).Sum():N0} m²"; } var groups = areaComs.GroupBy(a => a.AreaComType.DisplayName).Select(a => (a.Key, a.Sum(b => b.Area))).OrderByDescending(a => a.Item2).ToList(); StatusContracts.Text = $"Vertragsarten: {groups.Count} (" + string.Join(", ", groups.Select(g => $"{g.Key}: {g.Item2:N0} m²")) + ")"; StatusContracts.ToolTip = $"Vertragsarten: {groups.Count}\n" + string.Join($"\n", groups.Select(g => $"{g.Key}: {g.Item2:N0} m²")); } private async Task<(List, IQueryable, List)> GetFilters() { List filterNames = new(); IQueryable areaComQuery = Context.AreaCommitments.Where(a => a.MgNr == Member.MgNr).OrderBy(a => a.FbNr); if (ActiveAreaCommitmentInput.IsChecked == true) { areaComQuery = areaComQuery.Where(a => a.YearTo == null); filterNames.Add("ohne Enddatum"); } var filterVar = new List(); var filterNotVar = new List(); var filterAttr = new List(); var filterNotAttr = new List(); var filter = TextFilter.ToList(); if (filter.Count > 0) { var var = await Context.WineVarieties.ToDictionaryAsync(v => v.SortId, v => v); var attr = await Context.WineAttributes.ToDictionaryAsync(a => a.Name.ToLower().Split(" ")[0], a => a); for (int i = 0; i < filter.Count; i++) { var e = filter[i]; if (e.Length == 2 && var.ContainsKey(e.ToUpper())) { filterVar.Add(e.ToUpper()); filter.RemoveAt(i--); filterNames.Add(var[e.ToUpper()].Name); } else if (e.Length == 3 && e[0] == '!' && var.ContainsKey(e[1..].ToUpper())) { filterNotVar.Add(e[1..].ToUpper()); filter.RemoveAt(i--); } else if (attr.ContainsKey(e.ToLower())) { var a = attr[e.ToLower()]; filterAttr.Add(a.AttrId); filter.RemoveAt(i--); filterNames.Add($"Attribut {a.Name}"); } else if (e[0] == '!' && attr.ContainsKey(e[1..].ToLower())) { var a = attr[e[1..].ToLower()]; filterNotAttr.Add(a.AttrId); filter.RemoveAt(i--); filterNames.Add($"ohne Attribut {a.Name}"); } } if (filterVar.Count > 0) areaComQuery = areaComQuery.Where(a => filterVar.Contains(a.AreaComType.WineVar.SortId)); if (filterNotVar.Count > 0) areaComQuery = areaComQuery.Where(a => !filterNotVar.Contains(a.AreaComType.WineVar.SortId)); if (filterAttr.Count > 0) areaComQuery = areaComQuery.Where(a => a.AreaComType.WineAttr != null && a.AreaComType.WineAttr.AttrId != null && filterAttr.Contains(a.AreaComType.WineAttr.AttrId)); if (filterNotAttr.Count > 0) areaComQuery = areaComQuery.Where(a => a.AreaComType.WineAttr == null || a.AreaComType.WineAttr.AttrId == null || !filterAttr.Contains(a.AreaComType.WineAttr.AttrId)); } return (filterNames, areaComQuery, filter); } private void RefreshInputs(bool validate = false) { ClearInputStates(); if (AreaCommitmentList.SelectedItem is AreaCom a) { EditAreaCommitmentButton.IsEnabled = true; DeleteAreaCommitmentButton.IsEnabled = true; FillInputs(a); } else { EditAreaCommitmentButton.IsEnabled = false; DeleteAreaCommitmentButton.IsEnabled = false; ClearOriginalValues(); ClearDefaultValues(); ClearInputs(validate); ClearInputStates(); } GC.Collect(); } private void FillInputs(AreaCom a) { ClearOriginalValues(); ClearDefaultValues(); FbNrInput.Text = a.FbNr.ToString(); MgNrInput.Text = a.MgNr.ToString(); YearFromInput.Text = a.YearFrom.ToString(); YearToInput.Text = a.YearTo.ToString(); KgInput.SelectedItem = a.Kg.AtKg; RdInput.SelectedItem = a.Rd; GstNrInput.Text = a.GstNr; AreaInput.Text = a.Area.ToString(); AreaComTypeInput.SelectedItem = a.AreaComType; WineCultivationInput.SelectedItem = a.WineCult; CommentInput.Text = a.Comment; FinishInputFilling(); } private async void InitInputs() { ClearOriginalValues(); ClearDefaultValues(); FbNrInput.Text = (await Context.NextFbNr()).ToString(); MgNrInput.Text = Member.MgNr.ToString(); SetDefaultValue(FbNrInput); ValidateRequiredInputs(); } protected override async Task OnRenewContext() { await base.OnRenewContext(); ControlUtils.RenewItemsSource(KgInput, await Context.WbKgs.Select(k => k.AtKg).OrderBy(k => k.Name).ToListAsync(), i => (i as AT_Kg)?.KgNr); ControlUtils.RenewItemsSource(AreaComTypeInput, await Context.AreaCommitmentTypes.OrderBy(v => v.VtrgId).ToListAsync(), i => (i as AreaComType)?.VtrgId); ControlUtils.RenewItemsSource(WineCultivationInput, await Context.WineCultivations.OrderBy(c => c.Name).ToListAsync(), i => (i as WineCult)?.CultId); await RefreshAreaCommitmentList(); } private void NewAreaCommitmentButton_Click(object sender, RoutedEventArgs evt) { IsCreating = true; AreaCommitmentList.IsEnabled = false; AreaCommitmentList.SelectedItem = null; HideAreaCommitmentNewEditDeleteButtons(); ShowAreaCommitmentSaveResetCancelButtons(); UnlockInputs(); InitInputs(); LockSearchInputs(); } private void EditAreaCommitmentButton_Click(object sender, RoutedEventArgs evt) { if (AreaCommitmentList.SelectedItem == null) return; IsEditing = true; AreaCommitmentList.IsEnabled = false; HideAreaCommitmentNewEditDeleteButtons(); ShowAreaCommitmentSaveResetCancelButtons(); UnlockInputs(); LockSearchInputs(); } private async void DeleteAreaCommitmentButton_Click(object sender, RoutedEventArgs evt) { AreaCom a = (AreaCom)AreaCommitmentList.SelectedItem; if (a == null) return; var r = MessageBox.Show( $"Soll die Flächenbindung {a.GstNr} ({a.Area} m²) wirklich unwiderruflich gelöscht werden?", "Flächenbindung löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No); if (r == MessageBoxResult.Yes) { Context.Remove(a); Context.SaveChanges(); await RefreshAreaCommitmentList(); } } private async Task UpdateAreaCom(AreaCom a) { int newFbNr = int.Parse(FbNrInput.Text); a.MgNr = int.Parse(MgNrInput.Text); a.YearFrom = int.Parse(YearFromInput.Text); a.YearTo = (YearToInput.Text == "") ? null : int.Parse(YearToInput.Text); a.KgNr = ((AT_Kg)KgInput.SelectedItem).KgNr; a.RdNr = RdInput.SelectedItem.GetType() == typeof(NullItem) ? null : ((WbRd)RdInput.SelectedItem).RdNr; a.GstNr = GstNrInput.Text; a.Area = int.Parse(AreaInput.Text); a.VtrgId = (AreaComTypeInput.SelectedItem as AreaComType)?.VtrgId; a.CultId = (WineCultivationInput.SelectedItem as WineCult)?.CultId; a.Comment = (CommentInput.Text == "") ? null : CommentInput.Text; EntityEntry? tr = null; try { if (IsEditing) { tr = Context.Update(a); } else if (IsCreating) { a.FbNr = newFbNr; tr = (await Context.AddAsync(a)); } else { throw new Exception(); } await Context.SaveChangesAsync(); if (newFbNr != a.FbNr) { await Context.Database.ExecuteSqlAsync($"UPDATE area_commitment SET fbnr = {newFbNr} WHERE fbnr = {a.FbNr}"); tr.State = EntityState.Detached; await Context.SaveChangesAsync(); await tr.ReloadAsync(); a = await Context.AreaCommitments.FindAsync(newFbNr); } } catch (Exception exc) { if (tr != null) { tr.State = EntityState.Detached; await tr.ReloadAsync(); } 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, "Flächenbindung aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error); } return a; } private async void AreaCommitmentSaveButton_Click(object sender, RoutedEventArgs evt) { AreaCom a = await UpdateAreaCom(IsEditing ? (AreaCom)AreaCommitmentList.SelectedItem : Context.CreateProxy()); IsEditing = false; IsCreating = false; AreaCommitmentList.IsEnabled = true; HideAreaCommitmentSaveResetCancelButtons(); ShowAreaCommitmentNewEditDeleteButtons(); LockInputs(); UnlockSearchInputs(); await RefreshAreaCommitmentList(); AreaCommitmentList.SelectedItem = a; } private void AreaCommitmentResetButton_Click(object sender, RoutedEventArgs evt) { if (IsEditing) { RefreshInputs(); } else if (IsCreating) { InitInputs(); } UpdateButtons(); } private void AreaCommitmentCancelButton_Click(object sender, RoutedEventArgs evt) { IsEditing = false; IsCreating = false; AreaCommitmentList.IsEnabled = true; HideAreaCommitmentSaveResetCancelButtons(); ShowAreaCommitmentNewEditDeleteButtons(); RefreshInputs(); ClearInputStates(); LockInputs(); UnlockSearchInputs(); } override protected void UpdateButtons() { if (!IsEditing && !IsCreating) return; bool ch = HasChanged, v = IsValid; AreaCommitmentResetButton.IsEnabled = (ch); AreaCommitmentSaveButton.IsEnabled = (ch && v); } private void DisableAreaCommitmentNewEditDeleteButtons() { NewAreaCommitmentButton.IsEnabled = false; EditAreaCommitmentButton.IsEnabled = false; DeleteAreaCommitmentButton.IsEnabled = false; } private void EnableAreaCommitmentNewEditDeleteButtons() { NewAreaCommitmentButton.IsEnabled = true; EditAreaCommitmentButton.IsEnabled = AreaCommitmentList.SelectedItem != null; DeleteAreaCommitmentButton.IsEnabled = AreaCommitmentList.SelectedItem != null; } private void ShowAreaCommitmentSaveResetCancelButtons() { AreaCommitmentSaveButton.IsEnabled = false; AreaCommitmentResetButton.IsEnabled = false; AreaCommitmentCancelButton.IsEnabled = true; AreaCommitmentSaveButton.Visibility = Visibility.Visible; AreaCommitmentResetButton.Visibility = Visibility.Visible; AreaCommitmentCancelButton.Visibility = Visibility.Visible; } private void HideAreaCommitmentSaveResetCancelButtons() { AreaCommitmentSaveButton.IsEnabled = false; AreaCommitmentResetButton.IsEnabled = false; AreaCommitmentCancelButton.IsEnabled = false; AreaCommitmentSaveButton.Visibility = Visibility.Hidden; AreaCommitmentResetButton.Visibility = Visibility.Hidden; AreaCommitmentCancelButton.Visibility = Visibility.Hidden; } private void ShowAreaCommitmentNewEditDeleteButtons() { EnableAreaCommitmentNewEditDeleteButtons(); NewAreaCommitmentButton.Visibility = Visibility.Visible; EditAreaCommitmentButton.Visibility = Visibility.Visible; DeleteAreaCommitmentButton.Visibility = Visibility.Visible; } private void HideAreaCommitmentNewEditDeleteButtons() { DisableAreaCommitmentNewEditDeleteButtons(); NewAreaCommitmentButton.Visibility = Visibility.Hidden; EditAreaCommitmentButton.Visibility = Visibility.Hidden; DeleteAreaCommitmentButton.Visibility = Visibility.Hidden; } private void LockSearchInputs() { SearchInput.IsEnabled = false; ActiveAreaCommitmentInput.IsEnabled = false; } private void UnlockSearchInputs() { SearchInput.IsEnabled = true; ActiveAreaCommitmentInput.IsEnabled = true; } private void AreaCommitmentList_SelectionChanged(object sender, SelectionChangedEventArgs evt) { RefreshInputs(); } private void AttributesInput_SelectionChanged(object sender, ItemSelectionChangedEventArgs evt) { } private async void ActiveAreaCommitmentInput_Changed(object sender, RoutedEventArgs evt) { await RefreshAreaCommitmentListQuery(); } private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) { TextFilter = SearchInput.Text.ToLower().Split(" ").ToList().FindAll(e => e.Length > 0); await RefreshAreaCommitmentListQuery(true); } private async void KgInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) { if (KgInput.SelectedItem is AT_Kg curr_kg) { var rdList = await Context.WbRde.Where(r => r.KgNr == curr_kg.KgNr).OrderBy(r => r.Name).Cast().ToListAsync(); rdList.Insert(0, new NullItem()); ControlUtils.RenewItemsSource(RdInput, rdList, i => (i as WbRd)?.RdNr, null, ControlUtils.RenewSourceDefault.First); } else { var rdList = new object[] { new NullItem() }; ControlUtils.RenewItemsSource(RdInput, rdList, i => (i as WbRd)?.RdNr, null, ControlUtils.RenewSourceDefault.First); } ComboBox_SelectionChanged(sender, evt); } protected void InputTextChanged(TextBox input, Func checker) { InputTextChanged(input, checker(input, SenderIsRequired(input), Context, (AreaCom)AreaCommitmentList.SelectedItem)); } protected void InputLostFocus(TextBox input, Func checker, string? msg = null) { InputLostFocus(input, checker(input, SenderIsRequired(input), Context, (AreaCom)AreaCommitmentList.SelectedItem), msg); } private void FbNrInput_TextChanged(object sender, RoutedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckFbNr); } private void FbNrInput_LostFocus(object sender, RoutedEventArgs evt) { InputLostFocus((TextBox)sender, Validator.CheckFbNr); } private void GstNrInput_TextChanged(object sender, RoutedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckGstNr); } private void GstNrInput_LostFocus(object sender, RoutedEventArgs evt) { InputLostFocus((TextBox)sender, Validator.CheckGstNr); } } }