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 If
And 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 If
I'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 Function
And 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 Function
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?