Files
BeWoPlaner/BeWo/Scheduler/ViewModel/SchedulerAppointmentListVM.cs
2017-04-20 13:31:32 +02:00

607 lines
25 KiB
C#

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<SchedulerAppointmentDC, SchedulerAppointmentVM>, 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<IBeWoAppointment> mAppointmentList;
public BindingList<IBeWoAppointment> Appointments
{
get
{
if (mAppointmentList != null) return mAppointmentList;
mAppointmentList = new BindingList<IBeWoAppointment>();
mAppointmentList.AddingNew += mAppointmentList_AddingNew;
foreach (var item in VMList)
mAppointmentList.Add(item);
return mAppointmentList;
}
}
private readonly List<CompactCustomerDC> mAllCustomers;
private readonly List<CompactEmployeeDC> mAllEmployees;
private readonly Dictionary<ValueListEntryDC, List<ResourceDC>> mCategories2Resources;
static void mAppointmentList_AddingNew(object sender, AddingNewEventArgs e)
{
var dc = new SchedulerAppointmentDC
{
EmployeeList = new List<Employee2SchedulerAppointmentDC>(),
CustomerList = new List<CompactCustomerDC>(),
ResourceList = new List<ResourceDC>(),
//Originator = ServiceFacade.DoEmployeeServiceSync(),
Status = 0
};
var neu = new SchedulerAppointmentVM(dc);
e.NewObject = neu;
}
private Dictionary<Guid, Dictionary<String, Dictionary<String, Object>>> changedOccurencyCustomFields;
public Dictionary<Guid, Dictionary<String, Dictionary<String, Object>>> ChangedOccurencyCustomFields { get; private set; }
public List<CompactCustomerDC> AllCustomers
{
get { return mAllCustomers; }
}
public List<CompactEmployeeDC> AllEmployees
{
get { return mAllEmployees; }
}
public Dictionary<ValueListEntryDC, List<ResourceDC>> Categories2Resources
{
get { return mCategories2Resources; }
}
private Appointment geoeffneterTermin;
public SchedulerAppointmentListVM(List<SchedulerAppointmentDC> appList, List<CompactCustomerDC> allCustomers, List<CompactEmployeeDC> allEmployees, Dictionary<ValueListEntryDC, List<ResourceDC>> 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<SchedulerAppointmentDC> updatedDcList)
{
foreach (var dc in updatedDcList)
{
SchedulerAppointmentVM found = null;
foreach (var vm in Appointments.OfType<SchedulerAppointmentVM>().Where(vm => vm.DataContract.Equals(dc)))
{
found = vm;
}
if (found != null)
{
found.DataContract = dc;
}
}
}
public void SaveAppointments(SchedulerControl control, IEnumerable<Appointment> list)
{
var sindGleich = false;
var dcList = new List<SchedulerAppointmentDC>();
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<SchedulerAppointmentDC>();
ServiceFacade.DoResourceServiceSync(sync => mostRecentAppointments = sync.UpdateSchedulerAppointments(dcList));
UpdateViewModel(mostRecentAppointments);
control.ActiveView.LayoutChanged();
NewSchedulerView.IgnoreChangeEvents = false;
}
public void DeleteAppointments(SchedulerControl control, IEnumerable<Appointment> list)
{
var dcList = list.Select(item => item.GetSourceObject(control.GetCoreStorage())).OfType<SchedulerAppointmentVM>().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<SchedulerAppointmentDC>();
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<Appointment> list)
{
var dcList = new List<SchedulerAppointmentDC>();
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<SchedulerAppointmentDC>();
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<Employee2SchedulerAppointmentDC> ?? new List<Employee2SchedulerAppointmentDC>();
vm.CustomerList = app.CustomFields[CF_CUSTOMERLIST] as List<CompactCustomerDC>;
vm.ResourceList = app.CustomFields[CF_RESOURCELIST] as List<ResourceDC>;
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<long> {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();
var id = app.RecurrenceInfo.Id;
if (changedOccurencyCustomFields.ContainsKey(app.RecurrenceInfo.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;
var id = appointment.RecurrenceInfo.Id;
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<Employee2SchedulerAppointmentDC> employees, List<CompactCustomerDC> customers, List<ResourceDC> 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<CompactCustomerDC>();
appointment.CustomFields[CF_EMPLOYEELIST] = new List<Employee2SchedulerAppointmentDC>();
appointment.CustomFields[CF_RESOURCELIST] = new List<ResourceDC>();
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<Employee2SchedulerAppointmentDC>)appointment.CustomFields["EmployeeList"];
var customerList = (List<CompactCustomerDC>)appointment.CustomFields["CustomerList"];
var resourceList = (List<ResourceDC>)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<string, object>)selectedObject;
var ressourcen = (List<ResourceDC>)dictionary["Ressourcen"];
var mitarbeiter = (List<CompactEmployeeDC>)dictionary["Mitarbeiter"];
var klienten = (List<CompactCustomerDC>)dictionary["Klienten"];
var cfe = employeeList != null ? employeeList.Select(s => s.Employee).ToList() : new List<CompactEmployeeDC>();
var cfr = resourceList ?? new List<ResourceDC>();
var cfc = customerList ?? new List<CompactCustomerDC>();
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<bool>)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<SchedulerAppointmentDC> appList)
{
changedOccurencyCustomFields = new Dictionary<Guid, Dictionary<string, Dictionary<string, object>>>();
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<string, object>();
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;
if (!changedOccurencyCustomFields.ContainsKey(ri.Id))
changedOccurencyCustomFields.Add(ri.Id, new Dictionary<string, Dictionary<string, object>> { { index, customFieldCollection } });
else if (!changedOccurencyCustomFields[ri.Id].ContainsKey(index))
changedOccurencyCustomFields[ri.Id].Add(index, customFieldCollection);
else
changedOccurencyCustomFields[ri.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;
}
}
}