Kalender:

Die Abfrage nach der Ressourcenbelegung kommt nur ein mal und das Abbrechen des Speicherns hat keinen "kaputten" Reload zur Folge
    Das Löschen eines Serientermins mit veränderten oder gelöschten Elementen führt zu keiner Exception mehr, da ich den Service-Aufruf auf synchron geändert habe.
    Es gibt allerdings noch Bugs! -> Serientermin erstellen und ein Element davon ändern führt zu einer doppelten Abfrage, ausgelöst durch die Überlappungsprüfung, die eine    Überlappung mit der Serie selbst feststellt!
This commit is contained in:
Lyndon Jetten
2020-11-20 23:28:09 +01:00
parent 05a0436a9f
commit 659ec6b3eb
25 changed files with 3038 additions and 2382 deletions

View File

@@ -917,7 +917,7 @@
<dxsch:SchedulerControl Grid.Column="2" x:Name="Scheduler" dx:ThemeManager.ThemeName="Office2010Black"
FormCustomizationUsingMVVMLocal="False"
InplaceEditorShowing="Scheduler_OnInplaceEditorShowing"
GroupType="None" AppointmentDrag="Scheduler_OnAppointmentDrag"
GroupType="None" AppointmentDrag="Scheduler_OnAppointmentDrag" AppointmentDrop="Scheduler_OnAppointmentDrop"
VerticalAlignment="Stretch"
EditAppointmentFormShowing="Scheduler_EditAppointmentFormShowing"
EditRecurrentAppointmentFormShowing="SchedulerControl_EditRecurrentAppointmentFormShowing"

View File

