635 lines
23 KiB
C#
635 lines
23 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
|
|
using BeWo.Controls.Controls.Calendar;
|
|
|
|
using BS.Shared;
|
|
using BS.Shared.Core;
|
|
using BS.Shared.DataContracts;
|
|
using BS.Shared.DataContracts.Compact;
|
|
using BS.Shared.Extensions;
|
|
|
|
namespace BeWo.ViewModel
|
|
{
|
|
public class BookingSequenceVM : AbstractDCMapperVM<BookingSequenceDC>
|
|
{
|
|
public static string PropertyName_ChangedElements = "ChangedElements";
|
|
|
|
public static string PropertyName_Employee = "Employee";
|
|
|
|
public static string PropertyName_Frequency = "Frequency";
|
|
|
|
public static string PropertyName_Notice = "Notice";
|
|
|
|
public static string PropertyName_RepeatInterval = "RepeatInterval";
|
|
|
|
public static string PropertyName_Resource = "Resource";
|
|
|
|
public static string PropertyName_RootAppointment = "RootAppointment";
|
|
|
|
public static string PropertyName_SequenceEnd = "SequenceEnd";
|
|
|
|
private readonly Dictionary<int, Appointment> _ChangedElements = new Dictionary<int, Appointment>();
|
|
|
|
private readonly List<FrequencyTranslation> _PossibleFrequencies = new List<FrequencyTranslation>
|
|
{
|
|
new FrequencyTranslation
|
|
{
|
|
Frequency = ResourceBookingFrequencyType.Once,
|
|
Translation = "Einmalig"
|
|
},
|
|
new FrequencyTranslation
|
|
{
|
|
Frequency = ResourceBookingFrequencyType.Daily,
|
|
Translation = "jeden Tag"
|
|
},
|
|
new FrequencyTranslation
|
|
{
|
|
Frequency = ResourceBookingFrequencyType.Weekly
|
|
},
|
|
new FrequencyTranslation
|
|
{
|
|
Frequency = ResourceBookingFrequencyType.Monthly
|
|
},
|
|
new FrequencyTranslation
|
|
{
|
|
Frequency = ResourceBookingFrequencyType.MonthlyOnFirstDay
|
|
},
|
|
new FrequencyTranslation
|
|
{
|
|
Frequency = ResourceBookingFrequencyType.MonthlyOnLastDay
|
|
},
|
|
};
|
|
|
|
private Dictionary<int, Appointment> _AppointmentsInSpan = new Dictionary<int, Appointment>();
|
|
|
|
private CompactEmployeeDC _Employee;
|
|
|
|
private ResourceBookingFrequencyType _Frequency;
|
|
|
|
private bool _NeedsRecalculation = true;
|
|
|
|
private string _Notice;
|
|
|
|
private int _RepeatInterval = 1;
|
|
|
|
private ResourceDC _Resource;
|
|
|
|
private Appointment _RootAppointment;
|
|
|
|
private DateTime _SequenceEnd;
|
|
|
|
private DateTimeSpan _SpanToConsider;
|
|
|
|
public BookingSequenceVM(BookingSequenceDC pDC) : base(pDC, pDC.SequenceOid == null)
|
|
{
|
|
}
|
|
|
|
public List<Appointment> AppointmentsInSpan
|
|
{
|
|
get
|
|
{
|
|
if (_NeedsRecalculation && _SpanToConsider != null)
|
|
{
|
|
Dictionary<int, Appointment> lBak = _AppointmentsInSpan;
|
|
|
|
_AppointmentsInSpan = CalculateAppointmentsFromSequence(_SpanToConsider);
|
|
|
|
if (lBak.Count > 0)
|
|
{
|
|
foreach (int lPos in lBak.Keys)
|
|
{
|
|
if (_AppointmentsInSpan.ContainsKey(lPos) && _AppointmentsInSpan[lPos] != null)
|
|
{
|
|
lBak[lPos].Duration = _AppointmentsInSpan[lPos].Duration;
|
|
lBak[lPos].Notice = _AppointmentsInSpan[lPos].Notice;
|
|
lBak[lPos].Text = _AppointmentsInSpan[lPos].Text;
|
|
_AppointmentsInSpan[lPos] = lBak[lPos];
|
|
}
|
|
}
|
|
}
|
|
|
|
_NeedsRecalculation = false;
|
|
}
|
|
|
|
return _AppointmentsInSpan.Values.ToList();
|
|
}
|
|
}
|
|
|
|
public Dictionary<int, Appointment> ChangedElements
|
|
{
|
|
get { return _ChangedElements; }
|
|
}
|
|
|
|
public CompactEmployeeDC Employee
|
|
{
|
|
get { return _Employee; }
|
|
|
|
set
|
|
{
|
|
if (AreDifferent(_Employee, value))
|
|
{
|
|
_Employee = value;
|
|
|
|
// StoreDirtyInformation(AreDifferent(DataContract.Employee, value), PropertyName_Employee);
|
|
FirePropertyChanged(PropertyName_Employee);
|
|
}
|
|
}
|
|
}
|
|
|
|
public ResourceBookingFrequencyType Frequency
|
|
{
|
|
get { return _Frequency; }
|
|
|
|
set
|
|
{
|
|
if (AreDifferent(_Frequency, value))
|
|
{
|
|
_NeedsRecalculation = true;
|
|
_Frequency = value;
|
|
StoreDirtyInformation(AreDifferent(DataContract.Frequency, value), PropertyName_Frequency);
|
|
FirePropertyChanged(PropertyName_Frequency);
|
|
}
|
|
}
|
|
}
|
|
|
|
public string Notice
|
|
{
|
|
get { return _Notice; }
|
|
|
|
set
|
|
{
|
|
if (AreDifferent(_Notice, value))
|
|
{
|
|
_Notice = value;
|
|
StoreDirtyInformation(AreDifferent(DataContract.Notice, value), PropertyName_Notice);
|
|
FirePropertyChanged(PropertyName_Notice);
|
|
}
|
|
}
|
|
}
|
|
|
|
public List<FrequencyTranslation> PossibleFrequencies
|
|
{
|
|
get { return _PossibleFrequencies; }
|
|
}
|
|
|
|
public int RepeatInterval
|
|
{
|
|
get { return _RepeatInterval; }
|
|
|
|
set
|
|
{
|
|
if (AreDifferent(_RepeatInterval, value))
|
|
{
|
|
_NeedsRecalculation = true;
|
|
_RepeatInterval = value;
|
|
StoreDirtyInformation(AreDifferent(DataContract.RepeatInterval, value), PropertyName_RepeatInterval);
|
|
FirePropertyChanged(PropertyName_RepeatInterval);
|
|
}
|
|
}
|
|
}
|
|
|
|
public ResourceDC Resource
|
|
{
|
|
get { return _Resource; }
|
|
|
|
set
|
|
{
|
|
_Resource = value;
|
|
RootAppointment.Index = (int) value.ResourceOid.Value;
|
|
RootAppointment.Brush = value.GetBrush();
|
|
foreach (var iChanged in _ChangedElements)
|
|
{
|
|
iChanged.Value.Index = (int) value.ResourceOid.Value;
|
|
iChanged.Value.Brush = value.GetBrush();
|
|
}
|
|
|
|
FirePropertyChanged(PropertyName_Resource);
|
|
}
|
|
}
|
|
|
|
public Appointment RootAppointment
|
|
{
|
|
get { return _RootAppointment; }
|
|
|
|
set
|
|
{
|
|
if (AreDifferent(_RootAppointment, value))
|
|
{
|
|
_RootAppointment = value;
|
|
StoreDirtyInformation(!AreEqual(DataContract.RootBooking, _RootAppointment),
|
|
PropertyName_RootAppointment);
|
|
FirePropertyChanged(PropertyName_RootAppointment);
|
|
_RootAppointment.PropertyChanged += _RootAppointment_PropertyChanged;
|
|
_RootAppointment.Duration.PropertyChanged += Duration_PropertyChanged;
|
|
_RootAppointment.Duration.SynchEndDate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public DateTime SequenceEnd
|
|
{
|
|
get { return _SequenceEnd; }
|
|
|
|
set
|
|
{
|
|
if (AreDifferent(_SequenceEnd, value))
|
|
{
|
|
value = value.Date.AddHours(23).AddMinutes(59);
|
|
_SequenceEnd = value;
|
|
StoreDirtyInformation(AreDifferent(DataContract.SequenceEnd, value), PropertyName_SequenceEnd);
|
|
FirePropertyChanged(PropertyName_SequenceEnd);
|
|
}
|
|
}
|
|
}
|
|
|
|
public DateTimeSpan SpanToConsider
|
|
{
|
|
get { return _SpanToConsider; }
|
|
|
|
set
|
|
{
|
|
if (AreDifferent(_SpanToConsider, value))
|
|
{
|
|
_SpanToConsider = value;
|
|
_NeedsRecalculation = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool IsChangedElementsDirty
|
|
{
|
|
get
|
|
{
|
|
if (DataContract.ChangedElements.Count != _ChangedElements.Count)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (
|
|
DataContract.ChangedElements.Count(
|
|
dc =>
|
|
!_ChangedElements.ContainsKey(dc.SequencePosition) ||
|
|
!AreEqual(dc, _ChangedElements[dc.SequencePosition])) > 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public Dictionary<int, Appointment> CalculateAppointmentsFromSequence(DateTimeSpan pSpanToConsider)
|
|
{
|
|
var lResult = new Dictionary<int, Appointment>();
|
|
|
|
DateTime lCurrentStart = RootAppointment.Duration.StartDateTime;
|
|
DateTime lCurrentEnd = RootAppointment.Duration.EndDateTime;
|
|
int lCurrentPostion = 0;
|
|
int lCurrentSequencePosition = 0;
|
|
|
|
if (RootAppointment.Duration.Overlaps(pSpanToConsider))
|
|
{
|
|
lResult.Add(0, _RootAppointment);
|
|
}
|
|
|
|
lCurrentStart = Next(lCurrentStart, _Frequency);
|
|
lCurrentEnd = Next(lCurrentEnd, _Frequency);
|
|
|
|
if (_Frequency != ResourceBookingFrequencyType.Once)
|
|
{
|
|
while (lCurrentStart <= pSpanToConsider.EndDateTime && lCurrentStart <= _SequenceEnd)
|
|
{
|
|
lCurrentPostion++;
|
|
|
|
if (lCurrentPostion%_RepeatInterval == 0)
|
|
{
|
|
lCurrentSequencePosition++;
|
|
if (_ChangedElements.ContainsKey(lCurrentSequencePosition))
|
|
{
|
|
if (_ChangedElements[lCurrentSequencePosition] != null &&
|
|
_ChangedElements[lCurrentSequencePosition].Duration.Overlaps(pSpanToConsider))
|
|
{
|
|
lResult.Add(lCurrentSequencePosition, _ChangedElements[lCurrentSequencePosition]);
|
|
}
|
|
}
|
|
else if (new DateTimeSpan
|
|
{
|
|
StartDateTime = lCurrentStart,
|
|
EndDateTime = lCurrentEnd
|
|
}.Overlaps(pSpanToConsider))
|
|
{
|
|
var app = new Appointment();
|
|
var dts = new DateTimeSpan();
|
|
dts.StartDateTime = lCurrentStart;
|
|
dts.EndDateTime = lCurrentEnd;
|
|
|
|
app.Duration = dts;
|
|
app.Notice = RootAppointment.Notice;
|
|
|
|
app.Index = RootAppointment.Index;
|
|
app.Brush = _Resource.GetBrush();
|
|
app.Tag = RootAppointment.Tag;
|
|
|
|
string text = RootAppointment.Text;
|
|
if (text.LastIndexOf("\n") > 0)
|
|
{
|
|
text = text.Substring(0, text.LastIndexOf("\n") + 1);
|
|
text += dts.ToString();
|
|
}
|
|
|
|
app.Text = text;
|
|
|
|
lResult.Add(lCurrentSequencePosition, app);
|
|
}
|
|
}
|
|
|
|
lCurrentStart = Next(lCurrentStart, _Frequency);
|
|
lCurrentEnd = Next(lCurrentEnd, _Frequency);
|
|
}
|
|
}
|
|
|
|
return lResult;
|
|
}
|
|
|
|
public void ChangeElement(int pSequencePosition, Appointment pAppointment)
|
|
{
|
|
_ChangedElements[pSequencePosition] = pAppointment;
|
|
|
|
StoreDirtyInformation(IsChangedElementsDirty, PropertyName_ChangedElements);
|
|
}
|
|
|
|
public void ClearChanged()
|
|
{
|
|
_NeedsRecalculation = true;
|
|
_ChangedElements.Clear();
|
|
|
|
StoreDirtyInformation(IsChangedElementsDirty, PropertyName_ChangedElements);
|
|
}
|
|
|
|
public void DeleteElement(int pSequencePosition)
|
|
{
|
|
_ChangedElements[pSequencePosition] = null;
|
|
if (_AppointmentsInSpan.ContainsKey(pSequencePosition))
|
|
{
|
|
_AppointmentsInSpan.Remove(pSequencePosition);
|
|
}
|
|
|
|
StoreDirtyInformation(IsChangedElementsDirty, PropertyName_ChangedElements);
|
|
}
|
|
|
|
public Appointment GetAppointment(int pSequencePostion)
|
|
{
|
|
if (_AppointmentsInSpan.ContainsKey(pSequencePostion))
|
|
{
|
|
return _AppointmentsInSpan[pSequencePostion];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public int GetSequencePosition(Appointment pAppointment)
|
|
{
|
|
foreach (var iPair in _AppointmentsInSpan)
|
|
{
|
|
if (iPair.Value == pAppointment)
|
|
{
|
|
return iPair.Key;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
public DateTimeSpan GetSequenceSpan()
|
|
{
|
|
return new DateTimeSpan
|
|
{
|
|
StartDateTime = RootAppointment.Duration.StartDateTime,
|
|
EndDateTime = SequenceEnd
|
|
};
|
|
}
|
|
|
|
public void UpdatePossibleFrequencies(DateTime pStartDate)
|
|
{
|
|
DateTimeFormatInfo lDateInfo = DateTimeFormatInfo.CurrentInfo;
|
|
|
|
_PossibleFrequencies.Single(f => f.Frequency == ResourceBookingFrequencyType.Weekly).Translation =
|
|
"jeden " + lDateInfo.GetDayName(pStartDate.DayOfWeek);
|
|
|
|
_PossibleFrequencies.Single(f => f.Frequency == ResourceBookingFrequencyType.Monthly).Translation =
|
|
"jeden " + pStartDate.Day + "ten des Monats";
|
|
|
|
_PossibleFrequencies.Single(f => f.Frequency == ResourceBookingFrequencyType.MonthlyOnFirstDay).Translation
|
|
= "jeden " + pStartDate.GetWeekdayOccurence(true) + ". " +
|
|
lDateInfo.GetShortestDayName(pStartDate.DayOfWeek) + ". des Monats";
|
|
|
|
_PossibleFrequencies.Single(f => f.Frequency == ResourceBookingFrequencyType.MonthlyOnLastDay).Translation =
|
|
"jeden " + pStartDate.GetWeekdayOccurence(false) + ". letzten " +
|
|
lDateInfo.GetShortestDayName(pStartDate.DayOfWeek) + ". des Monats";
|
|
}
|
|
|
|
protected override void InitByDataContract(BookingSequenceDC pDataContract)
|
|
{
|
|
string text = string.Empty;
|
|
|
|
if (pDataContract.RootBooking.Employee != null)
|
|
{
|
|
text = pDataContract.RootBooking.Employee.FirstName + " " + pDataContract.RootBooking.Employee.LastName +
|
|
":\n";
|
|
}
|
|
|
|
if (pDataContract.Resource != null)
|
|
{
|
|
text += pDataContract.Resource.Name + "\n";
|
|
}
|
|
|
|
if (!String.IsNullOrEmpty(pDataContract.RootBooking.Notice))
|
|
{
|
|
text += "\n";
|
|
text += pDataContract.RootBooking.Notice;
|
|
text += "\n";
|
|
}
|
|
|
|
text += "\n";
|
|
|
|
if (pDataContract.RootBooking.Duration.StartDate.Date == pDataContract.RootBooking.Duration.EndDate.Date)
|
|
{
|
|
// return StartDateTime.ToMyDateTimeString() + " " + StartDateTime.ToShortTimeString() + " - " + EndDateTime.ToMyDateTimeString() + " " + EndDateTime.ToShortTimeString();
|
|
text += String.Format("{0:ddd, dd.MM.yy HH:mm} - {1:HH:mm}",
|
|
pDataContract.RootBooking.Duration.StartDateTime, pDataContract.RootBooking.Duration.EndDateTime);
|
|
|
|
// text += DataContract.RootBooking.Duration.ToString();
|
|
}
|
|
else
|
|
{
|
|
text += pDataContract.RootBooking.Duration.ToString();
|
|
}
|
|
|
|
RootAppointment = new Appointment
|
|
{
|
|
Duration = pDataContract.RootBooking.Duration,
|
|
Notice = pDataContract.RootBooking.Notice,
|
|
Text = text,
|
|
Tag = pDataContract.RootBooking.Employee,
|
|
};
|
|
|
|
if (pDataContract.Resource != null)
|
|
{
|
|
RootAppointment.Index = (int) pDataContract.Resource.ResourceOid.Value;
|
|
RootAppointment.Brush = pDataContract.Resource.GetBrush();
|
|
}
|
|
|
|
if (pDataContract.ChangedElements == null)
|
|
{
|
|
pDataContract.ChangedElements = new List<ResourceBookingDC>();
|
|
}
|
|
|
|
foreach (ResourceBookingDC iBooking in pDataContract.ChangedElements)
|
|
{
|
|
if (!_ChangedElements.ContainsKey(iBooking.SequencePosition))
|
|
{
|
|
_ChangedElements.Add(
|
|
iBooking.SequencePosition,
|
|
iBooking.IsDeleted
|
|
? null
|
|
: new Appointment
|
|
{
|
|
Duration = iBooking.Duration.Clone(),
|
|
Notice = iBooking.Notice,
|
|
Index = RootAppointment.Index,
|
|
Brush = RootAppointment.Brush,
|
|
Tag = iBooking.Employee
|
|
});
|
|
}
|
|
}
|
|
|
|
_Frequency = pDataContract.Frequency;
|
|
_RepeatInterval = pDataContract.RepeatInterval;
|
|
_SequenceEnd = pDataContract.SequenceEnd;
|
|
_Resource = pDataContract.Resource;
|
|
_Notice = pDataContract.Notice;
|
|
_Employee = pDataContract.Employee;
|
|
|
|
UpdatePossibleFrequencies(_RootAppointment.Duration.StartDateTime);
|
|
}
|
|
|
|
protected override BookingSequenceDC MapToDataContract(BookingSequenceDC pDataContract, bool doCommit)
|
|
{
|
|
pDataContract.Frequency = _Frequency;
|
|
pDataContract.RepeatInterval = _RepeatInterval;
|
|
pDataContract.Notice = _Notice;
|
|
pDataContract.Resource = _Resource;
|
|
pDataContract.SequenceEnd = _SequenceEnd;
|
|
pDataContract.Employee = RootAppointment.Tag as CompactEmployeeDC;
|
|
|
|
pDataContract.RootBooking.Duration = RootAppointment.Duration.Clone();
|
|
pDataContract.RootBooking.Notice = RootAppointment.Notice;
|
|
pDataContract.RootBooking.Employee = RootAppointment.Tag as CompactEmployeeDC;
|
|
|
|
if (_Frequency == ResourceBookingFrequencyType.Once)
|
|
{
|
|
pDataContract.SequenceEnd = pDataContract.RootBooking.Duration.EndDateTime;
|
|
}
|
|
|
|
pDataContract.ChangedElements.RemoveRange(dc => !_ChangedElements.ContainsKey(dc.SequencePosition));
|
|
|
|
foreach (ResourceBookingDC iDC in pDataContract.ChangedElements)
|
|
{
|
|
if (_ChangedElements[iDC.SequencePosition] != null)
|
|
{
|
|
iDC.Duration = _ChangedElements[iDC.SequencePosition].Duration.Clone();
|
|
iDC.Notice = _ChangedElements[iDC.SequencePosition].Notice;
|
|
iDC.Employee = _ChangedElements[iDC.SequencePosition].Tag as CompactEmployeeDC;
|
|
}
|
|
else
|
|
{
|
|
iDC.IsDeleted = true;
|
|
}
|
|
}
|
|
|
|
foreach (
|
|
var iEntry in
|
|
_ChangedElements.Where(
|
|
entry =>
|
|
pDataContract.ChangedElements.SingleOrDefault(dc => dc.SequencePosition == entry.Key) ==
|
|
null))
|
|
{
|
|
if (iEntry.Value == null)
|
|
{
|
|
pDataContract.ChangedElements.Add(
|
|
new ResourceBookingDC
|
|
{
|
|
SequencePosition = iEntry.Key,
|
|
IsDeleted = true,
|
|
Duration = null
|
|
});
|
|
}
|
|
else
|
|
{
|
|
pDataContract.ChangedElements.Add(
|
|
new ResourceBookingDC
|
|
{
|
|
SequencePosition = iEntry.Key,
|
|
IsDeleted = false,
|
|
Duration = iEntry.Value.Duration.Clone(),
|
|
Notice = iEntry.Value.Notice,
|
|
Employee = iEntry.Value.Tag as CompactEmployeeDC
|
|
});
|
|
}
|
|
}
|
|
|
|
return pDataContract;
|
|
}
|
|
|
|
private bool AreEqual(ResourceBookingDC x, Appointment y)
|
|
{
|
|
NullCompareResult lResult = Utils.NullCompare(x, y);
|
|
|
|
return lResult.BothNotNull
|
|
? x.Duration.StartDateTime == y.Duration.StartDateTime &&
|
|
x.Duration.EndDateTime == y.Duration.EndDateTime && x.Notice == y.Notice
|
|
: lResult.Different;
|
|
}
|
|
|
|
private void Duration_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
if (e.PropertyName == DateTimeSpan.PropertyName_StartDate)
|
|
{
|
|
UpdatePossibleFrequencies(_RootAppointment.Duration.StartDateTime);
|
|
}
|
|
}
|
|
|
|
private DateTime Next(DateTime pDate, ResourceBookingFrequencyType pFrequency)
|
|
{
|
|
switch (pFrequency)
|
|
{
|
|
case ResourceBookingFrequencyType.Daily:
|
|
return pDate.AddDays(1);
|
|
case ResourceBookingFrequencyType.Weekly:
|
|
return pDate.AddDays(7);
|
|
case ResourceBookingFrequencyType.Monthly:
|
|
return pDate.AddMonths(1);
|
|
case ResourceBookingFrequencyType.MonthlyOnFirstDay:
|
|
return pDate.AddMonthsDayDependent(1, true);
|
|
case ResourceBookingFrequencyType.MonthlyOnLastDay:
|
|
return pDate.AddMonthsDayDependent(1, false);
|
|
default:
|
|
return pDate;
|
|
}
|
|
}
|
|
|
|
private void _RootAppointment_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
if (e.PropertyName == Appointment.PropertyName_Duration)
|
|
{
|
|
UpdatePossibleFrequencies(_RootAppointment.Duration.StartDateTime);
|
|
}
|
|
|
|
StoreDirtyInformation(!AreEqual(DataContract.RootBooking, _RootAppointment), PropertyName_RootAppointment);
|
|
}
|
|
}
|
|
} |