I am using the scheduler with the following setup:
- Multiple scheduler instances
- Common resources (soccer fields, rooms etc.)
- Common categories (match, training, other)
- Advanced Form template
Conditions:
Resources is not allowed for double-booking/overlap in a timeslot in any scheduler instance.
Categories can be the same in multiple timeslots in any scheduler instance.
Now, to achieve this I've combined the functions "ExceedsLimit" and "ConflictsWithOccurrences" (described by Telerik elsewhere) and expanded them with ResourceID. Like this, used in the AppointmentInsert event:
And in the AppointmentUpdate event:
I've modified the "ExceedsLimit" like this:
And the "ConflictsWithOccurrences" like this:
This has helped me alot, but not enough as it fails in some cases:
1. The first ocurrence in a recurring appointment is not allowed to be updated, it conflicts whith itself.
No matter how I try to modify the functions, I can't seem to solve It completely. Only new pitfalls arises... I try to check and compare for "Insert new", "update existing", "If recurring" and so on.
Is there any obvoius faults in the above code or is there any better solution to meet these requirements?
- Multiple scheduler instances
- Common resources (soccer fields, rooms etc.)
- Common categories (match, training, other)
- Advanced Form template
Conditions:
Resources is not allowed for double-booking/overlap in a timeslot in any scheduler instance.
Categories can be the same in multiple timeslots in any scheduler instance.
Now, to achieve this I've combined the functions "ExceedsLimit" and "ConflictsWithOccurrences" (described by Telerik elsewhere) and expanded them with ResourceID. Like this, used in the AppointmentInsert event:
If ExceedsLimit(e.Appointment, e.Appointment.Resources.GetResourceByType("Resource").Key) OrElse ConflictsWithOccurrences(e.Appointment, e.Appointment.Resources.GetResourceByType("Resurs").Key) Then ... End IfAnd in the AppointmentUpdate event:
If ExceedsLimit(e.ModifiedAppointment, e.ModifiedAppointment.Resources.GetResourceByType("Resurs").Key) OrElse ConflictsWithOccurrences(e.ModifiedAppointment, e.ModifiedAppointment.Resources.GetResourceByType("Resurs").Key) Then ... End IfI've modified the "ExceedsLimit" like this:
Protected Function ExceedsLimit(ByVal apt As Appointment, ByVal ResourceID As String) As Boolean Dim appointmentsCount As Integer = 0 Dim allAppointments As New AppointmentCollection 'Fill temporary appointments collection for use in comparison 'Subjectfield is used for comparison on ResourceID For Each dr As DataRow In cS.GetReservationsByResourceID(ResourceID) DirectCast(allAppointments, IList).Add(New Appointment(dr("ID"), dr("Start"), dr("End"), dr("ResourceID"))) Next 'Search through all appointments from all calendar instances and compare to current moved/changed/inserted appointment For Each existingApt As Appointment In allAppointments.GetAppointmentsInRange(apt.Start, apt.[End]) If existingApt.Visible And existingApt.Subject = ResourceID Then appointmentsCount += 1 End If ' If this is a recurring appointment, we will also check if it's occurrences ' overlap with other appointments in the current view Dim parsedRule As RecurrenceRule If RecurrenceRule.TryParse(existingApt.RecurrenceRule.ToString(), parsedRule) And existingApt.Subject = ResourceID Then parsedRule.SetEffectiveRange(RadScheduler1.VisibleRangeStart, RadScheduler1.VisibleRangeEnd) For Each occurrence As DateTime In parsedRule.Occurrences appointmentsCount = RadScheduler1.Appointments.GetAppointmentsInRange(occurrence, occurrence.Add(existingApt.Duration)).Count If (appointmentsCount > (AppointmentsLimit - 1)) Then Return True End If Next End If Next Return (appointmentsCount > AppointmentsLimit - 1) End FunctionAnd the "ConflictsWithOccurrences" like this:
Protected Function ConflictsWithOccurrences(ByVal apt As Appointment, ByVal ResourceID As String) As Boolean Dim allAppointments As New AppointmentCollection 'Fill temporary appointments collection for use in comparison 'Subjectfield is used for comparison on ResourceID For Each dr As DataRow In cS.GetReservationsByResourceID(ResourceID) DirectCast(allAppointments, IList).Add(New Appointment(dr("ID"), dr("Start"), dr("End"), dr("ResourceID"))) Next Dim parsedRule As RecurrenceRule For Each existingApt As Appointment In allAppointments.GetAppointmentsInRange(apt.Start, apt.[End]) If RecurrenceRule.TryParse(existingApt.RecurrenceRule.ToString(), parsedRule) Then 'parsedRule.SetEffectiveRange(RadScheduler1.VisibleRangeStart, RadScheduler1.VisibleRangeEnd); For Each occurrence As DateTime In parsedRule.Occurrences 'check if the start time of the occurrence is within the range of the appointment: If (occurrence.CompareTo(apt.Start) > 0) And (occurrence.CompareTo(apt.[End]) < 0) Then Return True End If 'check if the end time of the occurrence is within the range of the appointment: If (occurrence.Add(existingApt.Duration).CompareTo(apt.Start) > 0) And (occurrence.Add(existingApt.Duration).CompareTo(apt.[End]) < 0) Then Return True End If 'check if the start time of the appointment is within the range of the occurrence: If (apt.Start.CompareTo(occurrence) > 0) And (apt.Start.CompareTo(occurrence.Add(existingApt.Duration)) < 0) Then Return True End If 'check if the end time of the appointment is within the range of the occurrence: If (apt.[End].CompareTo(occurrence) > 0) And (apt.[End].CompareTo(occurrence.Add(existingApt.Duration)) < 0) Then Return True End If 'check if start or end the appoitnment coincide with start or end of the occurrence If (apt.Start.CompareTo(occurrence) = 0) OrElse (apt.Start.CompareTo(occurrence.Add(existingApt.Duration)) = 0) OrElse (apt.[End].CompareTo(occurrence) = 0) OrElse (apt.[End].CompareTo(occurrence.Add(existingApt.Duration)) = 0) Then Return True End If Next End If Next Return False End FunctionThis has helped me alot, but not enough as it fails in some cases:
1. The first ocurrence in a recurring appointment is not allowed to be updated, it conflicts whith itself.
No matter how I try to modify the functions, I can't seem to solve It completely. Only new pitfalls arises... I try to check and compare for "Insert new", "update existing", "If recurring" and so on.
Is there any obvoius faults in the above code or is there any better solution to meet these requirements?