@@ -38,6 +38,7 @@ using DevExpress.Xpf.Scheduler.Reporting;
using DevExpress.XtraScheduler;
using DevExpress.XtraScheduler.Compatibility;
using DevExpress.XtraScheduler.iCalendar;
using DevExpress.XtraScheduler.Services;
using Microsoft.Win32;
using Appointment = DevExpress.XtraScheduler.Appointment;
using AppointmentViewInfoCustomizingEventArgs = DevExpress.Xpf.Scheduler.AppointmentViewInfoCustomizingEventArgs;
@@ -1029,23 +1030,22 @@ namespace BeWo.Scheduler.View
var idList = (from item in dcList where item.SchedulerAppointmentOid.HasValue select item.SchedulerAppointmentOid.Value).ToList();
IgnoreChangeEvents = true;
ServiceFacade.DoResourceServiceAsync(s => s.GetSchedulerAppointmentsById(idList), appointments =>
{
ServiceFacade.DoResourceServiceAsync(s2 => s2.DeactivateSchedulerAppointmentsForSync(appointments.ToDictionary(dc => dc.SchedulerAppointmentOid.Value, dc => dc.NewSchedulerAppointmentVersion.Value)), updatedAppointments =>
{
ViewModel.ActiveAppointmentViewModel.UpdateViewModel(updatedAppointments);
this.Dispatch(() =>
{
Scheduler.ActiveView.LayoutChanged();
UpdateRequestString();
ReloadVM(true);
});
IgnoreChangeEvents = false;
});
});
var appointments = new List<SchedulerAppointmentDC>();
var updatedAppointments = new List<SchedulerAppointmentDC>();
ServiceFacade.DoResourceServiceSync(s => appointments = s.GetSchedulerAppointmentsById(idList));
if(appointments.Any())
{
ServiceFacade.DoResourceServiceSync(s => updatedAppointments = s.DeactivateSchedulerAppointmentsForSync(appointments.ToDictionary(dc => dc.SchedulerAppointmentOid.Value, dc => dc.NewSchedulerAppointmentVersion.Value)));
ViewModel.ActiveAppointmentViewModel.UpdateViewModel(updatedAppointments);
Scheduler.ActiveView.LayoutChanged();
UpdateRequestString();
ReloadVM(true);
IgnoreChangeEvents = false;
}
}
}
}
@@ -1754,91 +1754,108 @@ namespace BeWo.Scheduler.View
var start = pIntervalStart - FetchPadding;
var end = pIntervalEnd + FetchPadding;
GetCacheObjects((c, e, r) =>
var service = Scheduler.GetService<ISchedulerStateService>();
this.Dispatch(() =>
{
ServiceFacade.DoResourceServiceAsync(s2 => s2.LoadFilteredAppointmentsMitAufgaben(BeWoApp.HasLoggedOnUserRight(new[] {UserRightType.KalenderMitarbeitertermineAnsehen}), BeWoApp.LoggedOnEmployee.EmployeeOid.Value, start, end, pSelectedEmployees, pSelectedCustomer, pSelectedResources, pEmployeesOnly, pCustomersOnly, pResourcesOnly, pPrivateAppointmentsOnly, pOnlyMyAppointments, IsTasksVisible),
appointments =>
{
ServiceFacade.DoResourceServiceAsync(s3 => s3.GetAllActiveAbsenceTimesInInterval(start, end, BeWoApp.LoggedOnEmployee.EmployeeOid.Value, BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderMitarbeitertermineAnsehen)),
absenceTimes =>
{
this.Dispatch(() =>
{
var prefilteredAppointments = appointments.Where(w => (w.EmployeeList.Count == 0 && w.Originator.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid) ||
w.EmployeeList.Count > 0 && w.EmployeeList.Any(a => a.Employee.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid)) ||
BeWoUtils.HasRight(UserRightType.KalenderMitarbeitertermineAnsehen)) && (!w.EmployeeList.TrueForAll(e2a => e2a.ParticipationAnswer == ParticipationAnswer.Absage) || w.EmployeeList == null || w.EmployeeList.Count == 0)).ToList();
if(service.IsDataRefreshAllowed)
{
GetCacheObjects((c, e, r) =>
{
ServiceFacade.DoResourceServiceAsync(s2 => s2.LoadFilteredAppointmentsMitAufgaben(BeWoApp.HasLoggedOnUserRight(new[] { UserRightType.KalenderMitarbeitertermineAnsehen }), BeWoApp.LoggedOnEmployee.EmployeeOid.Value, start, end, pSelectedEmployees, pSelectedCustomer, pSelectedResources, pEmployeesOnly, pCustomersOnly, pResourcesOnly, pPrivateAppointmentsOnly, pOnlyMyAppointments, IsTasksVisible),
appointments =>
{
ServiceFacade.DoResourceServiceAsync(s3 => s3.GetAllActiveAbsenceTimesInInterval(start, end, BeWoApp.LoggedOnEmployee.EmployeeOid.Value, BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderMitarbeitertermineAnsehen)),
absenceTimes =>
{
this.Dispatch(() =>
{
var prefilteredAppointments = appointments.Where(w => (w.EmployeeList.Count == 0 && w.Originator.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid) ||
w.EmployeeList.Count > 0 && w.EmployeeList.Any(a => a.Employee.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid)) ||
BeWoUtils.HasRight(UserRightType.KalenderMitarbeitertermineAnsehen)) && (!w.EmployeeList.TrueForAll(e2a => e2a.ParticipationAnswer == ParticipationAnswer.Absage) || w.EmployeeList == null || w.EmployeeList.Count == 0)).ToList();
var vm = new SchedulerAppointmentListVM(prefilteredAppointments, c, e, r);
if(pShouldShowAbsenceTimes)
{
vm.Appointments.AddRange(ViewModel.ConvertAbsenceTimesToAppointments(absenceTimes.Where(w =>
{
return SelectedEmployees.Count == 0 || SelectedEmployees.Any(a => a.EmployeeOid == w.EmployeeOid);
}), end, e));
}
if(!IsTasksVisible)
{
prefilteredAppointments = prefilteredAppointments.Where(app => !app.IsTask).ToList();
}
ViewModel.ActiveAppointmentViewModel = vm;
var vm = new SchedulerAppointmentListVM(prefilteredAppointments, c, e, r);
if(pShouldShowAbsenceTimes)
{
vm.Appointments.AddRange(ViewModel.ConvertAbsenceTimesToAppointments(absenceTimes.Where(w =>
{
return SelectedEmployees.Count == 0 || SelectedEmployees.Any(a => a.EmployeeOid == w.EmployeeOid);
}), end, e));
}
ViewModel.SchedulerSettings = ViewModel.GetActiveSettings();
ViewModel.SchedulerSettings.StartDate = pIntervalStart;
ViewModel.ActiveAppointmentViewModel = vm;
GefilterteMitarbeiter = ViewModel.ActiveAppointmentViewModel.AllEmployees;
AllEmployees = ViewModel.ActiveAppointmentViewModel.AllEmployees;
GefilterteKlienten = ViewModel.ActiveAppointmentViewModel.AllCustomers;
AllCustomers = ViewModel.ActiveAppointmentViewModel.AllCustomers;
ViewModel.SchedulerSettings = ViewModel.GetActiveSettings();
ViewModel.SchedulerSettings.StartDate = pIntervalStart;
Category2ResourcesDictionary = ViewModel.ActiveAppointmentViewModel.Categories2Resources;
GefilterteMitarbeiter = ViewModel.ActiveAppointmentViewModel.AllEmployees;
AllEmployees = ViewModel.ActiveAppointmentViewModel.AllEmployees;
GefilterteKlienten = ViewModel.ActiveAppointmentViewModel.AllCustomers;
AllCustomers = ViewModel.ActiveAppointmentViewModel.AllCustomers;
SelectedEmployees = AllEmployees.Where(w => SelectedEmployees.Any(a => a.EmployeeOid.Equals(w.EmployeeOid))).ToList();
SelectedCustomers = AllCustomers.Where(w => SelectedCustomers.Any(a => a.CustomerOid.Equals(w.CustomerOid))).ToList();
SelectedResources = AllResources.Where(w => SelectedResources.Any(a => a.ResourceOid.Equals(w.ResourceOid))).ToList();
Category2ResourcesDictionary = ViewModel.ActiveAppointmentViewModel.Categories2Resources;
var items = SelectedItems;
SelectedEmployees = AllEmployees.Where(w => SelectedEmployees.Any(a => a.EmployeeOid.Equals(w.EmployeeOid))).ToList();
SelectedCustomers = AllCustomers.Where(w => SelectedCustomers.Any(a => a.CustomerOid.Equals(w.CustomerOid))).ToList();
SelectedResources = AllResources.Where(w => SelectedResources.Any(a => a.ResourceOid.Equals(w.ResourceOid))).ToList();
var testtesttest = ViewModel.ActiveAppointmentViewModel;
var items = SelectedItems;
_ReloadingViewModel = false;
var testtesttest = ViewModel.ActiveAppointmentViewModel;
Scheduler.Storage.RefreshData();
Scheduler.Storage.RefreshUI();
_ReloadingViewModel = false;
if (_IsComingFromHomeDragPanel && _SelectedAppointmentFromHomePanelView != null)
{
var apps = Scheduler.ActiveView.GetAppointments().ToList();
Scheduler.Storage.RefreshData();
Scheduler.Storage.RefreshUI();
var oid = _SelectedAppointmentFromHomePanelView.SchedulerAppointmentOid;
Appointment appointmentToOpen;
if(_IsComingFromHomeDragPanel && _SelectedAppointmentFromHomePanelView != null)
{
var apps = Scheduler.ActiveView.GetAppointments().ToList();
if (oid != null)
{
appointmentToOpen = apps.Find(app =>
{
var oidValue = app.CF_SchedulerAppointmentOid();
var oid = _SelectedAppointmentFromHomePanelView.SchedulerAppointmentOid;
Appointment appointmentToOpen;
return oidValue.HasValue && oidValue.Value == oid;
});
if(oid != null)
{
appointmentToOpen = apps.Find(app =>
{
var oidValue = app.CF_SchedulerAppointmentOid();
return oidValue.HasValue && oidValue.Value == oid;
});
if (appointmentToOpen != null)
{
Scheduler.ShowEditAppointmentForm(appointmentToOpen);
}
}
else if (_SelectedAppointmentFromHomePanelView.RecurrenceId != null && _SelectedAppointmentFromHomePanelView.RecurrenceIndex > 0)
{
appointmentToOpen = apps.Find(appointment => appointment.RecurrenceInfo.Id.ToString().Equals(_SelectedAppointmentFromHomePanelView.RecurrenceId));
if(appointmentToOpen != null)
{
Scheduler.ShowEditAppointmentForm(appointmentToOpen);
}
}
else if(_SelectedAppointmentFromHomePanelView.RecurrenceId != null && _SelectedAppointmentFromHomePanelView.RecurrenceIndex > 0)
{
appointmentToOpen = apps.Find(appointment => appointment.RecurrenceInfo.Id.ToString().Equals(_SelectedAppointmentFromHomePanelView.RecurrenceId));
if (appointmentToOpen != null)
{
Scheduler.ShowEditAppointmentForm(appointmentToOpen);
}
}
if(appointmentToOpen != null)
{
Scheduler.ShowEditAppointmentForm(appointmentToOpen);
}
}
_IsComingFromHomeDragPanel = false;
}
});
});
});
_IsComingFromHomeDragPanel = false;
}
});
});
});
});
}
else
{
_ReloadingViewModel = false;
}
});
}
@@ -1855,7 +1872,7 @@ namespace BeWo.Scheduler.View
}
}
void ExportAppointmentsAs_iCal(Stream stream)
private void ExportAppointmentsAs_iCal(Stream stream)
{
if (stream == null)
return;
@@ -2385,8 +2402,7 @@ namespace BeWo.Scheduler.View
var editedIsTask = editedAppointment.CF_IsTask();
var editedEnd = editedAppointment.End;
var editedDueDate = editedAppointment.CF_DueDate();
var sourceAppointment = e.SourceAppointment;
var sourceIsTask = sourceAppointment.CF_IsTask();
@@ -2424,6 +2440,11 @@ namespace BeWo.Scheduler.View
WriteToDebug(sb.ToString());
}
private void Scheduler_OnAppointmentDrop(object sender, AppointmentDragEventArgs e)
{
}
}
#region Converter
@@ -2503,6 +2524,12 @@ namespace BeWo.Scheduler.View
try
{
var customFields = (CustomFieldCollection) value;
if(customFields == null)
{
return string.Empty;
}
var customFieldStorage = (CustomFieldStorage) customFields[nameof(CustomFieldStorage)];
var mitarbeiter = customFieldStorage.EmployeeList;

View File

@@ -57,11 +57,7 @@ namespace BeWo.Scheduler.ViewModel
}
}
private readonly List<CompactCustomerDC> _AllCustomers;
private readonly List<CompactEmployeeDC> _AllEmployees;
private readonly Dictionary<ValueListEntryDC, List<ResourceDC>> _Categories2Resources;
private static void AppointmentListAddingNew(object sender, AddingNewEventArgs e)
private static void AppointmentListAddingNew(object sender, AddingNewEventArgs e)
{
var dc = new SchedulerAppointmentDC
{
@@ -79,19 +75,19 @@ namespace BeWo.Scheduler.ViewModel
private Dictionary<Guid, Dictionary<string, Dictionary<string, object>>> _ChangedOccurenceCustomFields;
public Dictionary<Guid, Dictionary<string, Dictionary<string, object>>> ChangedOccurenceCustomFields { get; }
public List<CompactCustomerDC> AllCustomers => _AllCustomers;
public List<CompactCustomerDC> AllCustomers { get; }
public List<CompactEmployeeDC> AllEmployees => _AllEmployees;
public List<CompactEmployeeDC> AllEmployees { get; }
public Dictionary<ValueListEntryDC, List<ResourceDC>> Categories2Resources => _Categories2Resources;
public Dictionary<ValueListEntryDC, List<ResourceDC>> Categories2Resources { get; }
private Appointment _GeoeffneterTermin;
private Appointment _GeoeffneterTermin;
public SchedulerAppointmentListVM(List<SchedulerAppointmentDC> appList, List<CompactCustomerDC> allCustomers, List<CompactEmployeeDC> allEmployees, Dictionary<ValueListEntryDC, List<ResourceDC>> lCategoriesToResources) : base(appList)
{
_Categories2Resources = lCategoriesToResources;
_AllCustomers = allCustomers;
_AllEmployees = allEmployees;
Categories2Resources = lCategoriesToResources;
AllCustomers = allCustomers;
AllEmployees = allEmployees;
// TODO: Hier Rechte beachten!
@@ -150,7 +146,14 @@ namespace BeWo.Scheduler.ViewModel
UpdateSchedulerAppointment(item, vm);
if(vm.ResourceList.Any())
var shouldSkipResourceAvailablityCheck = false;
if(_RecurrenceInfoId != null && item.RecurrenceInfo?.Id is Guid recurrenceId)
{
shouldSkipResourceAvailablityCheck = recurrenceId.Equals(_RecurrenceInfoId);
}
if(vm.ResourceList.Any() && !shouldSkipResourceAvailablityCheck)
{
if(!CheckForUnavailableResources(vm))
{
@@ -158,7 +161,21 @@ namespace BeWo.Scheduler.ViewModel
}
}
if (!ShouldLockOverlappingAppointmentCheck && vm.EventType != 3 && !vm.IsTask)
/*
* EventTypes:
* 0: Normal
* 1: Pattern
* 2: Occurrence
* 3: ChangedOccurrence
* 4: DeletedOccurrence
*
*
*
* Wozu ist das gut?
* !ShouldLockOverlappingAppointmentCheck &&
*/
if(!vm.IsTask && vm.EventType != 4 && !(vm.EventType == 3 && vm.DataContract?.SchedulerAppointmentOid == null))
{
var isOverlapping = false;
@@ -203,10 +220,13 @@ namespace BeWo.Scheduler.ViewModel
var mostRecentAppointments = new List<SchedulerAppointmentDC>();
ServiceFacade.DoResourceServiceSync(sync => mostRecentAppointments = sync.UpdateSchedulerAppointments(dcList));
UpdateViewModel(mostRecentAppointments);
_RecurrenceInfoId = null;
control.ActiveView.LayoutChanged();
NewSchedulerView.IgnoreChangeEvents = false;
}
private Guid? _RecurrenceInfoId;
public void InsertAppointments(SchedulerControl control, IEnumerable<Appointment> list)
{
var dcList = new List<SchedulerAppointmentDC>();
@@ -218,25 +238,25 @@ namespace BeWo.Scheduler.ViewModel
{
var dc = new SchedulerAppointmentDC
{
IsPrivate = item.CF_IsPrivate(),
Subject = item.Subject,
Description = item.Description,
StartDate = item.Start,
EndDate = item.End,
Originator = item.CF_Originator(),
LabelId = item.LabelId,
AllDay = item.AllDay,
Status = item.StatusId,
Type = (int) item.Type,
Location = item.Location,
RecurrenceInfo = item.RecurrenceInfo.ToXml(),
ReminderInfo = item.Reminder?.ToXml(),
CustomerList = item.CF_CustomerList(),
EmployeeList = item.CF_EmployeeList().ToList(),
ResourceList = item.CF_ResourceList(),
SupportConceptList = item.CF_SupportConceptList(),
RecurrenceIndex = item.RecurrenceIndex,
RecurrenceId = item.RecurrenceInfo.Id.ToString(),
IsPrivate = item.CF_IsPrivate(),
Subject = item.Subject,
Description = item.Description,
StartDate = item.Start,
EndDate = item.End,
Originator = item.CF_Originator(),
LabelId = item.LabelId,
AllDay = item.AllDay,
Status = item.StatusId,
Type = (int) item.Type,
Location = item.Location,
RecurrenceInfo = item.RecurrenceInfo.ToXml(),
ReminderInfo = item.Reminder?.ToXml(),
CustomerList = item.CF_CustomerList(),
EmployeeList = item.CF_EmployeeList().ToList(),
ResourceList = item.CF_ResourceList(),
SupportConceptList = item.CF_SupportConceptList(),
RecurrenceIndex = item.RecurrenceIndex,
RecurrenceId = item.RecurrenceInfo.Id.ToString(),
HasServiceRecordEntry = item.CF_HasServiceRecordEntry()
};
@@ -247,7 +267,12 @@ namespace BeWo.Scheduler.ViewModel
continue;
}
}
if(item.RecurrenceInfo != null)
{
_RecurrenceInfoId = (Guid) item.RecurrenceInfo.Id;
}
UpdateSchedulerAppointment(item, vm);
if(vm.ResourceList.Any())
@@ -258,7 +283,7 @@ namespace BeWo.Scheduler.ViewModel
}
}
if (!ShouldLockOverlappingAppointmentCheck && !vm.IsTask)
if (!ShouldLockOverlappingAppointmentCheck && !vm.IsTask && vm.EventType != 4)
{
var isOverlapping = false;
ServiceFacade.DoResourceServiceSync(s => isOverlapping = s.OverlappingAppointmentsExist(
@@ -384,7 +409,7 @@ namespace BeWo.Scheduler.ViewModel
if (!appointment.Type.Equals(AppointmentType.ChangedOccurrence))
{
return new SchedulerAppointmentEditForm(this, control, appointment, _AllEmployees, _AllCustomers, _Categories2Resources, isTask);
return new SchedulerAppointmentEditForm(this, control, appointment, AllEmployees, AllCustomers, Categories2Resources, isTask);
}
var index = appointment.RecurrenceIndex;
@@ -402,7 +427,7 @@ namespace BeWo.Scheduler.ViewModel
}
}
return new SchedulerAppointmentEditForm(this, control, appointment, _AllEmployees, _AllCustomers, _Categories2Resources, isTask);
return new SchedulerAppointmentEditForm(this, control, appointment, AllEmployees, AllCustomers, Categories2Resources, isTask);
}
public void ApplyChangesToChangedOccurencyCustomFields(ObservableCollection<Employee2SchedulerAppointmentDC> employees, List<CompactCustomerDC> customers, List<ResourceDC> resources, CompactEmployeeDC originator, bool isPrivate, string index, Guid id, bool isTask, string taskDescription, DateTime? completedDate, DateTime? dueDate, string completedNotice, List<CompactSupportConceptDC> supportConcepts, string subject, bool isAllDay)
@@ -524,8 +549,8 @@ namespace BeWo.Scheduler.ViewModel
var istEigen = ersteller.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid);
var mVorhanden = appEList.Any(a2app => _AllEmployees.Contains(a2app.Employee));
var kVorhanden = customerList.Any(_AllCustomers.Contains);
var mVorhanden = appEList.Any(a2app => AllEmployees.Contains(a2app.Employee));
var kVorhanden = customerList.Any(AllCustomers.Contains);
wirdAngezeigt = liste[0] && mVorhanden || liste[1] && resourceList.Any() || liste[2] && kVorhanden;

