Files
BeWoPlaner/BeWo/Scheduling/View/AppointmentEditView.xaml.cs
Lyndon Jetten 23b8757ff5 FaC: Neues Scheduling-Modul hinzugefügt, aber noch lange nicht fertig.
ownChat: Neues TimeStamp-Objekt wird unterstützt und der Chat funktioniert wieder.
2024-06-05 14:45:33 +02:00

581 lines
23 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using BeWo.Annotations;
using BeWo.Core;
using BeWo.Scheduling.SchedulingUtils;
using BeWo.Scheduling.ViewModel;
using BeWo.ServiceProxy;
using BeWo.View;
using BeWo.View.Detail;
using BeWo.View.Search;
using BS.Shared;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;
using DevExpress.Xpf.Editors;
using DevExpress.XtraScheduler;
namespace BeWo.Scheduling.View
{
public partial class AppointmentEditView : INotifyPropertyChanged
{
private AppointmentWindowVM ViewModel => DataContext as AppointmentWindowVM;
private ObservableCollection<Employee2SchedulerAppointmentDC> _SelectedEmployees;
public ObservableCollection<Employee2SchedulerAppointmentDC> SelectedEmployees
{
get => _SelectedEmployees ?? (_SelectedEmployees = ViewModel.EmployeeList ?? new ObservableCollection<Employee2SchedulerAppointmentDC>());
set
{
if(!ICollectionExtensions.ListEquals(_SelectedEmployees, value))
{
_SelectedEmployees = value;
SelectedEmployees.CollectionChanged += SelectedEmployeesCollectionChanged;
ViewModel.EmployeeList = SelectedEmployees;
OnPropertyChanged();
}
}
}
private ObservableCollection<CompactCustomerDC> _SelectedCustomers;
public ObservableCollection<CompactCustomerDC> SelectedCustomers
{
get => _SelectedCustomers ?? (_SelectedCustomers = new ObservableCollection<CompactCustomerDC>(ViewModel?.CustomerList ?? new List<CompactCustomerDC>()));
set
{
if(!ICollectionExtensions.ListEquals(_SelectedCustomers, value))
{
_SelectedCustomers = value;
SelectedCustomers.CollectionChanged += SelectedCustomersCollectionChanged;
ViewModel.CustomerList = SelectedCustomers.ToList();
OnPropertyChanged();
}
}
}
private ObservableCollection<CompactSupportConceptDC> _SelectedSupportConcepts;
public ObservableCollection<CompactSupportConceptDC> SelectedSupportConcepts
{
get => _SelectedSupportConcepts ?? (_SelectedSupportConcepts = new ObservableCollection<CompactSupportConceptDC>(ViewModel?.SupportConceptList ?? new ObservableCollection<CompactSupportConceptDC>()));
set
{
if(!ICollectionExtensions.ListEquals(_SelectedSupportConcepts, value))
{
_SelectedSupportConcepts = value;
SelectedSupportConcepts.CollectionChanged += SelectedSupportConceptsCollectionChanged;
ViewModel.SupportConceptList = value;
OnPropertyChanged();
}
}
}
private ObservableCollection<ResourceDC> _SelectedResources;
public ObservableCollection<ResourceDC> SelectedResources
{
get => _SelectedResources ?? (_SelectedResources = new ObservableCollection<ResourceDC>(ViewModel?.ResourceList ?? new List<ResourceDC>()));
set
{
_SelectedResources = value;
SelectedResources.CollectionChanged += SelectedResourcesCollectionChanged;
ViewModel.ResourceList = value.ToList();
OnPropertyChanged();
}
}
#region Ausgewählte Mitarbeiter, Klienten, Ressourcen
private void SelectedEmployeesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
ViewModel.ActualViewModel.EmployeeList = SelectedEmployees;
MultiEmployeeSearch.AusgewaehlteMitarbeiter = SelectedEmployees.Select(e2s => e2s.Employee).ToList();
}
private void SelectedCustomersCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
ViewModel.ActualViewModel.CustomerList = SelectedCustomers.ToList();
MultiCustomerSearch.AusgewaehlteKlienten = SelectedCustomers.ToList();
}
private void SelectedSupportConceptsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
ViewModel.ActualViewModel.SupportConceptList = SelectedSupportConcepts;
}
private void SelectedResourcesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
ViewModel.ActualViewModel.ResourceList = SelectedResources.ToList();
ResourcesTreeSearchView.AusgewaehlteRessourcen = SelectedResources.ToList();
}
#endregion
#region Visibilities
private Visibility _EmployeeSelectionVisibility;
public Visibility EmployeeSelectionVisibility
{
get => _EmployeeSelectionVisibility;
set
{
_EmployeeSelectionVisibility = value;
OnPropertyChanged();
}
}
private Visibility _CustomerSelectionVisibility;
public Visibility CustomerSelectionVisibility
{
get => _CustomerSelectionVisibility;
set
{
_CustomerSelectionVisibility = value;
OnPropertyChanged();
}
}
private Visibility _ResourceSelectionVisibility;
public Visibility ResourceSelectionVisibility
{
get => _ResourceSelectionVisibility;
set
{
_ResourceSelectionVisibility = value;
OnPropertyChanged();
}
}
private Visibility _SupportConceptVisibility;
public Visibility SupportConceptVisibility
{
get => _SupportConceptVisibility;
set
{
if(_SupportConceptVisibility != value)
{
_SupportConceptVisibility = value;
OnPropertyChanged();
}
}
}
public Visibility DeleteButtonVisibility => ViewModel.ActualViewModel.IsNew ? Visibility.Collapsed : ViewModel.IsReadyOnly ? Visibility.Collapsed : Visibility.Visible;
public Visibility OkButtonVisibility => ViewModel.IsReadyOnly ? Visibility.Collapsed : Visibility.Visible;
#endregion
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
public virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public InformationView InformationView { get; set; }
public CompactCustomerDC Customer { get; set; }
public AppointmentEditView()
{
InitializeComponent();
}
private void InitRights()
{
var hasRightToSeeEmployees = !ViewModel.ActualViewModel.IsTask && (BeWoUtils.HasRight(UserRightType.Employee_AllowViewOwnTeam) || BeWoUtils.HasRight(UserRightType.EmployeeView_View)) && BeWoUtils.HasRight(UserRightType.KalenderMitarbeitertermineAnsehen);
var hasRightToSeeCustomers = !ViewModel.ActualViewModel.IsTask && BeWoUtils.HasRight(UserRightType.CustomerView_View) || BeWoUtils.HasRight(UserRightType.Customer_ViewMyTeams) || BeWoUtils.HasRight(UserRightType.Customer_ViewMyCustomers);
var hasRightToSeeResources = !ViewModel.ActualViewModel.IsTask && BeWoUtils.HasRight(UserRightType.KalenderRessourcentermineAnlegen) || BeWoUtils.HasRight(UserRightType.KalenderRessourcentermineAendern);
var hasRightToSeeSupportConcepts = ViewModel.ActualViewModel.IsTask && (BeWoUtils.HasRight(UserRightType.SupportConceptView_View) || BeWoUtils.HasRight(UserRightType.ViewAll) || BeWoUtils.HasRight(UserRightType.SupportConcept_ViewMyTeams) || BeWoUtils.HasRight(UserRightType.SupportConcept_ViewAllSupportConcepts));
EmployeeSelectionVisibility = hasRightToSeeEmployees ? Visibility.Visible : Visibility.Collapsed;
CustomerSelectionVisibility = hasRightToSeeCustomers ? Visibility.Visible : Visibility.Collapsed;
ResourceSelectionVisibility = hasRightToSeeResources ? Visibility.Visible : Visibility.Collapsed;
SupportConceptVisibility = hasRightToSeeSupportConcepts ? Visibility.Visible : Visibility.Collapsed;
}
private void RemoveSupportConceptButton_OnClick(object sender, RoutedEventArgs e)
{
if(((Button) sender).Tag is CompactSupportConceptDC dc)
{
SelectedSupportConcepts.Remove(dc);
}
}
// KGW?
private void InformationButton_OnClick(object sender, RoutedEventArgs e)
{
if(sender is Button button && button.Tag is CompactCustomerDC customer)
{
InformationView = new InformationView();
InformationView.SetXaml(ServiceFacade.DoOperationsServiceSync(s => s.GetXAMLInformationStringForScheduler(Customer.CustomerOid)));
var beWoWindow = new BeWoWindow();
InformationView.ButtonCloseClicked += () => beWoWindow.Close();
beWoWindow.Height = 200;
beWoWindow.Width = 600;
beWoWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
beWoWindow.GroupBoxContent = InformationView;
beWoWindow.Owner = BeWoApp.CurrentBeWo.MainWindow;
beWoWindow.ShowDialog();
}
}
private void RemoveElementButton_OnClick(object sender, RoutedEventArgs e)
{
if(!ViewModel.ActualViewModel.IsTask && sender is Button button)
{
var obj = button.Tag;
switch(obj)
{
case ResourceDC res:
SelectedResources.Remove(res);
break;
case CompactCustomerDC cus:
SelectedCustomers.Remove(cus);
break;
case CompactSupportConceptDC sup:
SelectedSupportConcepts.Remove(sup);
break;
}
if(obj is Employee2SchedulerAppointmentDC e2s)
{
SelectedEmployees.Remove(e2s);
}
}
}
private void MultiEmployeeSearch_OnSelectionChanged(object sender, RoutedEventArgs e)
{
if(e.Source is MultiEmployeeSearch multiEmployeeSearch)
{
foreach(var employee in multiEmployeeSearch.SelectedEmployees.Where(employee => !SelectedEmployees.Any(e2s => e2s.Employee.Equals(employee))))
{
SelectedEmployees.Add(new Employee2SchedulerAppointmentDC { Employee = employee, ParticipationAnswer = ParticipationAnswer.Offen });
}
}
}
#region Popups
private void EmployeePopupClick(object sender, RoutedEventArgs e)
{
PopupEmployee.IsOpen = true;
PopupEmployee.Height = 300;
}
private void CustomerPopUpEditClick(object sender, RoutedEventArgs e)
{
PopupCustomer.IsOpen = true;
PopupCustomer.Height = 300;
}
private void ResourcePopUpClick(object sender, RoutedEventArgs e)
{
PopupResource.IsOpen = true;
PopupResource.Height = 300;
}
private void SupportConceptPopupClick(object sender, RoutedEventArgs e)
{
PopupSupportConcepts.IsOpen = true;
PopupSupportConcepts.Height = 300;
}
#endregion
private void CloseButton_OnClick(object sender, RoutedEventArgs e)
{
if(ViewModel.ActualViewModel.IsDirty && !ViewModel.IsReadOnly)
{
var result = MessageBox.Show("Wollen Sie die Änderungen am Termin speichern?", ViewModel.ActualViewModel.Subject, MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
if(result == MessageBoxResult.Yes)
{
var dc = ViewModel.ActualViewModel.CommitToDataContract();
var ri = dc.RecurrenceInfo;
if(ViewModel.ActualViewModel.IsNew)
{
ServiceFacade.DoResourceServiceAsync(s => s.InsertSchedulerAppointments(new List<SchedulerAppointmentDC> { dc }),
cb =>
{
this.Dispatch(Close);
}
);
}
else
{
ServiceFacade.DoResourceServiceAsync(s => s.UpdateSchedulerAppointments(new List<SchedulerAppointmentDC> { dc }),
cb =>
{
this.Dispatch(Close);
}
);
}
}
else
{
Close();
}
}
else
{
Close();
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
if(ViewModel is null)
{
return;
}
InitRights();
var selectedEmployees = new ObservableCollection<CompactEmployeeDC>();
foreach(var e2s in ViewModel.EmployeeList)
{
selectedEmployees.AddIfNotIn(e2s.Employee);
}
SelectedResources.CollectionChanged += SelectedResourcesCollectionChanged;
SelectedCustomers.CollectionChanged += SelectedCustomersCollectionChanged;
SelectedEmployees.CollectionChanged += SelectedEmployeesCollectionChanged;
SelectedSupportConcepts.CollectionChanged += SelectedSupportConceptsCollectionChanged;
MultiEmployeeSearch.Sauce = ViewModel.AllEmployees;
MultiEmployeeSearch.AusgewaehlteMitarbeiter = selectedEmployees.ToList();
MultiEmployeeSearch.CommandBindings.Add(new CommandBinding(ApplicationCommands.Close, (s, es) => this.Dispatch(() => { PopupEmployee.IsOpen = false; })));
MultiCustomerSearch.Sauce = ViewModel.AllCustomers;
MultiCustomerSearch.AusgewaehlteKlienten = SelectedCustomers.ToList();
MultiCustomerSearch.CommandBindings.Add(new CommandBinding(ApplicationCommands.Close, (s, es) => this.Dispatch(() => { PopupCustomer.IsOpen = false; })));
ResourcesTreeSearchView.Sauce = ViewModel.AllCategories2Resources.ToDictionary(k => k.Key.ResourceCategory, k => k.Value.Select(s => s.DataContract).ToList());
ResourcesTreeSearchView.AusgewaehlteRessourcen = SelectedResources.ToList();
ResourcesTreeSearchView.CommandBindings.Add(new CommandBinding(ApplicationCommands.Close, (s, es) => this.Dispatch(() => { PopupResource.IsOpen = false; })));
if(ViewModel.IsTask && !SelectedEmployees.Any(e2a => e2a.Employee.Equals(BeWoApp.CompactLoggedOnEmployee)))
{
SelectedEmployees.Add(new Employee2SchedulerAppointmentDC { Employee = BeWoApp.CompactLoggedOnEmployee });
EmployeeToggleButton.IsChecked = true;
}
if(ViewModel.RecurrenceInfo != null)
{
_IgnoreRecurrenceTypeChange = true;
}
RecurrenceTypeComboBoxEdit.SelectedItem = ViewModel.RecurrenceTypeName;
}
private bool _IgnoreRecurrenceTypeChange;
public void SetRecurrenceInfo(string originalRecurrenceInfo)
{
if(!(originalRecurrenceInfo is null))
{
ViewModel.Appointment.RecurrenceInfo?.FromXml(originalRecurrenceInfo);
ViewModel.ActualViewModel.RecurrenceInfo = originalRecurrenceInfo;
}
else
{
ViewModel.Appointment.RecurrenceInfo = null;
ViewModel.ActualViewModel.RecurrenceInfo = null;
}
RecurrenceTypeComboBoxEdit.SelectedItem = ViewModel.RecurrenceTypeName;
}
private void OkButton_Click(object sender, RoutedEventArgs e)
{
if(ViewModel.IsReadyOnly)
{
MessageBox.Show("Sie verfügen nicht über die benötigten Rechte, um diesen Termin zu speichern!", "Speichern nicht möglich", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
var dataContract = ViewModel.ActualViewModel.CommitToDataContract();
var start = dataContract.StartDate.Value;
var end = dataContract.EndDate.Value;
var employeeOids = dataContract.EmployeeList.Select(s => s.Employee.EmployeeOid).ToList();
var customerOids = dataContract.CustomerList.Select(s => s.CustomerOid).ToList();
var resrouceOids = dataContract.ResourceList.Select(s => s.ResourceOid.Value).ToList();
var originatorOid = dataContract.Originator?.EmployeeOid ?? BeWoApp.LoggedOnEmployeeOid.Value;
var recurrenceId = dataContract.RecurrenceId;
var recurrenceIndex = dataContract.RecurrenceIndex;
ServiceFacade.DoResourceServiceAsync(s => s.OverlappingAppointmentsExist(start, end, employeeOids, customerOids, resrouceOids, originatorOid, dataContract.SchedulerAppointmentOid, recurrenceId, recurrenceIndex), isOverlapping =>
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action) (() =>
{
if(isOverlapping)
{
if(MessageBox.Show("Dieser Termin überschneidet sich mit einem anderen, bereits existierenden Termin.\r\n\r\nMöchten Sie trotzdem speichern?", "Überschneidung", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
{
SaveAppointment(dataContract);
}
}
else
{
SaveAppointment(dataContract);
}
}));
});
}
private void SaveAppointment(SchedulerAppointmentDC dataContract)
{
if(dataContract.SchedulerAppointmentOid is null)
{
ServiceFacade.DoResourceServiceAsync(s => s.InsertSchedulerAppointments(new List<SchedulerAppointmentDC> { dataContract }),
() => Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action) Close));
}
else
{
ServiceFacade.DoResourceServiceAsync(s => s.UpdateSchedulerAppointments(new List<SchedulerAppointmentDC> { dataContract }),
() => Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action) Close));
}
}
private void SupportConceptsPopUpClick(object sender, RoutedEventArgs e)
{
PopupSupportConcepts.IsOpen = true;
}
private void ResourcesTreeSearchView_OnSelectionChanged(object sender, RoutedEventArgs e)
{
if(!(e.Source is ResourcesTreeSearchView resourcesTreeSearchView))
{
return;
}
var resourcesCollection = resourcesTreeSearchView.SelectedResources.ToObservableCollection();
foreach(var resource in resourcesCollection)
{
SelectedResources.AddIfNotIn(resource);
}
SelectedResources = SelectedResources.Except(SelectedResources.Where(sr => !resourcesCollection.Contains(sr)).ToList()).ToObservableCollection();
}
private void MultiCustomerSearch_OnSelectionChanged(object sender, RoutedEventArgs e)
{
if(e.Source is MultiCustomerSearchView multiCustomerSearchView)
{
SelectedCustomers = multiCustomerSearchView.SelectedCustomers.ToObservableCollection();
}
}
private void SupportConceptSelectionControl_ItemSelected(object sender, BS.Shared.Core.EventArgs<CompactSupportConceptDC> e)
{
PopupSupportConcepts.IsOpen = false;
SelectedSupportConcepts.Clear();
SelectedSupportConcepts.Add(e.Data);
OnPropertyChanged(nameof(SelectedSupportConcepts));
}
private void RecurrenceTypeComboBoxEdit_OnChanged(object sender, EditValueChangedEventArgs e)
{
if(_IgnoreRecurrenceTypeChange)
{
_IgnoreRecurrenceTypeChange = false;
return;
}
if(e.NewValue is string newValue)
{
RecurrenceType? type;
switch(newValue)
{
case "(keine)":
type = null;
break;
case "täglich":
type = RecurrenceType.Daily;
break;
case "wöchentlich":
type = RecurrenceType.Weekly;
break;
case "monatlich":
type = RecurrenceType.Monthly;
break;
case "jährlich":
type = RecurrenceType.Yearly;
break;
default:
type = null;
break;
}
if(type is null)
{
// TODO: Typ bestimmen bzw. beim Loaded-Event merken! Zum zurücksetzen (nötig?)
return;
}
ViewModel.Appointment.Type = AppointmentType.Pattern;
ViewModel.Appointment.RecurrenceInfo.Type = type.Value;
ViewModel.ActualViewModel.RecurrenceInfo = ViewModel.Appointment.RecurrenceInfo.ToXml();
ViewModel.Scheduler.ShowRecurrenceWindow(ViewModel.Appointment);
}
}
//private IRecurrenceInfo RecurrenceInfo;
private void DeleteButton_OnClick(object sender, RoutedEventArgs e)
{
if(!ViewModel.IsReadyOnly && ViewModel.Appointment.Id is long appointmentOid)
{
var message = Utils.GetDeleteMessageForAppointment(ViewModel.Appointment);
if(MessageBox.Show(message, "Termin löschen", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
{
var dc = ViewModel.ActualViewModel.CommitToDataContract();
ServiceFacade.DoResourceServiceAsync(s => s.DeleteSchedulerAppointments(new Dictionary<long, long> { { dc.SchedulerAppointmentOid.Value, dc.NewSchedulerAppointmentVersion.Value } }), () =>
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action) Close);
});
}
}
}
// TODO: Fertig machen
private void EditRecurrenceButton_OnClick(object sender, RoutedEventArgs e)
{
if(!(ViewModel.Appointment.RecurrenceInfo is null))
{
ViewModel.Scheduler.ShowRecurrenceWindow(ViewModel.Appointment);
}
}
}
}