using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Windows; using System.Xml; using BeWo.Scheduler.View; using BeWo.ServiceProxy; using BeWo.ViewModel.ListViewModel; using BS.Shared; using BS.Shared.DataContracts; using BS.Shared.DataContracts.Compact; using BS.Shared.Extensions; using DevExpress.Xpf.Scheduler; using DevExpress.XtraScheduler; using DevExpress.XtraScheduler.Native; using SchedulerControl = DevExpress.Xpf.Scheduler.SchedulerControl; using SchedulerStorage = DevExpress.Xpf.Scheduler.SchedulerStorage; namespace BeWo.Scheduler.ViewModel { public class SchedulerAppointmentListVM : AbstractDCListMapperVM, ISchedulerViewModel { private const string CF_EMPLOYEELIST = "EmployeeList"; private const string CF_CUSTOMERLIST = "CustomerList"; private const string CF_RESOURCELIST = "ResourceList"; private const string CF_ORIGINATOR = "Originator"; private const string CF_ISPRIVATE = "IsPrivate"; public bool ShouldLockOverlappingAppointmentCheck { get; set; } public SchedulerSettings GetDefaultSchedulerSettings() { var settings = new SchedulerSettings(AppointmentKind.General, AppointmentViewType.WorkWeek); return settings; } private BindingList mAppointmentList; public BindingList Appointments { get { if (mAppointmentList != null) return mAppointmentList; mAppointmentList = new BindingList(); mAppointmentList.AddingNew += mAppointmentList_AddingNew; foreach (var item in VMList) mAppointmentList.Add(item); return mAppointmentList; } } private readonly List mAllCustomers; private readonly List mAllEmployees; private readonly Dictionary> mCategories2Resources; static void mAppointmentList_AddingNew(object sender, AddingNewEventArgs e) { var dc = new SchedulerAppointmentDC { EmployeeList = new List(), CustomerList = new List(), ResourceList = new List(), //Originator = ServiceFacade.DoEmployeeServiceSync(), Status = 0 }; var neu = new SchedulerAppointmentVM(dc); e.NewObject = neu; } private Dictionary>> changedOccurencyCustomFields; public Dictionary>> ChangedOccurencyCustomFields { get; private set; } public List AllCustomers { get { return mAllCustomers; } } public List AllEmployees { get { return mAllEmployees; } } public Dictionary> Categories2Resources { get { return mCategories2Resources; } } private Appointment geoeffneterTermin; public SchedulerAppointmentListVM(List appList, List allCustomers, List allEmployees, Dictionary> lCategoriesToResources) : base(appList) { mCategories2Resources = lCategoriesToResources; mAllCustomers = allCustomers; mAllEmployees = allEmployees; InitChangedOccurrencyCustomFields(appList.Where(t => t.Type == 3).ToList()); InitViewModel(); } private void InitViewModel() { foreach (var item in VMList) { item.CustomFields.Add(CF_EMPLOYEELIST, item.EmployeeList); item.CustomFields.Add(CF_CUSTOMERLIST, item.CustomerList); item.CustomFields.Add(CF_RESOURCELIST, item.ResourceList); item.CustomFields.Add(CF_ORIGINATOR, item.Originator); item.CustomFields.Add(CF_ISPRIVATE, item.IsPrivate); item.Id = item.DataContract.SchedulerAppointmentOid; if (!item.IsPrivate || item.Originator.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid)) { continue; } item.Description = "Privater Termin"; item.Subject = String.Format("Privat ({0})", item.Originator); } } private void UpdateViewModel(IEnumerable updatedDcList) { foreach (var dc in updatedDcList) { SchedulerAppointmentVM found = null; foreach (var vm in Appointments.OfType().Where(vm => vm.DataContract.Equals(dc))) { found = vm; } if (found != null) { found.DataContract = dc; } } } public void SaveAppointments(SchedulerControl control, IEnumerable list) { var sindGleich = false; var dcList = new List(); foreach (var item in list) { var vm = item.GetSourceObject(control.GetCoreStorage()) as SchedulerAppointmentVM; if (vm == null) { continue; } UpdateSchedulerAppointment(item, vm); if (!ShouldLockOverlappingAppointmentCheck && vm.EventType != 3) { var isOverlapping = false; ServiceFacade.DoResourceServiceSync(s => isOverlapping = s.OverlappingAppointmentsExist( vm.Start, vm.End, vm.EmployeeList.Select(emp => emp.Employee.EmployeeOid).ToList(), vm.CustomerList.Select(cc => cc.CustomerOid).ToList(), vm.ResourceList.Select(r => r.ResourceOid.Value).ToList(), vm.Originator.EmployeeOid, vm.DataContract.SchedulerAppointmentOid, item.RecurrenceInfo != null ? item.RecurrenceInfo.Id.ToString() : string.Empty, item.RecurrenceIndex)); if (isOverlapping) { var erg = MessageBox.Show("Dieser Termin überschneidet sich mit einem anderen bereits existierenden Termin.\n Möchten Sie ihn wirklich speichern?", "Überschneidung", MessageBoxButton.YesNo, MessageBoxImage.Exclamation); if (erg.Equals(MessageBoxResult.No)) { return; } } } if (item.Type.Equals(AppointmentType.ChangedOccurrence) && geoeffneterTermin != null) { sindGleich = geoeffneterTermin.Equals(item); } if(!sindGleich) { dcList.Add(vm.CommitToDataContract()); } } if (dcList.Count <= 0) { return; } NewSchedulerView.IgnoreChangeEvents = true; var mostRecentAppointments = new List(); ServiceFacade.DoResourceServiceSync(sync => mostRecentAppointments = sync.UpdateSchedulerAppointments(dcList)); UpdateViewModel(mostRecentAppointments); control.ActiveView.LayoutChanged(); NewSchedulerView.IgnoreChangeEvents = false; } public void DeleteAppointments(SchedulerControl control, IEnumerable list) { var dcList = list.Select(item => item.GetSourceObject(control.GetCoreStorage())).OfType().Select(vm => vm.CommitToDataContract()).Where(dc => dc.SchedulerAppointmentOid.HasValue).ToList(); var idList = (from item in dcList where item.SchedulerAppointmentOid.HasValue select item.SchedulerAppointmentOid.Value).ToList(); NewSchedulerView.IgnoreChangeEvents = true; var mostRecentAppointments = new List(); ServiceFacade.DoResourceServiceSync(s => mostRecentAppointments = s.GetSchedulerAppointmentsById(idList)); ServiceFacade.DoResourceServiceSync(s2 => mostRecentAppointments = s2.DeactivateSchedulerAppointmentsForSync(mostRecentAppointments.ToDictionary(dc => dc.SchedulerAppointmentOid != null ? dc.SchedulerAppointmentOid.Value : 0, dc => dc.NewSchedulerAppointmentVersion.HasValue ? dc.NewSchedulerAppointmentVersion.Value : 0))); UpdateViewModel(mostRecentAppointments); control.ActiveView.LayoutChanged(); NewSchedulerView.IgnoreChangeEvents = false; } public void InsertAppointments(SchedulerControl control, IEnumerable list) { var dcList = new List(); foreach (var item in list) { var vm = item.GetSourceObject(control.GetCoreStorage()) as SchedulerAppointmentVM; if (vm == null) { continue; } UpdateSchedulerAppointment(item, vm); if (!ShouldLockOverlappingAppointmentCheck) { var isOverlapping = false; ServiceFacade.DoResourceServiceSync(s => isOverlapping = s.OverlappingAppointmentsExist( vm.Start, vm.End, vm.EmployeeList.Select(emp => emp.Employee.EmployeeOid).ToList(), vm.CustomerList.Select(cc => cc.CustomerOid).ToList(), vm.ResourceList.Select(r => r.ResourceOid.Value).ToList(), vm.Originator.EmployeeOid, vm.DataContract.SchedulerAppointmentOid, item.RecurrenceInfo != null ? item.RecurrenceInfo.Id.ToString() : string.Empty, item.RecurrenceIndex)); if (isOverlapping) { var erg = MessageBox.Show("Dieser Termin überschneidet sich mit einem anderen bereits existierenden Termin.\n Möchten Sie ihn wirklich speichern?", "Überschneidung", MessageBoxButton.YesNo, MessageBoxImage.Exclamation); if (erg.Equals(MessageBoxResult.No)) { return; } } } dcList.Add(vm.CommitToDataContract()); } if (dcList.Count <= 0) { return; } NewSchedulerView.IgnoreChangeEvents = true; var mostRecentAppointments = new List(); ServiceFacade.DoResourceServiceSync(sync => mostRecentAppointments = sync.InsertSchedulerAppointments(dcList)); UpdateViewModel(mostRecentAppointments); control.ActiveView.LayoutChanged(); NewSchedulerView.IgnoreChangeEvents = false; } private void UpdateSchedulerAppointment(Appointment app, SchedulerAppointmentVM vm) { vm.EmployeeList = app.CustomFields[CF_EMPLOYEELIST] as List ?? new List(); vm.CustomerList = app.CustomFields[CF_CUSTOMERLIST] as List; vm.ResourceList = app.CustomFields[CF_RESOURCELIST] as List; vm.Originator = app.CustomFields[CF_ORIGINATOR] as CompactEmployeeDC; vm.IsPrivate = app.CustomFields[CF_ISPRIVATE] != null && (bool) app.CustomFields[CF_ISPRIVATE]; // Soll nicht mehr geschehen //if (!vm.EmployeeList.Select(s => s.Employee).Contains(vm.Originator)) // vm.EmployeeList.Add(new Employee2SchedulerAppointmentDC {Employee = vm.Originator, ParticipationAnswer = ParticipationAnswer.Zusage}); if (!vm.CustomFields.ContainsKey("EmployeeList")) { vm.CustomFields.Add("EmployeeList", vm.EmployeeList); } if (!vm.CustomFields.ContainsKey("CustomerList")) { vm.CustomFields.Add("CustomerList", vm.CustomerList); } if (!vm.CustomFields.ContainsKey("ResourceList")) { vm.CustomFields.Add("ResourceList", vm.ResourceList); } if (!vm.CustomFields.ContainsKey("Originator")) { vm.CustomFields.Add("Originator", vm.Originator); } if (!vm.CustomFields.ContainsKey("IsPrivate")) { vm.CustomFields.Add("IsPrivate", vm.IsPrivate); } if (vm.CommitToDataContract() != null && vm.CommitToDataContract().SchedulerAppointmentOid.HasValue && vm.EmployeeList != null && vm.EmployeeList.Count > 0) { var alt = new SchedulerAppointmentDC(); ServiceFacade.DoResourceServiceSync(s => alt = s.GetSchedulerAppointmentsById(new List {vm.CommitToDataContract().SchedulerAppointmentOid.Value}).First()); var alts = alt.StartDate; var alte = alt.EndDate; if(alts != vm.Start || alte != vm.End) { var neu = vm.EmployeeList; vm.EmployeeList = neu.DoForEach(f => { if (!f.Employee.Equals(vm.Originator)) { f.ParticipationAnswer = ParticipationAnswer.Offen; } }).ToList(); } } if (vm.ResourceList == null || vm.ResourceList.Count <= 0) return; if (app.RecurrenceInfo != null) { var index = app.RecurrenceIndex.ToString(); //###Lyndon testen!!! //var id = app.RecurrenceInfo.Id; var id = new Guid(app.RecurrenceInfo.Id.ToString()); if (changedOccurencyCustomFields.ContainsKey(id) && changedOccurencyCustomFields[id].ContainsKey(index)) { if (app.Type.Equals(AppointmentType.ChangedOccurrence)) { app.CustomFields["EmployeeList"] = changedOccurencyCustomFields[id][index]["EmployeeList"]; app.CustomFields["CustomerList"] = changedOccurencyCustomFields[id][index]["CustomerList"]; app.CustomFields["ResourceList"] = changedOccurencyCustomFields[id][index]["ResourceList"]; app.CustomFields["Originator"] = changedOccurencyCustomFields[id][index]["Originator"]; app.CustomFields["IsPrivate"] = changedOccurencyCustomFields[id][index]["IsPrivate"]; } } } app.LabelId = vm.LabelId; } AbstractAppointmentEditForm ISchedulerViewModel.GetEditAppointmentForm(SchedulerControl control, Appointment appointment) { geoeffneterTermin = control.Storage.CreateAppointment(AppointmentType.Normal); geoeffneterTermin.AllDay = appointment.AllDay; geoeffneterTermin.Start = appointment.Start; geoeffneterTermin.End = appointment.End; geoeffneterTermin.Description = appointment.Description; foreach (CustomField cf in appointment.CustomFields) { geoeffneterTermin.CustomFields[cf.Name] = cf.Value; } if (!appointment.Type.Equals(AppointmentType.ChangedOccurrence)) { return new SchedulerAppointmentEditForm(this, control, appointment, mAllEmployees, mAllCustomers, mCategories2Resources); } var index = appointment.RecurrenceIndex; //###Lyndon testen!!! //var id = app.RecurrenceInfo.Id; var id = new Guid(appointment.RecurrenceInfo.Id.ToString()); if (changedOccurencyCustomFields.ContainsKey(id) && changedOccurencyCustomFields[id].ContainsKey(index.ToString())) { var specialCustomFields = changedOccurencyCustomFields[id][index.ToString()]; foreach (var cf in specialCustomFields) { appointment.CustomFields[cf.Key] = cf.Value; geoeffneterTermin.CustomFields[cf.Key] = cf.Value; } } return new SchedulerAppointmentEditForm(this, control, appointment, mAllEmployees, mAllCustomers, mCategories2Resources); } public void ApplyChangesToChangedOccurencyCustomFields(List employees, List customers, List resources, CompactEmployeeDC originator, bool isPrivate, string index, Guid id) { if (!changedOccurencyCustomFields.ContainsKey(id) || !changedOccurencyCustomFields[id].ContainsKey(index)) { return; } changedOccurencyCustomFields[id][index][CF_EMPLOYEELIST] = employees; changedOccurencyCustomFields[id][index][CF_CUSTOMERLIST] = customers; changedOccurencyCustomFields[id][index][CF_RESOURCELIST] = resources; changedOccurencyCustomFields[id][index][CF_ORIGINATOR] = originator; changedOccurencyCustomFields[id][index][CF_ISPRIVATE] = isPrivate; } public void AddCustomFieldsMapping(SchedulerStorage schedulerStorage) { var employeeMapping = new SchedulerCustomFieldMapping(CF_EMPLOYEELIST, CF_EMPLOYEELIST); var customerMapping = new SchedulerCustomFieldMapping(CF_CUSTOMERLIST, CF_CUSTOMERLIST); var resourceMapping = new SchedulerCustomFieldMapping(CF_RESOURCELIST, CF_RESOURCELIST); var originatorMapping = new SchedulerCustomFieldMapping(CF_ORIGINATOR, CF_ORIGINATOR); var isPrivateMapping = new SchedulerCustomFieldMapping(CF_ISPRIVATE, CF_ISPRIVATE); schedulerStorage.AppointmentStorage.CustomFieldMappings.Add(employeeMapping); schedulerStorage.AppointmentStorage.CustomFieldMappings.Add(customerMapping); schedulerStorage.AppointmentStorage.CustomFieldMappings.Add(resourceMapping); schedulerStorage.AppointmentStorage.CustomFieldMappings.Add(originatorMapping); schedulerStorage.AppointmentStorage.CustomFieldMappings.Add(isPrivateMapping); } public void InitNewAppointment(Appointment appointment) { appointment.CustomFields[CF_CUSTOMERLIST] = new List(); appointment.CustomFields[CF_EMPLOYEELIST] = new List(); appointment.CustomFields[CF_RESOURCELIST] = new List(); ServiceFacade.DoEmployeeServiceSync(s => appointment.CustomFields[CF_ORIGINATOR] = s.LoadCompactEmployee(BeWoApp.LoggedOnEmployee.EmployeeOid.Value)); appointment.CustomFields[CF_ISPRIVATE] = false; appointment.StatusId = 0; } public bool HideAppointment(string filterCategory, object selectedObject, Appointment appointment, bool showPrivateAppointments) { var wirdAngezeigt = true; // -> wird standardmäßig angezeigt bool isPrivate = false; if (appointment.CustomFields["IsPrivate"] != null) { isPrivate = Convert.ToBoolean(appointment.CustomFields["IsPrivate"]); } if (showPrivateAppointments && !isPrivate) { return true; } var ersteller = (CompactEmployeeDC)appointment.CustomFields["Originator"]; var employeeList = (List)appointment.CustomFields["EmployeeList"]; var customerList = (List)appointment.CustomFields["CustomerList"]; var resourceList = (List)appointment.CustomFields["ResourceList"]; if (isPrivate) { if (ersteller == null || !ersteller.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid)) { return true; } } switch (filterCategory) { case "NurEigene": var istEigenerTermin = ersteller != null && ersteller.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid) && employeeList != null && employeeList.Count == 0 || employeeList != null && employeeList.Any(a => a.Employee.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid)); wirdAngezeigt = istEigenerTermin; break; case "NachAuswahl": var dictionary = (Dictionary)selectedObject; var ressourcen = (List)dictionary["Ressourcen"]; var mitarbeiter = (List)dictionary["Mitarbeiter"]; var klienten = (List)dictionary["Klienten"]; var cfe = employeeList != null ? employeeList.Select(s => s.Employee).ToList() : new List(); var cfr = resourceList ?? new List(); var cfc = customerList ?? new List(); var hasOnlyOriginatorInCommon = employeeList != null && ersteller != null && employeeList.Any() == false && mitarbeiter.Contains(ersteller); var m = cfe.Intersect(mitarbeiter).ToList(); var r = cfr.Intersect(ressourcen).ToList(); var k = cfc.Intersect(klienten).ToList(); wirdAngezeigt = (m.Any() || k.Any() || r.Any()) || hasOnlyOriginatorInCommon; break; case "Ebenen": var liste = (List)selectedObject; // mkr var appEList = employeeList.Where(w => !w.Employee.Equals(appointment.CustomFields["Originator"])).ToList(); // Ersteller und Rechte beachten var istEigen = ersteller.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid); var mVorhanden = appEList.Any(a2app => mAllEmployees.Contains(a2app.Employee)); var kVorhanden = customerList.Any(mAllCustomers.Contains); wirdAngezeigt = liste[0] && mVorhanden || liste[1] && resourceList.Any() || liste[2] && kVorhanden; // Nur Ansehen if (!istEigen && !BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderMitarbeitertermineAnsehen) && liste[0] && mVorhanden && !appEList.Select(e2sa => e2sa.Employee).Any(a => a.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid))) { wirdAngezeigt = false; } if (!istEigen && !BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderKliententermineAlleAnsehen) && liste[2] && kVorhanden) { wirdAngezeigt = false; } if (!istEigen && !BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderRessourcentermineAnsehen) && liste[1] && resourceList.Any()) { wirdAngezeigt = false; } break; } return !wirdAngezeigt; } public void InitChangedOccurrencyCustomFields(IEnumerable appList) { changedOccurencyCustomFields = new Dictionary>>(); foreach (var termin in appList) { var ri = new RecurrenceInfo(); ri.FromXml(termin.RecurrenceInfo); string index; using (var reader = XmlReader.Create(new StringReader(termin.RecurrenceInfo))) { reader.ReadToFollowing("RecurrenceInfo"); reader.MoveToAttribute("Index"); index = reader.Value; } if (index.Equals("")) index = "0"; var customFieldCollection = new Dictionary(); customFieldCollection[CF_CUSTOMERLIST] = termin.CustomerList; customFieldCollection[CF_EMPLOYEELIST] = termin.EmployeeList; customFieldCollection[CF_RESOURCELIST] = termin.ResourceList; customFieldCollection[CF_ORIGINATOR] = termin.Originator; customFieldCollection[CF_ISPRIVATE] = termin.IsPrivate; //###Lyndon testen!!! //var id = app.RecurrenceInfo.Id; var id = new Guid(ri.Id.ToString()); if (!changedOccurencyCustomFields.ContainsKey(id)) changedOccurencyCustomFields.Add(id, new Dictionary> { { index, customFieldCollection } }); else if (!changedOccurencyCustomFields[id].ContainsKey(index)) changedOccurencyCustomFields[id].Add(index, customFieldCollection); else changedOccurencyCustomFields[id][index] = customFieldCollection; } } //TODO: alle relevanten Eigenschaften beachten und eigene AreEqual Extension schreiben (erledigt) (https://www.devexpress.com/Support/Center/Question/Details/T270666) public override bool Equals(object pObj) { var obj = (SchedulerAppointmentListVM)pObj; if (obj == null) { return false; } var appointmentsAreEqual = Appointments == null && obj.Appointments == null || Appointments != null && Appointments.AreEqual(obj.Appointments); var allCustomersAreEqual = AllCustomers == null && obj.AllCustomers == null || AllCustomers != null && obj.AllCustomers != null && AllCustomers.Count == obj.AllCustomers.Count && !AllCustomers .Where( (t, i) => !( t.CustomerOid.Equals(obj.AllCustomers[i].CustomerOid) && t.CustomerVersion.Equals(obj.AllCustomers[i].CustomerVersion) ) ).Any(); var allEmployeesAreEqual = AllEmployees == null && obj.AllEmployees == null || AllEmployees != null && obj.AllEmployees != null && AllEmployees.Count == obj.AllEmployees.Count && !AllEmployees .Where( (t, i) => !( t.EmployeeOid.Equals(obj.AllEmployees[i].EmployeeOid) && t.EmployeeVersion.Equals(obj.AllEmployees[i].EmployeeVersion) ) ).Any(); var areEqual = VMList.AreEqual(obj.VMList) && IsDirty == obj.IsDirty && allCustomersAreEqual && allEmployeesAreEqual && appointmentsAreEqual && Equals(Categories2Resources, obj.Categories2Resources) && Equals(ChangedOccurencyCustomFields, obj.ChangedOccurencyCustomFields); return areEqual; } } }