View File

@@ -4,7 +4,7 @@ using System.Collections.ObjectModel;
using System.Linq;
using BeWo.ViewModel;
using BS.Shared;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
@@ -58,9 +58,10 @@ namespace BeWo.Scheduler.ViewModel
private DateTime? _DueDate;
private DateTime? _DueTime;
private bool _HasServiceRecordEntry;
private bool _IsArchived;
public bool HasServiceRecordEntry
public bool HasServiceRecordEntry
{
get => _HasServiceRecordEntry;
set
@@ -75,6 +76,21 @@ namespace BeWo.Scheduler.ViewModel
}
}
public bool IsArchived
{
get => _IsArchived;
set
{
if(AreDifferent(_IsArchived, value))
{
_IsArchived = value;
StoreDirtyInformation((value && DataContract.ActivationType == ActivationTypeId.Active) || (!value && DataContract.ActivationType == ActivationTypeId.Archived), nameof(IsArchived));
FirePropertyChanged(nameof(IsArchived));
}
}
}
public DateTime? AbsenceTimeStart { get; set; }
public DateTime? AbsenceTimeEnd { get; set; }
@@ -530,6 +546,15 @@ namespace BeWo.Scheduler.ViewModel
}
}
public Guid? RecurrenceId => BS.Shared.Core.Utils.GetRecurrenceIdFromRecurrenceInfo(RecurrenceInfo);
public int RecurrenceIndex {
get
{
return BS.Shared.Core.Utils.GetRecurrenceIndexFromRecurrenceInfo(RecurrenceInfo);
}
}
public SchedulerAppointmentVM(SchedulerAppointmentDC pDC) : base(pDC, pDC.SchedulerAppointmentOid == null)
{
IsTeilnahmeBestaetigung = pDC.IsTeilnahmeBestaetigung;
@@ -583,6 +608,8 @@ namespace BeWo.Scheduler.ViewModel
_SupportConceptList = pDataContract.SupportConceptList ?? new List<CompactSupportConceptDC>();
_HasServiceRecordEntry = pDataContract.HasServiceRecordEntry;
_IsArchived = pDataContract.ActivationType == ActivationTypeId.Archived;
if(pDataContract.DueDate.HasValue)
{
@@ -613,7 +640,7 @@ namespace BeWo.Scheduler.ViewModel
pDataContract.CompletedDate = _CompletedDate;
pDataContract.SupportConceptList = _SupportConceptList;
pDataContract.HasServiceRecordEntry = _HasServiceRecordEntry;
pDataContract.ActivationType = _IsArchived ? ActivationTypeId.Archived : ActivationTypeId.Active;
if(_DueDate.HasValue && _DueTime.HasValue)
{
@@ -679,7 +706,8 @@ namespace BeWo.Scheduler.ViewModel
Equals(Location, obj.Location) &&
ResourceList.AreEqual(obj.ResourceList) &&
Equals(RecurrenceInfo, obj.RecurrenceInfo) &&
HasServiceRecordEntry == obj.HasServiceRecordEntry;
HasServiceRecordEntry == obj.HasServiceRecordEntry
;
return areEqual;
}

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
<UseGlobalApplicationHostFile />
<LastActiveSolutionConfig>Release|Any CPU</LastActiveSolutionConfig>
<LastActiveSolutionConfig>Debug|Any CPU</LastActiveSolutionConfig>
<ProjectView>ShowAllFiles</ProjectView>
<WebStackScaffolding_ViewDialogWidth>600</WebStackScaffolding_ViewDialogWidth>
<Controller_SelectedScaffolderID>MvcControllerEmptyScaffolder</Controller_SelectedScaffolderID>

View File

@@ -27,9 +27,12 @@ namespace BeWoPlanerMobil.Controllers
{
var loginState = MobileUtils.GetLoginState(MobileSessionFacade.Tenant);
#if DEBUG
loginState = new BeWoLoginState(1, "Das ist nur ein Test");
#endif
if (loginState.Message != null && loginState.State > -1)
{
TempData[MobileUtils.TempDataLoginStateKey] = loginState;
}

View File

@@ -628,27 +628,6 @@ namespace BeWoPlanerMobil.Controllers
Model.Textbausteine.AddRangeIfElementsNotIn(Utils.GetParentTextModules(Model.Textbausteine));
// TODO: Hier Html-erzeugen -> aufklappen, einklappen bzw. toggle in main.js implementieren
/*
* <div class="list-group">
* <a href="#" class="list-group-item list-group-item-action">Mein Textbaustein I</a>
* <a href="#" class="list-group-item list-group-item-action">
* <span class="fas fa-angle-down"></span>
* Mein Textbaustein I
* </a>
* <div class="list-group">
* <a href="#" class="list-group-item list-group-item-action">Arztbesuch</a>
* <a href="#" class="list-group-item list-group-item-action">Amtsbesuch</a>
* <a href="#" class="list-group-item list-group-item-action">Einkaufen</a>
* <a href="#" class="list-group-item list-group-item-action">
* <span class="fas -fa-angle-up"></span>
* Inoffiziell
* </a>
* </div>
* </div>
*/
//TextbausteinDisplayItem(string name, string text, List<TextbausteinDisplayItem> children, long? parentOid, long oid, bool isExpanded)
var newItems = Model.Textbausteine.Where(tb => tb.TextModuleOid.HasValue).Select(tb => new TextbausteinDisplayItem(tb.Name, tb.Text, tb.Parent?.TextModuleOid, tb.TextModuleOid.Value, tb.IsExpanded)).ToList();
foreach(var item in newItems)
@@ -660,35 +639,24 @@ namespace BeWoPlanerMobil.Controllers
parent?.Children.AddIfNotIn(item);
}
}
var test = newItems.Where(item => item.ParentOid == null).ToList();
var displayItems = Model.Textbausteine.Select(s => new TextbausteinDisplayItem(s.Name, new List<string> {s.TextModuleOid.Value.ToString()}, s.Parent?.TextModuleOid, s.TextModuleOid.Value, s.IsParent)).ToList();
foreach(var item in displayItems)
if(test.Count == 0)
{
if(item.ParentOid != null)
{
var parent = displayItems.FirstOrDefault(f => f.Oid == item.ParentOid);
if (parent != null)
{
if (parent.nodes == null)
{
parent.nodes = new List<TextbausteinDisplayItem>();
}
parent.nodes.AddIfNotIn(item);
}
}
return _LeerzeichenFuerGetMethoden;
}
displayItems = displayItems.Where(w => w.ParentOid == null).OrderBy(t => t.Name).ToList();
_TextModuleTreeHtml = "<div class=\"list-group\">";
return JsonConvert.SerializeObject(displayItems, Formatting.None, new JsonSerializerSettings
foreach(var item in test)
{
NullValueHandling = NullValueHandling.Ignore
});
BuildTextModuleTreeBranch(item);
}
_TextModuleTreeHtml += "</div>";
return _TextModuleTreeHtml;
}
catch(Exception exception)
{
@@ -697,6 +665,31 @@ namespace BeWoPlanerMobil.Controllers
}
}
private string _TextModuleTreeHtml = "";
private void BuildTextModuleTreeBranch(TextbausteinDisplayItem textModuleItem)
{
if(textModuleItem.IsParent)
{
_TextModuleTreeHtml += $"<a href=\"#\" class=\"list-group-item list-group-item-action mx-0 px-1\" onclick=\"textCategoryOnClick('{textModuleItem.Oid}')\">" +
$"<span id=\"{textModuleItem.Oid}-icon-span\" class=\"fas fa-angle-up mr-1\"></span>" +
$"{textModuleItem.Name}" +
"</a>" +
$"<div id=\"{textModuleItem.Oid}-children-container\" style=\"display: none;\" class=\"list-group list-group-item mx-0 px-1\">";
foreach(var child in textModuleItem.Children)
{
BuildTextModuleTreeBranch(child);
}
_TextModuleTreeHtml += "</div>";
}
else
{
_TextModuleTreeHtml += $"<a href=\"#\" id=\"{textModuleItem.Oid}\" class=\"list-group-item list-group-item-action mx-0 px-1\" onclick=\"textModuleOnClick('{textModuleItem.Oid}')\">{textModuleItem.Name}</a>";
}
}
[Authorize]
public string LoadCompleteTextbausteinByOid(long pTextbausteinOid)
{
@@ -936,6 +929,8 @@ namespace BeWoPlanerMobil.Controllers
Log.Error(e.Message, e);
}
ResetGroupBookingMode(true);
return ResetEditingMode(null);
}
@@ -1579,6 +1574,16 @@ namespace BeWoPlanerMobil.Controllers
var cb2ScOids = group.ServiceRecordList.Where(w => w.CostBearer2SupportConceptOid.HasValue).Select(s => s.CostBearer2SupportConceptOid.Value).ToList();
Model.SelectedConceptCostBearerRelations.AddRangeIfElementsNotIn(OperationsService.GetSupportConceptCostBearerRelDCsByOids(cb2ScOids));
var selectedSupportConcepts = new List<SupportConceptDC>();
selectedSupportConcepts.AddRangeIfElementsNotIn(OperationsService.GetSupportConceptsById(group.ServiceRecordList.Select(s => s.SupportConcept.SupportConceptOid)));
// TODO: WARUM SIND DIE NICHT GLEICH?
var first = selectedSupportConcepts[0];
var second = selectedSupportConcepts[1];
var areEqual = first.Equals(second);
Model.SelectedSupportConcepts = selectedSupportConcepts;
}
return RedirectToActionPermanent("Main");
@@ -2592,7 +2597,7 @@ namespace BeWoPlanerMobil.Controllers
if(Model.IsInGroupBookingMode && Model.SelectedSupportConcepts.Count > 1)
{
ResetGroupBookingMode(true);
// ResetGroupBookingMode(true);
return SaveGroupBooking();
}

