using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; using System.Windows.Navigation; using BeWo.Core; using BeWo.Core.Service; using BeWo.Scheduler.View; using BeWo.Scheduling.Converter; using BeWo.Scheduling.SchedulingUtils; using BeWo.Scheduling.ViewModel; using BeWo.ServiceProxy; using BeWo.View; using BeWo.View.Detail; using BS.Shared; using BS.Shared.Core; using BS.Shared.DataContracts; using BS.Shared.DataContracts.Compact; using BS.Shared.Extensions; using BS.Shared.Translation; using DevExpress.Mvvm; using DevExpress.Xpf.Bars; using DevExpress.Xpf.Editors; using DevExpress.Xpf.Scheduling; using DevExpress.Xpf.Scheduling.VisualData; using DevExpress.XtraScheduler; using PopupMenuShowingEventArgs = DevExpress.Xpf.Scheduling.PopupMenuShowingEventArgs; using SchedulerControl = DevExpress.Xpf.Scheduling.SchedulerControl; using Utils = BeWo.Scheduling.SchedulingUtils.Utils; namespace BeWo.Scheduling.View { public partial class SchedulingView { private static CompactEmployeeDC LoggedOnCompactEmployee => BeWoApp.CompactLoggedOnEmployee; public SchedulingAppointmentListVM ViewModel { get; set; } private ViewType _CurrentViewType; public static TimeSpan FetchPadding = TimeSpan.FromDays(14); private TimeInterval _LastFetchedInterval = new TimeInterval(); public SchedulingCheckBoxConverter CheckBoxConverter => Resources[nameof(CheckBoxConverter)] as SchedulingCheckBoxConverter; // ----------- Konstruktor ----------- public SchedulingView() { ViewModel = new SchedulingAppointmentListVM { IsEmployeeBrushVisible = true }; InitializeComponent(); DataContext = ViewModel; InitializeSchedulerControl(); ReloadViewModel(true, true); } private DateTime? _SelectedAppointmentStartDate; private SchedulerAppointmentDC _SelectedAppointmentFromHomePanelView; private bool _IsComingFromHomeDragPanel; // Durch Doppelklick auf Termin im HomeView aufgerufen public SchedulingView(DateTime intervalStartDate, SchedulerAppointmentDC appointment) { _IsComingFromHomeDragPanel = true; _SelectedAppointmentFromHomePanelView = appointment; _SelectedAppointmentStartDate = intervalStartDate; ViewModel = new SchedulingAppointmentListVM { IsEmployeeBrushVisible = true }; InitializeComponent(); DataContext = ViewModel; if(_IsComingFromHomeDragPanel && _SelectedAppointmentStartDate.HasValue) { var monday = _SelectedAppointmentStartDate.Value.FirstDateOfWeek(_SelectedAppointmentStartDate.Value.GetIso8601WeekOfYear()); SchedulerControl.Start = monday; var viewType = _SelectedAppointmentStartDate.Value.DayOfWeek == DayOfWeek.Saturday || _SelectedAppointmentStartDate.Value.DayOfWeek == DayOfWeek.Sunday ? ViewType.WeekView : ViewType.WorkWeekView; SchedulerControl.ActiveViewType = viewType; _SelectedAppointmentStartDate = null; } //InitializeSchedulerControl(); ReloadViewModel(true, true); } // ----------- /Konstruktor ---------- private void InitializeSchedulerControl() { LoadRelatedTeamOids(); LoadSchedulingViewType(); } private void LoadRelatedTeamOids() { Cache.GetInstance().GetTeamRelatedCustomerOidsForEmployee(BeWoApp.CompactLoggedOnEmployee.EmployeeOid, false, teamMemberCustomerOids => { this.Dispatch(() => { ViewModel.TeamRelatedCustomerOids = teamMemberCustomerOids; }); }); } private void LoadSchedulingViewType() { _CurrentViewType = BeWoApp.AppSettings.SchedulingViewType; SetViewType(_CurrentViewType); } public void ReloadRights() { ViewModel.ReloadRights(); if(ViewModel.SelectedTabItemIndex > 0 && ViewModel.SelectedTabItemIndex < 3) { switch(ViewModel.SelectedTabItemIndex) { case 0: if(ViewModel.EmployeeControlsVisibility == Visibility.Visible) { ((TabItem) TabControl.Items[0]).IsSelected = true; } else { SelectDefaultTabItem(); } break; case 1: if(ViewModel.CustomerControlsVisibility == Visibility.Visible) { ((TabItem) TabControl.Items[1]).IsSelected = true; } else { SelectDefaultTabItem(); } break; case 2: if(ViewModel.ResourceControlsVisibility == Visibility.Visible) { ((TabItem) TabControl.Items[2]).IsSelected = true; } else { SelectDefaultTabItem(); } break; default: SelectDefaultTabItem(); break; } } else { SelectDefaultTabItem(); } var isLeftSideVisible = ViewModel.SelectionControlVisibility == Visibility.Visible; LeftExpanderButton.Visibility = isLeftSideVisible ? Visibility.Visible : Visibility.Collapsed; ZeigeNurMeineTermineCheckBox.Visibility = isLeftSideVisible ? Visibility.Visible : Visibility.Collapsed; AuswahlGrid.Visibility = isLeftSideVisible ? Visibility.Visible : Visibility.Collapsed; ObjectSelectionGrid.Visibility = isLeftSideVisible ? Visibility.Visible : Visibility.Collapsed; } private void SelectDefaultTabItem() { if(ViewModel.EmployeeControlsVisibility == Visibility.Visible) { ((TabItem) TabControl.Items[0]).IsSelected = true; } else if(ViewModel.CustomerControlsVisibility == Visibility.Visible) { ((TabItem) TabControl.Items[1]).IsSelected = true; } else if(ViewModel.ResourceControlsVisibility == Visibility.Visible) { ((TabItem) TabControl.Items[2]).IsSelected = true; } } public void ReloadViewModel(bool shouldForceReload = false, bool isFirstTimeLoading = false, bool reloadCachedObjects = false) { var visibleIntervals = SchedulerControl.VisibleIntervals; var start = visibleIntervals[0].Start; var end = visibleIntervals.Last().End; var newFetchingInterval = new TimeInterval(start - FetchPadding, end + FetchPadding); var selectedEmployeeOids = ViewModel.SelectedEmployees.Select(s => s.EmployeeOid).ToList(); var selectedCustomerOids = ViewModel.SelectedCustomers.Select(s => s.CustomerOid).ToList(); var selectedResourceOids = ViewModel.SelectedResources.Where(w => w.ResourceOid.HasValue).Select(s => s.ResourceOid.Value).ToList(); var employeesOnly = MitarbeiterEbenenCheckBox.IsChecked ?? false; var customersOnly = KlientenEbenenCheckBox.IsChecked ?? false; var resourcesOnly = RessourcenEbenenCheckBox.IsChecked ?? false; var onlyPrivateAppointments = ShowPrivateAppointmentsCheckBox.IsChecked ?? false; var showOnlyMyAppointments = ViewModel.ZeigeNurMeineTermine; var showAbsenceTimes = AbwesenheitenEinAusCheckBox.IsChecked ?? false; var showTasks = ViewModel.IsTasksVisible; if(!shouldForceReload && newFetchingInterval.Equals(_LastFetchedInterval)) { return; } _LastFetchedInterval = newFetchingInterval; GetCachedObjects(reloadCachedObjects, (customers, employees, resources) => { var hasRightToSeeAllEmployeeAppointments = BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderMitarbeitertermineAnsehen); var employeeOid = BeWoApp.LoggedOnEmployeeOid; if(employeeOid.HasValue) { ServiceFacade.DoResourceServiceAsync(s => s.LoadFilteredAppointmentsMitAufgaben(hasRightToSeeAllEmployeeAppointments, employeeOid.Value, newFetchingInterval.Start, newFetchingInterval.End, selectedEmployeeOids, selectedCustomerOids, selectedResourceOids, employeesOnly, customersOnly, resourcesOnly, onlyPrivateAppointments, showOnlyMyAppointments, showTasks), appointments => { ServiceFacade.DoResourceServiceAsync(s2 => s2.GetAllActiveAbsenceTimesInInterval(newFetchingInterval.Start, newFetchingInterval.End, employeeOid.Value, hasRightToSeeAllEmployeeAppointments), absenceTimes => { this.Dispatch(() => { ViewModel.AllCustomers = new ObservableSortCollection(customers); ViewModel.FilteredCustomers = new ObservableSortCollection(customers); ViewModel.AllEmployees = new ObservableSortCollection(employees); ViewModel.Employees = new ObservableSortCollection(); ViewModel.FilteredEmployees = new ObservableSortCollection(); foreach(var employee in employees) { var employeeDependencyObject = new EmployeeDependencyObject(employee); ViewModel.Employees.AddIfNotIn(employeeDependencyObject); ViewModel.FilteredEmployees.AddIfNotIn(employeeDependencyObject); } ViewModel.SelectEmployeesAfterReload(); var cats2Res = new ObservableDictionary>(); foreach(var cat2Res in resources) { cats2Res.Add(new CategoryDependencyObject(cat2Res.Key), cat2Res.Value.Select(s => new ResourceDependencyObject(s)).ToList()); } ViewModel.Categories2Resources = cats2Res; ViewModel.SelectedAppointments.Clear(); ViewModel.VMList.Clear(); foreach(var appointment in appointments) { ViewModel.VMList.AddIfNotIn(new SchedulingAppointmentVM(appointment)); } if(showAbsenceTimes) { ViewModel.VMList.AddRangeIfElementsNotIn(Utils.ConvertAbsenceTimesToAppointments(absenceTimes, end, employees)); } ViewModel.UpdateSelectedItems(); if(_IsComingFromHomeDragPanel && !(_SelectedAppointmentFromHomePanelView is null)) { var range = new DateTimeRange(start, end); var appointmentItems = SchedulerControl.GetAppointments(range); AppointmentItem appointment2Edit = null; if(_SelectedAppointmentFromHomePanelView.SchedulerAppointmentOid.HasValue) { appointment2Edit = appointmentItems.FirstOrDefault(f => long.TryParse(f.Id?.ToString(), out var oid) && oid == _SelectedAppointmentFromHomePanelView.SchedulerAppointmentOid.Value); } else { var recurrenceId = _SelectedAppointmentFromHomePanelView.RecurrenceId; var recurrenceIndex = _SelectedAppointmentFromHomePanelView.RecurrenceIndex; if(!string.IsNullOrEmpty(recurrenceId)) { appointment2Edit = appointmentItems.FirstOrDefault(f => f.RecurrenceIndex == recurrenceIndex && f.RecurrenceInfoId?.ToString() == recurrenceId); } } if(!(appointment2Edit is null)) { SchedulerControl.ShowAppointmentWindow(appointment2Edit, false); } _SelectedAppointmentFromHomePanelView = null; } ReloadRights(); UpdateRequestString(isFirstTimeLoading); if(!string.IsNullOrEmpty(MitarbeiterSuchTextBox.Text)) { ViewModel.FilterEmployees(MitarbeiterSuchTextBox.Text); } if(!string.IsNullOrEmpty(KlientenSuchTextBox.Text)) { ViewModel.FilterCustomers(KlientenSuchTextBox.Text); } }); }, true); }, true); } }); } private static void GetCachedObjects(bool reloadCachedObjects, Action, List, Dictionary>> callback) { if(BeWoApp.LoggedOnEmployeeOid.HasValue) { Cache.GetInstance().GetAllActiveCustomersCompactForEmployee(BeWoApp.LoggedOnEmployeeOid.Value, reloadCachedObjects, customers => { Cache.GetInstance().GetAllActiveCompactEmployeesForEmployee(BeWoApp.LoggedOnEmployeeOid.Value, reloadCachedObjects, employees => { ServiceFacade.DoResourceServiceAsync(s => s.GetAllCategories2ResourcesInDictionary(), cat2Res => { callback?.Invoke(customers, employees, cat2Res); }); }); }); } } private void CheckForAppointmentRequests() { var appointments = Utils.SeperateStatusUpdatesAndAppointments(_OpenAppointments); if(!appointments.Appointments.Any() && !appointments.StatusUpdates.Any()) { return; } var openAppointmentsView = new OpenAppointmentsView(appointments.Appointments, appointments.StatusUpdates); openAppointmentsView.Closed += (s, e) => { ReloadAndUpdateRequestStringEvent(); }; openAppointmentsView.ParticipationChanged += (s, e) => { ReloadAndUpdateRequestStringEvent(); }; openAppointmentsView.ShowDialog(); } private void ReloadAndUpdateRequestStringEvent() { ReloadViewModel(true); UpdateRequestString(); } private List _OpenAppointments = new List(); public void UpdateRequestString(bool openConfirmationView = false) { if(ViewModel.DisableUpdateRequestString || BeWoApp.LoggedOnEmployeeOid is null) { return; } ServiceFacade.DoResourceServiceAsync(s => s.GetAllOpenAppointmentsForEmployee(BeWoApp.LoggedOnEmployeeOid.Value), openAppointments => { this.Dispatch(() => { _OpenAppointments = openAppointments; var count = 0; var oidList = new List(); foreach(var openAppointment in _OpenAppointments) { if(openAppointment.Originator.Equals(BeWoApp.CompactLoggedOnEmployee)) { foreach(var employee2Appointment in openAppointment.EmployeeList.Where(e2a => e2a.Employee.Equals(BeWoApp.CompactLoggedOnEmployee))) { if(employee2Appointment.IsPChanged && employee2Appointment.ParticipationAnswer != ParticipationAnswer.Offen && employee2Appointment.ParticipationAnswer != ParticipationAnswer.Verstrichen && employee2Appointment.Employee2SchedulerAppointmentOid.HasValue) { oidList.AddIfNotIn(employee2Appointment.Employee2SchedulerAppointmentOid.Value); count++; } } } else if(openAppointment.EmployeeList.Any(e2a => e2a.Employee.Equals(BeWoApp.CompactLoggedOnEmployee))) { foreach(var employee2Appointment in openAppointment.EmployeeList) { if(employee2Appointment.IsPChanged && employee2Appointment.ParticipationAnswer == ParticipationAnswer.Offen && employee2Appointment.ParticipationAnswer != ParticipationAnswer.Verstrichen && employee2Appointment.Employee2SchedulerAppointmentOid.HasValue) { oidList.AddIfNotIn(employee2Appointment.Employee2SchedulerAppointmentOid.Value); count++; } } } } ViewModel.Enabled = count > 0; ViewModel.Requests = $"{(count == 0 ? "keine" : count.ToString())} Benachrichtigung{(count == 1 ? string.Empty : "en")}"; if(openConfirmationView) { CheckForAppointmentRequests(); } }); }, true); } private void SpinEditDayViewDayCount_OnLostFocus(object sender, RoutedEventArgs e) { BeWoApp.SaveAppSettings(); } private void SpinEditTimelineViewDayCount_OnLostFocus(object sender, RoutedEventArgs e) { BeWoApp.SaveAppSettings(); } private void ReloadButton_OnClick(object sender, RoutedEventArgs e) { ReloadViewModel(true); } // ToDo: Implementieren! private void ExportButton_OnClick(object sender, RoutedEventArgs e) { } private void AbwesenheitenEinAusCheckBox_OnChecked(object sender, RoutedEventArgs e) { ReloadViewModel(true); } private void ShowTasksCheckBox_OnClick(object sender, RoutedEventArgs e) { ReloadViewModel(true); } private void ShowAppointmentRequests(object sender, RequestNavigateEventArgs e) { CheckForAppointmentRequests(); } private void ShowPrivateAppointmentsCheckBox_OnClick(object sender, RoutedEventArgs e) { ReloadViewModel(true); } private void SpinEditDayViewDayCount_EditValueChanged(object sender, EditValueChangedEventArgs e) { if(e.NewValue != null && int.TryParse(e.NewValue.ToString(), out var count) && count > 0) { if(SchedulerControl.ActiveView is DevExpress.Xpf.Scheduling.DayView activeView) { activeView.DayCount = count; BeWoApp.AppSettings.SchedulerDayViewDayCount = count; } } } private void SpinEditTimelineViewDayCount_EditValueChanged(object sender, EditValueChangedEventArgs e) { if(e.NewValue != null && int.TryParse(e.NewValue.ToString(), out var count) && count > 0) { if(SchedulerControl.ActiveView is DevExpress.Xpf.Scheduling.TimelineView activeView) { activeView.IntervalCount = count; } BeWoApp.AppSettings.SchedulerTimelineViewDayCount = count; } } private void PrintCalendar(object sender, RequestNavigateEventArgs e) { var visibleIntervals = SchedulerControl.VisibleIntervals; var start = visibleIntervals[0].Start; var end = visibleIntervals.Last().End; var dtr = new DateTimeRange(start, end); var appointmentItems = SchedulerControl.GetAppointments(dtr, null); var appointmentsAndTasks = new List(); var dates = new List(); for(var i = 0; i < dtr.Duration.Days; i++) { dates.AddIfNotIn(start.AddDays(i)); } // Abwesenheiten rausfiltern foreach(var appointmentItem in appointmentItems) { if(appointmentItem.CustomFields["VMForCustomField"] is SchedulingAppointmentVM vm && !vm.IsAbsenceTime) { if(appointmentItem.Type == AppointmentType.Occurrence) { var occurrenceVM = CreateChangedOccurrence(appointmentItem); appointmentsAndTasks.AddIfNotIn(occurrenceVM.CommitToDataContract()); } else { appointmentsAndTasks.AddIfNotIn(vm.CommitToDataContract()); } } } var appointmentOids = appointmentsAndTasks.Where(w => w.SchedulerAppointmentOid.HasValue).Select(s => s.SchedulerAppointmentOid.Value).ToList(); var withoutOid = appointmentsAndTasks.Where(w => w.SchedulerAppointmentOid is null).ToList(); // ToDo: Für Montag, 18.07.2022: // ToDo: Serientermine kommen doppelt vor! Mehrtägige Serientermine aus den appointmentOids herausnehmen! var multipleDaysAppointments = appointmentsAndTasks.Where( w => { if(w.StartDate is null || w.EndDate is null || w.Type == (int) AppointmentType.Pattern) { return false; } if(w.AllDay) { return w.StartDate.Value.Date != w.EndDate.Value.AddMinutes(-1).Date; } return w.StartDate.Value.Date != w.EndDate.Value.Date; }).ToList(); appointmentOids.RemoveRange(multipleDaysAppointments.Where(w => w.SchedulerAppointmentOid.HasValue).Select(s => s.SchedulerAppointmentOid.Value)); var createdAppointments = BreakDownMultipleDaysAppointments(multipleDaysAppointments); var variables = new Dictionary { {"appointmentOidListe", appointmentOids}, {"datesList", dates}, {"employeeOid", BeWoApp.LoggedOnEmployee.EmployeeOid}, {"serienTermine", withoutOid}, {"mehrtaegigeTermine", createdAppointments} }; BeWoUtils.ShowReport("Kalender", variables, ReportEnum.KalenderMonatsReportEnum); } public static List BreakDownMultipleDaysAppointments(List appointments) { var result = new List(); foreach(var appointment in appointments) { if(appointment.StartDate is null || appointment.EndDate is null) { continue; } var days = appointment.StartDate.Value.GetDayNumberBetweenTwoDates(appointment.EndDate.Value); if(days > 31) { days = 31; } if(appointment.AllDay) { days -= 1; } if(days > 0) { if(appointment.AllDay) { for(var i = 0; i <= days; i++) { result.Add(new SchedulerAppointmentDC { AllDay = appointment.AllDay, CustomerList = appointment.CustomerList, Description = appointment.Description, EmployeeList = appointment.EmployeeList, EndDate = new DateTime(appointment.StartDate.Value.AddDays(i + 1).Year, appointment.StartDate.Value.AddDays(i + 1).Month, appointment.StartDate.Value.AddDays(i + 1).Day), FormerBookingSequenceOid = appointment.FormerBookingSequenceOid, IsPrivate = appointment.IsPrivate, LabelKey = appointment.LabelKey, Location = appointment.Location, Originator = appointment.Originator, RecurrenceInfo = appointment.RecurrenceInfo, ReminderInfo = appointment.ReminderInfo, ResourceList = appointment.ResourceList, StartDate = new DateTime(appointment.StartDate.Value.AddDays(i).Year, appointment.StartDate.Value.AddDays(i).Month, appointment.StartDate.Value.AddDays(i).Day), Status = appointment.Status, Subject = appointment.Subject, Type = appointment.Type }); } } else { for(var i = 0; i <= days; i++) { if(i == 0) { result.Add(new SchedulerAppointmentDC { AllDay = false, CustomerList = appointment.CustomerList, Description = appointment.Description, EmployeeList = appointment.EmployeeList, EndDate = new DateTime(appointment.StartDate.Value.AddDays(1).Year, appointment.StartDate.Value.AddDays(1).Month, appointment.StartDate.Value.AddDays(1).Day), FormerBookingSequenceOid = appointment.FormerBookingSequenceOid, IsPrivate = appointment.IsPrivate, LabelKey = appointment.LabelKey, Location = appointment.Location, Originator = appointment.Originator, RecurrenceInfo = appointment.RecurrenceInfo, ReminderInfo = appointment.ReminderInfo, ResourceList = appointment.ResourceList, StartDate = appointment.StartDate, Status = appointment.Status, Subject = appointment.Subject, Type = appointment.Type }); } else if(i == days) { result.Add(new SchedulerAppointmentDC { AllDay = false, CustomerList = appointment.CustomerList, Description = appointment.Description, EmployeeList = appointment.EmployeeList, EndDate = appointment.EndDate, FormerBookingSequenceOid = appointment.FormerBookingSequenceOid, IsPrivate = appointment.IsPrivate, LabelKey = appointment.LabelKey, Location = appointment.Location, Originator = appointment.Originator, RecurrenceInfo = appointment.RecurrenceInfo, ReminderInfo = appointment.ReminderInfo, ResourceList = appointment.ResourceList, StartDate = new DateTime(appointment.EndDate.Value.Year, appointment.EndDate.Value.Month, appointment.EndDate.Value.Day), Status = appointment.Status, Subject = appointment.Subject, Type = appointment.Type }); } else { result.Add(new SchedulerAppointmentDC { AllDay = true, CustomerList = appointment.CustomerList, Description = appointment.Description, EmployeeList = appointment.EmployeeList, EndDate = new DateTime(appointment.StartDate.Value.AddDays(i + 1).Year, appointment.StartDate.Value.AddDays(i + 1).Month, appointment.StartDate.Value.AddDays(i + 1).Day), FormerBookingSequenceOid = appointment.FormerBookingSequenceOid, IsPrivate = appointment.IsPrivate, LabelKey = appointment.LabelKey, Location = appointment.Location, Originator = appointment.Originator, RecurrenceInfo = appointment.RecurrenceInfo, ReminderInfo = appointment.ReminderInfo, ResourceList = appointment.ResourceList, StartDate = new DateTime(appointment.StartDate.Value.AddDays(i).Year, appointment.StartDate.Value.AddDays(i).Month, appointment.StartDate.Value.AddDays(i).Day), Status = appointment.Status, Subject = appointment.Subject, Type = appointment.Type }); } } } } } return result; } private void NurMeineTermineEinAusCheckBox_OnChecked(object sender, RoutedEventArgs e) { if(sender is CheckBox checkBox && CheckBoxConverter != null && BeWoApp.LoggedOnEmployee != null) { var isChecked = checkBox.IsChecked ?? false; if(isChecked) { ViewModel.SelectedEmployees.Clear(); ViewModel.SelectedEmployees.Add(LoggedOnCompactEmployee); } else { ViewModel.SelectedEmployees.Remove(LoggedOnCompactEmployee); } ReloadViewModel(true); } } // Ändert die Hintergrundfarbe der TabItems private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { var tabControl = (TabControl) sender; var selectedItem = (TabItem) tabControl.SelectedItem; var mitarbeiterPinsel = new LinearGradientBrush(new GradientStopCollection { new GradientStop(Color.FromRgb(69, 153, 59), 0), new GradientStop(Color.FromRgb(32, 92, 25), 1) }, new Point(0.5, 0), new Point(0.5, 1)); var klientenPinsel = new LinearGradientBrush(new GradientStopCollection { new GradientStop(Color.FromRgb(59, 119, 153), 0), new GradientStop(Color.FromRgb(25, 72, 92), 1) }, new Point(0.5, 0), new Point(0.5, 1)); var ressourcenPinsel = new LinearGradientBrush(new GradientStopCollection { new GradientStop(Color.FromRgb(4, 180, 208), 0), new GradientStop(Color.FromRgb(3, 129, 149), 1) }, new Point(0.5, 0), new Point(0.5, 1)); var header = selectedItem.Header.ToString(); if(header == Translator.Translate("Mitarbeiter")) { tabControl.Background = mitarbeiterPinsel; tabControl.BorderBrush = mitarbeiterPinsel; } else if(header == Translator.Translate("Klienten")) { tabControl.Background = klientenPinsel; tabControl.BorderBrush = klientenPinsel; } else { tabControl.Background = ressourcenPinsel; tabControl.BorderBrush = ressourcenPinsel; } } #region Mitarbeitersuche private void EmployeeSearchToggleButton_OnCheckedUnchecked(object sender, RoutedEventArgs e) { if(sender is ToggleButton toggleButton) { if(toggleButton.IsChecked ?? false) { MitarbeiterSuchGrid.Visibility = Visibility.Visible; MitarbeiterSuchTextBox.Focus(); } else { MitarbeiterSuchGrid.Visibility = Visibility.Collapsed; MitarbeiterSuchTextBox.Clear(); } } } private void TextBoxEmployees_OnTextChanged(object sender, TextChangedEventArgs e) { if(sender is TextBox textBox) { ViewModel.FilterEmployees(textBox.Text); } } # endregion Mitarbeitersuche #region Klientensuche private void CustomerSearchToggleButton_OnCheckedUnchecked(object sender, RoutedEventArgs e) { if(sender is ToggleButton toggleButton) { if(toggleButton.IsChecked ?? false) { KlientenSuchGrid.Visibility = Visibility.Visible; KlientenSuchTextBox.Focus(); } else { KlientenSuchGrid.Visibility = Visibility.Collapsed; KlientenSuchTextBox.Clear(); } } } private void TextBoxCustomers_OnTextChanged(object sender, TextChangedEventArgs e) { if(sender is TextBox textBox) { ViewModel.FilterCustomers(textBox.Text); } } #endregion Klientensuche private void AllEmployeesCheckBox_OnClick(object sender, RoutedEventArgs e) { if(sender is CheckBox checkBox) { if(checkBox.IsChecked ?? false) { ViewModel.SelectAllEmployees(); } else { ViewModel.DeselectAllEmployees(); ViewModel.AllEmployeesCheckBoxIsChecked = false; } if(ViewModel.SelectedEmployees.Count > 1 || ViewModel.SelectedEmployees.Count == 1 && ViewModel.SelectedEmployees.Any(f => f.EmployeeOid.Equals(LoggedOnCompactEmployee.EmployeeOid))) { ViewModel.OnlyMyCustomersCheckBoxIsChecked = false; } ViewModel.UpdateSelectedItems(); ReloadViewModel(true); } } private void ListItem_OnClick(object sender, RoutedEventArgs e) { if(!(sender is CheckBox checkBox)) { return; } var isChecked = checkBox.IsChecked ?? false; var item = checkBox.Tag; switch(item) { case CompactCustomerDC customer: if(!isChecked) { ViewModel.SelectedCustomers.Remove(customer); } else { ViewModel.SelectedCustomers.AddIfNotIn(customer); } SelectAllResourcesCheckBox.IsChecked = ViewModel.SelectedResources.Count == ViewModel.AllResources.Count; ViewModel.UpdateCustomerSelection(); break; } ViewModel.UpdateSelectedItems(); ReloadViewModel(true); } private void EmployeeInformationButton_OnClick(object sender, RoutedEventArgs e) { if(!(sender is Button button) || !(button.DataContext is CompactEmployeeDC employee)) { return; } var control = new InformationView(); ServiceFacade.DoOperationsServiceAsync(s => s.GetXAMLInformationStringForEmployee(employee.EmployeeOid), xaml => { this.Dispatch(() => { control.SetXaml(xaml); var beWoWindow = new BeWoWindow(); control.ButtonCloseClicked += () => beWoWindow.Close(); beWoWindow.Height = 200; beWoWindow.Width = 400; beWoWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner; beWoWindow.GroupBoxContent = control; beWoWindow.Owner = BeWoApp.CurrentBeWo.MainWindow; beWoWindow.rootGroupBox.Header = "Infos zu " + employee.FirstName + " " + employee.LastName; beWoWindow.ShowDialog(); }); }); } private void AllCustomersCheckBox_Checked(object sender, RoutedEventArgs e) { if(!(sender is CheckBox checkBox)) { return; } if(checkBox.IsChecked ?? false) { ViewModel.SelectedCustomers.AddRangeIfElementsNotIn(ViewModel.AllCustomers); } else { ViewModel.SelectedCustomers.Clear(); ViewModel.AllCustomersCheckBoxIsChecked = false; } ViewModel.UpdateSelectedItems(); ReloadViewModel(true); } private void OnlyMyCustomersCheckBox_Click(object sender, RoutedEventArgs e) { if(!(sender is CheckBox checkBox)) { return; } if(checkBox.IsChecked ?? false) { ViewModel.SelectedCustomers.Clear(); ViewModel.SelectedCustomers.AddRangeIfElementsNotIn(ViewModel.OwnCustomers); } else { ViewModel.SelectedCustomers.RemoveRange(ViewModel.OwnCustomers); } ViewModel.UpdateSelectedItems(); ReloadViewModel(true); } private void CustomerInformationButton_OnClick(object sender, RoutedEventArgs e) { if(!(sender is Button button) || !(button.DataContext is CompactCustomerDC customer)) { return; } var control = new InformationView(); ServiceFacade.DoOperationsServiceAsync(s => s.GetXAMLInformationStringForScheduler(customer.CustomerOid), xaml => { this.Dispatch(() => { control.SetXaml(xaml); var beWoWindow = new BeWoWindow(); control.ButtonCloseClicked += () => beWoWindow.Close(); beWoWindow.Height = 200; beWoWindow.Width = 600; beWoWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner; beWoWindow.GroupBoxContent = control; beWoWindow.Owner = BeWoApp.CurrentBeWo.MainWindow; beWoWindow.rootGroupBox.Header = "Infos zu " + customer.FirstName + " " + customer.LastName; beWoWindow.ShowDialog(); }); }); } private void AllResourcesCheckBox_OnClick(object sender, RoutedEventArgs e) { if(!(sender is CheckBox checkBox) || CheckBoxConverter is null) { return; } if(checkBox.IsChecked ?? false) { ViewModel.SelectAllResources(); } else { ViewModel.DeselectAllResources(); ViewModel.AllResourcesCheckBoxChecked = false; } ViewModel.UpdateSelectedItems(); ReloadViewModel(true); } private void AuswahlAufhebenClick(object sender, RoutedEventArgs e) { ViewModel.DeselectAllResources(); ViewModel.DeselectAllEmployees(); ViewModel.SelectedCustomers.Clear(); if(ViewModel.SelectedEmployees.Count > 1 || ViewModel.SelectedEmployees.Count == 1 && ViewModel.SelectedEmployees.Any(f => f.EmployeeOid.Equals(LoggedOnCompactEmployee.EmployeeOid))) { ViewModel.OnlyMyCustomersCheckBoxIsChecked = false; } AlleMitarbeiterCB.IsChecked = false; SelectAllCustomersCheckBox.IsChecked = false; ViewModel.AllEmployeesCheckBoxIsChecked = false; ViewModel.AllCustomersCheckBoxIsChecked = false; ViewModel.AllResourcesCheckBoxChecked = false; ViewModel.OnlyMyCustomersCheckBoxIsChecked = false; ViewModel.UpdateSelectedItems(); ReloadViewModel(true); } private void LeftExpanderClick(object sender, RoutedEventArgs e) { if(sender is ToggleButton toggleButton) { var isChecked = toggleButton.IsChecked ?? false; var visibility = ZeigeNurMeineTermineCheckBox.Visibility = isChecked ? Visibility.Collapsed : Visibility.Visible; AuswahlGrid.Visibility = visibility; } } private void RightExpanderClick(object sender, RoutedEventArgs e) { if(sender is ToggleButton toggleButton) { var isChecked = toggleButton.IsChecked ?? false; var visibility = isChecked ? Visibility.Collapsed : Visibility.Visible; DateNavigator.Visibility = visibility; } } // TODO: Alle Klienten auswählen fertig machen! private void RemoveElementButton_OnClick(object sender, RoutedEventArgs e) { if(sender is Button button) { if(button.Tag is IDataContract iDataContract) { switch(iDataContract) { case CompactEmployeeDC employee: ViewModel.DeselectEmployee(employee.EmployeeOid); if(ViewModel.Employees.Count != ViewModel.SelectedEmployees.Count) { AlleMitarbeiterCB.IsChecked = false; } ViewModel.ZeigeNurMeineTermine = ViewModel.SelectedEmployees.Count == 1 && ViewModel.SelectedEmployees.First().Equals(BeWoApp.CompactLoggedOnEmployee); break; case CompactCustomerDC customer: ViewModel.SelectedCustomers.Remove(customer); if(ViewModel.SelectedCustomers.Count != ViewModel.AllCustomers.Count) { SelectAllCustomersCheckBox.IsChecked = false; } break; case ResourceDC resource: if(resource.ResourceOid.HasValue) { ViewModel.DeselectResource(resource.ResourceOid.Value); SelectAllResourcesCheckBox.IsChecked = ViewModel.SelectedResources.Count == ViewModel.AllResources.Count; } break; } } ViewModel.UpdateSelectedItems(); ReloadViewModel(true); } } private void DateNavigator_OnSelectedDatesChanged(object sender, EventArgs e) { var navigator = (DevExpress.Xpf.Editors.DateNavigator.DateNavigator) sender; var selectedDates = navigator.SelectedDates; var isSelectedDateFetched = _LastFetchedInterval.ContainsEveryDateFromList(selectedDates); if(!isSelectedDateFetched && !(_LastFetchedInterval.Start.Equals(new DateTime(1, 1, 1, 0, 0, 0)) && _LastFetchedInterval.End.Equals(new DateTime(1, 1, 1, 0, 30, 0)))) { ReloadViewModel(); } } private AppointmentWindowVM _AppointmentWindowVM; private AppointmentEditView _AppointmentEditView; private void SchedulerControl_OnAppointmentWindowShowing(object sender, AppointmentWindowShowingEventArgs e) { if(!(e.Appointment.CustomFields["VMForCustomField"] is SchedulingAppointmentVM viewModel)) { return; } var appointmentItem = e.Appointment; var appointmentType = Utils.GetAppointmentTypeFromViewModel(viewModel.EventType); if(appointmentType == AppointmentType.Pattern && e.Appointment.Type == AppointmentType.Occurrence) { var index = e.Appointment.RecurrenceIndex; var patternAppointment = SchedulerControl.GetAppointmentItemById(viewModel.DataContract?.SchedulerAppointmentOid); if(patternAppointment != null) { var exception = SchedulerControl.GetOccurrenceOrException(patternAppointment, index); appointmentItem = exception; viewModel = CreateChangedOccurrence(appointmentItem); } else { return; } } // Nur, wenn es sich nicht um einen Termin aus dem HomeView handelt // TODO: trifft ebenfalls zu, wenn es sich um eine neuerstellte Ausnahme handelt if(viewModel.IsNew && !_IsComingFromHomeDragPanel && viewModel.EventType != (int) AppointmentType.ChangedOccurrence) { viewModel.CustomerList = ViewModel.SelectedCustomers; viewModel.ResourceList = ViewModel.SelectedResources; viewModel.EmployeeList = new ObservableCollection(); foreach(var employee in ViewModel.SelectedEmployees) { viewModel.EmployeeList.Add(new Employee2SchedulerAppointmentDC { Employee = employee }); } } _IsComingFromHomeDragPanel = false; var teamsRelatedCustomerOids = new List(); ServiceFacade.DoEmployeeServiceAsync(s => teamsRelatedCustomerOids = s.LoadTeamsRelatedCustomerOids(BeWoApp.CompactLoggedOnEmployee.EmployeeOid)); _AppointmentWindowVM = new AppointmentWindowVM(appointmentItem, (SchedulerControl) sender, ViewModel.AllEmployees, ViewModel.AllCustomers, ViewModel.Categories2Resources, viewModel.Originator ?? BeWoApp.CompactLoggedOnEmployee, teamsRelatedCustomerOids, viewModel); e.Window.DataContext = _AppointmentWindowVM; e.Cancel = true; e.Window.Closed += (o, args) => { this.Dispatch(() => { _AppointmentWindowVM = null; _AppointmentEditView = null; ReloadViewModel(true); }); }; _AppointmentEditView = (AppointmentEditView) e.Window; e.Window.ShowDialog(); } #region Ansicht ändern private void DayViewButton_OnClick(object sender, RoutedEventArgs e) { SetViewType(ViewType.DayView); } private void WorkWeekButton_OnClick(object sender, RoutedEventArgs e) { SetViewType(ViewType.WorkWeekView); } private void WeekButton_OnClick(object sender, RoutedEventArgs e) { SetViewType(ViewType.WeekView); } private void MonthButton_OnClick(object sender, RoutedEventArgs e) { SetViewType(ViewType.MonthView); } private void TimelineButton_OnClick(object sender, RoutedEventArgs e) { SetViewType(ViewType.TimelineView); } private void SetViewType(ViewType viewType) { SchedulerControl.ActiveViewType = viewType; _CurrentViewType = SchedulerControl.ActiveViewType ?? ViewType.WorkWeekView; if(SchedulerControl.ActiveView is DevExpress.Xpf.Scheduling.DayView activeView) { activeView.DayCount = BeWoApp.AppSettings.SchedulerDayViewDayCount; SpinEditDayViewDayCount.Value = activeView.DayCount; } if(SchedulerControl.ActiveView is DevExpress.Xpf.Scheduling.TimelineView timelineView) { timelineView.IntervalCount = BeWoApp.AppSettings.SchedulerTimelineViewDayCount; SpinEditTimelineViewDayCount.Value = timelineView.IntervalCount; } BeWoApp.AppSettings.SchedulingViewType = _CurrentViewType; BeWoApp.SaveAppSettings(); } #endregion Ansicht ändern #region Termine endgültig löschen private void DeleteAppointmentsForGood_Click(object sender, RoutedEventArgs e) { var employeesOnly = MitarbeiterEbenenCheckBox.IsChecked ?? false; var customersOnly = KlientenEbenenCheckBox.IsChecked ?? false; var resourcesOnly = RessourcenEbenenCheckBox.IsChecked ?? false; var onlyPrivateAppointments = ShowPrivateAppointmentsCheckBox.IsChecked ?? false; var showOnlyMyAppointments = ViewModel.ZeigeNurMeineTermine; var loggedOnUserHasRightToSeeAllAppointments = BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderKliententermineAlleAnsehen) || BeWoApp.LoggedOnUser.HasRight(UserRightType.ViewAll); var loggedOnEmployeeOid = BeWoApp.CompactLoggedOnEmployee.EmployeeOid; var date = DeleteForGoodIntervalEndDateEdit.DateTime; var userRights = new Dictionary { { UserRightType.KalenderKliententermineAendern, BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderKliententermineAendern) }, { UserRightType.KalenderMitarbeitertermineAendern, BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderMitarbeitertermineAendern) }, { UserRightType.KalenderRessourcentermineAendern, BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderRessourcentermineAendern) }, { UserRightType.KalenderRessourcentermineAndererAendern, BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderRessourcentermineAndererAendern) } }; var dialog = new MessageDialog(() => { ServiceFacade.DoOperationsServiceAsync(s => s.DeleteAppointmentsInInterval( loggedOnUserHasRightToSeeAllAppointments, loggedOnEmployeeOid, date, ViewModel.SelectedEmployees.Select(employee => employee.EmployeeOid).ToList(), ViewModel.SelectedCustomers.Select(customer => customer.CustomerOid).ToList(), ViewModel.SelectedResources.Where(resource => resource.ResourceOid.HasValue).Select(resource => resource.ResourceOid.Value).ToList(), employeesOnly, customersOnly, resourcesOnly, onlyPrivateAppointments, showOnlyMyAppointments, userRights), () => { this.Dispatch(() => { DeleteAppointmentsPopup.IsOpen = false; ReloadViewModel(true); }); }); }); ServiceFacade.DoOperationsServiceAsync( s => s.GetMessageFromServerForDeletingAppointments( loggedOnUserHasRightToSeeAllAppointments, loggedOnEmployeeOid, date, ViewModel.SelectedEmployees.Select(employee => employee.EmployeeOid).ToList(), ViewModel.SelectedCustomers.Select(customer => customer.CustomerOid).ToList(), ViewModel.SelectedResources.Where(resource => resource.ResourceOid.HasValue).Select(resource => resource.ResourceOid.Value).ToList(), employeesOnly, customersOnly, resourcesOnly, onlyPrivateAppointments, showOnlyMyAppointments, userRights), xaml => { this.Dispatch(() => { dialog.SetXaml(xaml); dialog.ShowDialog(); }); }); } private void AbortDeletingAppointments_Click(object sender, RoutedEventArgs e) { DeleteAppointmentsPopup.IsOpen = false; } #endregion Termine endgültig löschen private void SchedulerControl_CustomAllowAppointmentCreate(object sender, AppointmentItemOperationEventArgs e) { if(e.Appointment is null) { return; } CanAppointmentBeEdited(e.Appointment, allow => { e.Allow = allow; }); } private void SchedulerControl_CustomAllowAppointmentEdit(object sender, AppointmentItemOperationEventArgs e) { if(e.Appointment is null) { return; } CanAppointmentBeEdited(e.Appointment, allow => { e.Allow = allow; }); } private void CanAppointmentBeEdited(AppointmentItem appointment, Action callback) { if(appointment is null) { callback?.Invoke(false); return; } var viewModel = appointment.CustomFields["VMForCustomField"] as SchedulingAppointmentVM; var customers = viewModel?.CustomerList ?? new List(); var employees = viewModel?.EmployeeList ?? new ObservableCollection(); var resources = viewModel?.ResourceList; var originator = viewModel?.Originator; var canBeEdited = viewModel?.CanBeEdited ?? false; if(canBeEdited is false) { callback?.Invoke(false); return; } Cache.GetInstance().GetTeamRelatedCustomerOidsForEmployee(BeWoApp.CompactLoggedOnEmployee.EmployeeOid, false, teamMemberCustomerOids => { this.Dispatch(() => { var result = BS.Shared.Core.Utils.CheckSchedulerRights(customers, resources, employees.ToList(), originator, true, SchedulerRightsCheckType.Create, BeWoApp.LoggedOnUser, teamMemberCustomerOids); callback?.Invoke(result); }); }); } private void SchedulerControl_CustomAllowAppointmentDrag(object sender, AppointmentItemOperationEventArgs e) { if(e.Appointment is null) { return; } CanAppointmentBeEdited(e.Appointment, allow => { e.Allow = allow; }); } private void SchedulerControl_CustomAllowAppointmentResize(object sender, AppointmentItemOperationEventArgs e) { if(e.Appointment is null) { return; } CanAppointmentBeEdited(e.Appointment, allow => { e.Allow = allow; }); } private void SchedulerControl_CustomAllowAppointmentDragBetweenResources(object sender, AppointmentItemOperationEventArgs e) { if(e.Appointment is null) { return; } CanAppointmentBeEdited(e.Appointment, allow => { e.Allow = allow; }); } private void SchedulerControl_OnEditOccurrenceWindowShowing(object sender, EditOccurrenceWindowShowingEventArgs e) { e.Cancel = true; e.ViewModel.EditSeries = false; } private void SchedulerControl_OnPopupMenuShowing(object sender, PopupMenuShowingEventArgs e) { if(e.MenuType == ContextMenuType.AppointmentContextMenu) { var menu = (PopupMenu) e.Menu; for(var i = 0; i < menu.Items.Count; i++) { if(menu.Items[i] is BarItem menuItem && !(menuItem.Content is null)) { var content = menuItem.Content.ToString(); if(content.Equals("Terminserie wiederherstellen")) { menuItem.ItemClick -= RestoreChangedOccurrence; menuItem.ItemClick += RestoreChangedOccurrence; } else if(content.Equals("Zusagen") || content.Equals("Mit Vorbehalt zusagen") || content.Equals("Absagen")) { menuItem.IsVisible = GetParticipationMenuItemIsVisibleValue(SchedulerControl.SelectedAppointments); } else if(content.Equals("Agenda View")) { menuItem.IsVisible = false; } else if(content.Equals("Löschen")) { menuItem.IsVisible = GetDeleteContextMenuItemVisibility(SchedulerControl.SelectedAppointments.ToList()); } } else if(menu.Items[i] is BarItemSeparator separator) { if(separator.Name?.Contains("ZusagenStackSeperator") ?? false) { separator.IsVisible = GetParticipationMenuItemIsVisibleValue(SchedulerControl.SelectedAppointments); } } } } else if(e.MenuType == ContextMenuType.CellContextMenu) { var menu = (PopupMenu) e.Menu; foreach(var item in menu.Items) { if(!(item is BarItem menuItem) || menuItem.Content is null) { continue; } var content = menuItem.Content.ToString(); if(!content.Equals("Ansichtwechsel")) { continue; } var barSubItem = (BarSubItem) item; foreach(var item2 in barSubItem.Items) { if(item2 is BarCheckItem barCheckItem && (barCheckItem.Content?.Equals("Agenda View") ?? false)) { barCheckItem.IsVisible = false; } } } } } private static bool GetParticipationMenuItemIsVisibleValue(IEnumerable selectedAppointments) { return selectedAppointments.Any(appointment => appointment.CustomFields["VMForCustomField"] is SchedulingAppointmentVM vm && vm.EmployeeList.Any(a => a.Employee.Equals(BeWoApp.CompactLoggedOnEmployee))); } private static bool GetDeleteContextMenuItemVisibility(List selectedAppointments) { var hasRightToDelete = false; var dataContracts = new List(); foreach(var appointmentItem in selectedAppointments) { if((appointmentItem.Type == AppointmentType.Normal || appointmentItem.Type == AppointmentType.ChangedOccurrence) && appointmentItem.CustomFields["VMForCustomField"] is SchedulingAppointmentVM viewModel) { dataContracts.Add(viewModel.CommitToDataContract()); } else { dataContracts.Add(new SchedulingAppointmentVM(appointmentItem).CommitToDataContract()); } } // ToDo: EINKOMMENTIEREN! //ServiceFacade.DoResourceServiceSync(s => hasRightToDelete = s.CheckSchedulerRightsForAppointmentsToEdit(dataContracts, BeWoApp.LoggedOnUser).Any()); return hasRightToDelete; } private void RestoreChangedOccurrence(object sender, ItemClickEventArgs e) { var selectedAppointments = SchedulerControl.SelectedAppointments; if(!(sender is BarButtonItem barButtonItem) || selectedAppointments.Count != 1) { return; } var selectedAppointment = selectedAppointments.FirstOrDefault(); if(selectedAppointment is null || selectedAppointment.Type != AppointmentType.ChangedOccurrence || !(selectedAppointment.CustomFields["VMForCustomField"] is SchedulingAppointmentVM vm) || vm.EventType != (int) AppointmentType.ChangedOccurrence) { return; } var pattern = SchedulerControl.GetPattern(selectedAppointment); if(!(pattern.CustomFields["VMForCustomField"] is SchedulingAppointmentVM patternVM)) { return; } var start = patternVM.Start; var end = patternVM.End; var employees = patternVM.EmployeeList.Select(e2s => e2s.Employee.EmployeeOid).ToList(); var customers = patternVM.CustomerList.Select(s => s.CustomerOid).ToList(); var resources = patternVM.ResourceList.Where(resource => resource.ResourceOid.HasValue).Select(s => s.ResourceOid.Value).ToList(); var originator = patternVM.Originator.EmployeeOid; var recurrenceId = selectedAppointment.RecurrenceInfoId?.ToString(); var recurrenceIndex = selectedAppointment.RecurrenceIndex; var dataContract = vm.CommitToDataContract(); ServiceFacade.DoResourceServiceAsync(s => s.OverlappingAppointmentsExist(start, end, employees, customers, resources, originator, dataContract.SchedulerAppointmentOid, recurrenceId, recurrenceIndex), isOverlapping => { if(isOverlapping) { if(MessageBox.Show("Dieser Termin überschneidet sich mit einem anderen, bereits existierenden Termin.", "Überschneidung", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes) { DeleteAppointment(vm.CommitToDataContract()); } else { this.Dispatch(() => { ReloadViewModel(true); }); } } else { DeleteAppointment(vm.CommitToDataContract()); } }); } private void EmployeeAvailabilityBarItem_OnItemClick(object sender, ItemClickEventArgs e) { var interval = SchedulerControl.SelectedInterval; ServiceFacade.DoEmployeeServiceAsync(s1 => s1.GetAllActiveEmployeesCompact(), dcs => ServiceFacade.DoReportServiceAsync( s2 => s2.GetMitarbeiterverfuegbarkeiten(dcs, interval.Start, interval.End), s3 => this.Dispatch(() => { var employeeAvailabilityView = new MitarbeiterverfuegbarkeitsinfoView(s3, interval.Start, interval.End); if(employeeAvailabilityView.CommandBindings.Count == 0) { employeeAvailabilityView.CommandBindings.Add( new CommandBinding( ApplicationCommands.Close, (s, e2) => { if(!employeeAvailabilityView.DoSaveCheck()) { return; } PopupContent.Visibility = Visibility.Hidden; PopupContent.Child = null; })); } PopupContent.Child = employeeAvailabilityView; PopupContent.Height = 400; PopupContent.Width = 450; PopupContent.Visibility = Visibility.Visible; }))); } private void SchedulerControl_OnRecurrenceWindowShowing(object sender, RecurrenceWindowShowingEventArgs e) { e.Window.Closed += (sender2, e2) => { if(!(sender2 is AppointmentRecurrenceEditView recurrenceEditView) || !(e.Appointment.CustomFields["VMForCustomField"] is SchedulingAppointmentVM vm)) { return; } if(recurrenceEditView.IsCancelled) { vm.RecurrenceInfo = _AppointmentWindowVM.OriginalRecurrenceInfo; _AppointmentEditView?.SetRecurrenceInfo(vm.RecurrenceInfo); } else { if(!(recurrenceEditView.DataContext is RecurrenceWindowViewModel viewModel)) { return; } vm.RecurrenceInfo = viewModel.RecurrenceInfo?.ToXml(); _AppointmentEditView.SetRecurrenceInfo(vm.RecurrenceInfo); } }; } private void ResourceTreeViewCheckBox_OnChecked(object sender, RoutedEventArgs e) { ViewModel.UpdateResourceSelection(); } private void SchedulerControl_OnDropAppointment(object sender, DropAppointmentEventArgs e) { var draggedAppointments = e.DragAppointments; var dataContracts = new List(); draggedAppointments.DoForEach(app => { if(!(app.CustomFields["VMForCustomField"] is SchedulingAppointmentVM viewModel)) { return; } viewModel.Start = app.Start; viewModel.End = app.End; // Serientermin wird immer zu ChangedOccurrence, Normal bleibt Normal und DeletedOccurrence wird erst gar nicht angezeigt if(app.Type == AppointmentType.ChangedOccurrence) { if(viewModel.EventType != (int) app.Type) { viewModel = CreateChangedOccurrence(app); } } dataContracts.AddIfNotIn(viewModel.CommitToDataContract()); }); InsertOrUpdateAppointments(dataContracts); } private void SchedulerControl_OnCommitAppointmentResize(object sender, CommitAppointmentResizeEventArgs e) { var sourceAppointment = e.SourceAppointment; var resizeAppointment = e.ResizeAppointment; if(!(sourceAppointment.CustomFields["VMForCustomField"] is SchedulingAppointmentVM vm) || !BeWoApp.LoggedOnUser.UserOid.HasValue) { return; } if(vm.IsAbsenceTime) { e.Cancel = true; return; } if(sourceAppointment.Type == AppointmentType.Occurrence && resizeAppointment.Type == AppointmentType.ChangedOccurrence) { vm = CreateChangedOccurrence(resizeAppointment); } vm.End = resizeAppointment.End; InsertOrUpdateAppointments(new List { vm.CommitToDataContract() }, () => { e.Cancel = true; }); } private void ZeiterfassungButtonItem_OnItemClick(object sender, ItemClickEventArgs e) { if(SchedulerControl.SelectedAppointments.Count <= 0) { return; } var appointment = SchedulerControl.SelectedAppointments.FirstOrDefault(); if(appointment?.CustomFields["VMForCustomField"] is SchedulingAppointmentVM vm) { var employee2SchedulerAppointmentList = vm.EmployeeList;// appointment.CustomFields["EmployeeList"] as ObservableCollection ?? new ObservableCollection(); var customerList = vm.CustomerList;// appointment.CustomFields["CustomerList"] as List; var employeeList = employee2SchedulerAppointmentList.Select(employee2SchedulerAppointment => employee2SchedulerAppointment.Employee).ToList(); BeWoUtils.CreateZeiterfassung(appointment.Start, appointment.End, customerList, employeeList, appointment.Subject, appointment, () => { // Serientermin; Es wird eine Ausnahme in der Datenbank gespeichert mit der dann der Buchungseintrag verknüpft ist. if(appointment.Type == AppointmentType.Occurrence) { vm = CreateChangedOccurrence(appointment); vm.HasServiceRecordEntry = true; ServiceFacade.DoResourceServiceAsync(s => s.CheckSchedulerRightsForAppointmentsToEdit(new List { vm.CommitToDataContract() }, BeWoApp.LoggedOnUser), appointments2Insert => { // Ist maximal ein Termin var app = appointments2Insert.FirstOrDefault(); if(!(app is null)) { ServiceFacade.DoResourceServiceAsync(s2 => s2.InsertSchedulerAppointments(new List { app }), cb => { this.Dispatch(() => { ReloadViewModel(true); }); }); } else { this.Dispatch(() => { ReloadViewModel(true); }); } }); } else { vm.HasServiceRecordEntry = true; ServiceFacade.DoResourceServiceAsync(s => s.CheckSchedulerRightsForAppointmentEditing(vm.DataContract.SchedulerAppointmentOid.Value, BeWoApp.LoggedOnUser.UserOid.Value), hasRightToEdit => { if(hasRightToEdit) { ServiceFacade.DoResourceServiceAsync(s2 => s2.UpdateSchedulerAppointments(new List { vm.CommitToDataContract() }), cb => { this.Dispatch(() => { ReloadViewModel(true); }); }); } else { this.Dispatch(() => { ReloadViewModel(true); }); } }); } }); } } private void DeleteAppointmentsInIntervalButton_OnClick(object sender, RoutedEventArgs e) { DeleteAppointmentsPopup.IsOpen = true; } private void DeleteAppointment(SchedulerAppointmentDC dataContract) { if(dataContract is null || !BeWoApp.LoggedOnUser.UserOid.HasValue || dataContract.SchedulerAppointmentOid is null || dataContract.NewSchedulerAppointmentVersion is null) { return; } var userOid = BeWoApp.LoggedOnUser.UserOid.Value; var appointmentOid = dataContract.SchedulerAppointmentOid.Value; var appointmentVersion = dataContract.NewSchedulerAppointmentVersion.Value; ServiceFacade.DoResourceServiceAsync(s => s.CheckSchedulerRightsForAppointmentEditing(appointmentOid, userOid), hasRightToEdit => { if(hasRightToEdit) { ServiceFacade.DoResourceServiceAsync(s2 => s2.DeleteSchedulerAppointments(new Dictionary { { appointmentOid, appointmentVersion } }), () => { this.Dispatch(() => { ReloadViewModel(true); }); }); } }); } private void InsertOrUpdateAppointments(List dataContracts, Action noRightToEditCallback = null) { var stopwatch = new Stopwatch(); stopwatch.Start(); ServiceFacade.DoResourceServiceAsync(s => s.CheckSchedulerRightsForAppointmentsToEdit(dataContracts, BeWoApp.LoggedOnUser), appointments => { if(appointments.Any()) { ServiceFacade.DoResourceServiceAsync(s3 => s3.OverlappingAppointmentsExistForMultiple(dataContracts), app2Overlapping => { this.Dispatch(() => { stopwatch.Stop(); BeWoApp.LogMessage($"Es hat {stopwatch.ElapsedMilliseconds}ms gedauert, um {dataContracts.Count} Termin{(dataContracts.Count > 1 ? "e" : "")} auf Überschneidungen zu prüfen"); }); var overlappingAppointmentCount = app2Overlapping.Count(c => c.Value); if(overlappingAppointmentCount > 0) { this.Dispatch(() => { var message = "Dieser Termin überschneidet sich mit einem anderen, bereits existierenden Termin."; if(overlappingAppointmentCount > 1) { message = $"{overlappingAppointmentCount} Termine überschneiden sich mit anderen, bereits existierenden Terminen."; } message += "\r\n\r\nMöchten Sie trotzdem speichern?"; if(MessageBox.Show(message, "Überschneidung", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes) { ServiceFacade.DoResourceServiceAsync(s2 => s2.InsertOrUpdateSchedulerAppointments(app2Overlapping.Select(kvp => kvp.Key).ToList()), () => { this.Dispatch(() => { ReloadViewModel(true); }); }); } else { ServiceFacade.DoResourceServiceAsync(s2 => s2.InsertOrUpdateSchedulerAppointments(app2Overlapping.Where(w => w.Value == false).Select(kvp => kvp.Key).ToList()), () => { this.Dispatch(() => { ReloadViewModel(true); }); }); } }); } else { ServiceFacade.DoResourceServiceAsync(s2 => s2.InsertOrUpdateSchedulerAppointments(app2Overlapping.Select(kvp => kvp.Key).ToList()), () => { this.Dispatch(() => { ReloadViewModel(true); }); }); } }); } else { this.Dispatch(() => { MessageBox.Show("Sie verfügen nicht über die benötigten Rechte, um diesen Termin zu speichern!", "Speichern nicht möglich", MessageBoxButton.OK, MessageBoxImage.Error); ReloadViewModel(true); noRightToEditCallback?.Invoke(); }); } }); } private void DeactivateAppointments(List appointments2Deactivate) { ServiceFacade.DoResourceServiceAsync(s => s.CheckSchedulerRightsForAppointmentsToEdit(appointments2Deactivate, BeWoApp.LoggedOnUser), appointments => { if(appointments.Any()) { ServiceFacade.DoResourceServiceAsync(s2 => s2.DeleteOrUpdateSchedulerAppointments(appointments), () => { this.Dispatch(() => { ReloadViewModel(true); }); }); } else { this.Dispatch(() => { ReloadViewModel(true); }); } }); } private void ConfirmParticipationBarButtonItem_OnClick(object sender, ItemClickEventArgs e) { SetParticipationAnswer(ParticipationAnswer.Zusage, SchedulerControl.SelectedAppointments.ToList()); } private void AcceptWithReservationParticipationBarButtonItem_OnClick(object sender, ItemClickEventArgs e) { SetParticipationAnswer(ParticipationAnswer.Vorbehalt, SchedulerControl.SelectedAppointments.ToList()); } private void DeclineParticipationBarButtonItem_OnClick(object sender, ItemClickEventArgs e) { SetParticipationAnswer(ParticipationAnswer.Absage, SchedulerControl.SelectedAppointments.ToList()); } private void SetParticipationAnswer(ParticipationAnswer participationAnswer, List appointmentItems) { if(appointmentItems is null) { return; } var applyForAllOccurrences = false; bool? createChangedOccurrencesOrAbort = false; var dataContracts = new List(); var str = string.Empty; switch(participationAnswer) { case ParticipationAnswer.Zusage: str = "zusagen"; break; case ParticipationAnswer.Vorbehalt: str = "mit Vorbehalt zusagen"; break; case ParticipationAnswer.Absage: str = "absagen"; break; } var isCheckBoxVisible = appointmentItems.Count(s => s.Type == AppointmentType.Occurrence) > 1; foreach(var appointment in appointmentItems) { var vm = appointment.CustomFields["VMForCustomField"] as SchedulingAppointmentVM; if(appointment.Type == AppointmentType.Occurrence && applyForAllOccurrences == false) { var window = new OccurrenceParticipationConfirmationView(appointment.Subject, str, isCheckBoxVisible, appointment.Start, appointment.End) { Owner = BeWoApp.CurrentBeWo.MainWindow }; window.ShowDialog(); createChangedOccurrencesOrAbort = window.ShouldChangeSeries; if(createChangedOccurrencesOrAbort is null) { break; } applyForAllOccurrences = window.ApplyForAllOccurrences; } if(createChangedOccurrencesOrAbort == true) { vm = new SchedulingAppointmentVM(appointment, $""); } if(!(vm is null)) { var employeeList = vm.EmployeeList; foreach(var employee2SchedulerAppointment in employeeList) { if(!employee2SchedulerAppointment.Employee.EmployeeOid.Equals(BeWoApp.LoggedOnEmployeeOid)) { continue; } employee2SchedulerAppointment.ParticipationAnswer = participationAnswer; employee2SchedulerAppointment.IsPC_CheckedTs = null; } dataContracts.AddIfNotIn(vm.CommitToDataContract()); } } if(dataContracts.Any() && createChangedOccurrencesOrAbort.HasValue) { InsertOrUpdateAppointments(dataContracts); } } private void SchedulerControl_OnAppointmentRemoved(object sender, AppointmentRemovedEventArgs e) { var appointments2Deactivate = new List(); foreach(var appointmentItem in e.Appointments) { var vm = appointmentItem.CustomFields["VMForCustomField"] as SchedulingAppointmentVM; if(appointmentItem.Type == AppointmentType.DeletedOccurrence && vm?.EventType != 4) { vm = CreateChangedOccurrence(appointmentItem); vm.EventType = (int) AppointmentType.DeletedOccurrence; appointments2Deactivate.AddIfNotIn(vm.CommitToDataContract()); } else if(!(vm is null)) { appointments2Deactivate.AddIfNotIn(vm.CommitToDataContract()); } } DeactivateAppointments(appointments2Deactivate); } private void SchedulerControl_OnAppointmentAdded(object sender, AppointmentAddedEventArgs e) { var appointments2Insert = e.Appointments; var dataContracts = new List(); foreach(var appointment in appointments2Insert) { if(appointment.CustomFields["VMForCustomField"] is SchedulingAppointmentVM vm) { vm.Originator = BeWoApp.CompactLoggedOnEmployee; dataContracts.Add(vm.CommitToDataContract()); } } InsertOrUpdateAppointments(dataContracts); } private void SchedulerControl_OnPastingFromClipboard(object sender, SchedulerPastingFromClipboardEventArgs e) { var appointmentItems2Copy = e.Appointments; var dataContracts = new List(); foreach(var appointmentItem in appointmentItems2Copy) { dataContracts.AddIfNotIn(new SchedulingAppointmentVM(appointmentItem).CommitToDataContract()); } if(dataContracts.Any()) { InsertOrUpdateAppointments(dataContracts); } e.Cancel = true; } private static SchedulingAppointmentVM CreateChangedOccurrence(AppointmentItem appointmentItem) { return new SchedulingAppointmentVM(appointmentItem, $""); } private void SchedulerControl_OnAppointmentRemoving(object sender, AppointmentRemovingEventArgs e) { var message = SchedulingUtils.Utils.GetDeactivationMessageForAppointments(e.Appointments); if(MessageBox.Show(message, "BeWoPlaner", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No) { e.Cancel = true; } } private void EmployeeListViewCheckBox_OnChecked(object sender, RoutedEventArgs e) { ViewModel.UpdateEmployeeSelection2(); } private void ClearEmployeeSearchButton_OnClick(object sender, RoutedEventArgs e) { MitarbeiterSuchTextBox.Text = string.Empty; } private void ClearCustomerSearchButton_OnClick(object sender, RoutedEventArgs e) { KlientenSuchTextBox.Text = string.Empty; } } }