using Microsoft.EntityFrameworkCore; using System; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using Elwig.Helpers; using Elwig.Models.Entities; using System.Threading.Tasks; using Elwig.Documents; using System.Diagnostics; using Elwig.Dialogs; using Elwig.Services; using Elwig.ViewModels; using System.Windows.Data; namespace Elwig.Windows { public partial class MemberAdminWindow : AdministrationWindow { public MemberAdminViewModel ViewModel => (MemberAdminViewModel)DataContext; private readonly (ComboBox Type, TextBox Number, TextBox Comment)[] PhoneNrInputs; private readonly (Label Label, TextBox Address)[] EmailAddressInputs; private readonly RoutedCommand CtrlF = new("CtrlF", typeof(MemberAdminWindow), [new KeyGesture(Key.F, ModifierKeys.Control)]); 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 CtrlO = new("CtrlO", typeof(MemberAdminWindow), [new KeyGesture(Key.O, ModifierKeys.Control)]); private readonly RoutedCommand CtrlShiftP = new("CtrlShiftP", typeof(MemberAdminWindow), [new KeyGesture(Key.P, ModifierKeys.Control | ModifierKeys.Shift)]); private readonly RoutedCommand CtrlShiftO = new("CtrlShiftO", typeof(MemberAdminWindow), [new KeyGesture(Key.O, ModifierKeys.Control | ModifierKeys.Shift)]); public MemberAdminWindow() { InitializeComponent(); CommandBindings.Add(new CommandBinding(CtrlF, FocusSearchInput)); CommandBindings.Add(new CommandBinding(CtrlL, Menu_List_SaveActive_Click)); CommandBindings.Add(new CommandBinding(CtrlP, Menu_MemberDataSheet_Show_Click)); CommandBindings.Add(new CommandBinding(CtrlO, Menu_List_ShowActive_Click)); CommandBindings.Add(new CommandBinding(CtrlShiftP, Menu_MemberDataSheet_Print_Click)); CommandBindings.Add(new CommandBinding(CtrlShiftO, Menu_List_PrintActive_Click)); ExemptInputs = [ SearchInput, ActiveMemberInput, MemberList, ]; RequiredInputs = [ MgNrInput, GivenNameInput, FamilyNameInput, AddressInput, PlzInput, OrtInput, BillingOrtInput, BusinessSharesInput, BranchInput, DefaultKgInput ]; EmailAddressInputs = [ (EmailAddress1Label, EmailAddress1Input), (EmailAddress2Label, EmailAddress2Input), (EmailAddress3Label, EmailAddress3Input), (EmailAddress4Label, EmailAddress4Input), (EmailAddress5Label, EmailAddress5Input), (EmailAddress6Label, EmailAddress6Input), (EmailAddress7Label, EmailAddress7Input), (EmailAddress8Label, EmailAddress8Input), (EmailAddress9Label, EmailAddress9Input), ]; PhoneNrInputs = [ (PhoneNr1TypeInput, PhoneNr1Input, PhoneNr1CommentInput), (PhoneNr2TypeInput, PhoneNr2Input, PhoneNr2CommentInput), (PhoneNr3TypeInput, PhoneNr3Input, PhoneNr3CommentInput), (PhoneNr4TypeInput, PhoneNr4Input, PhoneNr4CommentInput), (PhoneNr5TypeInput, PhoneNr5Input, PhoneNr5CommentInput), (PhoneNr6TypeInput, PhoneNr6Input, PhoneNr6CommentInput), (PhoneNr7TypeInput, PhoneNr7Input, PhoneNr7CommentInput), (PhoneNr8TypeInput, PhoneNr8Input, PhoneNr8CommentInput), (PhoneNr9TypeInput, PhoneNr9Input, PhoneNr9CommentInput), ]; InitializeDelayTimer(SearchInput, SearchInput_TextChanged); SearchInput.TextChanged -= SearchInput_TextChanged; ViewModel.MemberListOrderByMgNr = false; ViewModel.MemberListOrderByName = false; ViewModel.MemberListOrderByOrt = false; switch (App.Client.OrderingMemberList) { case 0: ViewModel.MemberListOrderByMgNr = true; break; case 1: ViewModel.MemberListOrderByName = true; break; case 2: ViewModel.MemberListOrderByOrt = true; break; } Menu_Export_UploadFilters.IsEnabled = App.Config.SyncUrl != null; Menu_Export_UploadAll.IsEnabled = App.Config.SyncUrl != null; } private void Window_Loaded(object sender, RoutedEventArgs evt) { ViewModel.ShowOnlyActiveMembers = true; UpdateContactInfoVisibility(); LockInputs(); } public void FocusMember(int mgnr) { if (IsEditing || IsCreating) return; var item = ViewModel.Members.FirstOrDefault(m => m.MgNr == mgnr); if (item == null) { using var ctx = new AppDbContext(); var m = ctx.Members.Find(mgnr); if (m == null) return; if (ViewModel.SearchQuery?.Length > 0) { ViewModel.SearchQuery = ""; } if (!m.IsActive) { ViewModel.ShowOnlyActiveMembers = false; } App.MainDispatcher.BeginInvoke(async () => { await Task.Delay(500); FocusMember(mgnr); }); } else { ControlUtils.SelectItem(MemberList, item); } } private async Task RefreshList(bool updateSort = false) { using var ctx = new AppDbContext(); var (_, memberQuery, filter) = await ViewModel.GetFilters(ctx); var members = await memberQuery .Include(m => m.Branch) .Include(m => m.DefaultWbKg!.AtKg) .Include(m => m.EmailAddresses) .Include(m => m.TelephoneNumbers) .Include(m => m.PostalDest.AtPlz!.Ort) .Include(m => m.PostalDest.AtPlz!.Country) .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort) .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Country) .ToListAsync(); if (filter.Count > 0 && members.Count > 0) { var dict = members.AsParallel() .ToDictionary(m => m, m => m.SearchScore(filter)) .OrderByDescending(a => a.Value) .ThenBy(a => a.Key.FamilyName) .ThenBy(a => a.Key.GivenName); var threshold = dict.Select(a => a.Value).Max() * 3 / 4; members = dict .Where(a => a.Value > threshold) .Select(a => a.Key) .ToList(); } else { members = members .OrderBy(m => m.FamilyName) .ThenBy(m => m.GivenName) .ToList(); } ControlUtils.RenewItemsSource(MemberList, members, MemberList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort); if (updateSort && MemberList.SelectedItem != null) MemberList.ScrollIntoView(MemberList.SelectedItem); } private async Task RefreshInputs(bool validate = false) { ClearInputStates(); if (ViewModel.SelectedMember is Member m) { EditMemberButton.IsEnabled = true; DeleteMemberButton.IsEnabled = true; await FillInputs(m); } else { EditMemberButton.IsEnabled = false; DeleteMemberButton.IsEnabled = false; ClearOriginalValues(); ClearDefaultValues(); ClearInputs(validate); ClearInputStates(); } GC.Collect(); } private async void InitInputs() { ClearOriginalValues(); ClearDefaultValues(); await ViewModel.InitInputs(); SetDefaultValue(MgNrInput); SetDefaultValue(EntryDateInput); SetDefaultValue(ActiveInput); ValidateRequiredInputs(); } protected override async Task OnRenewContext(AppDbContext ctx) { await base.OnRenewContext(ctx); ControlUtils.RenewItemsSource(BranchInput, await ctx.Branches.OrderBy(b => b.Name).ToListAsync()); ControlUtils.RenewItemsSource(DefaultKgInput, await ctx.WbKgs.Select(k => k.AtKg).OrderBy(k => k.Name).ToListAsync()); var seasons = await ctx.Seasons.OrderByDescending(s => s.Year).ToListAsync(); Menu_DeliveryConfirmation.Items.Clear(); foreach (var s in seasons) { var i = new MenuItem { Header = $"Saison {s.Year}...", Tag = s.Year }; i.SetBinding(IsEnabledProperty, new Binding() { Path = new("IsMemberSelected") }); var show = new MenuItem { Header = "...anzeigen (PDF)" }; show.Click += Menu_DeliveryConfirmation_Show_Click; i.Items.Add(show); var pdf = new MenuItem { Header = "...speichern... (PDF)" }; pdf.Click += Menu_DeliveryConfirmation_Email_Click; i.Items.Add(pdf); var print = new MenuItem { Header = "...drucken" }; print.Click += Menu_DeliveryConfirmation_Print_Click; i.Items.Add(print); var email = new MenuItem { Header = "...per E-Mail schicken" }; email.Click += Menu_DeliveryConfirmation_Email_Click; email.SetBinding(IsEnabledProperty, new Binding() { Path = new("MemberCanSendEmail") }); i.Items.Add(email); Menu_DeliveryConfirmation.Items.Add(i); } Menu_CreditNote.Items.Clear(); foreach (var s in seasons) { var i1 = new MenuItem { Header = $"Saison {s.Year}...", Tag = s.Year, IsEnabled = MemberList.SelectedItem != null }; i1.SetBinding(IsEnabledProperty, new Binding() { Path = new($"MemberHasDeliveries[{s.Year}]") }); foreach (var v in s.PaymentVariants.OrderByDescending(v => v.AvNr)) { var i2 = new MenuItem { Header = $"...{v.Name}...", Tag = v.AvNr }; var show = new MenuItem { Header = "...anzeigen (PDF)" }; show.Click += Menu_CreditNote_Show_Click; i2.Items.Add(show); var pdf = new MenuItem { Header = "...speichern... (PDF)" }; pdf.Click += Menu_CreditNote_Email_Click; i2.Items.Add(pdf); var print = new MenuItem { Header = "...drucken" }; print.Click += Menu_CreditNote_Print_Click; i2.Items.Add(print); var email = new MenuItem { Header = "...per E-Mail schicken" }; email.SetBinding(IsEnabledProperty, new Binding { Path = new("MemberCanSendEmail") }); email.Click += Menu_CreditNote_Email_Click; i2.Items.Add(email); i1.Items.Add(i2); } Menu_CreditNote.Items.Add(i1); } await RefreshList(); var (s1, s2) = ('\u2007', '\u202f'); var mA = $"{await ctx.Members.CountAsync(m => m.IsActive):N0}"; var mI = $"{await ctx.Members.CountAsync(m => !m.IsActive):N0}"; var mT = $"{await ctx.Members.CountAsync():N0}"; var mM = Math.Max(mA.Length, Math.Max(mI.Length, mT.Length)); var mS = mM > 3; if (mS) mM--; ViewModel.StatusMembers = $"{mA} ({mT})"; ViewModel.StatusMembersToolTip = $"{new string(s1, Math.Max(0, mM - mA.Length))}{(mS && mA.Length < 4 ? s2 : "")}{mA} aktive Mitglieder\n" + $"{new string(s1, Math.Max(0, mM - mI.Length))}{(mS && mI.Length < 4 ? s2 : "")}{mI} nicht aktive Mitglieder\n" + $"{new string(s1, Math.Max(0, mM - mT.Length))}{(mS && mT.Length < 4 ? s2 : "")}{mT} Mitglieder gesamt"; var bA = $"{await ctx.Members.Where(m => m.IsActive).SumAsync(m => m.BusinessShares):N0}"; var bI = $"{await ctx.Members.Where(m => !m.IsActive).SumAsync(m => m.BusinessShares):N0}"; var bT = $"{await ctx.Members.SumAsync(m => m.BusinessShares):N0}"; var bM = Math.Max(bA.Length, Math.Max(bI.Length, bT.Length)); var bS = bM > 3; if (bS) bM--; ViewModel.StatusBusinessShares = $"{bA} ({bT})"; ViewModel.StatusBusinessSharesToolTip = $"{new string(s1, Math.Max(0, bM - bA.Length))}{(bS && bA.Length < 4 ? s2 : "")}{bA} Geschäftsanteile von aktiven Mitgliedern\n" + $"{new string(s1, Math.Max(0, bM - bI.Length))}{(bS && bI.Length < 4 ? s2 : "")}{bI} Geschäftsanteile von nicht aktiven Mitgliedern\n" + $"{new string(s1, Math.Max(0, bM - bT.Length))}{(bS && bT.Length < 4 ? s2 : "")}{bT} Geschäftsanteile gesamt"; } private void SetPhoneNrInputVisible(int nr, bool visible, int? position = null) { var inputs = PhoneNrInputs[nr]; if (position is int p) { var mt = 10 + p * 30; inputs.Type.Margin = new(6, mt, 5, 0); inputs.Number.Margin = new(0, mt, 5, 0); inputs.Comment.Margin = new(0, mt, 10, 0); } var vis = visible ? Visibility.Visible : Visibility.Hidden; inputs.Type.Visibility = vis; inputs.Number.Visibility = vis; inputs.Comment.Visibility = vis; } private void SetEmailAddressInputVisible(int nr, bool visible, int? position = null) { var inputs = EmailAddressInputs[nr]; if (position is int p) { var mt = 10 + p * 30; inputs.Label.Margin = new(10, mt, 0, 0); inputs.Address.Margin = new(0, mt, 10, 0); } var vis = visible ? Visibility.Visible : Visibility.Hidden; inputs.Label.Visibility = vis; inputs.Address.Visibility = vis; } private async void MemberList_SelectionChanged(object sender, RoutedEventArgs evt) { await RefreshInputs(); } private async void ActiveMemberInput_Changed(object sender, RoutedEventArgs evt) { await RefreshList(); } protected override void ShortcutNew() { if (!NewMemberButton.IsEnabled || NewMemberButton.Visibility != Visibility.Visible) return; NewMemberButton_Click(null, null); } private void NewMemberButton_Click(object? sender, RoutedEventArgs? evt) { IsCreating = true; MemberList.IsEnabled = false; ViewModel.SelectedMember = null; ViewModel.TransferPredecessorAreaComs = null; ViewModel.CancelAreaComs = null; HideNewEditDeleteButtons(); ShowSaveResetCancelButtons(); UnlockInputs(); UpdateContactInfoVisibility(true); InitInputs(); ViewModel.EnableSearchInputs = false; } protected override void ShortcutEdit() { if (!EditMemberButton.IsEnabled || EditMemberButton.Visibility != Visibility.Visible) return; EditMemberButton_Click(null, null); } private void EditMemberButton_Click(object? sender, RoutedEventArgs? evt) { if (ViewModel.SelectedMember == null) return; IsEditing = true; MemberList.IsEnabled = false; ViewModel.TransferPredecessorAreaComs = null; ViewModel.CancelAreaComs = null; HideNewEditDeleteButtons(); ShowSaveResetCancelButtons(); UnlockInputs(); UpdateContactInfoVisibility(true); ViewModel.EnableSearchInputs = false; } protected override void ShortcutDelete() { if (!DeleteMemberButton.IsEnabled || DeleteMemberButton.Visibility != Visibility.Visible) return; DeleteMemberButton_Click(null, null); } private async void DeleteMemberButton_Click(object? sender, RoutedEventArgs? evt) { if (ViewModel.SelectedMember is not Member m) return; int areaComs = 0, deliveries = 0, credits = 0; using (var ctx = new AppDbContext()) { var l = (await ctx.Members.FindAsync(m.MgNr))!; areaComs = l.AreaCommitments.Count; deliveries = l.Deliveries.Count; credits = l.Credits.Count; } var d = new DeleteMemberDialog(m.MgNr, m.AdministrativeName, areaComs, deliveries, credits); if (d.ShowDialog() == true) { Mouse.OverrideCursor = Cursors.AppStarting; try { using (var ctx = new AppDbContext()) { var l = (await ctx.Members.FindAsync(m.MgNr))!; if (d.DeletePaymentData) { ctx.RemoveRange(l.Credits); } if (d.DeleteDeliveries) { ctx.RemoveRange(l.Deliveries); } if (d.DeleteAreaComs) { ctx.RemoveRange(l.AreaCommitments); } ctx.Remove(l); 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, "Mitglied 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) { int? mgnr = null; try { mgnr = await ViewModel.UpdateMember(ViewModel.SelectedMember?.MgNr); } 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, "Mitglied aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error); } IsEditing = false; IsCreating = false; MemberList.IsEnabled = true; HideSaveResetCancelButtons(); ShowNewEditDeleteButtons(); LockInputs(); UpdateContactInfoVisibility(); ViewModel.EnableSearchInputs = true; FinishInputFilling(); await RefreshList(); await RefreshInputs(); ViewModel.SearchQuery = ""; if (mgnr is int m) FocusMember(m); } 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) { ViewModel.TransferPredecessorAreaComs = null; ViewModel.CancelAreaComs = null; if (IsEditing) { await RefreshInputs(); } else if (IsCreating) { ClearInputs(); InitInputs(); } UpdateButtons(); } private async void CancelButton_Click(object sender, RoutedEventArgs evt) { IsEditing = false; IsCreating = false; MemberList.IsEnabled = true; ViewModel.TransferPredecessorAreaComs = null; ViewModel.CancelAreaComs = null; HideSaveResetCancelButtons(); ShowNewEditDeleteButtons(); await RefreshInputs(); LockInputs(); UpdateContactInfoVisibility(); ViewModel.EnableSearchInputs = true; } private void AreaCommitmentButton_Click(object sender, RoutedEventArgs evt) { App.FocusMemberAreaComs(ViewModel.SelectedMember!.MgNr); } private void DeliveryButton_Click(object sender, RoutedEventArgs evt) { App.FocusMemberDeliveries(ViewModel.SelectedMember!.MgNr); } private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) { await RefreshList(true); } private void Menu_Contact_Email_Click(object sender, RoutedEventArgs evt) { if (ViewModel.SelectedMember is not Member m) return; Utils.MailTo(m.EmailAddresses.Select(a => a.Address)); } private async void Menu_Contact_Letterhead_Click(object sender, RoutedEventArgs evt) { if (ViewModel.SelectedMember is not Member m) return; Mouse.OverrideCursor = Cursors.AppStarting; try { using var doc = new Letterhead(m); await doc.Generate(); if (!App.Config.Debug) { await doc.Print(); } else { doc.Show(); } } catch (Exception exc) { MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); } Mouse.OverrideCursor = null; } private async void Menu_MemberDataSheet_Show_Click(object sender, RoutedEventArgs evt) { if (ViewModel.SelectedMember is not Member m) return; await MemberService.GenerateMemberDataSheet(m, ExportMode.Show); } private async void Menu_MemberDataSheet_SavePdf_Click(object sender, RoutedEventArgs evt) { if (ViewModel.SelectedMember is not Member m) return; await MemberService.GenerateMemberDataSheet(m, ExportMode.SavePdf); } private async void Menu_MemberDataSheet_Print_Click(object sender, RoutedEventArgs evt) { if (ViewModel.SelectedMember is not Member m) return; await MemberService.GenerateMemberDataSheet(m, ExportMode.Print); } private async void Menu_MemberDataSheet_Email_Click(object sender, RoutedEventArgs evt) { if (ViewModel.SelectedMember is not Member m) return; await MemberService.GenerateMemberDataSheet(m, ExportMode.Email); } private async void Menu_DeliveryConfirmation_Show_Click(object sender, RoutedEventArgs evt) { var year = (int?)((sender as MenuItem)?.Parent as MenuItem)?.Tag; if (ViewModel.SelectedMember is not Member m || year == null) return; await MemberService.GenerateDeliveryConfirmation(m, (int)year, ExportMode.Show); } private async void Menu_DeliveryConfirmation_SavePdf_Click(object sender, RoutedEventArgs evt) { var year = (int?)((sender as MenuItem)?.Parent as MenuItem)?.Tag; if (ViewModel.SelectedMember is not Member m || year == null) return; await MemberService.GenerateDeliveryConfirmation(m, (int)year, ExportMode.SavePdf); } private async void Menu_DeliveryConfirmation_Print_Click(object sender, RoutedEventArgs evt) { var year = (int?)((sender as MenuItem)?.Parent as MenuItem)?.Tag; if (ViewModel.SelectedMember is not Member m || year == null) return; await MemberService.GenerateDeliveryConfirmation(m, (int)year, ExportMode.Print); } private async void Menu_DeliveryConfirmation_Email_Click(object sender, RoutedEventArgs evt) { var year = (int?)((sender as MenuItem)?.Parent as MenuItem)?.Tag; if (ViewModel.SelectedMember is not Member m || year == null) return; await MemberService.GenerateDeliveryConfirmation(m, (int)year, ExportMode.Email); } private async void Menu_CreditNote_Show_Click(object sender, RoutedEventArgs evt) { var year = (int?)(((sender as MenuItem)?.Parent as MenuItem)?.Parent as MenuItem)?.Tag; var avnr = (int?)((sender as MenuItem)?.Parent as MenuItem)?.Tag; if (ViewModel.SelectedMember is not Member m || year == null || avnr == null) return; await MemberService.GenerateCreditNote(m, (int)year, (int)avnr, ExportMode.Show); } private async void Menu_CreditNote_SavePdf_Click(object sender, RoutedEventArgs evt) { var year = (int?)(((sender as MenuItem)?.Parent as MenuItem)?.Parent as MenuItem)?.Tag; var avnr = (int?)((sender as MenuItem)?.Parent as MenuItem)?.Tag; if (ViewModel.SelectedMember is not Member m || year == null || avnr == null) return; await MemberService.GenerateCreditNote(m, (int)year, (int)avnr, ExportMode.SavePdf); } private async void Menu_CreditNote_Print_Click(object sender, RoutedEventArgs evt) { var year = (int?)(((sender as MenuItem)?.Parent as MenuItem)?.Parent as MenuItem)?.Tag; var avnr = (int?)((sender as MenuItem)?.Parent as MenuItem)?.Tag; if (ViewModel.SelectedMember is not Member m || year == null || avnr == null) return; await MemberService.GenerateCreditNote(m, (int)year, (int)avnr, ExportMode.Print); } private async void Menu_CreditNote_Email_Click(object sender, RoutedEventArgs evt) { var year = (int?)(((sender as MenuItem)?.Parent as MenuItem)?.Parent as MenuItem)?.Tag; var avnr = (int?)((sender as MenuItem)?.Parent as MenuItem)?.Tag; if (ViewModel.SelectedMember is not Member m || year == null || avnr == null) return; await MemberService.GenerateCreditNote(m, (int)year, (int)avnr, ExportMode.Email); } private async void Menu_List_SaveActive_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(0, ExportMode.SaveList); } private async void Menu_List_ShowActive_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(0, ExportMode.Show); } private async void Menu_List_SavePdfActive_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(0, ExportMode.SavePdf); } private async void Menu_List_PrintActive_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(0, ExportMode.Print); } private async void Menu_List_SaveFilters_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(1, ExportMode.SaveList); } private async void Menu_List_ShowFilters_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(1, ExportMode.Show); } private async void Menu_List_SavePdfFilters_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(1, ExportMode.SavePdf); } private async void Menu_List_PrintFilters_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(1, ExportMode.Print); } private async void Menu_List_SaveAll_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(2, ExportMode.SaveList); } private async void Menu_List_ShowAll_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(2, ExportMode.Show); } private async void Menu_List_SavePdfAll_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(2, ExportMode.SavePdf); } private async void Menu_List_PrintAll_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(2, ExportMode.Print); } private async void Menu_Export_ExportAll_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(2, ExportMode.Export); } private async void Menu_Export_ExportFilters_Click(object sender, RoutedEventArgs evt) { await ViewModel.GenerateMemberList(1, ExportMode.Export); } private async void Menu_Export_UploadAll_Click(object sender, RoutedEventArgs evt) { if (App.Config.SyncUrl == null) return; await ViewModel.GenerateMemberList(2, ExportMode.Upload); } private async void Menu_Export_UploadFilters_Click(object sender, RoutedEventArgs evt) { if (App.Config.SyncUrl == null) return; await ViewModel.GenerateMemberList(1, ExportMode.Upload); } private async void Menu_List_Order_Click(object sender, RoutedEventArgs evt) { Menu_List.IsSubmenuOpen = true; if (sender == Menu_List_OrderMgNr) { App.Client.OrderingMemberList = 0; ViewModel.MemberListOrderByMgNr = true; ViewModel.MemberListOrderByName = false; ViewModel.MemberListOrderByOrt = false; } else if (sender == Menu_List_OrderName) { App.Client.OrderingMemberList = 1; ViewModel.MemberListOrderByMgNr = false; ViewModel.MemberListOrderByName = true; ViewModel.MemberListOrderByOrt = false; } else if (sender == Menu_List_OrderOrt) { App.Client.OrderingMemberList = 2; ViewModel.MemberListOrderByMgNr = false; ViewModel.MemberListOrderByName = false; ViewModel.MemberListOrderByOrt = true; } await App.Client.UpdateValues(); } 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() { NewMemberButton.IsEnabled = true; EditMemberButton.IsEnabled = ViewModel.SelectedMember != null; DeleteMemberButton.IsEnabled = ViewModel.SelectedMember != null; ViewModel.ControlButtonsVisibility = Visibility.Visible; } private void HideNewEditDeleteButtons() { NewMemberButton.IsEnabled = false; EditMemberButton.IsEnabled = false; DeleteMemberButton.IsEnabled = false; ViewModel.ControlButtonsVisibility = Visibility.Hidden; } private void UpdateContactInfoVisibility(bool extra = false) { var m = ViewModel.SelectedMember; bool lastVisible; int num = 0; lastVisible = true; for (int i = 0; i < EmailAddressInputs.Length; i++) { var input = EmailAddressInputs[i]; var vis = !string.IsNullOrEmpty(input.Address.Text) || (m?.EmailAddresses.Any(a => a.Nr - 1 == i) ?? false); var cVis = vis || (extra && lastVisible); SetEmailAddressInputVisible(i, cVis, cVis ? num++ : null); lastVisible = vis; } lastVisible = true; for (int i = 0; i < PhoneNrInputs.Length; i++) { var input = PhoneNrInputs[i]; var vis = !string.IsNullOrEmpty(input.Number.Text) || (m?.TelephoneNumbers.Any(n => n.Nr - 1 == i) ?? false); var cVis = vis || (extra && lastVisible); SetPhoneNrInputVisible(i, cVis, cVis ? num++ : null); lastVisible = vis; } } private async Task FillInputs(Member m) { ClearOriginalValues(); ClearDefaultValues(); await ViewModel.FillInputs(m); UpdateContactInfoVisibility(IsEditing || IsCreating); FinishInputFilling(); } new protected void ClearInputs(bool validate = false) { ViewModel.ClearInputs(); base.ClearInputs(validate); } override protected void UpdateButtons() { if (!IsEditing && !IsCreating) return; bool ch = HasChanged, v = IsValid; ResetButton.IsEnabled = ch; SaveButton.IsEnabled = v && ch; } protected void InputTextChanged(TextBox input, Func checker) { InputTextChanged(input, checker(input, SenderIsRequired(input), ViewModel.SelectedMember)); } protected void InputLostFocus(TextBox input, Func checker, string? msg = null) { InputLostFocus(input, checker(input, SenderIsRequired(input), ViewModel.SelectedMember), msg); } private void MgNrInput_TextChanged(object sender, RoutedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckNewMgNr); } private void MgNrInput_LostFocus(object sender, RoutedEventArgs evt) { InputLostFocus((TextBox)sender, Validator.CheckNewMgNr); } private void PredecessorMgNrInput_TextChanged(object sender, RoutedEventArgs evt) { InputTextChanged((TextBox)sender, Validator.CheckPredecessorMgNr); } private async void PredecessorMgNrInput_LostFocus(object sender, RoutedEventArgs evt) { var valid = InputLostFocus((TextBox)sender, Validator.CheckPredecessorMgNr); if (valid && ViewModel.PredecessorMgNr is int mgnr && (IsEditing || IsCreating)) { if (MemberList.SelectedItem is not Member m || m.MgNr == mgnr) return; using var ctx = new AppDbContext(); var areaComs = await ctx.AreaCommitments .Where(c => c.MgNr == mgnr && (c.YearTo == null || c.YearTo >= Utils.FollowingSeason)) .ToListAsync(); if (areaComs.Count == 0) return; var oldMember = (await ctx.Members.FindAsync(mgnr))!; var d = new AreaComDialog(oldMember.AdministrativeName, m.AdministrativeName, areaComs.Count, areaComs.Sum(c => c.Area)); if (d.ShowDialog() != true) return; ViewModel.TransferPredecessorAreaComs = d.SuccessorSeason; SetOriginalValue(PredecessorMgNrInput, -1); // hack to allow user to save UpdateButtons(); } } private new void EmailAddressInput_TextChanged(object sender, TextChangedEventArgs evt) { if (sender == EmailAddress1Input && ViewModel.ContactViaEmail) { InputTextChanged((TextBox)sender, Validator.CheckEmailAddress((TextBox)sender, true)); } else { base.EmailAddressInput_TextChanged(sender, evt); } UpdateContactInfoVisibility(IsEditing || IsCreating); } private new void PhoneNrInput_TextChanged(object sender, TextChangedEventArgs evt) { base.PhoneNrInput_TextChanged(sender, evt); UpdateContactInfoVisibility(IsEditing || IsCreating); } private void ContactEmailInput_Changed(object sender, RoutedEventArgs evt) { EmailAddressInput_TextChanged(EmailAddress1Input, new TextChangedEventArgs(evt.RoutedEvent, UndoAction.None)); } private void KgDetailsButton_Click(object sender, RoutedEventArgs evt) { if (DefaultKgInput.SelectedItem is AT_Kg kg) { App.FocusOriginHierarchyKg(kg.KgNr); } else { App.FocusOriginHierarchy(); } } private void OrganicButton_Click(object sender, RoutedEventArgs evt) { if (ViewModel.SelectedMember is not Member m) return; var url = "https://www.easy-cert.com/htm/suchergebnis.htm?" + //$"CustomerNumber={m.LfbisNr}&" + $"Name={(m.BillingAddress?.Name ?? m.Name).Replace(' ', '+')}&" + $"PostalCode={(m.BillingAddress?.PostalDest ?? m.PostalDest).AtPlz?.Plz}"; Process.Start(new ProcessStartInfo(url) { UseShellExecute = true, }); } private void MemberReferenceButton_Click(object sender, RoutedEventArgs evt) { if (ViewModel.SelectedMember is not Member m || m.PredecessorMgNr == null) return; FocusMember((int)m.PredecessorMgNr); } private async void ActiveInput_Changed(object sender, RoutedEventArgs evt) { if (MemberList.SelectedItem is not Member m) return; if ((IsEditing || IsCreating) && ViewModel.IsActive == false && ViewModel.MgNr is int mgnr) { using var ctx = new AppDbContext(); var areaComs = await ctx.AreaCommitments .Where(c => c.MgNr == mgnr && (c.YearTo == null || c.YearTo >= Utils.FollowingSeason)) .ToListAsync(); if (areaComs.Count > 0) { var d = new AreaComDialog(m.AdministrativeName, areaComs.Count, areaComs.Sum(c => c.Area)); if (d.ShowDialog() == true) { ViewModel.CancelAreaComs = d.CancelSeason; } } } CheckBox_Changed(sender, evt); } } }