View File

@@ -230,6 +230,7 @@ function logColorfulMessage(message, color) {
function isUndefinedOrNull(obj) {
return obj == null;
}
function areUndefinedOrNull(array) {
if (array == null) {
return true;

View File

@@ -58,12 +58,7 @@ function loadServiceDescriptions() {
}
$.get(getLoadTextbausteineForServiceCategoryUrl(), { pServiceCategoryOid: selectedCategoryOid }).done(function(result) {
if(checkJson(result) === false) {
return;
}
var test = $.parseJSON(result);
if(test.length === 0) {
if(result.length <= 2) {
$("#textmodule-container").hide();
return;
@@ -71,45 +66,47 @@ function loadServiceDescriptions() {
$("#textmodule-container").show();
$("#tree").treeview({
data: result,
onNodeSelected: function (event, data) {
var tags = data.tags;
$("#tree").html(result);
if (tags === undefined || tags === null || tags.length === 0) {
return;
}
//$("#tree").treeview({
// data: result,
// onNodeSelected: function (event, data) {
// var tags = data.tags;
var textbausteinOid = parseInt(tags[0], 10);
var focusedDokuFeld;
// if (tags === undefined || tags === null || tags.length === 0) {
// return;
// }
$.get(getLoadCompleteTextbausteinByOidUrl(), { pTextbausteinOid: textbausteinOid }).done(function (textModuleText) {
if ($("#dokufeld").length > 0) {
focusedDokuFeld = $("#dokufeld");
} else {
var numberOfDokutypes = getNumberOfDokutypes();
// var textbausteinOid = parseInt(tags[0], 10);
// var focusedDokuFeld;
for (var i = 0; i < numberOfDokutypes; i++) {
var currentElement = $("#doku_" + i);
// $.get(getLoadCompleteTextbausteinByOidUrl(), { pTextbausteinOid: textbausteinOid }).done(function (textModuleText) {
// if ($("#dokufeld").length > 0) {
// focusedDokuFeld = $("#dokufeld");
// } else {
// var numberOfDokutypes = getNumberOfDokutypes();
if (currentElement.css("display") !== "none") {
focusedDokuFeld = $("#doku-textarea-" + i);
break;
}
}
}
// for (var i = 0; i < numberOfDokutypes; i++) {
// var currentElement = $("#doku_" + i);
var cursorPosition = focusedDokuFeld.prop("selectionStart");
var v = focusedDokuFeld.val();
var textBefore = v.substring(0, cursorPosition);
var textAfter = v.substring(cursorPosition, v.length);
// if (currentElement.css("display") !== "none") {
// focusedDokuFeld = $("#doku-textarea-" + i);
// break;
// }
// }
// }
focusedDokuFeld.val(textBefore + textModuleText + textAfter);
// var cursorPosition = focusedDokuFeld.prop("selectionStart");
// var v = focusedDokuFeld.val();
// var textBefore = v.substring(0, cursorPosition);
// var textAfter = v.substring(cursorPosition, v.length);
$("#textbausteine-popup").modal("hide");
});
}
});
// focusedDokuFeld.val(textBefore + textModuleText + textAfter);
// $("#textbausteine-popup").modal("hide");
// });
// }
//});
});
});
}
@@ -626,4 +623,49 @@ function toggleHoursMinutesDropdownButton(element) {
setInputFilter();
calculateDuration(true);
}
function textCategoryOnClick(categoryId) {
var childrenContainer = $("#" + categoryId + "-children-container");
var iconSpan = $("#" + categoryId + "-icon-span");
var displayValue = childrenContainer.css("display");
var classToRemove = displayValue === "block" ? "fa-angle-down" : "fa-angle-up";
var classToAdd = displayValue === "block" ? "fa-angle-up" : "fa-angle-down";
iconSpan.removeClass(classToRemove);
iconSpan.addClass(classToAdd);
childrenContainer.toggle();
}
function textModuleOnClick(textModuleOid) {
var focusedDokuFeld;
$.get(getLoadCompleteTextbausteinByOidUrl(), { pTextbausteinOid: textModuleOid }).done(function(textModuleText) {
if ($("#dokufeld").length > 0) {
focusedDokuFeld = $("#dokufeld");
} else {
var numberOfDokutypes = getNumberOfDokutypes();
for (var i = 0; i < numberOfDokutypes; i++) {
var currentElement = $("#doku_" + i);
if (currentElement.css("display") !== "none") {
focusedDokuFeld = $("#doku-textarea-" + i);
break;
}
}
}
var cursorPosition = focusedDokuFeld.prop("selectionStart");
var v = focusedDokuFeld.val();
var textBefore = v.substring(0, cursorPosition);
var textAfter = v.substring(cursorPosition, v.length);
focusedDokuFeld.val(textBefore + textModuleText + textAfter);
$("#textbausteine-popup").modal("hide");
});
}

View File

@@ -354,8 +354,6 @@ namespace BeWoPlanerMobil.Util
public static BeWoLoginState GetLoginState(string tenant)
{
Debug.WriteLine($"GetLoginState {DateTime.Now:DD.MM.yyyy HH:mm:sss}");
var result = new BeWoLoginState(-1, null);
const string baseUrl = "https://support.bewoplaner.de/api";

View File

@@ -1,51 +1,30 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Linq;
namespace BeWoPlanerMobil.Util
{
public class TextbausteinDisplayItem
{
public bool selectable { get; }
public string text { get; set; }
public List<TextbausteinDisplayItem> nodes { get; set; }
public List<string> tags { get; set; }
[JsonIgnore]
public string Name { get; set; }
[JsonIgnore]
public long Oid { get; set; }
[JsonIgnore]
public long? ParentOid { get; set; }
[JsonIgnore]
public bool IsParent { get; set; }
[JsonIgnore]
public bool IsParent => Children.Any();
public string Text { get; set; }
[JsonIgnore] public List<TextbausteinDisplayItem> Children { get; set; } = new List<TextbausteinDisplayItem>();
public List<TextbausteinDisplayItem> Children { get; set; } = new List<TextbausteinDisplayItem>();
[JsonIgnore]
public bool IsExpanded { get; set; }
public TextbausteinDisplayItem(string pText, List<string> pTags, long? pParentOid, long pOid, bool pIsParent)
{
text = pText;
tags = pTags;
ParentOid = pParentOid;
Oid = pOid;
selectable = !pIsParent;
}
public TextbausteinDisplayItem(string name, string text, long? parentOid, long oid, bool isExpanded)
{
Name = name;
Text = text;
Oid = oid;
IsExpanded = isExpanded;
IsParent = parentOid != null;
ParentOid = parentOid;
}
}

View File

@@ -1301,36 +1301,26 @@ namespace BeWo.Data.Access
return c.List<ApplicationUser>().Count > 0;
}
// TODO: Ändert man einen Serientermin, wird ZWEIMAL eine Warnung angezeigt, dass sich der Termin mit einem anderen Termin überschneidet! Dieser Termin ist die Serie selbst!
public bool OverlappingAppointmentsExist(DateTime start, DateTime end, IEnumerable<long> employees, IEnumerable<long> customers, IEnumerable<long> resources, long originator, long? appointmentOid, string recurrenceId = "", int occurrenceIndex = 0)
{
{
var isRecurrenceException = appointmentOid == null;
Guid? recurrenceGuid = null;
if(Guid.TryParse(recurrenceId, out var parsedGuid))
{
recurrenceGuid = parsedGuid;
}
var betweenDateTimesCriterion = CreateBetweenDateTimesCriterion(start, end, nameof(SchedulerAppointment.StartDate), nameof(SchedulerAppointment.EndDate));
var criteria = CreateCriteria<SchedulerAppointment>()
.Add(Restrictions.Eq(nameof(BeWoEntityBase.IsActive), ActivationTypeId.Active))
.Add(Restrictions.Eq(nameof(SchedulerAppointment.IsTask), false))
.Add(Restrictions.Or(
Restrictions.Or(
Restrictions.And(
Restrictions.Gt(SchedulerAppointment.PropertyName_EndDate, start),
Restrictions.Lt(SchedulerAppointment.PropertyName_EndDate, end)
),
Restrictions.And(
Restrictions.Gt(SchedulerAppointment.PropertyName_StartDate, start),
Restrictions.Lt(SchedulerAppointment.PropertyName_StartDate, end)
)
),
Restrictions.Or(
Restrictions.And(
Restrictions.Lt(SchedulerAppointment.PropertyName_StartDate, start),
Restrictions.Gt(SchedulerAppointment.PropertyName_EndDate, start)
),
Restrictions.And(
Restrictions.Eq(SchedulerAppointment.PropertyName_StartDate, start),
Restrictions.Eq(SchedulerAppointment.PropertyName_EndDate, end)
)
)
)
);
.Add(betweenDateTimesCriterion);
if (appointmentOid != null)
if (isRecurrenceException == false)
{
criteria.Add(Restrictions.Not(Restrictions.Eq(BeWoEntityBase.PropertyName_Oid, appointmentOid)));
}
@@ -1344,11 +1334,9 @@ namespace BeWo.Data.Access
return true;
}
var recId = GetSpecificValueFromRecurrenceInfo(a.RecurrenceInfo, a.RecurrenceInfo.IndexOf("Id=\"") + 4);
var index = GetSpecificValueFromRecurrenceInfo(a.RecurrenceInfo, a.RecurrenceInfo.IndexOf("Index=\"") + 7);
int.TryParse(index, out var intIndex);
var recId2 = a.GetRecurrenceIdAndIndex(out var index);
return !(recurrenceId.Equals(recId) && occurrenceIndex == intIndex);
return !(Guid.TryParse(recurrenceId, out var guid) && guid.Equals(recId2) && occurrenceIndex == index);
});
var schedulerAppointments = appointments as IList<SchedulerAppointment> ?? appointments.ToList();
@@ -1357,8 +1345,7 @@ namespace BeWo.Data.Access
var deletedOccurences = schedulerAppointments.Where(app => app.Type == 4).Select(app => Utils.GetOccurrenceId(app.RecurrenceInfo)).ToList();
var changedOccurences = schedulerAppointments.Where(app => app.Type == 3).Select(app => Utils.GetOccurrenceId(app.RecurrenceInfo)).ToList();
var recurringAppointmentsCriteria = CreateRecurrenceCriteria(start, end)
.Add(Restrictions.Eq(nameof(SchedulerAppointment.Type), 1));
var recurringAppointmentsCriteria = CreateRecurrenceCriteria(start, end).Add(Restrictions.Eq(nameof(SchedulerAppointment.Type), 1));
var recurringAppointments = recurringAppointmentsCriteria.List<SchedulerAppointment>().ToList();
@@ -1381,9 +1368,9 @@ namespace BeWo.Data.Access
var interval = new TimeInterval(start, end);
// Die Serientermine werden berechnet (ausnahmslos, d.h. es werden auch bearbeitete und gelöschte Termine erstellt, die herausgefiltert werden müssen).
var occurences = occurenceCalculator.CalcOccurrences(interval, pattern);
var occurrences = occurenceCalculator.CalcOccurrences(interval, pattern);
foreach(var occurence in occurences.GetAppointments(interval))
foreach(var occurrence in occurrences.GetAppointments(interval))
{
if(appointment.EndDate == null || appointment.StartDate == null)
{
@@ -1391,35 +1378,82 @@ namespace BeWo.Data.Access
}
// Terminindex in der Serie
var index = occurence.RecurrenceIndex;
var index = occurrence.RecurrenceIndex;
// Das Ende ist offen, da die Terminserie kein Ende hat. Deshalb wird das Ende berechnet.
var duration = (appointment.EndDate.Value - appointment.StartDate.Value).TotalMinutes;
var guidParsingSuccessful = Guid.TryParse(occurrence.RecurrenceInfo?.Id?.ToString(), out var occurrenceGuid);
// Der generierte Serientermin muss sich zeitlich mit dem neuen Termin überschneiden
// und darf nicht in der Liste der geänderten Serientermine oder der Liste der gelöschten Serientermine sein.
if(!start.IsInInterval(end, occurence.Start, occurence.Start.AddMinutes(duration)) ||
if(!start.IsInInterval(end, occurrence.Start, occurrence.Start.AddMinutes(duration)) ||
changedOccurences.Any(changedOccurence => changedOccurence.PatternId.Equals(patternId) && changedOccurence.Index == index) ||
deletedOccurences.Any(deletedOccurence => deletedOccurence.PatternId.Equals(patternId) && deletedOccurence.Index == index))
deletedOccurences.Any(deletedOccurence => deletedOccurence.PatternId.Equals(patternId) && deletedOccurence.Index == index) ||
index == occurrenceIndex && guidParsingSuccessful && recurrenceGuid.Equals(occurrenceGuid))
{
continue;
}
// Prüfen, ob es eine Ausnahme an dem Tag gibt, die zu dem Pattern gehört, um das Pattern auszuschließen
var relatedAppointments = FindAppointmentsByRecurrenceId(new List<string> {recurrenceInfo.Id.ToString()}, true);
var relatedAppointmentsInInterval = relatedAppointments.Where(a =>
{
if(a.StartDate == null || a.EndDate == null)
{
return false;
}
var myStart = a.StartDate.Value.Date;
var myEnd = a.EndDate.Value.Date;
var isInInterval = start.Date.InBetween(myStart.GetShortDateTime(), myEnd, true);
return isInInterval && a.Type != 4;
}).ToList();
var hasToStop = false;
// Indices und Ids der RecurrenceInfo vergleichen. Stimmen sie überein, dann wird das generiert Serienelement ignoriert.
if(occurrence.RecurrenceInfo?.Id != null)
{
if(Guid.TryParse(occurrence.RecurrenceInfo.Id.ToString(), out var guid))
{
foreach(var relatedAppointment in relatedAppointmentsInInterval)
{
var relatedAppointmentRecurrenceId = relatedAppointment.GetRecurrenceIdAndIndex(out var relatedAppointmentRecurrenceIndex);
if(relatedAppointmentRecurrenceId != null)
{
if(guid.Equals(relatedAppointmentRecurrenceId) && relatedAppointmentRecurrenceIndex.Equals(occurrence.RecurrenceIndex))
{
hasToStop = true;
break;
}
}
}
}
}
if(hasToStop)
{
continue;
}
var recurringAppointment = new SchedulerAppointment
{
AllDay = occurence.AllDay,
AllDay = occurrence.AllDay,
CustomerList = appointment.CustomerList,
Notice = appointment.Notice,
EmployeeList = appointment.EmployeeList,
EndDate = occurence.Start.AddMinutes(duration),
EndDate = occurrence.Start.AddMinutes(duration),
FormerBookingSequenceOid = appointment.FormerBookingSequenceOid,
IsPrivate = appointment.IsPrivate,
Location = appointment.Location,
Originator = appointment.Originator,
RecurrenceInfo = occurence.RecurrenceInfo.ToXml(),
RecurrenceInfo = occurrence.RecurrenceInfo.ToXml(),
ReminderInfo = appointment.ReminderInfo,
ResourceList = appointment.ResourceList,
StartDate = occurence.Start,
StartDate = occurrence.Start,
Subject = appointment.Subject ?? "",
Type = appointment.Type
};
@@ -1429,58 +1463,94 @@ namespace BeWo.Data.Access
}
// --------------------------------------------------------------------------------------------------------------------------------------
// Falls es sich um eine Ausnahme einer Serie handelt, muss die Serie ignoriert werden
var shouldIgnoreAppointment = false;
if(isRecurrenceException && recurrenceId != null)
{
if(recurrenceGuid.HasValue)
{
shouldIgnoreAppointment = true;
}
}
var oidList = new List<long>();
foreach (var appointment in schedulerAppointments)
{
schedulerAppointments = schedulerAppointments.Where(appointment => appointment.Type != 4).ToList();
foreach (var appointment in schedulerAppointments)
{
if(shouldIgnoreAppointment)
{
if(!ShouldDoAppointmentOverlappingCheck(appointment, recurrenceGuid.Value))
{
continue;
}
}
oidList.AddRange(appointment.EmployeeList.Select(rel => rel.ParticipationAnswer != ParticipationAnswer.Absage && rel.Employee.Oid != null ? rel.Employee.Oid.Value : 0));
}
var hasOverlappingEmployeeAppointments = oidList.Intersect(employees).Any();
var hasOverlappingCustomerAppointments = schedulerAppointments.Any(app => app.CustomerList.Select(c => c.Oid ?? 0).Intersect(customers).Any());
var hasOverlappingResourceAppointments = schedulerAppointments.Any(app => app.ResourceList.Select(r => r.Oid ?? 0).Intersect(resources).Any());
var hasOverlappingCustomerAppointments = schedulerAppointments.Any(app =>
{
return ShouldDoAppointmentOverlappingCheck(app, recurrenceGuid) && app.CustomerList.Select(c => c.Oid ?? 0).Intersect(customers).Any();
});
var hasOverlappingOriginatorAppointments = schedulerAppointments.Any(appointment =>
appointment.Originator.Oid.HasValue &&
appointment.Originator.Oid.Value == originator &&
(appointment.EmployeeList.Count == 0 || appointment.EmployeeList.Any(a => a.Employee.Oid.HasValue && a.Employee.Oid.Value == originator)));
var hasOverlappingResourceAppointments = schedulerAppointments.Any(app =>
{
return ShouldDoAppointmentOverlappingCheck(app, recurrenceGuid) && app.ResourceList.Select(r => r.Oid ?? 0).Intersect(resources).Any();
});
var hasOverlappingOriginatorAppointments = schedulerAppointments.Any(appointment =>
{
if(!ShouldDoAppointmentOverlappingCheck(appointment, recurrenceGuid))
{
return false;
}
return appointment.Originator.Oid.HasValue &&
appointment.Originator.Oid.Value == originator &&
(appointment.EmployeeList.Count == 0 || appointment.EmployeeList.Any(a => a.Employee.Oid.HasValue && a.Employee.Oid.Value == originator));
});
return hasOverlappingEmployeeAppointments || hasOverlappingCustomerAppointments || hasOverlappingResourceAppointments || hasOverlappingOriginatorAppointments;
}
private static bool ShouldDoAppointmentOverlappingCheck(SchedulerAppointment appointment, Guid? recurrenceId)
{
if(appointment.Oid.HasValue && recurrenceId.HasValue)
{
var recId = appointment.GetRecurrenceIdAndIndex(out var recIndex);
if(appointment.RecurrenceInfo != null && recId != null)
{
if(recId.Equals(recurrenceId))
{
return false;
}
}
}
return true;
}
public IEnumerable<SchedulerAppointment> GetAllActiveAppointmentsForEmployeeInInterval(DateTime start, DateTime end, long pEmployeeOid)
{
var hasResources = $"{BeWoEntityBase.PropertyName_Oid} IN (SELECT newschappoid FROM resource2newschapp)";
{
var hasResources = $"{BeWoEntityBase.PropertyName_Oid} IN (SELECT newschappoid FROM resource2newschapp)";
var criteria = CreateRecurrenceCriteria(start, end)
.Add(Restrictions.Or(
Expression.Sql(new SqlString(hasResources)),
CreateOwnAppointmentsCriteria(pEmployeeOid)));
var criteria = CreateRecurrenceCriteria(start, end)
.Add(Restrictions.Or(
Expression.Sql(new SqlString(hasResources)),
CreateOwnAppointmentsCriteria(pEmployeeOid)));
return criteria.List<SchedulerAppointment>();
}
return criteria.List<SchedulerAppointment>();
}
public IEnumerable<SchedulerAppointment> GetAllActiveAppointmentsInInterval(DateTime start, DateTime end)
public IEnumerable<SchedulerAppointment> GetAllActiveAppointmentsInInterval(DateTime start, DateTime end)
{
return CreateRecurrenceCriteria(start, end).List<SchedulerAppointment>();
}
private static string GetSpecificValueFromRecurrenceInfo(string str, int startIndex)
{
var valueBuilder = new StringBuilder();
for (; startIndex < str.Length; startIndex++)
{
var cr = str[startIndex];
if (cr.Equals('"'))
break;
valueBuilder.Append(cr);
}
return valueBuilder.ToString();
}
public ResourceBooking GetFirstResourceBookingFromSequence(long sequenceOid)
{
return CreateCriteria<ResourceBooking>()
@@ -2839,6 +2909,20 @@ namespace BeWo.Data.Access
return c.List<SchedulerAppointment>();
}
public SchedulerAppointment FindRootAppointmentByRecurrenceId(string recurrenceId)
{
if(Guid.TryParse(recurrenceId, out var guid))
{
var criteria = CreateCriteria<SchedulerAppointment>()
.Add(Restrictions.Like(nameof(SchedulerAppointment.RecurrenceInfo), recurrenceId, MatchMode.Anywhere))
.Add(Restrictions.Eq(nameof(Appointment.Type), 1));
return criteria.List<SchedulerAppointment>().FirstOrDefault();
}
return null;
}
public IList<SchedulerAppointment> FindAppointmentsForCustomer(long pCustomerOid)
{
var blah = $"{BeWoEntityBase.PropertyName_Oid} IN (SELECT newschappoid FROM customer2newschapp WHERE customeroid IN ({pCustomerOid}))";
@@ -3128,7 +3212,7 @@ namespace BeWo.Data.Access
private static AbstractCriterion CreateBetweenDateTimesCriterion(DateTime start, DateTime end, string propertyNameStart, string propertyNameEnd)
{
/*
/* -- VERALTET ----- VERALTET ----- VERALTET ----- VERALTET ----- VERALTET ----- VERALTET ----- VERALTET ----- VERALTET --
* Sql für Spalten namens 'StartDate' und 'EndDate':
* WHERE
* ((start >= StartDate AND end <= StartDate) OR (start <= StartDate AND end >= EndDate))
@@ -3136,12 +3220,35 @@ namespace BeWo.Data.Access
* ((start <= StartDate AND start >= EndDate) OR (start >= StartDate AND end <= EndDate))
*/
var inBetween1 = Restrictions.And(Restrictions.Ge(propertyNameStart, start), Restrictions.Le(propertyNameStart, end));
var inBetween2 = Restrictions.And(Restrictions.Le(propertyNameStart, start), Restrictions.Ge(propertyNameEnd, end));
var inBetween3 = Restrictions.And(Restrictions.Le(propertyNameStart, start), Restrictions.Ge(propertyNameEnd, start));
var inBetween4 = Restrictions.And(Restrictions.Ge(propertyNameStart, start), Restrictions.Le(propertyNameEnd, end));
//var inBetween1 = Restrictions.And(Restrictions.Ge(propertyNameStart, start), Restrictions.Le(propertyNameStart, end));
//var inBetween2 = Restrictions.And(Restrictions.Le(propertyNameStart, start), Restrictions.Ge(propertyNameEnd, end));
//var inBetween3 = Restrictions.And(Restrictions.Le(propertyNameStart, start), Restrictions.Ge(propertyNameEnd, start));
//var inBetween4 = Restrictions.And(Restrictions.Ge(propertyNameStart, start), Restrictions.Le(propertyNameEnd, end));
return Restrictions.Or(Restrictions.Or(inBetween1, inBetween2), Restrictions.Or(inBetween3, inBetween4));
//return Restrictions.Or(Restrictions.Or(inBetween1, inBetween2), Restrictions.Or(inBetween3, inBetween4));
// -- VERALTET ----- VERALTET ----- VERALTET ----- VERALTET ----- VERALTET ----- VERALTET ----- VERALTET ----- VERALTET --
// NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU
/* Sql für Spalten namens 'StartDate' und 'EndDate':
* (StartDate < '2020-11-19 10:00:00' AND EndDate <= '2020-11-19 12:00:00' AND EndDate > '2020-11-19 10:00:00')
OR
(StartDate < '2020-11-19 10:00:00' AND EndDate > '2020-11-19 12:00:00')
OR
(StartDate > '2020-11-19 10:00:00' AND StartDate < '2020-11-19 12:00:00')
OR
(StartDate = '2020-11-19 10:00:00' AND EndDate = '2020-11-19 12:00:00')
OR
(StartDate = '2020-11-19 10:00:00' AND EndDate >= '2020-11-19 12:00:00')
*/
// NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU -- NEU
var inBetween1 = Restrictions.And(Restrictions.Lt(propertyNameStart, start), Restrictions.And(Restrictions.Le(propertyNameEnd, end), Restrictions.Gt(propertyNameEnd, start)));
var inBetween2 = Restrictions.And(Restrictions.Lt(propertyNameStart, start), Restrictions.Gt(propertyNameEnd, end));
var inBetween3 = Restrictions.And(Restrictions.Gt(propertyNameStart, start), Restrictions.Lt(propertyNameStart, end));
var inBetween4 = Restrictions.And(Restrictions.Eq(propertyNameStart, start), Restrictions.Eq(propertyNameEnd, end));
var inBetween5 = Restrictions.And(Restrictions.Eq(propertyNameStart, start), Restrictions.Le(propertyNameEnd, end));
return Restrictions.Or(inBetween1, Restrictions.Or(Restrictions.Or(inBetween2, inBetween3), Restrictions.Or(inBetween4, inBetween5)));
}
public bool CheckForOverlappingAbsenceTimes(DateTime startDate, DateTime endDate, long? employeeOid, long? customerOid)
@@ -3322,7 +3429,7 @@ namespace BeWo.Data.Access
var sql = "Oid IN " +
"(SELECT resourceoid FROM resource2newschapp r2n WHERE r2n.newschappoid IN " +
$"(SELECT oid FROM newschedulerappointment WHERE {excludingSelectedAppointment}('{start:yyyy-MM-dd HH:mm:ss}' > startdate OR '{end:yyyy-MM-dd HH:mm:ss}' > startdate) AND ('{start:yyyy-MM-dd HH:mm:ss}' < enddate OR '{end:yyyy-MM-dd HH:mm:ss}' < enddate)))";
$"(SELECT oid FROM newschedulerappointment WHERE IsActive = 1 AND {excludingSelectedAppointment}('{start:yyyy-MM-dd HH:mm:ss}' > startdate OR '{end:yyyy-MM-dd HH:mm:ss}' > startdate) AND ('{start:yyyy-MM-dd HH:mm:ss}' < enddate OR '{end:yyyy-MM-dd HH:mm:ss}' < enddate)))";
var criterion = Expression.Sql(sql);

View File

@@ -241,9 +241,78 @@ namespace BeWo.Data.Entities
}
}
public virtual Guid? GetRecurrenceIdAndIndex(out int index)
{
if(RecurrenceInfo != null)
{
var recurrenceId = BS.Shared.Core.Utils.GetSpecificValueFromRecurrenceInfo(RecurrenceInfo, RecurrenceInfo.IndexOf("Id=\"") + 4);
var recurrenceIndex = BS.Shared.Core.Utils.GetSpecificValueFromRecurrenceInfo(RecurrenceInfo, RecurrenceInfo.IndexOf("Index=\"") + 7);
int.TryParse(recurrenceIndex, out index);
if(Guid.TryParse(recurrenceId, out var guid))
{
return guid;
}
}
index = -1;
return null;
}
public virtual string GetAppointmentType()
{
switch(Type)
{
case 0:
return "Normal";
case 1:
return "Pattern";
case 2:
return "Occurrence";
case 3:
return "Changed Occurrence";
case 4:
return "Deleted Occurrence";
default:
return "Normal";
}
}
public override string ToString()
{
return $"{StartDate?.ToString("dd.MM.yyyy HH:mm:ss")} - {EndDate?.ToString("dd.MM.yyyy HH:mm:ss")}: {Subject}";
}
public virtual int? GetRecurrenceIndex()
{
if(RecurrenceInfo != null)
{
var indexString = BS.Shared.Core.Utils.GetSpecificValueFromRecurrenceInfo(RecurrenceInfo, RecurrenceInfo.IndexOf("Index=\\") + 7);
if(int.TryParse(indexString, out var index))
{
return index;
}
}
return null;
}
public virtual Guid? GetRecurrenceId()
{
if(RecurrenceInfo != null)
{
var idString = BS.Shared.Core.Utils.GetSpecificValueFromRecurrenceInfo(RecurrenceInfo, RecurrenceInfo.IndexOf("Id=\"") + 4);
if(Guid.TryParse(idString, out var guid))
{
return guid;
}
}
return null;
}
}
}

View File

@@ -52,6 +52,8 @@ namespace BeWo.Service.DCEntityMapper
pDataContract.Originator = MapperFactory.CompactEmployeeDC_Employee.MapToNewDC(pEntity.Originator);
}
pDataContract.ActivationType = pEntity.IsActive;
return pDataContract;
}
@@ -109,6 +111,8 @@ namespace BeWo.Service.DCEntityMapper
throw new InternalException(e.Message);
}
pEntity.IsActive = pDataContract.ActivationType;
return pEntity;
}

View File

@@ -983,5 +983,9 @@ namespace BeWo.Service.ServiceContracts
[FaultContract(typeof(BeWoFault))]
[OperationContract]
List<ConfirmationReceiptSignatureDC> FindConfirmationReceiptSignaturesByEmployeeAndServiceRecords(long employeeOid, IEnumerable<long> serviceRecordOids);
[FaultContract(typeof(BeWoFault))]
[OperationContract]
List<SupportConceptDC> GetSupportConceptsById(IEnumerable<long> supportConceptOids);
}
}

View File

@@ -204,5 +204,9 @@ namespace BeWo.Service.ServiceContracts
[FaultContract(typeof(BeWoFault))]
[OperationContract]
List<ResourceDC> CheckResourceAvailability(DateTime start, DateTime end, List<long> resourceOids, long? selectedAppointmentOid);
[FaultContract(typeof(BeWoFault))]
[OperationContract]
SchedulerAppointmentDC FindRootAppointmentByRecurrenceId(string recurrenceId);
}
}

View File

@@ -6549,5 +6549,19 @@ namespace BeWo.Service.ServiceImplementations
throw Utils.CreateBeWoFaultException(e);
}
}
public List<SupportConceptDC> GetSupportConceptsById(IEnumerable<long> supportConceptOids)
{
try
{
var supportConcepts = DAOFactory.GenericDAO.LoadByIDs<SupportConcept>(supportConceptOids);
return MapperFactory.SupportConceptDC_SupportConcept.MapToNewDCs(supportConcepts);
}
catch(Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
}
}

View File

@@ -2249,5 +2249,12 @@ namespace BeWo.Service.ServiceImplementations
{
return MapperFactory.ResourceDC_Resource.MapToNewDCs(DAOFactory.SearchDAO.CheckAvailabilityOfResources(resourceOids, start, end, selectedAppointmentOid));
}
public SchedulerAppointmentDC FindRootAppointmentByRecurrenceId(string recurrenceId)
{
var rootAppointment = DAOFactory.SearchDAO.FindRootAppointmentByRecurrenceId(recurrenceId);
return rootAppointment == null ? null : MapperFactory.SchedulerAppointmentDCSchedulerAppointment.MapToNewDC(rootAppointment);
}
}
}

View File

@@ -985,6 +985,111 @@ namespace BS.Shared.Core
String saveFilename = filename.Replace("..", "").Replace("\"", "").Replace("/", "").Replace(":", "").Replace(";", "");
return Path.Combine(tempPath, saveFilename);
}
/// <summary>
/// Vergleicht die Elemente zweier Listen. Diese müssen vorher sortiert werden!
/// </summary>
/// <typeparam name="T">Typ. Muss gleich sein</typeparam>
/// <param name="a">Die erste Liste</param>
/// <param name="b">Die Liste mit der die erste Liste verglichen wird</param>
/// <returns>True, wenn die Elemente beider Listen gleich sind</returns>
public static bool ListsEqual<T>(IEnumerable<T> a, IEnumerable<T> b)
{
if(a == null && b == null)
{
return true;
}
if(a == null || b == null)
{
return false;
}
var x = a.ToArray();
var y = b.ToArray();
if(x.Length != y.Length)
{
return false;
}
for(var i = 0; i < x.Length; i++)
{
var obj1 = x[i];
var obj2 = y[i];
if(!Equals(obj1, obj2))
{
return false;
}
}
return true;
}
public static string GetSpecificValueFromRecurrenceInfo(string recurrenecInfoString, int startIndex)
{
var valueBuilder = new StringBuilder();
for(; startIndex < recurrenecInfoString.Length; startIndex++)
{
var cr = recurrenecInfoString[startIndex];
if(cr.Equals('"'))
{
break;
}
valueBuilder.Append(cr);
}
return valueBuilder.ToString();
}
public static Guid? GetRecurrenceIdFromRecurrenceInfo(string recurrenceInfo)
{
if(recurrenceInfo?.Length > 0)
{
var idString = GetSpecificValueFromRecurrenceInfo(recurrenceInfo, recurrenceInfo.IndexOf("Id=\"", StringComparison.InvariantCulture) + 4);
if(Guid.TryParse(idString, out var recurrenceId))
{
return recurrenceId;
}
}
return null;
}
public static int GetRecurrenceIndexFromRecurrenceInfo(string recurrenceInfo)
{
if(recurrenceInfo?.Length > 0)
{
var indexString = GetSpecificValueFromRecurrenceInfo(recurrenceInfo, recurrenceInfo.IndexOf("Index=\"", StringComparison.InvariantCulture) + 7);
if(int.TryParse(indexString, out var index))
{
return index;
}
}
return 0;
}
public static void WriteToTextFileOnDesktop(string fileName, string text)
{
#if DEBUG
var path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
using(var fileStream = new FileStream($"{path}/{fileName}", FileMode.Append, FileAccess.Write))
{
using(var streamWriter = new StreamWriter(fileStream))
{
streamWriter.WriteLine(text);
}
}
#endif
}
}
public struct NullCompareResult

View File

@@ -10,6 +10,9 @@ namespace BS.Shared.DataContracts
[DataContract]
public class SchedulerAppointmentDC : IDataContract
{
[DataMember]
public ActivationTypeId ActivationType { get; set; }
[DataMember]
public long? SchedulerAppointmentOid { get; set; }

View File

@@ -90,5 +90,52 @@ namespace BS.Shared.DataContracts
[DataMember]
public Bewilligungsart Bewilligungsart { get; set; }
public override bool Equals(object obj)
{
if(obj is SupportConceptApprovalPeriodDC x)
{
var a = Equals(ApprovedBEInterval, x.ApprovedBEInterval);
var b = Equals(ApprovedBEPerInterval, x.ApprovedBEPerInterval);
var c = Equals(ContactCountInterval, x.ContactCountInterval);
var d = Equals(ContactCountPerInterval, x.ContactCountPerInterval);
var e = Equals(ApprovedBETotal, x.ApprovedBETotal);
var f = Equals(ApprovedFixedAmount, x.ApprovedFixedAmount);
var g = Equals(ApprovedFixedAmountInterval, x.ApprovedFixedAmountInterval);
var h = Equals(EndDate, x.EndDate);
var i = Equals(IsApprovedBEShifting, x.IsApprovedBEShifting);
var j = Equals(IsApprovedFixedAmountShifting, x.IsApprovedFixedAmountShifting);
var k = Equals(MonthlyPayment, x.MonthlyPayment);
var l = Equals(Span, x.Span);
var m = Equals(StartDate, x.StartDate);
var n = Equals(Percentage, x.Percentage);
var o = Equals(SupportConceptApprovalPeriodOid, x.SupportConceptApprovalPeriodOid);
var p = Equals(SupportConceptApprovalPeriodVersion, x.SupportConceptApprovalPeriodVersion);
var q = Equals(ServiceCategory, x.ServiceCategory);
var r = Equals(BudgetDC, x.BudgetDC);
var s = Utils.ListsEqual(SupportConceptApprovalPeriodEmployeeRelations, x.SupportConceptApprovalPeriodEmployeeRelations);
var t = Equals(Bewilligungsart, x.Bewilligungsart);
return a && b && c && d && e && f && g && h && i && j && k && l && m && n && o && p && q && r && s && t;
}
return false;
}
public override int GetHashCode()
{
unchecked
{
const int hashingBase = (int)2166136261;
const int hashingMultiplier = 16777619;
var hash = hashingBase;
hash = (hash * hashingMultiplier) ^ (SupportConceptApprovalPeriodOid?.GetHashCode() ?? 0);
hash = (hash * hashingMultiplier) ^ (SupportConceptApprovalPeriodVersion?.GetHashCode() ?? 0);
return hash;
}
}
}
}

View File

@@ -21,5 +21,37 @@ namespace BS.Shared.DataContracts
[DataMember]
public long? SupportConceptApprovalPeriod2EmployeeOid { get; set; }
public override bool Equals(object obj)
{
if(obj is SupportConceptApprovalPeriodEmployeeRelDC x)
{
var a = Employee?.Equals(x.Employee) ?? false;
var b = Betreuungsschluessel == x.Betreuungsschluessel;
var c = IsAbsolut == x.IsAbsolut;
var d = SupportConceptApprovalPeriod2EmployeeVersion?.Equals(x.SupportConceptApprovalPeriod2EmployeeVersion) ?? false;
var e = SupportConceptApprovalPeriod2EmployeeOid?.Equals(x.SupportConceptApprovalPeriod2EmployeeOid) ?? false;
return a && b && c && d && e;
}
return false;
}
public override int GetHashCode()
{
unchecked
{
const int hashingBase = (int) 2166136261;
const int hashingMultiplier = 16777619;
var hash = hashingBase;
hash = (hash * hashingMultiplier) ^ (SupportConceptApprovalPeriod2EmployeeOid?.GetHashCode() ?? 0);
hash = (hash * hashingMultiplier) ^ (SupportConceptApprovalPeriod2EmployeeVersion?.GetHashCode() ?? 0);
return hash;
}
}
}
}

View File

@@ -1,7 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using BS.Shared.Core;
using BS.Shared.DataContracts.Compact;
namespace BS.Shared.DataContracts
@@ -96,5 +97,37 @@ namespace BS.Shared.DataContracts
[DataMember]
public List<VarFieldDC> VarFields { get; set; }
public override bool Equals(object obj)
{
if(obj is SupportConceptDC sc)
{
var c = Equals(ActivationType, sc.ActivationType);
var d = Equals(ApprovalDate, sc.ApprovalDate);
var e = Equals(Conference, sc.Conference);
var f = Equals(ConferenceDate, sc.ConferenceDate);
var g = Equals(ConferenceVenue, sc.ConferenceVenue);
var h = Equals(ConsultingNeeded, sc.ConsultingNeeded);
var i = Utils.ListsEqual(CostBearerRelations.OrderBy(z => z.CostBearer2SupportConceptOid), sc.CostBearerRelations.OrderBy(z => z.CostBearer2SupportConceptOid));
var k = Utils.ListsEqual(Ratings.OrderBy(z => z.RatingOid), sc.Ratings.OrderBy(z => z.RatingOid));
var l = Equals(Customer, sc.Customer);
var m = Equals(DocumentUploadLockedBy, sc.DocumentUploadLockedBy);
var n = Equals(DocumentUploadLockedOn, sc.DocumentUploadLockedOn);
var o = Utils.ListsEqual(Goals.OrderBy(z => z.ValueListEntryOid), sc.Goals.OrderBy(z => z.ValueListEntryOid));
var p = Equals(Notice, sc.Notice);
var q = Equals(Originator, sc.Originator);
var r = Equals(RenewalSendDate, sc.RenewalSendDate);
var s = Equals(RequisitionSendDate, sc.RequisitionSendDate);
var t = Utils.ListsEqual(ServiceAccountings.OrderBy(z => z.ServiceAccountingOid), sc.ServiceAccountings.OrderBy(z => z.ServiceAccountingOid));
var u = Utils.ListsEqual(VarFields.OrderBy(z => z.VarFieldDefOid), sc.VarFields.OrderBy(z => z.VarFieldDefOid));
var x = SupportConceptOid?.Equals(sc.SupportConceptOid) ?? false;
var y = SupportConceptVersion?.Equals(sc.SupportConceptVersion) ?? false;
return c && d && e && f && g && h && i && k && l && m && n && o && p && q && r && s && t && u && x && y;
}
return false;
}
}
}

View File

@@ -50,5 +50,31 @@ namespace BS.Shared.DataContracts
[DataMember]
public int YCoordinate { get; set; }
//public override bool Equals(object obj)
//{
// if(obj is VarFieldDC varField)
// {
// var a = Equals(ColumnSpan, varField.ColumnSpan);
// var b = Equals(ControlType, varField.ControlType);
// var c = Equals(DecimalPlaces, varField.DecimalPlaces);
// var d = Equals(Group, varField.Group);
// var e = Equals(Height, varField.Height);
// var f = Equals(Label, varField.Label);
// var g = Equals(PossibleItems, varField.PossibleItems);
// var h = Equals(RowSpan, varField.RowSpan);
// var i = Equals(VarFieldDefOid, varField.VarFieldDefOid);
// var j = Equals(VarFieldValue, varField.VarFieldValue);
// var k = Equals(VarFieldValueOid, varField.VarFieldValueOid);
// var l = Equals(VarFieldValueVersion, varField.VarFieldValueVersion);
// var m = Equals(Width, varField.Width);
// var n = Equals(XCoordinate, varField.XCoordinate);
// var o = Equals(YCoordinate, varField.YCoordinate);
// return a && b && c && d && e && f && g && h && i && j && k && l && m && n && o;
// }
// return false;
//}
}
}